mirror of
https://github.com/topjohnwu/Magisk.git
synced 2025-12-02 18:31:53 +00:00
Convert indentation to spaces
The tab war is lost
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@@ -9,35 +9,35 @@
|
||||
*****************/
|
||||
|
||||
struct mtk_hdr {
|
||||
uint32_t magic; /* MTK magic */
|
||||
uint32_t size; /* Size of the content */
|
||||
char name[32]; /* The type of the header */
|
||||
uint32_t magic; /* MTK magic */
|
||||
uint32_t size; /* Size of the content */
|
||||
char name[32]; /* The type of the header */
|
||||
|
||||
char padding[472]; /* Padding to 512 bytes */
|
||||
char padding[472]; /* Padding to 512 bytes */
|
||||
} __attribute__((packed));
|
||||
|
||||
struct dhtb_hdr {
|
||||
char magic[8]; /* DHTB magic */
|
||||
uint8_t checksum[40]; /* Payload SHA256, whole image + SEANDROIDENFORCE + 0xFFFFFFFF */
|
||||
uint32_t size; /* Payload size, whole image + SEANDROIDENFORCE + 0xFFFFFFFF */
|
||||
char magic[8]; /* DHTB magic */
|
||||
uint8_t checksum[40]; /* Payload SHA256, whole image + SEANDROIDENFORCE + 0xFFFFFFFF */
|
||||
uint32_t size; /* Payload size, whole image + SEANDROIDENFORCE + 0xFFFFFFFF */
|
||||
|
||||
char padding[460]; /* Padding to 512 bytes */
|
||||
char padding[460]; /* Padding to 512 bytes */
|
||||
} __attribute__((packed));
|
||||
|
||||
struct blob_hdr {
|
||||
char secure_magic[20]; /* "-SIGNED-BY-SIGNBLOB-" */
|
||||
uint32_t datalen; /* 0x00000000 */
|
||||
uint32_t signature; /* 0x00000000 */
|
||||
char magic[16]; /* "MSM-RADIO-UPDATE" */
|
||||
uint32_t hdr_version; /* 0x00010000 */
|
||||
uint32_t hdr_size; /* Size of header */
|
||||
uint32_t part_offset; /* Same as size */
|
||||
uint32_t num_parts; /* Number of partitions */
|
||||
uint32_t unknown[7]; /* All 0x00000000 */
|
||||
char name[4]; /* Name of partition */
|
||||
uint32_t offset; /* offset in blob where this partition starts */
|
||||
uint32_t size; /* Size of data */
|
||||
uint32_t version; /* 0x00000001 */
|
||||
char secure_magic[20]; /* "-SIGNED-BY-SIGNBLOB-" */
|
||||
uint32_t datalen; /* 0x00000000 */
|
||||
uint32_t signature; /* 0x00000000 */
|
||||
char magic[16]; /* "MSM-RADIO-UPDATE" */
|
||||
uint32_t hdr_version; /* 0x00010000 */
|
||||
uint32_t hdr_size; /* Size of header */
|
||||
uint32_t part_offset; /* Same as size */
|
||||
uint32_t num_parts; /* Number of partitions */
|
||||
uint32_t unknown[7]; /* All 0x00000000 */
|
||||
char name[4]; /* Name of partition */
|
||||
uint32_t offset; /* offset in blob where this partition starts */
|
||||
uint32_t size; /* Size of data */
|
||||
uint32_t version; /* 0x00000001 */
|
||||
} __attribute__((packed));
|
||||
|
||||
|
||||
@@ -78,54 +78,54 @@ struct blob_hdr {
|
||||
*/
|
||||
|
||||
struct boot_img_hdr_common {
|
||||
char magic[BOOT_MAGIC_SIZE];
|
||||
char magic[BOOT_MAGIC_SIZE];
|
||||
|
||||
uint32_t kernel_size; /* size in bytes */
|
||||
uint32_t kernel_addr; /* physical load addr */
|
||||
uint32_t kernel_size; /* size in bytes */
|
||||
uint32_t kernel_addr; /* physical load addr */
|
||||
|
||||
uint32_t ramdisk_size; /* size in bytes */
|
||||
uint32_t ramdisk_addr; /* physical load addr */
|
||||
uint32_t ramdisk_size; /* size in bytes */
|
||||
uint32_t ramdisk_addr; /* physical load addr */
|
||||
|
||||
uint32_t second_size; /* size in bytes */
|
||||
uint32_t second_addr; /* physical load addr */
|
||||
uint32_t second_size; /* size in bytes */
|
||||
uint32_t second_addr; /* physical load addr */
|
||||
} __attribute__((packed));
|
||||
|
||||
struct boot_img_hdr_v0 : public boot_img_hdr_common {
|
||||
uint32_t tags_addr; /* physical addr for kernel tags */
|
||||
uint32_t page_size; /* flash page size we assume */
|
||||
uint32_t tags_addr; /* physical addr for kernel tags */
|
||||
uint32_t page_size; /* flash page size we assume */
|
||||
|
||||
// In header v1, this field is used for header version
|
||||
// However, on some devices like Samsung, this field is used to store DTB
|
||||
// We treat this field differently based on its value
|
||||
union {
|
||||
uint32_t header_version; /* the version of the header */
|
||||
uint32_t extra_size; /* extra blob size in bytes */
|
||||
};
|
||||
// In header v1, this field is used for header version
|
||||
// However, on some devices like Samsung, this field is used to store DTB
|
||||
// We treat this field differently based on its value
|
||||
union {
|
||||
uint32_t header_version; /* the version of the header */
|
||||
uint32_t extra_size; /* extra blob size in bytes */
|
||||
};
|
||||
|
||||
// Operating system version and security patch level.
|
||||
// For version "A.B.C" and patch level "Y-M-D":
|
||||
// (7 bits for each of A, B, C; 7 bits for (Y-2000), 4 bits for M)
|
||||
// os_version = A[31:25] B[24:18] C[17:11] (Y-2000)[10:4] M[3:0]
|
||||
uint32_t os_version;
|
||||
// Operating system version and security patch level.
|
||||
// For version "A.B.C" and patch level "Y-M-D":
|
||||
// (7 bits for each of A, B, C; 7 bits for (Y-2000), 4 bits for M)
|
||||
// os_version = A[31:25] B[24:18] C[17:11] (Y-2000)[10:4] M[3:0]
|
||||
uint32_t os_version;
|
||||
|
||||
char name[BOOT_NAME_SIZE]; /* asciiz product name */
|
||||
char cmdline[BOOT_ARGS_SIZE];
|
||||
char id[BOOT_ID_SIZE]; /* timestamp / checksum / sha1 / etc */
|
||||
char name[BOOT_NAME_SIZE]; /* asciiz product name */
|
||||
char cmdline[BOOT_ARGS_SIZE];
|
||||
char id[BOOT_ID_SIZE]; /* timestamp / checksum / sha1 / etc */
|
||||
|
||||
// Supplemental command line data; kept here to maintain
|
||||
// binary compatibility with older versions of mkbootimg.
|
||||
char extra_cmdline[BOOT_EXTRA_ARGS_SIZE];
|
||||
// Supplemental command line data; kept here to maintain
|
||||
// binary compatibility with older versions of mkbootimg.
|
||||
char extra_cmdline[BOOT_EXTRA_ARGS_SIZE];
|
||||
} __attribute__((packed));
|
||||
|
||||
struct boot_img_hdr_v1 : public boot_img_hdr_v0 {
|
||||
uint32_t recovery_dtbo_size; /* size in bytes for recovery DTBO/ACPIO image */
|
||||
uint64_t recovery_dtbo_offset; /* offset to recovery dtbo/acpio in boot image */
|
||||
uint32_t header_size;
|
||||
uint32_t recovery_dtbo_size; /* size in bytes for recovery DTBO/ACPIO image */
|
||||
uint64_t recovery_dtbo_offset; /* offset to recovery dtbo/acpio in boot image */
|
||||
uint32_t header_size;
|
||||
} __attribute__((packed));
|
||||
|
||||
struct boot_img_hdr_v2 : public boot_img_hdr_v1 {
|
||||
uint32_t dtb_size; /* size in bytes for DTB image */
|
||||
uint64_t dtb_addr; /* physical load address for DTB image */
|
||||
uint32_t dtb_size; /* size in bytes for DTB image */
|
||||
uint64_t dtb_addr; /* physical load address for DTB image */
|
||||
} __attribute__((packed));
|
||||
|
||||
// Default to hdr v2
|
||||
@@ -133,16 +133,16 @@ using boot_img_hdr = boot_img_hdr_v2;
|
||||
|
||||
// Special Samsung header
|
||||
struct boot_img_hdr_pxa : public boot_img_hdr_common {
|
||||
uint32_t extra_size; /* extra blob size in bytes */
|
||||
uint32_t unknown;
|
||||
uint32_t tags_addr; /* physical addr for kernel tags */
|
||||
uint32_t page_size; /* flash page size we assume */
|
||||
uint32_t extra_size; /* extra blob size in bytes */
|
||||
uint32_t unknown;
|
||||
uint32_t tags_addr; /* physical addr for kernel tags */
|
||||
uint32_t page_size; /* flash page size we assume */
|
||||
|
||||
char name[24]; /* asciiz product name */
|
||||
char cmdline[BOOT_ARGS_SIZE];
|
||||
char id[BOOT_ID_SIZE]; /* timestamp / checksum / sha1 / etc */
|
||||
char name[24]; /* asciiz product name */
|
||||
char cmdline[BOOT_ARGS_SIZE];
|
||||
char id[BOOT_ID_SIZE]; /* timestamp / checksum / sha1 / etc */
|
||||
|
||||
char extra_cmdline[BOOT_EXTRA_ARGS_SIZE];
|
||||
char extra_cmdline[BOOT_EXTRA_ARGS_SIZE];
|
||||
} __attribute__((packed));
|
||||
|
||||
/* When the boot image header has a version of 3, the structure of the boot
|
||||
@@ -178,34 +178,34 @@ struct boot_img_hdr_pxa : public boot_img_hdr_common {
|
||||
*/
|
||||
|
||||
struct boot_img_hdr_v3 {
|
||||
uint8_t magic[BOOT_MAGIC_SIZE];
|
||||
uint8_t magic[BOOT_MAGIC_SIZE];
|
||||
|
||||
uint32_t kernel_size; /* size in bytes */
|
||||
uint32_t ramdisk_size; /* size in bytes */
|
||||
uint32_t os_version;
|
||||
uint32_t header_size;
|
||||
uint32_t reserved[4];
|
||||
uint32_t kernel_size; /* size in bytes */
|
||||
uint32_t ramdisk_size; /* size in bytes */
|
||||
uint32_t os_version;
|
||||
uint32_t header_size;
|
||||
uint32_t reserved[4];
|
||||
|
||||
uint32_t header_version;
|
||||
uint32_t header_version;
|
||||
|
||||
char cmdline[BOOT_ARGS_SIZE + BOOT_EXTRA_ARGS_SIZE];
|
||||
char cmdline[BOOT_ARGS_SIZE + BOOT_EXTRA_ARGS_SIZE];
|
||||
} __attribute__((packed));
|
||||
|
||||
struct boot_img_hdr_vnd_v3 {
|
||||
// Must be VENDOR_BOOT_MAGIC.
|
||||
uint8_t magic[BOOT_MAGIC_SIZE];
|
||||
// Version of the vendor boot image header.
|
||||
uint32_t header_version;
|
||||
uint32_t page_size; /* flash page size we assume */
|
||||
uint32_t kernel_addr; /* physical load addr */
|
||||
uint32_t ramdisk_addr; /* physical load addr */
|
||||
uint32_t ramdisk_size; /* size in bytes */
|
||||
char cmdline[VENDOR_BOOT_ARGS_SIZE];
|
||||
uint32_t tags_addr; /* physical addr for kernel tags (if required) */
|
||||
char name[BOOT_NAME_SIZE]; /* asciiz product name */
|
||||
uint32_t header_size;
|
||||
uint32_t dtb_size; /* size in bytes for DTB image */
|
||||
uint64_t dtb_addr; /* physical load address for DTB image */
|
||||
// Must be VENDOR_BOOT_MAGIC.
|
||||
uint8_t magic[BOOT_MAGIC_SIZE];
|
||||
// Version of the vendor boot image header.
|
||||
uint32_t header_version;
|
||||
uint32_t page_size; /* flash page size we assume */
|
||||
uint32_t kernel_addr; /* physical load addr */
|
||||
uint32_t ramdisk_addr; /* physical load addr */
|
||||
uint32_t ramdisk_size; /* size in bytes */
|
||||
char cmdline[VENDOR_BOOT_ARGS_SIZE];
|
||||
uint32_t tags_addr; /* physical addr for kernel tags (if required) */
|
||||
char name[BOOT_NAME_SIZE]; /* asciiz product name */
|
||||
uint32_t header_size;
|
||||
uint32_t dtb_size; /* size in bytes for DTB image */
|
||||
uint64_t dtb_addr; /* physical load address for DTB image */
|
||||
} __attribute__((packed));
|
||||
|
||||
/*******************************
|
||||
@@ -219,51 +219,51 @@ virtual type name() { return 0; }
|
||||
|
||||
struct dyn_img_hdr {
|
||||
|
||||
// Standard entries
|
||||
decl_var(kernel_size, 32)
|
||||
decl_var(ramdisk_size, 32)
|
||||
decl_var(second_size, 32)
|
||||
decl_var(page_size, 32)
|
||||
decl_val(header_version, uint32_t)
|
||||
decl_var(extra_size, 32)
|
||||
decl_var(os_version, 32)
|
||||
decl_val(name, char *)
|
||||
decl_val(cmdline, char *)
|
||||
decl_val(id, char *)
|
||||
decl_val(extra_cmdline, char *)
|
||||
// Standard entries
|
||||
decl_var(kernel_size, 32)
|
||||
decl_var(ramdisk_size, 32)
|
||||
decl_var(second_size, 32)
|
||||
decl_var(page_size, 32)
|
||||
decl_val(header_version, uint32_t)
|
||||
decl_var(extra_size, 32)
|
||||
decl_var(os_version, 32)
|
||||
decl_val(name, char *)
|
||||
decl_val(cmdline, char *)
|
||||
decl_val(id, char *)
|
||||
decl_val(extra_cmdline, char *)
|
||||
|
||||
// v1/v2 specific
|
||||
decl_var(recovery_dtbo_size, 32)
|
||||
decl_var(recovery_dtbo_offset, 64)
|
||||
decl_var(header_size, 32)
|
||||
decl_var(dtb_size, 32)
|
||||
// v1/v2 specific
|
||||
decl_var(recovery_dtbo_size, 32)
|
||||
decl_var(recovery_dtbo_offset, 64)
|
||||
decl_var(header_size, 32)
|
||||
decl_var(dtb_size, 32)
|
||||
|
||||
virtual ~dyn_img_hdr() {
|
||||
free(raw);
|
||||
}
|
||||
virtual ~dyn_img_hdr() {
|
||||
free(raw);
|
||||
}
|
||||
|
||||
virtual size_t hdr_size() = 0;
|
||||
virtual size_t hdr_space() { return page_size(); }
|
||||
virtual size_t hdr_size() = 0;
|
||||
virtual size_t hdr_space() { return page_size(); }
|
||||
|
||||
const void *raw_hdr() const { return raw; }
|
||||
void print();
|
||||
void dump_hdr_file();
|
||||
void load_hdr_file();
|
||||
const void *raw_hdr() const { return raw; }
|
||||
void print();
|
||||
void dump_hdr_file();
|
||||
void load_hdr_file();
|
||||
|
||||
protected:
|
||||
union {
|
||||
// Main header could be either AOSP or PXA
|
||||
boot_img_hdr_v2 *v2_hdr; /* AOSP v2 header */
|
||||
boot_img_hdr_v3 *v3_hdr; /* AOSP v3 header */
|
||||
boot_img_hdr_pxa *hdr_pxa; /* Samsung PXA header */
|
||||
boot_img_hdr_vnd_v3 *vnd; /* AOSP vendor v3 header */
|
||||
void *raw; /* Raw pointer */
|
||||
};
|
||||
union {
|
||||
// Main header could be either AOSP or PXA
|
||||
boot_img_hdr_v2 *v2_hdr; /* AOSP v2 header */
|
||||
boot_img_hdr_v3 *v3_hdr; /* AOSP v3 header */
|
||||
boot_img_hdr_pxa *hdr_pxa; /* Samsung PXA header */
|
||||
boot_img_hdr_vnd_v3 *vnd; /* AOSP vendor v3 header */
|
||||
void *raw; /* Raw pointer */
|
||||
};
|
||||
|
||||
private:
|
||||
// Junk for references
|
||||
static uint32_t j32;
|
||||
static uint64_t j64;
|
||||
// Junk for references
|
||||
static uint32_t j32;
|
||||
static uint64_t j64;
|
||||
};
|
||||
|
||||
#undef decl_var
|
||||
@@ -273,8 +273,8 @@ private:
|
||||
protected: name() = default; \
|
||||
public: \
|
||||
name(void *ptr) { \
|
||||
raw = xmalloc(sizeof(hdr)); \
|
||||
memcpy(raw, ptr, sizeof(hdr)); \
|
||||
raw = xmalloc(sizeof(hdr)); \
|
||||
memcpy(raw, ptr, sizeof(hdr)); \
|
||||
} \
|
||||
size_t hdr_size() override { return sizeof(hdr); }
|
||||
|
||||
@@ -285,93 +285,93 @@ decltype(std::declval<dyn_img_hdr>().name()) name() override { return hdr_name->
|
||||
#define impl_val(name) __impl_val(name, v2_hdr)
|
||||
|
||||
struct dyn_img_common : public dyn_img_hdr {
|
||||
impl_val(kernel_size)
|
||||
impl_val(ramdisk_size)
|
||||
impl_val(second_size)
|
||||
impl_val(kernel_size)
|
||||
impl_val(ramdisk_size)
|
||||
impl_val(second_size)
|
||||
};
|
||||
|
||||
struct dyn_img_v0 : public dyn_img_common {
|
||||
impl_cls(v0)
|
||||
impl_cls(v0)
|
||||
|
||||
impl_val(page_size)
|
||||
impl_val(extra_size)
|
||||
impl_val(os_version)
|
||||
impl_val(name)
|
||||
impl_val(cmdline)
|
||||
impl_val(id)
|
||||
impl_val(extra_cmdline)
|
||||
impl_val(page_size)
|
||||
impl_val(extra_size)
|
||||
impl_val(os_version)
|
||||
impl_val(name)
|
||||
impl_val(cmdline)
|
||||
impl_val(id)
|
||||
impl_val(extra_cmdline)
|
||||
};
|
||||
|
||||
struct dyn_img_v1 : public dyn_img_v0 {
|
||||
impl_cls(v1)
|
||||
impl_cls(v1)
|
||||
|
||||
impl_val(header_version)
|
||||
impl_val(recovery_dtbo_size)
|
||||
impl_val(recovery_dtbo_offset)
|
||||
impl_val(header_size)
|
||||
impl_val(header_version)
|
||||
impl_val(recovery_dtbo_size)
|
||||
impl_val(recovery_dtbo_offset)
|
||||
impl_val(header_size)
|
||||
|
||||
uint32_t &extra_size() override { return dyn_img_hdr::extra_size(); }
|
||||
uint32_t &extra_size() override { return dyn_img_hdr::extra_size(); }
|
||||
};
|
||||
|
||||
struct dyn_img_v2 : public dyn_img_v1 {
|
||||
impl_cls(v2)
|
||||
impl_cls(v2)
|
||||
|
||||
impl_val(dtb_size)
|
||||
impl_val(dtb_size)
|
||||
};
|
||||
|
||||
#undef impl_val
|
||||
#define impl_val(name) __impl_val(name, hdr_pxa)
|
||||
|
||||
struct dyn_img_pxa : public dyn_img_common {
|
||||
impl_cls(pxa)
|
||||
impl_cls(pxa)
|
||||
|
||||
impl_val(extra_size)
|
||||
impl_val(page_size)
|
||||
impl_val(name)
|
||||
impl_val(cmdline)
|
||||
impl_val(id)
|
||||
impl_val(extra_cmdline)
|
||||
impl_val(extra_size)
|
||||
impl_val(page_size)
|
||||
impl_val(name)
|
||||
impl_val(cmdline)
|
||||
impl_val(id)
|
||||
impl_val(extra_cmdline)
|
||||
};
|
||||
|
||||
#undef impl_val
|
||||
#define impl_val(name) __impl_val(name, v3_hdr)
|
||||
|
||||
struct dyn_img_v3 : public dyn_img_hdr {
|
||||
impl_cls(v3)
|
||||
impl_cls(v3)
|
||||
|
||||
impl_val(kernel_size)
|
||||
impl_val(ramdisk_size)
|
||||
impl_val(os_version)
|
||||
impl_val(header_size)
|
||||
impl_val(header_version)
|
||||
impl_val(cmdline)
|
||||
impl_val(kernel_size)
|
||||
impl_val(ramdisk_size)
|
||||
impl_val(os_version)
|
||||
impl_val(header_size)
|
||||
impl_val(header_version)
|
||||
impl_val(cmdline)
|
||||
|
||||
// Make API compatible
|
||||
uint32_t &page_size() override { page_sz = 4096; return page_sz; }
|
||||
char *extra_cmdline() override { return &v3_hdr->cmdline[BOOT_ARGS_SIZE]; }
|
||||
// Make API compatible
|
||||
uint32_t &page_size() override { page_sz = 4096; return page_sz; }
|
||||
char *extra_cmdline() override { return &v3_hdr->cmdline[BOOT_ARGS_SIZE]; }
|
||||
|
||||
private:
|
||||
uint32_t page_sz;
|
||||
uint32_t page_sz;
|
||||
};
|
||||
|
||||
#undef impl_val
|
||||
#define impl_val(name) __impl_val(name, vnd)
|
||||
|
||||
struct dyn_img_vnd_v3 : public dyn_img_hdr {
|
||||
impl_cls(vnd_v3)
|
||||
impl_cls(vnd_v3)
|
||||
|
||||
impl_val(header_version)
|
||||
impl_val(page_size)
|
||||
impl_val(ramdisk_size)
|
||||
impl_val(cmdline)
|
||||
impl_val(name)
|
||||
impl_val(header_size)
|
||||
impl_val(dtb_size)
|
||||
impl_val(header_version)
|
||||
impl_val(page_size)
|
||||
impl_val(ramdisk_size)
|
||||
impl_val(cmdline)
|
||||
impl_val(name)
|
||||
impl_val(header_size)
|
||||
impl_val(dtb_size)
|
||||
|
||||
size_t hdr_space() override { auto sz = page_size(); return do_align(hdr_size(), sz); }
|
||||
size_t hdr_space() override { auto sz = page_size(); return do_align(hdr_size(), sz); }
|
||||
|
||||
// Make API compatible
|
||||
char *extra_cmdline() override { return &vnd->cmdline[BOOT_ARGS_SIZE]; }
|
||||
// Make API compatible
|
||||
char *extra_cmdline() override { return &vnd->cmdline[BOOT_ARGS_SIZE]; }
|
||||
};
|
||||
|
||||
#undef __impl_cls
|
||||
@@ -395,48 +395,48 @@ struct dyn_img_vnd_v3 : public dyn_img_hdr {
|
||||
#define ACCLAIM_FLAG (1 << 9)
|
||||
|
||||
struct boot_img {
|
||||
// Memory map of the whole image
|
||||
uint8_t *map_addr;
|
||||
size_t map_size;
|
||||
// Memory map of the whole image
|
||||
uint8_t *map_addr;
|
||||
size_t map_size;
|
||||
|
||||
// Android image header
|
||||
dyn_img_hdr *hdr;
|
||||
// Android image header
|
||||
dyn_img_hdr *hdr;
|
||||
|
||||
// Flags to indicate the state of current boot image
|
||||
uint16_t flags = 0;
|
||||
// Flags to indicate the state of current boot image
|
||||
uint16_t flags = 0;
|
||||
|
||||
// The format of kernel, ramdisk and extra
|
||||
format_t k_fmt = UNKNOWN;
|
||||
format_t r_fmt = UNKNOWN;
|
||||
format_t e_fmt = UNKNOWN;
|
||||
// The format of kernel, ramdisk and extra
|
||||
format_t k_fmt = UNKNOWN;
|
||||
format_t r_fmt = UNKNOWN;
|
||||
format_t e_fmt = UNKNOWN;
|
||||
|
||||
/***************************************************
|
||||
* Following pointers points within the mmap region
|
||||
***************************************************/
|
||||
/***************************************************
|
||||
* Following pointers points within the mmap region
|
||||
***************************************************/
|
||||
|
||||
// MTK headers
|
||||
mtk_hdr *k_hdr;
|
||||
mtk_hdr *r_hdr;
|
||||
// MTK headers
|
||||
mtk_hdr *k_hdr;
|
||||
mtk_hdr *r_hdr;
|
||||
|
||||
// Pointer to dtb that is embedded in kernel
|
||||
uint8_t *kernel_dtb;
|
||||
uint32_t kernel_dt_size = 0;
|
||||
// Pointer to dtb that is embedded in kernel
|
||||
uint8_t *kernel_dtb;
|
||||
uint32_t kernel_dt_size = 0;
|
||||
|
||||
// Pointer to end of image
|
||||
uint8_t *tail;
|
||||
size_t tail_size = 0;
|
||||
// Pointer to end of image
|
||||
uint8_t *tail;
|
||||
size_t tail_size = 0;
|
||||
|
||||
// Pointers to blocks defined in header
|
||||
uint8_t *hdr_addr;
|
||||
uint8_t *kernel;
|
||||
uint8_t *ramdisk;
|
||||
uint8_t *second;
|
||||
uint8_t *extra;
|
||||
uint8_t *recovery_dtbo;
|
||||
uint8_t *dtb;
|
||||
// Pointers to blocks defined in header
|
||||
uint8_t *hdr_addr;
|
||||
uint8_t *kernel;
|
||||
uint8_t *ramdisk;
|
||||
uint8_t *second;
|
||||
uint8_t *extra;
|
||||
uint8_t *recovery_dtbo;
|
||||
uint8_t *dtb;
|
||||
|
||||
boot_img(const char *);
|
||||
~boot_img();
|
||||
boot_img(const char *);
|
||||
~boot_img();
|
||||
|
||||
void parse_image(uint8_t *addr, format_t type);
|
||||
void parse_image(uint8_t *addr, format_t type);
|
||||
};
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -18,437 +18,437 @@ constexpr int MAX_DEPTH = 32;
|
||||
static bitset<MAX_DEPTH> depth_set;
|
||||
|
||||
static void pretty_node(int depth) {
|
||||
if (depth == 0)
|
||||
return;
|
||||
if (depth == 0)
|
||||
return;
|
||||
|
||||
for (int i = 0; i < depth - 1; ++i)
|
||||
printf(depth_set[i] ? "│ " : " ");
|
||||
for (int i = 0; i < depth - 1; ++i)
|
||||
printf(depth_set[i] ? "│ " : " ");
|
||||
|
||||
printf(depth_set[depth - 1] ? "├── " : "└── ");
|
||||
printf(depth_set[depth - 1] ? "├── " : "└── ");
|
||||
}
|
||||
|
||||
static void pretty_prop(int depth) {
|
||||
for (int i = 0; i < depth; ++i)
|
||||
printf(depth_set[i] ? "│ " : " ");
|
||||
for (int i = 0; i < depth; ++i)
|
||||
printf(depth_set[i] ? "│ " : " ");
|
||||
|
||||
printf(depth_set[depth] ? "│ " : " ");
|
||||
printf(depth_set[depth] ? "│ " : " ");
|
||||
}
|
||||
|
||||
static void print_node(const void *fdt, int node = 0, int depth = 0) {
|
||||
// Print node itself
|
||||
pretty_node(depth);
|
||||
printf("#%d: %s\n", node, fdt_get_name(fdt, node, nullptr));
|
||||
// Print node itself
|
||||
pretty_node(depth);
|
||||
printf("#%d: %s\n", node, fdt_get_name(fdt, node, nullptr));
|
||||
|
||||
// Print properties
|
||||
depth_set[depth] = fdt_first_subnode(fdt, node) >= 0;
|
||||
int prop;
|
||||
fdt_for_each_property_offset(prop, fdt, node) {
|
||||
pretty_prop(depth);
|
||||
int size;
|
||||
const char *name;
|
||||
auto value = static_cast<const char *>(fdt_getprop_by_offset(fdt, prop, &name, &size));
|
||||
// Print properties
|
||||
depth_set[depth] = fdt_first_subnode(fdt, node) >= 0;
|
||||
int prop;
|
||||
fdt_for_each_property_offset(prop, fdt, node) {
|
||||
pretty_prop(depth);
|
||||
int size;
|
||||
const char *name;
|
||||
auto value = static_cast<const char *>(fdt_getprop_by_offset(fdt, prop, &name, &size));
|
||||
|
||||
bool is_str = !(size > 1 && value[0] == 0);
|
||||
if (is_str) {
|
||||
// Scan through value to see if printable
|
||||
for (int i = 0; i < size; ++i) {
|
||||
char c = value[i];
|
||||
if (i == size - 1) {
|
||||
// Make sure null terminate
|
||||
is_str = c == '\0';
|
||||
} else if ((c > 0 && c < 32) || c >= 127) {
|
||||
is_str = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
bool is_str = !(size > 1 && value[0] == 0);
|
||||
if (is_str) {
|
||||
// Scan through value to see if printable
|
||||
for (int i = 0; i < size; ++i) {
|
||||
char c = value[i];
|
||||
if (i == size - 1) {
|
||||
// Make sure null terminate
|
||||
is_str = c == '\0';
|
||||
} else if ((c > 0 && c < 32) || c >= 127) {
|
||||
is_str = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (is_str) {
|
||||
printf("[%s]: [%s]\n", name, value);
|
||||
} else {
|
||||
printf("[%s]: <bytes>(%d)\n", name, size);
|
||||
}
|
||||
}
|
||||
if (is_str) {
|
||||
printf("[%s]: [%s]\n", name, value);
|
||||
} else {
|
||||
printf("[%s]: <bytes>(%d)\n", name, size);
|
||||
}
|
||||
}
|
||||
|
||||
// Recursive
|
||||
if (depth_set[depth]) {
|
||||
int child;
|
||||
int prev = -1;
|
||||
fdt_for_each_subnode(child, fdt, node) {
|
||||
if (prev >= 0)
|
||||
print_node(fdt, prev, depth + 1);
|
||||
prev = child;
|
||||
}
|
||||
depth_set[depth] = false;
|
||||
print_node(fdt, prev, depth + 1);
|
||||
}
|
||||
// Recursive
|
||||
if (depth_set[depth]) {
|
||||
int child;
|
||||
int prev = -1;
|
||||
fdt_for_each_subnode(child, fdt, node) {
|
||||
if (prev >= 0)
|
||||
print_node(fdt, prev, depth + 1);
|
||||
prev = child;
|
||||
}
|
||||
depth_set[depth] = false;
|
||||
print_node(fdt, prev, depth + 1);
|
||||
}
|
||||
}
|
||||
|
||||
static int find_fstab(const void *fdt, int node = 0) {
|
||||
if (fdt_get_name(fdt, node, nullptr) == "fstab"sv)
|
||||
return node;
|
||||
int child;
|
||||
fdt_for_each_subnode(child, fdt, node) {
|
||||
int fstab = find_fstab(fdt, child);
|
||||
if (fstab >= 0)
|
||||
return fstab;
|
||||
}
|
||||
return -1;
|
||||
if (fdt_get_name(fdt, node, nullptr) == "fstab"sv)
|
||||
return node;
|
||||
int child;
|
||||
fdt_for_each_subnode(child, fdt, node) {
|
||||
int fstab = find_fstab(fdt, child);
|
||||
if (fstab >= 0)
|
||||
return fstab;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void dtb_print(const char *file, bool fstab) {
|
||||
size_t size;
|
||||
uint8_t *dtb;
|
||||
fprintf(stderr, "Loading dtbs from [%s]\n", file);
|
||||
mmap_ro(file, dtb, size);
|
||||
// Loop through all the dtbs
|
||||
int dtb_num = 0;
|
||||
for (int i = 0; i < size; ++i) {
|
||||
if (memcmp(dtb + i, FDT_MAGIC_STR, 4) == 0) {
|
||||
auto fdt = dtb + i;
|
||||
if (fstab) {
|
||||
int node = find_fstab(fdt);
|
||||
if (node >= 0) {
|
||||
fprintf(stderr, "Found fstab in dtb.%04d\n", dtb_num);
|
||||
print_node(fdt, node);
|
||||
}
|
||||
} else {
|
||||
fprintf(stderr, "Printing dtb.%04d\n", dtb_num);
|
||||
print_node(fdt);
|
||||
}
|
||||
++dtb_num;
|
||||
i += fdt_totalsize(fdt) - 1;
|
||||
}
|
||||
}
|
||||
fprintf(stderr, "\n");
|
||||
munmap(dtb, size);
|
||||
size_t size;
|
||||
uint8_t *dtb;
|
||||
fprintf(stderr, "Loading dtbs from [%s]\n", file);
|
||||
mmap_ro(file, dtb, size);
|
||||
// Loop through all the dtbs
|
||||
int dtb_num = 0;
|
||||
for (int i = 0; i < size; ++i) {
|
||||
if (memcmp(dtb + i, FDT_MAGIC_STR, 4) == 0) {
|
||||
auto fdt = dtb + i;
|
||||
if (fstab) {
|
||||
int node = find_fstab(fdt);
|
||||
if (node >= 0) {
|
||||
fprintf(stderr, "Found fstab in dtb.%04d\n", dtb_num);
|
||||
print_node(fdt, node);
|
||||
}
|
||||
} else {
|
||||
fprintf(stderr, "Printing dtb.%04d\n", dtb_num);
|
||||
print_node(fdt);
|
||||
}
|
||||
++dtb_num;
|
||||
i += fdt_totalsize(fdt) - 1;
|
||||
}
|
||||
}
|
||||
fprintf(stderr, "\n");
|
||||
munmap(dtb, size);
|
||||
}
|
||||
|
||||
static bool dtb_patch(const char *file) {
|
||||
bool keepverity = check_env("KEEPVERITY");
|
||||
bool patched = false;
|
||||
size_t size;
|
||||
uint8_t *dtb;
|
||||
fprintf(stderr, "Loading dtbs from [%s]\n", file);
|
||||
mmap_rw(file, dtb, size);
|
||||
// Loop through all the dtbs
|
||||
int dtb_num = 0;
|
||||
for (int i = 0; i < size; ++i) {
|
||||
if (memcmp(dtb + i, FDT_MAGIC_STR, 4) == 0) {
|
||||
auto fdt = dtb + i;
|
||||
fprintf(stderr, "Loading dtb.%04d\n", dtb_num);
|
||||
if (int fstab = find_fstab(fdt); fstab >= 0) {
|
||||
int node;
|
||||
fdt_for_each_subnode(node, fdt, fstab) {
|
||||
const char *name = fdt_get_name(fdt, node, nullptr);
|
||||
fprintf(stderr, "Found fstab entry [%s]\n", name);
|
||||
if (!keepverity) {
|
||||
int len;
|
||||
auto value = fdt_getprop(fdt, node, "fsmgr_flags", &len);
|
||||
patched |= patch_verity(const_cast<void *>(value), len) != len;
|
||||
}
|
||||
}
|
||||
}
|
||||
++dtb_num;
|
||||
i += fdt_totalsize(fdt) - 1;
|
||||
}
|
||||
}
|
||||
fprintf(stderr, "\n");
|
||||
munmap(dtb, size);
|
||||
return patched;
|
||||
bool keepverity = check_env("KEEPVERITY");
|
||||
bool patched = false;
|
||||
size_t size;
|
||||
uint8_t *dtb;
|
||||
fprintf(stderr, "Loading dtbs from [%s]\n", file);
|
||||
mmap_rw(file, dtb, size);
|
||||
// Loop through all the dtbs
|
||||
int dtb_num = 0;
|
||||
for (int i = 0; i < size; ++i) {
|
||||
if (memcmp(dtb + i, FDT_MAGIC_STR, 4) == 0) {
|
||||
auto fdt = dtb + i;
|
||||
fprintf(stderr, "Loading dtb.%04d\n", dtb_num);
|
||||
if (int fstab = find_fstab(fdt); fstab >= 0) {
|
||||
int node;
|
||||
fdt_for_each_subnode(node, fdt, fstab) {
|
||||
const char *name = fdt_get_name(fdt, node, nullptr);
|
||||
fprintf(stderr, "Found fstab entry [%s]\n", name);
|
||||
if (!keepverity) {
|
||||
int len;
|
||||
auto value = fdt_getprop(fdt, node, "fsmgr_flags", &len);
|
||||
patched |= patch_verity(const_cast<void *>(value), len) != len;
|
||||
}
|
||||
}
|
||||
}
|
||||
++dtb_num;
|
||||
i += fdt_totalsize(fdt) - 1;
|
||||
}
|
||||
}
|
||||
fprintf(stderr, "\n");
|
||||
munmap(dtb, size);
|
||||
return patched;
|
||||
}
|
||||
|
||||
int dtb_commands(int argc, char *argv[]) {
|
||||
char *dtb = argv[0];
|
||||
++argv;
|
||||
--argc;
|
||||
char *dtb = argv[0];
|
||||
++argv;
|
||||
--argc;
|
||||
|
||||
if (argv[0] == "print"sv) {
|
||||
dtb_print(dtb, argc > 1 && argv[1] == "-f"sv);
|
||||
return 0;
|
||||
} else if (argv[0] == "patch"sv) {
|
||||
if (!dtb_patch(dtb))
|
||||
exit(1);
|
||||
return 0;
|
||||
} else {
|
||||
return 1;
|
||||
}
|
||||
if (argv[0] == "print"sv) {
|
||||
dtb_print(dtb, argc > 1 && argv[1] == "-f"sv);
|
||||
return 0;
|
||||
} else if (argv[0] == "patch"sv) {
|
||||
if (!dtb_patch(dtb))
|
||||
exit(1);
|
||||
return 0;
|
||||
} else {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
namespace {
|
||||
// Unused, but keep these precious code as they took TONs of effort to write
|
||||
// Unused, but keep these precious code as they took TONs of effort to write
|
||||
|
||||
struct fdt_blob {
|
||||
void *fdt;
|
||||
uint32_t offset;
|
||||
uint32_t len;
|
||||
};
|
||||
struct fdt_blob {
|
||||
void *fdt;
|
||||
uint32_t offset;
|
||||
uint32_t len;
|
||||
};
|
||||
|
||||
template <class Iter>
|
||||
class fdt_map_iter {
|
||||
public:
|
||||
typedef decltype(std::declval<typename Iter::value_type::second_type>().fdt) value_type;
|
||||
typedef value_type* pointer;
|
||||
typedef value_type& reference;
|
||||
template <class Iter>
|
||||
class fdt_map_iter {
|
||||
public:
|
||||
typedef decltype(std::declval<typename Iter::value_type::second_type>().fdt) value_type;
|
||||
typedef value_type* pointer;
|
||||
typedef value_type& reference;
|
||||
|
||||
explicit fdt_map_iter(Iter j) : i(j) {}
|
||||
fdt_map_iter& operator++() { ++i; return *this; }
|
||||
fdt_map_iter operator++(int) { auto tmp = *this; ++(*this); return tmp; }
|
||||
fdt_map_iter& operator--() { --i; return *this; }
|
||||
fdt_map_iter operator--(int) { auto tmp = *this; --(*this); return tmp; }
|
||||
bool operator==(fdt_map_iter j) const { return i == j.i; }
|
||||
bool operator!=(fdt_map_iter j) const { return !(*this == j); }
|
||||
reference operator*() { return i->second.fdt; }
|
||||
pointer operator->() { return &i->second.fdt; }
|
||||
private:
|
||||
Iter i;
|
||||
};
|
||||
explicit fdt_map_iter(Iter j) : i(j) {}
|
||||
fdt_map_iter& operator++() { ++i; return *this; }
|
||||
fdt_map_iter operator++(int) { auto tmp = *this; ++(*this); return tmp; }
|
||||
fdt_map_iter& operator--() { --i; return *this; }
|
||||
fdt_map_iter operator--(int) { auto tmp = *this; --(*this); return tmp; }
|
||||
bool operator==(fdt_map_iter j) const { return i == j.i; }
|
||||
bool operator!=(fdt_map_iter j) const { return !(*this == j); }
|
||||
reference operator*() { return i->second.fdt; }
|
||||
pointer operator->() { return &i->second.fdt; }
|
||||
private:
|
||||
Iter i;
|
||||
};
|
||||
|
||||
template<class Iter>
|
||||
inline fdt_map_iter<Iter> make_iter(Iter j) { return fdt_map_iter<Iter>(j); }
|
||||
template<class Iter>
|
||||
inline fdt_map_iter<Iter> make_iter(Iter j) { return fdt_map_iter<Iter>(j); }
|
||||
|
||||
template <typename Iter>
|
||||
static bool fdt_patch(Iter first, Iter last) {
|
||||
bool keepverity = check_env("KEEPVERITY");
|
||||
bool redirect = check_env("TWOSTAGEINIT");
|
||||
bool modified = false;
|
||||
template <typename Iter>
|
||||
static bool fdt_patch(Iter first, Iter last) {
|
||||
bool keepverity = check_env("KEEPVERITY");
|
||||
bool redirect = check_env("TWOSTAGEINIT");
|
||||
bool modified = false;
|
||||
|
||||
int idx = 0;
|
||||
for (auto it = first; it != last; ++it) {
|
||||
++idx;
|
||||
auto fdt = *it;
|
||||
int fstab = find_fstab(fdt);
|
||||
if (fstab < 0)
|
||||
continue;
|
||||
fprintf(stderr, "Found fstab in dtb.%04d\n", idx - 1);
|
||||
int block;
|
||||
fdt_for_each_subnode(block, fdt, fstab) {
|
||||
const char *name = fdt_get_name(fdt, block, nullptr);
|
||||
fprintf(stderr, "Found entry [%s] in fstab\n", name);
|
||||
if (!keepverity) {
|
||||
int size;
|
||||
auto value = fdt_getprop(fdt, block, "fsmgr_flags", &size);
|
||||
char *copy = static_cast<char *>(memcpy(malloc(size), value, size));
|
||||
if (patch_verity(copy, size) != size) {
|
||||
modified = true;
|
||||
fdt_setprop_string(fdt, block, "fsmgr_flags", copy);
|
||||
}
|
||||
free(copy);
|
||||
}
|
||||
if (redirect && name == "system"sv) {
|
||||
modified = true;
|
||||
fprintf(stderr, "Changing mnt_point to /system_root\n");
|
||||
fdt_setprop_string(fdt, block, "mnt_point", "/system_root");
|
||||
}
|
||||
}
|
||||
}
|
||||
return modified;
|
||||
}
|
||||
int idx = 0;
|
||||
for (auto it = first; it != last; ++it) {
|
||||
++idx;
|
||||
auto fdt = *it;
|
||||
int fstab = find_fstab(fdt);
|
||||
if (fstab < 0)
|
||||
continue;
|
||||
fprintf(stderr, "Found fstab in dtb.%04d\n", idx - 1);
|
||||
int block;
|
||||
fdt_for_each_subnode(block, fdt, fstab) {
|
||||
const char *name = fdt_get_name(fdt, block, nullptr);
|
||||
fprintf(stderr, "Found entry [%s] in fstab\n", name);
|
||||
if (!keepverity) {
|
||||
int size;
|
||||
auto value = fdt_getprop(fdt, block, "fsmgr_flags", &size);
|
||||
char *copy = static_cast<char *>(memcpy(malloc(size), value, size));
|
||||
if (patch_verity(copy, size) != size) {
|
||||
modified = true;
|
||||
fdt_setprop_string(fdt, block, "fsmgr_flags", copy);
|
||||
}
|
||||
free(copy);
|
||||
}
|
||||
if (redirect && name == "system"sv) {
|
||||
modified = true;
|
||||
fprintf(stderr, "Changing mnt_point to /system_root\n");
|
||||
fdt_setprop_string(fdt, block, "mnt_point", "/system_root");
|
||||
}
|
||||
}
|
||||
}
|
||||
return modified;
|
||||
}
|
||||
|
||||
#define MAX_FDT_GROWTH 256
|
||||
|
||||
template <class Table, class Header>
|
||||
static int dt_table_patch(const Header *hdr, const char *out) {
|
||||
map<uint32_t, fdt_blob> dtb_map;
|
||||
auto buf = reinterpret_cast<const uint8_t *>(hdr);
|
||||
auto tables = reinterpret_cast<const Table *>(hdr + 1);
|
||||
template <class Table, class Header>
|
||||
static int dt_table_patch(const Header *hdr, const char *out) {
|
||||
map<uint32_t, fdt_blob> dtb_map;
|
||||
auto buf = reinterpret_cast<const uint8_t *>(hdr);
|
||||
auto tables = reinterpret_cast<const Table *>(hdr + 1);
|
||||
|
||||
constexpr bool is_dt_table = std::is_same_v<Header, dt_table_header>;
|
||||
constexpr bool is_dt_table = std::is_same_v<Header, dt_table_header>;
|
||||
|
||||
using endian_conv = uint32_t (*)(uint32_t);
|
||||
endian_conv be_to_le;
|
||||
endian_conv le_to_be;
|
||||
if constexpr (is_dt_table) {
|
||||
be_to_le = fdt32_to_cpu;
|
||||
le_to_be = cpu_to_fdt32;
|
||||
} else {
|
||||
be_to_le = le_to_be = [](uint32_t x) -> auto { return x; };
|
||||
}
|
||||
using endian_conv = uint32_t (*)(uint32_t);
|
||||
endian_conv be_to_le;
|
||||
endian_conv le_to_be;
|
||||
if constexpr (is_dt_table) {
|
||||
be_to_le = fdt32_to_cpu;
|
||||
le_to_be = cpu_to_fdt32;
|
||||
} else {
|
||||
be_to_le = le_to_be = [](uint32_t x) -> auto { return x; };
|
||||
}
|
||||
|
||||
// Collect all dtbs
|
||||
auto num_dtb = be_to_le(hdr->num_dtbs);
|
||||
for (int i = 0; i < num_dtb; ++i) {
|
||||
auto offset = be_to_le(tables[i].offset);
|
||||
if (dtb_map.count(offset) == 0) {
|
||||
auto blob = buf + offset;
|
||||
uint32_t size = fdt_totalsize(blob);
|
||||
auto fdt = xmalloc(size + MAX_FDT_GROWTH);
|
||||
memcpy(fdt, blob, size);
|
||||
fdt_open_into(fdt, fdt, size + MAX_FDT_GROWTH);
|
||||
dtb_map[offset] = { fdt, offset };
|
||||
}
|
||||
}
|
||||
if (dtb_map.empty())
|
||||
return 1;
|
||||
// Collect all dtbs
|
||||
auto num_dtb = be_to_le(hdr->num_dtbs);
|
||||
for (int i = 0; i < num_dtb; ++i) {
|
||||
auto offset = be_to_le(tables[i].offset);
|
||||
if (dtb_map.count(offset) == 0) {
|
||||
auto blob = buf + offset;
|
||||
uint32_t size = fdt_totalsize(blob);
|
||||
auto fdt = xmalloc(size + MAX_FDT_GROWTH);
|
||||
memcpy(fdt, blob, size);
|
||||
fdt_open_into(fdt, fdt, size + MAX_FDT_GROWTH);
|
||||
dtb_map[offset] = { fdt, offset };
|
||||
}
|
||||
}
|
||||
if (dtb_map.empty())
|
||||
return 1;
|
||||
|
||||
// Patch fdt
|
||||
if (!fdt_patch(make_iter(dtb_map.begin()), make_iter(dtb_map.end())))
|
||||
return 1;
|
||||
// Patch fdt
|
||||
if (!fdt_patch(make_iter(dtb_map.begin()), make_iter(dtb_map.end())))
|
||||
return 1;
|
||||
|
||||
unlink(out);
|
||||
int fd = xopen(out, O_RDWR | O_CREAT | O_CLOEXEC, 0644);
|
||||
unlink(out);
|
||||
int fd = xopen(out, O_RDWR | O_CREAT | O_CLOEXEC, 0644);
|
||||
|
||||
uint32_t total_size = 0;
|
||||
uint32_t total_size = 0;
|
||||
|
||||
// Copy headers and tables
|
||||
total_size += xwrite(fd, buf, dtb_map.begin()->first);
|
||||
// Copy headers and tables
|
||||
total_size += xwrite(fd, buf, dtb_map.begin()->first);
|
||||
|
||||
// mmap rw to patch table values retroactively
|
||||
auto mmap_sz = lseek(fd, 0, SEEK_CUR);
|
||||
auto addr = (uint8_t *) xmmap(nullptr, mmap_sz, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
|
||||
// mmap rw to patch table values retroactively
|
||||
auto mmap_sz = lseek(fd, 0, SEEK_CUR);
|
||||
auto addr = (uint8_t *) xmmap(nullptr, mmap_sz, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
|
||||
|
||||
// Guess alignment using gcd
|
||||
uint32_t align = 1;
|
||||
if constexpr (!is_dt_table) {
|
||||
auto it = dtb_map.begin();
|
||||
align = (it++)->first;
|
||||
for (; it != dtb_map.end(); ++it)
|
||||
align = binary_gcd(align, it->first);
|
||||
}
|
||||
// Guess alignment using gcd
|
||||
uint32_t align = 1;
|
||||
if constexpr (!is_dt_table) {
|
||||
auto it = dtb_map.begin();
|
||||
align = (it++)->first;
|
||||
for (; it != dtb_map.end(); ++it)
|
||||
align = binary_gcd(align, it->first);
|
||||
}
|
||||
|
||||
// Write dtbs
|
||||
for (auto &val : dtb_map) {
|
||||
val.second.offset = lseek(fd, 0, SEEK_CUR);
|
||||
auto fdt = val.second.fdt;
|
||||
fdt_pack(fdt);
|
||||
auto size = fdt_totalsize(fdt);
|
||||
total_size += xwrite(fd, fdt, size);
|
||||
val.second.len = do_align(size, align);
|
||||
write_zero(fd, align_off(lseek(fd, 0, SEEK_CUR), align));
|
||||
// total_size += align_off(lseek(fd, 0, SEEK_CUR), align); /* Not needed */
|
||||
free(fdt);
|
||||
}
|
||||
// Write dtbs
|
||||
for (auto &val : dtb_map) {
|
||||
val.second.offset = lseek(fd, 0, SEEK_CUR);
|
||||
auto fdt = val.second.fdt;
|
||||
fdt_pack(fdt);
|
||||
auto size = fdt_totalsize(fdt);
|
||||
total_size += xwrite(fd, fdt, size);
|
||||
val.second.len = do_align(size, align);
|
||||
write_zero(fd, align_off(lseek(fd, 0, SEEK_CUR), align));
|
||||
// total_size += align_off(lseek(fd, 0, SEEK_CUR), align); /* Not needed */
|
||||
free(fdt);
|
||||
}
|
||||
|
||||
// Patch headers
|
||||
if constexpr (is_dt_table) {
|
||||
auto hdr_rw = reinterpret_cast<Header *>(addr);
|
||||
hdr_rw->total_size = le_to_be(total_size);
|
||||
}
|
||||
auto tables_rw = reinterpret_cast<Table *>(addr + sizeof(Header));
|
||||
for (int i = 0; i < num_dtb; ++i) {
|
||||
auto &blob = dtb_map[be_to_le(tables_rw[i].offset)];
|
||||
tables_rw[i].offset = le_to_be(blob.offset);
|
||||
tables_rw[i].len = le_to_be(blob.len);
|
||||
}
|
||||
// Patch headers
|
||||
if constexpr (is_dt_table) {
|
||||
auto hdr_rw = reinterpret_cast<Header *>(addr);
|
||||
hdr_rw->total_size = le_to_be(total_size);
|
||||
}
|
||||
auto tables_rw = reinterpret_cast<Table *>(addr + sizeof(Header));
|
||||
for (int i = 0; i < num_dtb; ++i) {
|
||||
auto &blob = dtb_map[be_to_le(tables_rw[i].offset)];
|
||||
tables_rw[i].offset = le_to_be(blob.offset);
|
||||
tables_rw[i].len = le_to_be(blob.len);
|
||||
}
|
||||
|
||||
munmap(addr, mmap_sz);
|
||||
close(fd);
|
||||
munmap(addr, mmap_sz);
|
||||
close(fd);
|
||||
|
||||
return 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int blob_patch(uint8_t *dtb, size_t dtb_sz, const char *out) {
|
||||
vector<uint8_t *> fdt_list;
|
||||
vector<uint32_t> padding_list;
|
||||
for (int i = 0; i < dtb_sz; ++i) {
|
||||
if (memcmp(dtb + i, FDT_MAGIC_STR, 4) == 0) {
|
||||
auto len = fdt_totalsize(dtb + i);
|
||||
auto fdt = static_cast<uint8_t *>(xmalloc(len + MAX_FDT_GROWTH));
|
||||
memcpy(fdt, dtb + i, len);
|
||||
fdt_pack(fdt);
|
||||
uint32_t padding = len - fdt_totalsize(fdt);
|
||||
padding_list.push_back(padding);
|
||||
fdt_open_into(fdt, fdt, len + MAX_FDT_GROWTH);
|
||||
fdt_list.push_back(fdt);
|
||||
i += len - 1;
|
||||
}
|
||||
}
|
||||
static int blob_patch(uint8_t *dtb, size_t dtb_sz, const char *out) {
|
||||
vector<uint8_t *> fdt_list;
|
||||
vector<uint32_t> padding_list;
|
||||
for (int i = 0; i < dtb_sz; ++i) {
|
||||
if (memcmp(dtb + i, FDT_MAGIC_STR, 4) == 0) {
|
||||
auto len = fdt_totalsize(dtb + i);
|
||||
auto fdt = static_cast<uint8_t *>(xmalloc(len + MAX_FDT_GROWTH));
|
||||
memcpy(fdt, dtb + i, len);
|
||||
fdt_pack(fdt);
|
||||
uint32_t padding = len - fdt_totalsize(fdt);
|
||||
padding_list.push_back(padding);
|
||||
fdt_open_into(fdt, fdt, len + MAX_FDT_GROWTH);
|
||||
fdt_list.push_back(fdt);
|
||||
i += len - 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (!fdt_patch(fdt_list.begin(), fdt_list.end()))
|
||||
return 1;
|
||||
if (!fdt_patch(fdt_list.begin(), fdt_list.end()))
|
||||
return 1;
|
||||
|
||||
unlink(out);
|
||||
int fd = xopen(out, O_WRONLY | O_CREAT | O_CLOEXEC, 0644);
|
||||
unlink(out);
|
||||
int fd = xopen(out, O_WRONLY | O_CREAT | O_CLOEXEC, 0644);
|
||||
|
||||
for (int i = 0; i < fdt_list.size(); ++i) {
|
||||
auto fdt = fdt_list[i];
|
||||
fdt_pack(fdt);
|
||||
// Only add padding back if it is anything meaningful
|
||||
if (padding_list[i] > 4) {
|
||||
auto len = fdt_totalsize(fdt);
|
||||
fdt_set_totalsize(fdt, len + padding_list[i]);
|
||||
}
|
||||
xwrite(fd, fdt, fdt_totalsize(fdt));
|
||||
free(fdt);
|
||||
}
|
||||
close(fd);
|
||||
for (int i = 0; i < fdt_list.size(); ++i) {
|
||||
auto fdt = fdt_list[i];
|
||||
fdt_pack(fdt);
|
||||
// Only add padding back if it is anything meaningful
|
||||
if (padding_list[i] > 4) {
|
||||
auto len = fdt_totalsize(fdt);
|
||||
fdt_set_totalsize(fdt, len + padding_list[i]);
|
||||
}
|
||||
xwrite(fd, fdt, fdt_totalsize(fdt));
|
||||
free(fdt);
|
||||
}
|
||||
close(fd);
|
||||
|
||||
return 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define MATCH(s) (memcmp(dtb, s, sizeof(s) - 1) == 0)
|
||||
|
||||
[[maybe_unused]] static int dtb_patch(const char *in, const char *out) {
|
||||
if (!out)
|
||||
out = in;
|
||||
size_t dtb_sz ;
|
||||
uint8_t *dtb;
|
||||
fprintf(stderr, "Loading dtbs from [%s]\n", in);
|
||||
mmap_ro(in, dtb, dtb_sz);
|
||||
run_finally f([&]{ munmap(dtb, dtb_sz); });
|
||||
[[maybe_unused]] static int dtb_patch(const char *in, const char *out) {
|
||||
if (!out)
|
||||
out = in;
|
||||
size_t dtb_sz ;
|
||||
uint8_t *dtb;
|
||||
fprintf(stderr, "Loading dtbs from [%s]\n", in);
|
||||
mmap_ro(in, dtb, dtb_sz);
|
||||
run_finally f([&]{ munmap(dtb, dtb_sz); });
|
||||
|
||||
if (MATCH(QCDT_MAGIC)) {
|
||||
auto hdr = reinterpret_cast<qcdt_hdr*>(dtb);
|
||||
switch (hdr->version) {
|
||||
case 1:
|
||||
fprintf(stderr, "QCDT v1\n");
|
||||
return dt_table_patch<qctable_v1>(hdr, out);
|
||||
case 2:
|
||||
fprintf(stderr, "QCDT v2\n");
|
||||
return dt_table_patch<qctable_v2>(hdr, out);
|
||||
case 3:
|
||||
fprintf(stderr, "QCDT v3\n");
|
||||
return dt_table_patch<qctable_v3>(hdr, out);
|
||||
default:
|
||||
return 1;
|
||||
}
|
||||
} else if (MATCH(DTBH_MAGIC)) {
|
||||
auto hdr = reinterpret_cast<dtbh_hdr *>(dtb);
|
||||
switch (hdr->version) {
|
||||
case 2:
|
||||
fprintf(stderr, "DTBH v2\n");
|
||||
return dt_table_patch<bhtable_v2>(hdr, out);
|
||||
default:
|
||||
return 1;
|
||||
}
|
||||
} else if (MATCH(PXADT_MAGIC)) {
|
||||
auto hdr = reinterpret_cast<pxadt_hdr *>(dtb);
|
||||
switch (hdr->version) {
|
||||
case 1:
|
||||
fprintf(stderr, "PXA-DT v1\n");
|
||||
return dt_table_patch<pxatable_v1>(hdr, out);
|
||||
default:
|
||||
return 1;
|
||||
}
|
||||
} else if (MATCH(PXA19xx_MAGIC)) {
|
||||
auto hdr = reinterpret_cast<pxa19xx_hdr *>(dtb);
|
||||
switch (hdr->version) {
|
||||
case 1:
|
||||
fprintf(stderr, "PXA-19xx v1\n");
|
||||
return dt_table_patch<pxatable_v1>(hdr, out);
|
||||
default:
|
||||
return 1;
|
||||
}
|
||||
} else if (MATCH(SPRD_MAGIC)) {
|
||||
auto hdr = reinterpret_cast<sprd_hdr *>(dtb);
|
||||
switch (hdr->version) {
|
||||
case 1:
|
||||
fprintf(stderr, "SPRD v1\n");
|
||||
return dt_table_patch<sprdtable_v1>(hdr, out);
|
||||
default:
|
||||
return 1;
|
||||
}
|
||||
} else if (MATCH(DT_TABLE_MAGIC)) {
|
||||
auto hdr = reinterpret_cast<dt_table_header *>(dtb);
|
||||
switch (hdr->version) {
|
||||
case 0:
|
||||
fprintf(stderr, "DT_TABLE v0\n");
|
||||
return dt_table_patch<dt_table_entry>(hdr, out);
|
||||
default:
|
||||
return 1;
|
||||
}
|
||||
} else {
|
||||
return blob_patch(dtb, dtb_sz, out);
|
||||
}
|
||||
}
|
||||
if (MATCH(QCDT_MAGIC)) {
|
||||
auto hdr = reinterpret_cast<qcdt_hdr*>(dtb);
|
||||
switch (hdr->version) {
|
||||
case 1:
|
||||
fprintf(stderr, "QCDT v1\n");
|
||||
return dt_table_patch<qctable_v1>(hdr, out);
|
||||
case 2:
|
||||
fprintf(stderr, "QCDT v2\n");
|
||||
return dt_table_patch<qctable_v2>(hdr, out);
|
||||
case 3:
|
||||
fprintf(stderr, "QCDT v3\n");
|
||||
return dt_table_patch<qctable_v3>(hdr, out);
|
||||
default:
|
||||
return 1;
|
||||
}
|
||||
} else if (MATCH(DTBH_MAGIC)) {
|
||||
auto hdr = reinterpret_cast<dtbh_hdr *>(dtb);
|
||||
switch (hdr->version) {
|
||||
case 2:
|
||||
fprintf(stderr, "DTBH v2\n");
|
||||
return dt_table_patch<bhtable_v2>(hdr, out);
|
||||
default:
|
||||
return 1;
|
||||
}
|
||||
} else if (MATCH(PXADT_MAGIC)) {
|
||||
auto hdr = reinterpret_cast<pxadt_hdr *>(dtb);
|
||||
switch (hdr->version) {
|
||||
case 1:
|
||||
fprintf(stderr, "PXA-DT v1\n");
|
||||
return dt_table_patch<pxatable_v1>(hdr, out);
|
||||
default:
|
||||
return 1;
|
||||
}
|
||||
} else if (MATCH(PXA19xx_MAGIC)) {
|
||||
auto hdr = reinterpret_cast<pxa19xx_hdr *>(dtb);
|
||||
switch (hdr->version) {
|
||||
case 1:
|
||||
fprintf(stderr, "PXA-19xx v1\n");
|
||||
return dt_table_patch<pxatable_v1>(hdr, out);
|
||||
default:
|
||||
return 1;
|
||||
}
|
||||
} else if (MATCH(SPRD_MAGIC)) {
|
||||
auto hdr = reinterpret_cast<sprd_hdr *>(dtb);
|
||||
switch (hdr->version) {
|
||||
case 1:
|
||||
fprintf(stderr, "SPRD v1\n");
|
||||
return dt_table_patch<sprdtable_v1>(hdr, out);
|
||||
default:
|
||||
return 1;
|
||||
}
|
||||
} else if (MATCH(DT_TABLE_MAGIC)) {
|
||||
auto hdr = reinterpret_cast<dt_table_header *>(dtb);
|
||||
switch (hdr->version) {
|
||||
case 0:
|
||||
fprintf(stderr, "DT_TABLE v0\n");
|
||||
return dt_table_patch<dt_table_entry>(hdr, out);
|
||||
default:
|
||||
return 1;
|
||||
}
|
||||
} else {
|
||||
return blob_patch(dtb, dtb_sz, out);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,94 +11,94 @@
|
||||
#define SPRD_MAGIC "SPRD"
|
||||
|
||||
struct qcdt_hdr {
|
||||
char magic[4]; /* "QCDT" */
|
||||
uint32_t version; /* QCDT version */
|
||||
uint32_t num_dtbs; /* Number of DTBs */
|
||||
char magic[4]; /* "QCDT" */
|
||||
uint32_t version; /* QCDT version */
|
||||
uint32_t num_dtbs; /* Number of DTBs */
|
||||
} __attribute__((packed));
|
||||
|
||||
struct qctable_v1 {
|
||||
uint32_t cpu_info[3]; /* Some CPU info */
|
||||
uint32_t offset; /* DTB offset in QCDT */
|
||||
uint32_t len; /* DTB size */
|
||||
uint32_t cpu_info[3]; /* Some CPU info */
|
||||
uint32_t offset; /* DTB offset in QCDT */
|
||||
uint32_t len; /* DTB size */
|
||||
} __attribute__((packed));
|
||||
|
||||
struct qctable_v2 {
|
||||
uint32_t cpu_info[4]; /* Some CPU info */
|
||||
uint32_t offset; /* DTB offset in QCDT */
|
||||
uint32_t len; /* DTB size */
|
||||
uint32_t cpu_info[4]; /* Some CPU info */
|
||||
uint32_t offset; /* DTB offset in QCDT */
|
||||
uint32_t len; /* DTB size */
|
||||
} __attribute__((packed));
|
||||
|
||||
struct qctable_v3 {
|
||||
uint32_t cpu_info[8]; /* Some CPU info */
|
||||
uint32_t offset; /* DTB offset in QCDT */
|
||||
uint32_t len; /* DTB size */
|
||||
uint32_t cpu_info[8]; /* Some CPU info */
|
||||
uint32_t offset; /* DTB offset in QCDT */
|
||||
uint32_t len; /* DTB size */
|
||||
} __attribute__((packed));
|
||||
|
||||
struct dtbh_hdr {
|
||||
char magic[4]; /* "DTBH" */
|
||||
uint32_t version; /* DTBH version */
|
||||
uint32_t num_dtbs; /* Number of DTBs */
|
||||
char magic[4]; /* "DTBH" */
|
||||
uint32_t version; /* DTBH version */
|
||||
uint32_t num_dtbs; /* Number of DTBs */
|
||||
} __attribute__((packed));
|
||||
|
||||
struct bhtable_v2 {
|
||||
uint32_t cpu_info[5]; /* Some CPU info */
|
||||
uint32_t offset; /* DTB offset in DTBH */
|
||||
uint32_t len; /* DTB size */
|
||||
uint32_t space; /* 0x00000020 */
|
||||
uint32_t cpu_info[5]; /* Some CPU info */
|
||||
uint32_t offset; /* DTB offset in DTBH */
|
||||
uint32_t len; /* DTB size */
|
||||
uint32_t space; /* 0x00000020 */
|
||||
} __attribute__((packed));
|
||||
|
||||
struct pxadt_hdr {
|
||||
char magic[6]; /* "PXA-DT" */
|
||||
uint32_t version; /* PXA-* version */
|
||||
uint32_t num_dtbs; /* Number of DTBs */
|
||||
char magic[6]; /* "PXA-DT" */
|
||||
uint32_t version; /* PXA-* version */
|
||||
uint32_t num_dtbs; /* Number of DTBs */
|
||||
} __attribute__((packed));
|
||||
|
||||
struct pxa19xx_hdr {
|
||||
char magic[8]; /* "PXA-19xx" */
|
||||
uint32_t version; /* PXA-* version */
|
||||
uint32_t num_dtbs; /* Number of DTBs */
|
||||
char magic[8]; /* "PXA-19xx" */
|
||||
uint32_t version; /* PXA-* version */
|
||||
uint32_t num_dtbs; /* Number of DTBs */
|
||||
} __attribute__((packed));
|
||||
|
||||
struct pxatable_v1 {
|
||||
uint32_t cpu_info[2]; /* Some CPU info */
|
||||
uint32_t offset; /* DTB offset in PXA-* */
|
||||
uint32_t len; /* DTB size */
|
||||
uint32_t cpu_info[2]; /* Some CPU info */
|
||||
uint32_t offset; /* DTB offset in PXA-* */
|
||||
uint32_t len; /* DTB size */
|
||||
} __attribute__((packed));
|
||||
|
||||
struct sprd_hdr {
|
||||
char magic[4]; /* "SPRD" */
|
||||
uint32_t version; /* SPRD version */
|
||||
uint32_t num_dtbs; /* Number of DTBs */
|
||||
char magic[4]; /* "SPRD" */
|
||||
uint32_t version; /* SPRD version */
|
||||
uint32_t num_dtbs; /* Number of DTBs */
|
||||
} __attribute__((packed));
|
||||
|
||||
struct sprdtable_v1 {
|
||||
uint32_t cpu_info[3]; /* Some CPU info */
|
||||
uint32_t offset; /* DTB offset in SPRD */
|
||||
uint32_t len; /* DTB size */
|
||||
uint32_t cpu_info[3]; /* Some CPU info */
|
||||
uint32_t offset; /* DTB offset in SPRD */
|
||||
uint32_t len; /* DTB size */
|
||||
} __attribute__((packed));
|
||||
|
||||
/* AOSP DTB/DTBO partition layout */
|
||||
|
||||
struct dt_table_header {
|
||||
uint32_t magic; /* DT_TABLE_MAGIC */
|
||||
uint32_t total_size; /* includes dt_table_header + all dt_table_entry */
|
||||
uint32_t header_size; /* sizeof(dt_table_header) */
|
||||
uint32_t magic; /* DT_TABLE_MAGIC */
|
||||
uint32_t total_size; /* includes dt_table_header + all dt_table_entry */
|
||||
uint32_t header_size; /* sizeof(dt_table_header) */
|
||||
|
||||
uint32_t dt_entry_size; /* sizeof(dt_table_entry) */
|
||||
uint32_t num_dtbs; /* number of dt_table_entry */
|
||||
uint32_t dt_entries_offset; /* offset to the first dt_table_entry */
|
||||
uint32_t dt_entry_size; /* sizeof(dt_table_entry) */
|
||||
uint32_t num_dtbs; /* number of dt_table_entry */
|
||||
uint32_t dt_entries_offset; /* offset to the first dt_table_entry */
|
||||
|
||||
uint32_t page_size; /* flash page size we assume */
|
||||
uint32_t version; /* DTBO image version */
|
||||
uint32_t page_size; /* flash page size we assume */
|
||||
uint32_t version; /* DTBO image version */
|
||||
} __attribute__((packed));
|
||||
|
||||
struct dt_table_entry {
|
||||
uint32_t len; /* DTB size */
|
||||
uint32_t offset;
|
||||
uint32_t len; /* DTB size */
|
||||
uint32_t offset;
|
||||
|
||||
uint32_t id;
|
||||
uint32_t rev;
|
||||
uint32_t flags;
|
||||
uint32_t id;
|
||||
uint32_t rev;
|
||||
uint32_t flags;
|
||||
|
||||
uint32_t custom[3];
|
||||
uint32_t custom[3];
|
||||
} __attribute__((packed));
|
||||
|
||||
@@ -8,15 +8,15 @@ Fmt2Ext fmt2ext;
|
||||
|
||||
class FormatInit {
|
||||
public:
|
||||
FormatInit() {
|
||||
name2fmt["gzip"] = GZIP;
|
||||
name2fmt["xz"] = XZ;
|
||||
name2fmt["lzma"] = LZMA;
|
||||
name2fmt["bzip2"] = BZIP2;
|
||||
name2fmt["lz4"] = LZ4;
|
||||
name2fmt["lz4_legacy"] = LZ4_LEGACY;
|
||||
name2fmt["lz4_lg"] = LZ4_LG;
|
||||
}
|
||||
FormatInit() {
|
||||
name2fmt["gzip"] = GZIP;
|
||||
name2fmt["xz"] = XZ;
|
||||
name2fmt["lzma"] = LZMA;
|
||||
name2fmt["bzip2"] = BZIP2;
|
||||
name2fmt["lz4"] = LZ4;
|
||||
name2fmt["lz4_legacy"] = LZ4_LEGACY;
|
||||
name2fmt["lz4_lg"] = LZ4_LG;
|
||||
}
|
||||
};
|
||||
|
||||
static FormatInit init;
|
||||
@@ -24,82 +24,82 @@ static FormatInit init;
|
||||
#define MATCH(s) (len >= (sizeof(s) - 1) && memcmp(buf, s, sizeof(s) - 1) == 0)
|
||||
|
||||
format_t check_fmt(const void *buf, size_t len) {
|
||||
if (MATCH(CHROMEOS_MAGIC)) {
|
||||
return CHROMEOS;
|
||||
} else if (MATCH(BOOT_MAGIC)) {
|
||||
return AOSP;
|
||||
} else if (MATCH(VENDOR_BOOT_MAGIC)) {
|
||||
return AOSP_VENDOR;
|
||||
} else if (MATCH(GZIP1_MAGIC) || MATCH(GZIP2_MAGIC)) {
|
||||
return GZIP;
|
||||
} else if (MATCH(LZOP_MAGIC)) {
|
||||
return LZOP;
|
||||
} else if (MATCH(XZ_MAGIC)) {
|
||||
return XZ;
|
||||
} else if (len >= 13 && memcmp(buf, "\x5d\x00\x00", 3) == 0
|
||||
&& (((char *)buf)[12] == '\xff' || ((char *)buf)[12] == '\x00')) {
|
||||
return LZMA;
|
||||
} else if (MATCH(BZIP_MAGIC)) {
|
||||
return BZIP2;
|
||||
} else if (MATCH(LZ41_MAGIC) || MATCH(LZ42_MAGIC)) {
|
||||
return LZ4;
|
||||
} else if (MATCH(LZ4_LEG_MAGIC)) {
|
||||
return LZ4_LEGACY;
|
||||
} else if (MATCH(MTK_MAGIC)) {
|
||||
return MTK;
|
||||
} else if (MATCH(DTB_MAGIC)) {
|
||||
return DTB;
|
||||
} else if (MATCH(DHTB_MAGIC)) {
|
||||
return DHTB;
|
||||
} else if (MATCH(TEGRABLOB_MAGIC)) {
|
||||
return BLOB;
|
||||
} else {
|
||||
return UNKNOWN;
|
||||
}
|
||||
if (MATCH(CHROMEOS_MAGIC)) {
|
||||
return CHROMEOS;
|
||||
} else if (MATCH(BOOT_MAGIC)) {
|
||||
return AOSP;
|
||||
} else if (MATCH(VENDOR_BOOT_MAGIC)) {
|
||||
return AOSP_VENDOR;
|
||||
} else if (MATCH(GZIP1_MAGIC) || MATCH(GZIP2_MAGIC)) {
|
||||
return GZIP;
|
||||
} else if (MATCH(LZOP_MAGIC)) {
|
||||
return LZOP;
|
||||
} else if (MATCH(XZ_MAGIC)) {
|
||||
return XZ;
|
||||
} else if (len >= 13 && memcmp(buf, "\x5d\x00\x00", 3) == 0
|
||||
&& (((char *)buf)[12] == '\xff' || ((char *)buf)[12] == '\x00')) {
|
||||
return LZMA;
|
||||
} else if (MATCH(BZIP_MAGIC)) {
|
||||
return BZIP2;
|
||||
} else if (MATCH(LZ41_MAGIC) || MATCH(LZ42_MAGIC)) {
|
||||
return LZ4;
|
||||
} else if (MATCH(LZ4_LEG_MAGIC)) {
|
||||
return LZ4_LEGACY;
|
||||
} else if (MATCH(MTK_MAGIC)) {
|
||||
return MTK;
|
||||
} else if (MATCH(DTB_MAGIC)) {
|
||||
return DTB;
|
||||
} else if (MATCH(DHTB_MAGIC)) {
|
||||
return DHTB;
|
||||
} else if (MATCH(TEGRABLOB_MAGIC)) {
|
||||
return BLOB;
|
||||
} else {
|
||||
return UNKNOWN;
|
||||
}
|
||||
}
|
||||
|
||||
const char *Fmt2Name::operator[](format_t fmt) {
|
||||
switch (fmt) {
|
||||
case GZIP:
|
||||
return "gzip";
|
||||
case LZOP:
|
||||
return "lzop";
|
||||
case XZ:
|
||||
return "xz";
|
||||
case LZMA:
|
||||
return "lzma";
|
||||
case BZIP2:
|
||||
return "bzip2";
|
||||
case LZ4:
|
||||
return "lz4";
|
||||
case LZ4_LEGACY:
|
||||
return "lz4_legacy";
|
||||
case LZ4_LG:
|
||||
return "lz4_lg";
|
||||
case DTB:
|
||||
return "dtb";
|
||||
default:
|
||||
return "raw";
|
||||
}
|
||||
switch (fmt) {
|
||||
case GZIP:
|
||||
return "gzip";
|
||||
case LZOP:
|
||||
return "lzop";
|
||||
case XZ:
|
||||
return "xz";
|
||||
case LZMA:
|
||||
return "lzma";
|
||||
case BZIP2:
|
||||
return "bzip2";
|
||||
case LZ4:
|
||||
return "lz4";
|
||||
case LZ4_LEGACY:
|
||||
return "lz4_legacy";
|
||||
case LZ4_LG:
|
||||
return "lz4_lg";
|
||||
case DTB:
|
||||
return "dtb";
|
||||
default:
|
||||
return "raw";
|
||||
}
|
||||
}
|
||||
|
||||
const char *Fmt2Ext::operator[](format_t fmt) {
|
||||
switch (fmt) {
|
||||
case GZIP:
|
||||
return ".gz";
|
||||
case LZOP:
|
||||
return ".lzo";
|
||||
case XZ:
|
||||
return ".xz";
|
||||
case LZMA:
|
||||
return ".lzma";
|
||||
case BZIP2:
|
||||
return ".bz2";
|
||||
case LZ4:
|
||||
case LZ4_LEGACY:
|
||||
case LZ4_LG:
|
||||
return ".lz4";
|
||||
default:
|
||||
return "";
|
||||
}
|
||||
switch (fmt) {
|
||||
case GZIP:
|
||||
return ".gz";
|
||||
case LZOP:
|
||||
return ".lzo";
|
||||
case XZ:
|
||||
return ".xz";
|
||||
case LZMA:
|
||||
return ".lzma";
|
||||
case BZIP2:
|
||||
return ".bz2";
|
||||
case LZ4:
|
||||
case LZ4_LEGACY:
|
||||
case LZ4_LG:
|
||||
return ".lz4";
|
||||
default:
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,26 +4,26 @@
|
||||
#include <string_view>
|
||||
|
||||
typedef enum {
|
||||
UNKNOWN,
|
||||
UNKNOWN,
|
||||
/* Boot formats */
|
||||
CHROMEOS,
|
||||
AOSP,
|
||||
AOSP_VENDOR,
|
||||
DHTB,
|
||||
BLOB,
|
||||
CHROMEOS,
|
||||
AOSP,
|
||||
AOSP_VENDOR,
|
||||
DHTB,
|
||||
BLOB,
|
||||
/* Compression formats */
|
||||
GZIP,
|
||||
XZ,
|
||||
LZMA,
|
||||
BZIP2,
|
||||
LZ4,
|
||||
LZ4_LEGACY,
|
||||
LZ4_LG,
|
||||
GZIP,
|
||||
XZ,
|
||||
LZMA,
|
||||
BZIP2,
|
||||
LZ4,
|
||||
LZ4_LEGACY,
|
||||
LZ4_LG,
|
||||
/* Unsupported compression */
|
||||
LZOP,
|
||||
LZOP,
|
||||
/* Misc */
|
||||
MTK,
|
||||
DTB,
|
||||
MTK,
|
||||
DTB,
|
||||
} format_t;
|
||||
|
||||
#define COMPRESSED(fmt) ((fmt) >= GZIP && (fmt) < LZOP)
|
||||
@@ -57,12 +57,12 @@ typedef enum {
|
||||
|
||||
class Fmt2Name {
|
||||
public:
|
||||
const char *operator[](format_t fmt);
|
||||
const char *operator[](format_t fmt);
|
||||
};
|
||||
|
||||
class Fmt2Ext {
|
||||
public:
|
||||
const char *operator[](format_t fmt);
|
||||
const char *operator[](format_t fmt);
|
||||
};
|
||||
|
||||
format_t check_fmt(const void *buf, size_t len);
|
||||
|
||||
@@ -8,36 +8,36 @@
|
||||
#include "magiskboot.hpp"
|
||||
|
||||
static void hex2byte(uint8_t *hex, uint8_t *str) {
|
||||
char high, low;
|
||||
for (int i = 0, length = strlen((char *) hex); i < length; i += 2) {
|
||||
high = toupper(hex[i]) - '0';
|
||||
low = toupper(hex[i + 1]) - '0';
|
||||
str[i / 2] = ((high > 9 ? high - 7 : high) << 4) + (low > 9 ? low - 7 : low);
|
||||
}
|
||||
char high, low;
|
||||
for (int i = 0, length = strlen((char *) hex); i < length; i += 2) {
|
||||
high = toupper(hex[i]) - '0';
|
||||
low = toupper(hex[i + 1]) - '0';
|
||||
str[i / 2] = ((high > 9 ? high - 7 : high) << 4) + (low > 9 ? low - 7 : low);
|
||||
}
|
||||
}
|
||||
|
||||
int hexpatch(const char *image, const char *from, const char *to) {
|
||||
int patternsize = strlen(from) / 2, patchsize = strlen(to) / 2;
|
||||
int patched = 1;
|
||||
size_t filesize;
|
||||
uint8_t *file, *pattern, *patch;
|
||||
mmap_rw(image, file, filesize);
|
||||
pattern = (uint8_t *) xmalloc(patternsize);
|
||||
patch = (uint8_t *) xmalloc(patchsize);
|
||||
hex2byte((uint8_t *) from, pattern);
|
||||
hex2byte((uint8_t *) to, patch);
|
||||
for (size_t i = 0; filesize > 0 && i < filesize - patternsize; ++i) {
|
||||
if (memcmp(file + i, pattern, patternsize) == 0) {
|
||||
fprintf(stderr, "Patch @ %08X [%s]->[%s]\n", (unsigned) i, from, to);
|
||||
memset(file + i, 0, patternsize);
|
||||
memcpy(file + i, patch, patchsize);
|
||||
i += patternsize - 1;
|
||||
patched = 0;
|
||||
}
|
||||
}
|
||||
munmap(file, filesize);
|
||||
free(pattern);
|
||||
free(patch);
|
||||
int patternsize = strlen(from) / 2, patchsize = strlen(to) / 2;
|
||||
int patched = 1;
|
||||
size_t filesize;
|
||||
uint8_t *file, *pattern, *patch;
|
||||
mmap_rw(image, file, filesize);
|
||||
pattern = (uint8_t *) xmalloc(patternsize);
|
||||
patch = (uint8_t *) xmalloc(patchsize);
|
||||
hex2byte((uint8_t *) from, pattern);
|
||||
hex2byte((uint8_t *) to, patch);
|
||||
for (size_t i = 0; filesize > 0 && i < filesize - patternsize; ++i) {
|
||||
if (memcmp(file + i, pattern, patternsize) == 0) {
|
||||
fprintf(stderr, "Patch @ %08X [%s]->[%s]\n", (unsigned) i, from, to);
|
||||
memset(file + i, 0, patternsize);
|
||||
memcpy(file + i, patch, patchsize);
|
||||
i += patternsize - 1;
|
||||
patched = 0;
|
||||
}
|
||||
}
|
||||
munmap(file, filesize);
|
||||
free(pattern);
|
||||
free(patch);
|
||||
|
||||
return patched;
|
||||
return patched;
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
using namespace std;
|
||||
|
||||
static void usage(char *arg0) {
|
||||
fprintf(stderr,
|
||||
fprintf(stderr,
|
||||
R"EOF(MagiskBoot - Boot Image Modification Tool
|
||||
|
||||
Usage: %s <action> [args...]
|
||||
@@ -96,100 +96,100 @@ Supported actions:
|
||||
<infile>/[outfile] can be '-' to be STDIN/STDOUT
|
||||
Supported methods: )EOF", arg0);
|
||||
|
||||
for (auto &it : name2fmt)
|
||||
fprintf(stderr, "%s ", it.first.data());
|
||||
for (auto &it : name2fmt)
|
||||
fprintf(stderr, "%s ", it.first.data());
|
||||
|
||||
fprintf(stderr, R"EOF(
|
||||
fprintf(stderr, R"EOF(
|
||||
|
||||
decompress <infile> [outfile]
|
||||
Detect method and decompress <infile>, optionally to [outfile]
|
||||
<infile>/[outfile] can be '-' to be STDIN/STDOUT
|
||||
Supported methods: )EOF");
|
||||
|
||||
for (auto &it : name2fmt)
|
||||
fprintf(stderr, "%s ", it.first.data());
|
||||
for (auto &it : name2fmt)
|
||||
fprintf(stderr, "%s ", it.first.data());
|
||||
|
||||
fprintf(stderr, "\n\n");
|
||||
exit(1);
|
||||
fprintf(stderr, "\n\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
cmdline_logging();
|
||||
umask(0);
|
||||
cmdline_logging();
|
||||
umask(0);
|
||||
|
||||
if (argc < 2)
|
||||
usage(argv[0]);
|
||||
if (argc < 2)
|
||||
usage(argv[0]);
|
||||
|
||||
// Skip '--' for backwards compatibility
|
||||
string_view action(argv[1]);
|
||||
if (str_starts(action, "--"))
|
||||
action = argv[1] + 2;
|
||||
// Skip '--' for backwards compatibility
|
||||
string_view action(argv[1]);
|
||||
if (str_starts(action, "--"))
|
||||
action = argv[1] + 2;
|
||||
|
||||
if (action == "cleanup") {
|
||||
fprintf(stderr, "Cleaning up...\n");
|
||||
unlink(HEADER_FILE);
|
||||
unlink(KERNEL_FILE);
|
||||
unlink(RAMDISK_FILE);
|
||||
unlink(SECOND_FILE);
|
||||
unlink(KER_DTB_FILE);
|
||||
unlink(EXTRA_FILE);
|
||||
unlink(RECV_DTBO_FILE);
|
||||
unlink(DTB_FILE);
|
||||
} else if (argc > 2 && action == "sha1") {
|
||||
uint8_t sha1[SHA_DIGEST_SIZE];
|
||||
void *buf;
|
||||
size_t size;
|
||||
mmap_ro(argv[2], buf, size);
|
||||
SHA_hash(buf, size, sha1);
|
||||
for (uint8_t i : sha1)
|
||||
printf("%02x", i);
|
||||
printf("\n");
|
||||
munmap(buf, size);
|
||||
} else if (argc > 2 && action == "split") {
|
||||
return split_image_dtb(argv[2]);
|
||||
} else if (argc > 2 && action == "unpack") {
|
||||
int idx = 2;
|
||||
bool nodecomp = false;
|
||||
bool hdr = false;
|
||||
for (;;) {
|
||||
if (idx >= argc)
|
||||
usage(argv[0]);
|
||||
if (argv[idx][0] != '-')
|
||||
break;
|
||||
for (char *flag = &argv[idx][1]; *flag; ++flag) {
|
||||
if (*flag == 'n')
|
||||
nodecomp = true;
|
||||
else if (*flag == 'h')
|
||||
hdr = true;
|
||||
else
|
||||
usage(argv[0]);
|
||||
}
|
||||
++idx;
|
||||
}
|
||||
return unpack(argv[idx], nodecomp, hdr);
|
||||
} else if (argc > 2 && action == "repack") {
|
||||
if (argv[2] == "-n"sv) {
|
||||
if (argc == 3)
|
||||
usage(argv[0]);
|
||||
repack(argv[3], argv[4] ? argv[4] : NEW_BOOT, true);
|
||||
} else {
|
||||
repack(argv[2], argv[3] ? argv[3] : NEW_BOOT);
|
||||
}
|
||||
} else if (argc > 2 && action == "decompress") {
|
||||
decompress(argv[2], argv[3]);
|
||||
} else if (argc > 2 && str_starts(action, "compress")) {
|
||||
compress(action[8] == '=' ? &action[9] : "gzip", argv[2], argv[3]);
|
||||
} else if (argc > 4 && action == "hexpatch") {
|
||||
return hexpatch(argv[2], argv[3], argv[4]);
|
||||
} else if (argc > 2 && action == "cpio"sv) {
|
||||
if (cpio_commands(argc - 2, argv + 2))
|
||||
usage(argv[0]);
|
||||
} else if (argc > 3 && action == "dtb") {
|
||||
if (dtb_commands(argc - 2, argv + 2))
|
||||
usage(argv[0]);
|
||||
} else {
|
||||
usage(argv[0]);
|
||||
}
|
||||
if (action == "cleanup") {
|
||||
fprintf(stderr, "Cleaning up...\n");
|
||||
unlink(HEADER_FILE);
|
||||
unlink(KERNEL_FILE);
|
||||
unlink(RAMDISK_FILE);
|
||||
unlink(SECOND_FILE);
|
||||
unlink(KER_DTB_FILE);
|
||||
unlink(EXTRA_FILE);
|
||||
unlink(RECV_DTBO_FILE);
|
||||
unlink(DTB_FILE);
|
||||
} else if (argc > 2 && action == "sha1") {
|
||||
uint8_t sha1[SHA_DIGEST_SIZE];
|
||||
void *buf;
|
||||
size_t size;
|
||||
mmap_ro(argv[2], buf, size);
|
||||
SHA_hash(buf, size, sha1);
|
||||
for (uint8_t i : sha1)
|
||||
printf("%02x", i);
|
||||
printf("\n");
|
||||
munmap(buf, size);
|
||||
} else if (argc > 2 && action == "split") {
|
||||
return split_image_dtb(argv[2]);
|
||||
} else if (argc > 2 && action == "unpack") {
|
||||
int idx = 2;
|
||||
bool nodecomp = false;
|
||||
bool hdr = false;
|
||||
for (;;) {
|
||||
if (idx >= argc)
|
||||
usage(argv[0]);
|
||||
if (argv[idx][0] != '-')
|
||||
break;
|
||||
for (char *flag = &argv[idx][1]; *flag; ++flag) {
|
||||
if (*flag == 'n')
|
||||
nodecomp = true;
|
||||
else if (*flag == 'h')
|
||||
hdr = true;
|
||||
else
|
||||
usage(argv[0]);
|
||||
}
|
||||
++idx;
|
||||
}
|
||||
return unpack(argv[idx], nodecomp, hdr);
|
||||
} else if (argc > 2 && action == "repack") {
|
||||
if (argv[2] == "-n"sv) {
|
||||
if (argc == 3)
|
||||
usage(argv[0]);
|
||||
repack(argv[3], argv[4] ? argv[4] : NEW_BOOT, true);
|
||||
} else {
|
||||
repack(argv[2], argv[3] ? argv[3] : NEW_BOOT);
|
||||
}
|
||||
} else if (argc > 2 && action == "decompress") {
|
||||
decompress(argv[2], argv[3]);
|
||||
} else if (argc > 2 && str_starts(action, "compress")) {
|
||||
compress(action[8] == '=' ? &action[9] : "gzip", argv[2], argv[3]);
|
||||
} else if (argc > 4 && action == "hexpatch") {
|
||||
return hexpatch(argv[2], argv[3], argv[4]);
|
||||
} else if (argc > 2 && action == "cpio"sv) {
|
||||
if (cpio_commands(argc - 2, argv + 2))
|
||||
usage(argv[0]);
|
||||
} else if (argc > 3 && action == "dtb") {
|
||||
if (dtb_commands(argc - 2, argv + 2))
|
||||
usage(argv[0]);
|
||||
} else {
|
||||
usage(argv[0]);
|
||||
}
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -8,56 +8,56 @@
|
||||
#define MATCH(p) else if (strncmp(s + skip, p, sizeof(p) - 1) == 0) skip += (sizeof(p) - 1)
|
||||
|
||||
static int check_verity_pattern(const char *s) {
|
||||
int skip = s[0] == ',';
|
||||
int skip = s[0] == ',';
|
||||
|
||||
if (0) {}
|
||||
MATCH("verifyatboot");
|
||||
MATCH("verify");
|
||||
MATCH("avb_keys");
|
||||
MATCH("avb");
|
||||
MATCH("support_scfs");
|
||||
MATCH("fsverity");
|
||||
else return -1;
|
||||
if (0) {}
|
||||
MATCH("verifyatboot");
|
||||
MATCH("verify");
|
||||
MATCH("avb_keys");
|
||||
MATCH("avb");
|
||||
MATCH("support_scfs");
|
||||
MATCH("fsverity");
|
||||
else return -1;
|
||||
|
||||
if (s[skip] == '=') {
|
||||
while (s[skip] != '\0' && s[skip] != ' ' && s[skip] != '\n' && s[skip] != ',')
|
||||
++skip;
|
||||
}
|
||||
return skip;
|
||||
if (s[skip] == '=') {
|
||||
while (s[skip] != '\0' && s[skip] != ' ' && s[skip] != '\n' && s[skip] != ',')
|
||||
++skip;
|
||||
}
|
||||
return skip;
|
||||
}
|
||||
|
||||
#undef MATCH
|
||||
#define MATCH(p) else if (strncmp(s, p, sizeof(p) - 1) == 0) return (sizeof(p) - 1)
|
||||
|
||||
static int check_encryption_pattern(const char *s) {
|
||||
if (0) {}
|
||||
MATCH("forceencrypt");
|
||||
MATCH("forcefdeorfbe");
|
||||
MATCH("fileencryption");
|
||||
else return -1;
|
||||
if (0) {}
|
||||
MATCH("forceencrypt");
|
||||
MATCH("forcefdeorfbe");
|
||||
MATCH("fileencryption");
|
||||
else return -1;
|
||||
}
|
||||
|
||||
static uint32_t remove_pattern(void *buf, uint32_t size, int(*pattern_skip)(const char *)) {
|
||||
auto src = static_cast<char *>(buf);
|
||||
int orig_sz = size;
|
||||
int write = 0;
|
||||
for (int read = 0; read < orig_sz;) {
|
||||
if (int skip = pattern_skip(src + read); skip > 0) {
|
||||
fprintf(stderr, "Remove pattern [%.*s]\n", skip, src + read);
|
||||
size -= skip;
|
||||
read += skip;
|
||||
} else {
|
||||
src[write++] = src[read++];
|
||||
}
|
||||
}
|
||||
memset(src + write, 0, orig_sz - write);
|
||||
return size;
|
||||
auto src = static_cast<char *>(buf);
|
||||
int orig_sz = size;
|
||||
int write = 0;
|
||||
for (int read = 0; read < orig_sz;) {
|
||||
if (int skip = pattern_skip(src + read); skip > 0) {
|
||||
fprintf(stderr, "Remove pattern [%.*s]\n", skip, src + read);
|
||||
size -= skip;
|
||||
read += skip;
|
||||
} else {
|
||||
src[write++] = src[read++];
|
||||
}
|
||||
}
|
||||
memset(src + write, 0, orig_sz - write);
|
||||
return size;
|
||||
}
|
||||
|
||||
uint32_t patch_verity(void *buf, uint32_t size) {
|
||||
return remove_pattern(buf, size, check_verity_pattern);
|
||||
return remove_pattern(buf, size, check_verity_pattern);
|
||||
}
|
||||
|
||||
uint32_t patch_encryption(void *buf, uint32_t size) {
|
||||
return remove_pattern(buf, size, check_encryption_pattern);
|
||||
return remove_pattern(buf, size, check_encryption_pattern);
|
||||
}
|
||||
|
||||
@@ -13,60 +13,60 @@ using namespace std;
|
||||
constexpr char RAMDISK_XZ[] = "ramdisk.cpio.xz";
|
||||
|
||||
static const char *UNSUPPORT_LIST[] =
|
||||
{ "sbin/launch_daemonsu.sh", "sbin/su", "init.xposed.rc",
|
||||
"boot/sbin/launch_daemonsu.sh" };
|
||||
{ "sbin/launch_daemonsu.sh", "sbin/su", "init.xposed.rc",
|
||||
"boot/sbin/launch_daemonsu.sh" };
|
||||
|
||||
static const char *MAGISK_LIST[] =
|
||||
{ ".backup/.magisk", "init.magisk.rc",
|
||||
"overlay/init.magisk.rc" };
|
||||
{ ".backup/.magisk", "init.magisk.rc",
|
||||
"overlay/init.magisk.rc" };
|
||||
|
||||
class magisk_cpio : public cpio_rw {
|
||||
public:
|
||||
magisk_cpio() = default;
|
||||
explicit magisk_cpio(const char *filename) : cpio_rw(filename) {}
|
||||
void patch();
|
||||
int test();
|
||||
char *sha1();
|
||||
void restore();
|
||||
void backup(const char *orig);
|
||||
void compress();
|
||||
void decompress();
|
||||
magisk_cpio() = default;
|
||||
explicit magisk_cpio(const char *filename) : cpio_rw(filename) {}
|
||||
void patch();
|
||||
int test();
|
||||
char *sha1();
|
||||
void restore();
|
||||
void backup(const char *orig);
|
||||
void compress();
|
||||
void decompress();
|
||||
};
|
||||
|
||||
bool check_env(const char *name) {
|
||||
const char *val = getenv(name);
|
||||
return val ? strcmp(val, "true") == 0 : false;
|
||||
const char *val = getenv(name);
|
||||
return val ? strcmp(val, "true") == 0 : false;
|
||||
}
|
||||
|
||||
void magisk_cpio::patch() {
|
||||
bool keepverity = check_env("KEEPVERITY");
|
||||
bool keepforceencrypt = check_env("KEEPFORCEENCRYPT");
|
||||
fprintf(stderr, "Patch with flag KEEPVERITY=[%s] KEEPFORCEENCRYPT=[%s]\n",
|
||||
keepverity ? "true" : "false", keepforceencrypt ? "true" : "false");
|
||||
bool keepverity = check_env("KEEPVERITY");
|
||||
bool keepforceencrypt = check_env("KEEPFORCEENCRYPT");
|
||||
fprintf(stderr, "Patch with flag KEEPVERITY=[%s] KEEPFORCEENCRYPT=[%s]\n",
|
||||
keepverity ? "true" : "false", keepforceencrypt ? "true" : "false");
|
||||
|
||||
for (auto it = entries.begin(); it != entries.end();) {
|
||||
auto cur = it++;
|
||||
bool fstab = (!keepverity || !keepforceencrypt) &&
|
||||
S_ISREG(cur->second->mode) &&
|
||||
!str_starts(cur->first, ".backup") &&
|
||||
!str_contains(cur->first, "twrp") &&
|
||||
!str_contains(cur->first, "recovery") &&
|
||||
str_contains(cur->first, "fstab");
|
||||
if (!keepverity) {
|
||||
if (fstab) {
|
||||
fprintf(stderr, "Found fstab file [%s]\n", cur->first.data());
|
||||
cur->second->filesize = patch_verity(cur->second->data, cur->second->filesize);
|
||||
} else if (cur->first == "verity_key") {
|
||||
rm(cur);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (!keepforceencrypt) {
|
||||
if (fstab) {
|
||||
cur->second->filesize = patch_encryption(cur->second->data, cur->second->filesize);
|
||||
}
|
||||
}
|
||||
}
|
||||
for (auto it = entries.begin(); it != entries.end();) {
|
||||
auto cur = it++;
|
||||
bool fstab = (!keepverity || !keepforceencrypt) &&
|
||||
S_ISREG(cur->second->mode) &&
|
||||
!str_starts(cur->first, ".backup") &&
|
||||
!str_contains(cur->first, "twrp") &&
|
||||
!str_contains(cur->first, "recovery") &&
|
||||
str_contains(cur->first, "fstab");
|
||||
if (!keepverity) {
|
||||
if (fstab) {
|
||||
fprintf(stderr, "Found fstab file [%s]\n", cur->first.data());
|
||||
cur->second->filesize = patch_verity(cur->second->data, cur->second->filesize);
|
||||
} else if (cur->first == "verity_key") {
|
||||
rm(cur);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (!keepforceencrypt) {
|
||||
if (fstab) {
|
||||
cur->second->filesize = patch_encryption(cur->second->data, cur->second->filesize);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#define STOCK_BOOT 0
|
||||
@@ -76,274 +76,274 @@ void magisk_cpio::patch() {
|
||||
#define TWO_STAGE_INIT (1 << 3)
|
||||
|
||||
int magisk_cpio::test() {
|
||||
for (auto file : UNSUPPORT_LIST)
|
||||
if (exists(file))
|
||||
return UNSUPPORTED_CPIO;
|
||||
for (auto file : UNSUPPORT_LIST)
|
||||
if (exists(file))
|
||||
return UNSUPPORTED_CPIO;
|
||||
|
||||
int flags = STOCK_BOOT;
|
||||
int flags = STOCK_BOOT;
|
||||
|
||||
if (exists(RAMDISK_XZ)) {
|
||||
flags |= COMPRESSED_CPIO | MAGISK_PATCHED;
|
||||
decompress();
|
||||
}
|
||||
if (exists(RAMDISK_XZ)) {
|
||||
flags |= COMPRESSED_CPIO | MAGISK_PATCHED;
|
||||
decompress();
|
||||
}
|
||||
|
||||
if (exists("apex") || exists("first_stage_ramdisk"))
|
||||
flags |= TWO_STAGE_INIT;
|
||||
if (exists("apex") || exists("first_stage_ramdisk"))
|
||||
flags |= TWO_STAGE_INIT;
|
||||
|
||||
for (auto file : MAGISK_LIST) {
|
||||
if (exists(file)) {
|
||||
flags |= MAGISK_PATCHED;
|
||||
break;
|
||||
}
|
||||
}
|
||||
for (auto file : MAGISK_LIST) {
|
||||
if (exists(file)) {
|
||||
flags |= MAGISK_PATCHED;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return flags;
|
||||
return flags;
|
||||
}
|
||||
|
||||
#define for_each_line(line, buf, size) \
|
||||
for (line = (char *) buf; line < (char *) buf + size && line[0]; line = strchr(line + 1, '\n') + 1)
|
||||
|
||||
char *magisk_cpio::sha1() {
|
||||
decompress();
|
||||
char sha1[41];
|
||||
char *line;
|
||||
for (auto &e : entries) {
|
||||
if (e.first == "init.magisk.rc" || e.first == "overlay/init.magisk.rc") {
|
||||
for_each_line(line, e.second->data, e.second->filesize) {
|
||||
if (strncmp(line, "#STOCKSHA1=", 11) == 0) {
|
||||
strncpy(sha1, line + 12, 40);
|
||||
sha1[40] = '\0';
|
||||
return strdup(sha1);
|
||||
}
|
||||
}
|
||||
} else if (e.first == ".backup/.magisk") {
|
||||
for_each_line(line, e.second->data, e.second->filesize) {
|
||||
if (strncmp(line, "SHA1=", 5) == 0) {
|
||||
strncpy(sha1, line + 5, 40);
|
||||
sha1[40] = '\0';
|
||||
return strdup(sha1);
|
||||
}
|
||||
}
|
||||
} else if (e.first == ".backup/.sha1") {
|
||||
return (char *) e.second->data;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
decompress();
|
||||
char sha1[41];
|
||||
char *line;
|
||||
for (auto &e : entries) {
|
||||
if (e.first == "init.magisk.rc" || e.first == "overlay/init.magisk.rc") {
|
||||
for_each_line(line, e.second->data, e.second->filesize) {
|
||||
if (strncmp(line, "#STOCKSHA1=", 11) == 0) {
|
||||
strncpy(sha1, line + 12, 40);
|
||||
sha1[40] = '\0';
|
||||
return strdup(sha1);
|
||||
}
|
||||
}
|
||||
} else if (e.first == ".backup/.magisk") {
|
||||
for_each_line(line, e.second->data, e.second->filesize) {
|
||||
if (strncmp(line, "SHA1=", 5) == 0) {
|
||||
strncpy(sha1, line + 5, 40);
|
||||
sha1[40] = '\0';
|
||||
return strdup(sha1);
|
||||
}
|
||||
}
|
||||
} else if (e.first == ".backup/.sha1") {
|
||||
return (char *) e.second->data;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
#define for_each_str(str, buf, size) \
|
||||
for (str = (char *) buf; str < (char *) buf + size; str = str += strlen(str) + 1)
|
||||
|
||||
void magisk_cpio::restore() {
|
||||
decompress();
|
||||
decompress();
|
||||
|
||||
if (auto it = entries.find(".backup/.rmlist"); it != entries.end()) {
|
||||
char *file;
|
||||
for_each_str(file, it->second->data, it->second->filesize)
|
||||
rm(file, false);
|
||||
rm(it);
|
||||
}
|
||||
if (auto it = entries.find(".backup/.rmlist"); it != entries.end()) {
|
||||
char *file;
|
||||
for_each_str(file, it->second->data, it->second->filesize)
|
||||
rm(file, false);
|
||||
rm(it);
|
||||
}
|
||||
|
||||
for (auto it = entries.begin(); it != entries.end();) {
|
||||
auto cur = it++;
|
||||
if (str_starts(cur->first, ".backup")) {
|
||||
if (cur->first.length() == 7 || cur->first.substr(8) == ".magisk") {
|
||||
rm(cur);
|
||||
} else {
|
||||
mv(cur, &cur->first[8]);
|
||||
}
|
||||
} else if (str_starts(cur->first, "magisk") ||
|
||||
cur->first == "overlay/init.magisk.rc" ||
|
||||
cur->first == "sbin/magic_mask.sh" ||
|
||||
cur->first == "init.magisk.rc") {
|
||||
// Some known stuff we can remove
|
||||
rm(cur);
|
||||
}
|
||||
}
|
||||
for (auto it = entries.begin(); it != entries.end();) {
|
||||
auto cur = it++;
|
||||
if (str_starts(cur->first, ".backup")) {
|
||||
if (cur->first.length() == 7 || cur->first.substr(8) == ".magisk") {
|
||||
rm(cur);
|
||||
} else {
|
||||
mv(cur, &cur->first[8]);
|
||||
}
|
||||
} else if (str_starts(cur->first, "magisk") ||
|
||||
cur->first == "overlay/init.magisk.rc" ||
|
||||
cur->first == "sbin/magic_mask.sh" ||
|
||||
cur->first == "init.magisk.rc") {
|
||||
// Some known stuff we can remove
|
||||
rm(cur);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void magisk_cpio::backup(const char *orig) {
|
||||
if (access(orig, R_OK))
|
||||
return;
|
||||
entry_map bkup_entries;
|
||||
string remv;
|
||||
if (access(orig, R_OK))
|
||||
return;
|
||||
entry_map bkup_entries;
|
||||
string remv;
|
||||
|
||||
auto b = new cpio_entry(".backup", S_IFDIR);
|
||||
bkup_entries[b->filename].reset(b);
|
||||
auto b = new cpio_entry(".backup", S_IFDIR);
|
||||
bkup_entries[b->filename].reset(b);
|
||||
|
||||
magisk_cpio o(orig);
|
||||
magisk_cpio o(orig);
|
||||
|
||||
// Remove possible backups in original ramdisk
|
||||
o.rm(".backup", true);
|
||||
rm(".backup", true);
|
||||
// Remove possible backups in original ramdisk
|
||||
o.rm(".backup", true);
|
||||
rm(".backup", true);
|
||||
|
||||
auto lhs = o.entries.begin();
|
||||
auto rhs = entries.begin();
|
||||
auto lhs = o.entries.begin();
|
||||
auto rhs = entries.begin();
|
||||
|
||||
while (lhs != o.entries.end() || rhs != entries.end()) {
|
||||
int res;
|
||||
bool backup = false;
|
||||
if (lhs != o.entries.end() && rhs != entries.end()) {
|
||||
res = lhs->first.compare(rhs->first);
|
||||
} else if (lhs == o.entries.end()) {
|
||||
res = 1;
|
||||
} else {
|
||||
res = -1;
|
||||
}
|
||||
while (lhs != o.entries.end() || rhs != entries.end()) {
|
||||
int res;
|
||||
bool backup = false;
|
||||
if (lhs != o.entries.end() && rhs != entries.end()) {
|
||||
res = lhs->first.compare(rhs->first);
|
||||
} else if (lhs == o.entries.end()) {
|
||||
res = 1;
|
||||
} else {
|
||||
res = -1;
|
||||
}
|
||||
|
||||
if (res < 0) {
|
||||
// Something is missing in new ramdisk, backup!
|
||||
backup = true;
|
||||
fprintf(stderr, "Backup missing entry: ");
|
||||
} else if (res == 0) {
|
||||
if (lhs->second->filesize != rhs->second->filesize ||
|
||||
memcmp(lhs->second->data, rhs->second->data, lhs->second->filesize) != 0) {
|
||||
// Not the same!
|
||||
backup = true;
|
||||
fprintf(stderr, "Backup mismatch entry: ");
|
||||
}
|
||||
} else {
|
||||
// Something new in ramdisk
|
||||
remv += rhs->first;
|
||||
remv += (char) '\0';
|
||||
fprintf(stderr, "Record new entry: [%s] -> [.backup/.rmlist]\n", rhs->first.data());
|
||||
}
|
||||
if (backup) {
|
||||
string back_name(".backup/");
|
||||
back_name += lhs->first;
|
||||
fprintf(stderr, "[%s] -> [%s]\n", lhs->first.data(), back_name.data());
|
||||
auto ex = static_cast<cpio_entry*>(lhs->second.release());
|
||||
ex->filename = back_name;
|
||||
bkup_entries[ex->filename].reset(ex);
|
||||
}
|
||||
if (res < 0) {
|
||||
// Something is missing in new ramdisk, backup!
|
||||
backup = true;
|
||||
fprintf(stderr, "Backup missing entry: ");
|
||||
} else if (res == 0) {
|
||||
if (lhs->second->filesize != rhs->second->filesize ||
|
||||
memcmp(lhs->second->data, rhs->second->data, lhs->second->filesize) != 0) {
|
||||
// Not the same!
|
||||
backup = true;
|
||||
fprintf(stderr, "Backup mismatch entry: ");
|
||||
}
|
||||
} else {
|
||||
// Something new in ramdisk
|
||||
remv += rhs->first;
|
||||
remv += (char) '\0';
|
||||
fprintf(stderr, "Record new entry: [%s] -> [.backup/.rmlist]\n", rhs->first.data());
|
||||
}
|
||||
if (backup) {
|
||||
string back_name(".backup/");
|
||||
back_name += lhs->first;
|
||||
fprintf(stderr, "[%s] -> [%s]\n", lhs->first.data(), back_name.data());
|
||||
auto ex = static_cast<cpio_entry*>(lhs->second.release());
|
||||
ex->filename = back_name;
|
||||
bkup_entries[ex->filename].reset(ex);
|
||||
}
|
||||
|
||||
// Increment positions
|
||||
if (res < 0) {
|
||||
++lhs;
|
||||
} else if (res == 0) {
|
||||
++lhs; ++rhs;
|
||||
} else {
|
||||
++rhs;
|
||||
}
|
||||
}
|
||||
// Increment positions
|
||||
if (res < 0) {
|
||||
++lhs;
|
||||
} else if (res == 0) {
|
||||
++lhs; ++rhs;
|
||||
} else {
|
||||
++rhs;
|
||||
}
|
||||
}
|
||||
|
||||
if (!remv.empty()) {
|
||||
auto rmlist = new cpio_entry(".backup/.rmlist", S_IFREG);
|
||||
rmlist->filesize = remv.length();
|
||||
rmlist->data = xmalloc(remv.length());
|
||||
memcpy(rmlist->data, remv.data(), remv.length());
|
||||
bkup_entries[rmlist->filename].reset(rmlist);
|
||||
}
|
||||
if (!remv.empty()) {
|
||||
auto rmlist = new cpio_entry(".backup/.rmlist", S_IFREG);
|
||||
rmlist->filesize = remv.length();
|
||||
rmlist->data = xmalloc(remv.length());
|
||||
memcpy(rmlist->data, remv.data(), remv.length());
|
||||
bkup_entries[rmlist->filename].reset(rmlist);
|
||||
}
|
||||
|
||||
if (bkup_entries.size() > 1)
|
||||
entries.merge(bkup_entries);
|
||||
if (bkup_entries.size() > 1)
|
||||
entries.merge(bkup_entries);
|
||||
}
|
||||
|
||||
void magisk_cpio::compress() {
|
||||
if (exists(RAMDISK_XZ))
|
||||
return;
|
||||
fprintf(stderr, "Compressing cpio -> [%s]\n", RAMDISK_XZ);
|
||||
auto init = entries.extract("init");
|
||||
if (exists(RAMDISK_XZ))
|
||||
return;
|
||||
fprintf(stderr, "Compressing cpio -> [%s]\n", RAMDISK_XZ);
|
||||
auto init = entries.extract("init");
|
||||
|
||||
uint8_t *data;
|
||||
size_t len;
|
||||
auto strm = make_stream_fp(get_encoder(XZ, make_unique<byte_stream>(data, len)));
|
||||
dump(strm.release());
|
||||
uint8_t *data;
|
||||
size_t len;
|
||||
auto strm = make_stream_fp(get_encoder(XZ, make_unique<byte_stream>(data, len)));
|
||||
dump(strm.release());
|
||||
|
||||
entries.clear();
|
||||
entries.insert(std::move(init));
|
||||
auto xz = new cpio_entry(RAMDISK_XZ, S_IFREG);
|
||||
xz->data = data;
|
||||
xz->filesize = len;
|
||||
insert(xz);
|
||||
entries.clear();
|
||||
entries.insert(std::move(init));
|
||||
auto xz = new cpio_entry(RAMDISK_XZ, S_IFREG);
|
||||
xz->data = data;
|
||||
xz->filesize = len;
|
||||
insert(xz);
|
||||
}
|
||||
|
||||
void magisk_cpio::decompress() {
|
||||
auto it = entries.find(RAMDISK_XZ);
|
||||
if (it == entries.end())
|
||||
return;
|
||||
fprintf(stderr, "Decompressing cpio [%s]\n", RAMDISK_XZ);
|
||||
auto it = entries.find(RAMDISK_XZ);
|
||||
if (it == entries.end())
|
||||
return;
|
||||
fprintf(stderr, "Decompressing cpio [%s]\n", RAMDISK_XZ);
|
||||
|
||||
char *data;
|
||||
size_t len;
|
||||
{
|
||||
auto strm = get_decoder(XZ, make_unique<byte_stream>(data, len));
|
||||
strm->write(it->second->data, it->second->filesize);
|
||||
}
|
||||
char *data;
|
||||
size_t len;
|
||||
{
|
||||
auto strm = get_decoder(XZ, make_unique<byte_stream>(data, len));
|
||||
strm->write(it->second->data, it->second->filesize);
|
||||
}
|
||||
|
||||
entries.erase(it);
|
||||
load_cpio(data, len);
|
||||
free(data);
|
||||
entries.erase(it);
|
||||
load_cpio(data, len);
|
||||
free(data);
|
||||
}
|
||||
|
||||
int cpio_commands(int argc, char *argv[]) {
|
||||
char *incpio = argv[0];
|
||||
++argv;
|
||||
--argc;
|
||||
char *incpio = argv[0];
|
||||
++argv;
|
||||
--argc;
|
||||
|
||||
magisk_cpio cpio;
|
||||
if (access(incpio, R_OK) == 0)
|
||||
cpio.load_cpio(incpio);
|
||||
magisk_cpio cpio;
|
||||
if (access(incpio, R_OK) == 0)
|
||||
cpio.load_cpio(incpio);
|
||||
|
||||
int cmdc;
|
||||
char *cmdv[6];
|
||||
int cmdc;
|
||||
char *cmdv[6];
|
||||
|
||||
while (argc) {
|
||||
// Clean up
|
||||
cmdc = 0;
|
||||
memset(cmdv, NULL, sizeof(cmdv));
|
||||
while (argc) {
|
||||
// Clean up
|
||||
cmdc = 0;
|
||||
memset(cmdv, NULL, sizeof(cmdv));
|
||||
|
||||
// Split the commands
|
||||
for (char *tok = strtok(argv[0], " "); tok; tok = strtok(nullptr, " "))
|
||||
cmdv[cmdc++] = tok;
|
||||
// Split the commands
|
||||
for (char *tok = strtok(argv[0], " "); tok; tok = strtok(nullptr, " "))
|
||||
cmdv[cmdc++] = tok;
|
||||
|
||||
if (cmdc == 0)
|
||||
continue;
|
||||
if (cmdc == 0)
|
||||
continue;
|
||||
|
||||
if (strcmp(cmdv[0], "test") == 0) {
|
||||
exit(cpio.test());
|
||||
} else if (strcmp(cmdv[0], "restore") == 0) {
|
||||
cpio.restore();
|
||||
} else if (strcmp(cmdv[0], "sha1") == 0) {
|
||||
char *sha1 = cpio.sha1();
|
||||
if (sha1) printf("%s\n", sha1);
|
||||
return 0;
|
||||
} else if (strcmp(cmdv[0], "compress") == 0){
|
||||
cpio.compress();
|
||||
} else if (strcmp(cmdv[0], "decompress") == 0){
|
||||
cpio.decompress();
|
||||
} else if (strcmp(cmdv[0], "patch") == 0) {
|
||||
cpio.patch();
|
||||
} else if (cmdc == 2 && strcmp(cmdv[0], "exists") == 0) {
|
||||
exit(!cpio.exists(cmdv[1]));
|
||||
} else if (cmdc == 2 && strcmp(cmdv[0], "backup") == 0) {
|
||||
cpio.backup(cmdv[1]);
|
||||
} else if (cmdc >= 2 && strcmp(cmdv[0], "rm") == 0) {
|
||||
bool r = cmdc > 2 && strcmp(cmdv[1], "-r") == 0;
|
||||
cpio.rm(cmdv[1 + r], r);
|
||||
} else if (cmdc == 3 && strcmp(cmdv[0], "mv") == 0) {
|
||||
cpio.mv(cmdv[1], cmdv[2]);
|
||||
} else if (strcmp(cmdv[0], "extract") == 0) {
|
||||
if (cmdc == 3) {
|
||||
return !cpio.extract(cmdv[1], cmdv[2]);
|
||||
} else {
|
||||
cpio.extract();
|
||||
return 0;
|
||||
}
|
||||
} else if (cmdc == 3 && strcmp(cmdv[0], "mkdir") == 0) {
|
||||
cpio.mkdir(strtoul(cmdv[1], nullptr, 8), cmdv[2]);
|
||||
} else if (cmdc == 3 && strcmp(cmdv[0], "ln") == 0) {
|
||||
cpio.ln(cmdv[1], cmdv[2]);
|
||||
} else if (cmdc == 4 && strcmp(cmdv[0], "add") == 0) {
|
||||
cpio.add(strtoul(cmdv[1], nullptr, 8), cmdv[2], cmdv[3]);
|
||||
} else {
|
||||
return 1;
|
||||
}
|
||||
if (strcmp(cmdv[0], "test") == 0) {
|
||||
exit(cpio.test());
|
||||
} else if (strcmp(cmdv[0], "restore") == 0) {
|
||||
cpio.restore();
|
||||
} else if (strcmp(cmdv[0], "sha1") == 0) {
|
||||
char *sha1 = cpio.sha1();
|
||||
if (sha1) printf("%s\n", sha1);
|
||||
return 0;
|
||||
} else if (strcmp(cmdv[0], "compress") == 0){
|
||||
cpio.compress();
|
||||
} else if (strcmp(cmdv[0], "decompress") == 0){
|
||||
cpio.decompress();
|
||||
} else if (strcmp(cmdv[0], "patch") == 0) {
|
||||
cpio.patch();
|
||||
} else if (cmdc == 2 && strcmp(cmdv[0], "exists") == 0) {
|
||||
exit(!cpio.exists(cmdv[1]));
|
||||
} else if (cmdc == 2 && strcmp(cmdv[0], "backup") == 0) {
|
||||
cpio.backup(cmdv[1]);
|
||||
} else if (cmdc >= 2 && strcmp(cmdv[0], "rm") == 0) {
|
||||
bool r = cmdc > 2 && strcmp(cmdv[1], "-r") == 0;
|
||||
cpio.rm(cmdv[1 + r], r);
|
||||
} else if (cmdc == 3 && strcmp(cmdv[0], "mv") == 0) {
|
||||
cpio.mv(cmdv[1], cmdv[2]);
|
||||
} else if (strcmp(cmdv[0], "extract") == 0) {
|
||||
if (cmdc == 3) {
|
||||
return !cpio.extract(cmdv[1], cmdv[2]);
|
||||
} else {
|
||||
cpio.extract();
|
||||
return 0;
|
||||
}
|
||||
} else if (cmdc == 3 && strcmp(cmdv[0], "mkdir") == 0) {
|
||||
cpio.mkdir(strtoul(cmdv[1], nullptr, 8), cmdv[2]);
|
||||
} else if (cmdc == 3 && strcmp(cmdv[0], "ln") == 0) {
|
||||
cpio.ln(cmdv[1], cmdv[2]);
|
||||
} else if (cmdc == 4 && strcmp(cmdv[0], "add") == 0) {
|
||||
cpio.add(strtoul(cmdv[1], nullptr, 8), cmdv[2], cmdv[3]);
|
||||
} else {
|
||||
return 1;
|
||||
}
|
||||
|
||||
--argc;
|
||||
++argv;
|
||||
}
|
||||
--argc;
|
||||
++argv;
|
||||
}
|
||||
|
||||
cpio.dump(incpio);
|
||||
return 0;
|
||||
cpio.dump(incpio);
|
||||
return 0;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user