mirror of
https://github.com/topjohnwu/Magisk.git
synced 2024-12-25 12:57:39 +00:00
Fix unpacking vendor boot images
This commit is contained in:
parent
68ac409bfd
commit
aebf2672cd
@ -235,64 +235,69 @@ static format_t check_fmt_lg(uint8_t *buf, unsigned sz) {
|
|||||||
return fmt;
|
return fmt;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define get_block(name) {\
|
|
||||||
name = addr + off; \
|
|
||||||
off += hdr->name##_size(); \
|
|
||||||
off = do_align(off, hdr->page_size()); \
|
|
||||||
}
|
|
||||||
|
|
||||||
#define CMD_MATCH(s) BUFFER_MATCH(h->cmdline, s)
|
#define CMD_MATCH(s) BUFFER_MATCH(h->cmdline, s)
|
||||||
|
|
||||||
void boot_img::parse_image(uint8_t *addr, format_t type) {
|
dyn_img_hdr *boot_img::create_hdr(uint8_t *addr, format_t type) {
|
||||||
auto h = reinterpret_cast<boot_img_hdr_v0*>(addr);
|
|
||||||
if (type == AOSP_VENDOR) {
|
if (type == AOSP_VENDOR) {
|
||||||
fprintf(stderr, "VENDOR_BOOT_HDR\n");
|
fprintf(stderr, "VENDOR_BOOT_HDR\n");
|
||||||
|
auto h = reinterpret_cast<boot_img_hdr_vnd_v3*>(addr);
|
||||||
|
hdr_addr = addr;
|
||||||
switch (h->header_version) {
|
switch (h->header_version) {
|
||||||
case 4:
|
case 4:
|
||||||
hdr = new dyn_img_vnd_v4(addr);
|
return new dyn_img_vnd_v4(addr);
|
||||||
break;
|
|
||||||
case 3:
|
|
||||||
default:
|
default:
|
||||||
hdr = new dyn_img_vnd_v3(addr);
|
return new dyn_img_vnd_v3(addr);
|
||||||
break;
|
|
||||||
}
|
|
||||||
} else if (h->page_size >= 0x02000000) {
|
|
||||||
fprintf(stderr, "PXA_BOOT_HDR\n");
|
|
||||||
hdr = new dyn_img_pxa(addr);
|
|
||||||
} else {
|
|
||||||
if (CMD_MATCH(NOOKHD_RL_MAGIC) ||
|
|
||||||
CMD_MATCH(NOOKHD_GL_MAGIC) ||
|
|
||||||
CMD_MATCH(NOOKHD_GR_MAGIC) ||
|
|
||||||
CMD_MATCH(NOOKHD_EB_MAGIC) ||
|
|
||||||
CMD_MATCH(NOOKHD_ER_MAGIC)) {
|
|
||||||
flags[NOOKHD_FLAG] = true;
|
|
||||||
fprintf(stderr, "NOOKHD_LOADER\n");
|
|
||||||
addr += NOOKHD_PRE_HEADER_SZ;
|
|
||||||
} else if (memcmp(h->name, ACCLAIM_MAGIC, 10) == 0) {
|
|
||||||
flags[ACCLAIM_FLAG] = true;
|
|
||||||
fprintf(stderr, "ACCLAIM_LOADER\n");
|
|
||||||
addr += ACCLAIM_PRE_HEADER_SZ;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (h->header_version) {
|
|
||||||
case 1:
|
|
||||||
hdr = new dyn_img_v1(addr);
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
hdr = new dyn_img_v2(addr);
|
|
||||||
break;
|
|
||||||
case 3:
|
|
||||||
hdr = new dyn_img_v3(addr);
|
|
||||||
break;
|
|
||||||
case 4:
|
|
||||||
hdr = new dyn_img_v4(addr);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
hdr = new dyn_img_v0(addr);
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto h = reinterpret_cast<boot_img_hdr_v0*>(addr);
|
||||||
|
|
||||||
|
if (h->page_size >= 0x02000000) {
|
||||||
|
fprintf(stderr, "PXA_BOOT_HDR\n");
|
||||||
|
hdr_addr = addr;
|
||||||
|
return new dyn_img_pxa(addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (CMD_MATCH(NOOKHD_RL_MAGIC) ||
|
||||||
|
CMD_MATCH(NOOKHD_GL_MAGIC) ||
|
||||||
|
CMD_MATCH(NOOKHD_GR_MAGIC) ||
|
||||||
|
CMD_MATCH(NOOKHD_EB_MAGIC) ||
|
||||||
|
CMD_MATCH(NOOKHD_ER_MAGIC)) {
|
||||||
|
flags[NOOKHD_FLAG] = true;
|
||||||
|
fprintf(stderr, "NOOKHD_LOADER\n");
|
||||||
|
addr += NOOKHD_PRE_HEADER_SZ;
|
||||||
|
} else if (memcmp(h->name, ACCLAIM_MAGIC, 10) == 0) {
|
||||||
|
flags[ACCLAIM_FLAG] = true;
|
||||||
|
fprintf(stderr, "ACCLAIM_LOADER\n");
|
||||||
|
addr += ACCLAIM_PRE_HEADER_SZ;
|
||||||
|
}
|
||||||
|
|
||||||
|
// addr could be adjusted
|
||||||
|
h = reinterpret_cast<boot_img_hdr_v0*>(addr);
|
||||||
|
hdr_addr = addr;
|
||||||
|
|
||||||
|
switch (h->header_version) {
|
||||||
|
case 1:
|
||||||
|
return new dyn_img_v1(addr);
|
||||||
|
case 2:
|
||||||
|
return new dyn_img_v2(addr);
|
||||||
|
case 3:
|
||||||
|
return new dyn_img_v3(addr);
|
||||||
|
case 4:
|
||||||
|
return new dyn_img_v4(addr);
|
||||||
|
default:
|
||||||
|
return new dyn_img_v0(addr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#define get_block(name) \
|
||||||
|
name = hdr_addr + off; \
|
||||||
|
off += hdr->name##_size(); \
|
||||||
|
off = do_align(off, hdr->page_size());
|
||||||
|
|
||||||
|
void boot_img::parse_image(uint8_t *addr, format_t type) {
|
||||||
|
hdr = create_hdr(addr, type);
|
||||||
|
|
||||||
if (char *id = hdr->id()) {
|
if (char *id = hdr->id()) {
|
||||||
for (int i = SHA_DIGEST_SIZE + 4; i < SHA256_DIGEST_SIZE; ++i) {
|
for (int i = SHA_DIGEST_SIZE + 4; i < SHA256_DIGEST_SIZE; ++i) {
|
||||||
if (id[i]) {
|
if (id[i]) {
|
||||||
@ -305,7 +310,6 @@ void boot_img::parse_image(uint8_t *addr, format_t type) {
|
|||||||
hdr->print();
|
hdr->print();
|
||||||
|
|
||||||
size_t off = hdr->hdr_space();
|
size_t off = hdr->hdr_space();
|
||||||
hdr_addr = addr;
|
|
||||||
get_block(kernel);
|
get_block(kernel);
|
||||||
get_block(ramdisk);
|
get_block(ramdisk);
|
||||||
get_block(second);
|
get_block(second);
|
||||||
|
@ -151,7 +151,15 @@ struct boot_img_hdr_v0_common {
|
|||||||
|
|
||||||
struct boot_img_hdr_v0 : public boot_img_hdr_v0_common {
|
struct boot_img_hdr_v0 : public boot_img_hdr_v0_common {
|
||||||
uint32_t tags_addr; /* physical addr for kernel tags */
|
uint32_t tags_addr; /* physical addr for kernel tags */
|
||||||
uint32_t page_size; /* flash page size we assume */
|
|
||||||
|
// In AOSP headers, this field is used for page size.
|
||||||
|
// For Samsung PXA headers, the use of this field is unknown;
|
||||||
|
// however, its value is something unrealistic to be treated as page size.
|
||||||
|
// We use this fact to determine whether this is an AOSP or PXA header.
|
||||||
|
union {
|
||||||
|
uint32_t unknown;
|
||||||
|
uint32_t page_size; /* flash page size we assume */
|
||||||
|
};
|
||||||
|
|
||||||
// In header v1, this field is used for header version
|
// In header v1, this field is used for header version
|
||||||
// However, on some devices like Samsung, this field is used to store DTB
|
// However, on some devices like Samsung, this field is used to store DTB
|
||||||
@ -374,13 +382,10 @@ struct dyn_img_hdr {
|
|||||||
|
|
||||||
protected:
|
protected:
|
||||||
union {
|
union {
|
||||||
// Main header could be either AOSP or PXA
|
|
||||||
boot_img_hdr_v2 *v2_hdr; /* AOSP v2 header */
|
boot_img_hdr_v2 *v2_hdr; /* AOSP v2 header */
|
||||||
boot_img_hdr_v3 *v3_hdr; /* AOSP v3 header */
|
|
||||||
boot_img_hdr_v4 *v4_hdr; /* AOSP v4 header */
|
boot_img_hdr_v4 *v4_hdr; /* AOSP v4 header */
|
||||||
boot_img_hdr_pxa *hdr_pxa; /* Samsung PXA header */
|
|
||||||
boot_img_hdr_vnd_v3 *v3_vnd; /* AOSP vendor v3 header */
|
|
||||||
boot_img_hdr_vnd_v4 *v4_vnd; /* AOSP vendor v4 header */
|
boot_img_hdr_vnd_v4 *v4_vnd; /* AOSP vendor v4 header */
|
||||||
|
boot_img_hdr_pxa *hdr_pxa; /* Samsung PXA header */
|
||||||
void *raw; /* Raw pointer */
|
void *raw; /* Raw pointer */
|
||||||
};
|
};
|
||||||
dyn_img_hdr(bool b) : is_vendor(b) {}
|
dyn_img_hdr(bool b) : is_vendor(b) {}
|
||||||
@ -394,31 +399,33 @@ private:
|
|||||||
#undef decl_var
|
#undef decl_var
|
||||||
#undef decl_val
|
#undef decl_val
|
||||||
|
|
||||||
#define __impl_cls(name, hdr) \
|
#define __impl_cls(name, hdr) \
|
||||||
protected: name() = default; \
|
protected: name() = default; \
|
||||||
public: \
|
public: \
|
||||||
name(void *ptr) { \
|
name(void *ptr) { \
|
||||||
raw = xmalloc(sizeof(hdr)); \
|
raw = xmalloc(sizeof(hdr)); \
|
||||||
memcpy(raw, ptr, sizeof(hdr)); \
|
memcpy(raw, ptr, sizeof(hdr)); \
|
||||||
} \
|
} \
|
||||||
size_t hdr_size() override { return sizeof(hdr); } \
|
size_t hdr_size() override { \
|
||||||
dyn_img_hdr *clone() override { \
|
return sizeof(hdr); \
|
||||||
auto p = new name(this->raw); \
|
} \
|
||||||
|
dyn_img_hdr *clone() override { \
|
||||||
|
auto p = new name(raw); \
|
||||||
p->kernel_dt_size = kernel_dt_size; \
|
p->kernel_dt_size = kernel_dt_size; \
|
||||||
return p; \
|
return p; \
|
||||||
};
|
};
|
||||||
|
|
||||||
#define __impl_val(name, hdr_name) \
|
#define __impl_val(name, hdr_name) \
|
||||||
decltype(std::declval<dyn_img_hdr>().name()) name() override { return hdr_name->name; }
|
decltype(std::declval<dyn_img_hdr>().name()) name() override { return hdr_name->name; }
|
||||||
|
|
||||||
#define impl_cls(ver) __impl_cls(dyn_img_##ver, boot_img_hdr_##ver)
|
|
||||||
#define impl_val(name) __impl_val(name, v2_hdr)
|
|
||||||
|
|
||||||
struct dyn_img_hdr_boot : public dyn_img_hdr {
|
struct dyn_img_hdr_boot : public dyn_img_hdr {
|
||||||
protected:
|
protected:
|
||||||
dyn_img_hdr_boot() : dyn_img_hdr(false) {}
|
dyn_img_hdr_boot() : dyn_img_hdr(false) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define impl_cls(ver) __impl_cls(dyn_img_##ver, boot_img_hdr_##ver)
|
||||||
|
#define impl_val(name) __impl_val(name, v2_hdr)
|
||||||
|
|
||||||
struct dyn_img_common : public dyn_img_hdr_boot {
|
struct dyn_img_common : public dyn_img_hdr_boot {
|
||||||
impl_val(kernel_size)
|
impl_val(kernel_size)
|
||||||
impl_val(ramdisk_size)
|
impl_val(ramdisk_size)
|
||||||
@ -469,7 +476,7 @@ struct dyn_img_pxa : public dyn_img_common {
|
|||||||
};
|
};
|
||||||
|
|
||||||
#undef impl_val
|
#undef impl_val
|
||||||
#define impl_val(name) __impl_val(name, v3_hdr)
|
#define impl_val(name) __impl_val(name, v4_hdr)
|
||||||
|
|
||||||
struct dyn_img_v3 : public dyn_img_hdr_boot {
|
struct dyn_img_v3 : public dyn_img_hdr_boot {
|
||||||
impl_cls(v3)
|
impl_cls(v3)
|
||||||
@ -483,15 +490,12 @@ struct dyn_img_v3 : public dyn_img_hdr_boot {
|
|||||||
|
|
||||||
// Make API compatible
|
// Make API compatible
|
||||||
uint32_t &page_size() override { page_sz = 4096; return page_sz; }
|
uint32_t &page_size() override { page_sz = 4096; return page_sz; }
|
||||||
char *extra_cmdline() override { return &v3_hdr->cmdline[BOOT_ARGS_SIZE]; }
|
char *extra_cmdline() override { return &v4_hdr->cmdline[BOOT_ARGS_SIZE]; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
uint32_t page_sz = 4096;
|
uint32_t page_sz = 4096;
|
||||||
};
|
};
|
||||||
|
|
||||||
#undef impl_val
|
|
||||||
#define impl_val(name) __impl_val(name, v4_hdr)
|
|
||||||
|
|
||||||
struct dyn_img_v4 : public dyn_img_v3 {
|
struct dyn_img_v4 : public dyn_img_v3 {
|
||||||
impl_cls(v4)
|
impl_cls(v4)
|
||||||
};
|
};
|
||||||
@ -502,7 +506,7 @@ protected:
|
|||||||
};
|
};
|
||||||
|
|
||||||
#undef impl_val
|
#undef impl_val
|
||||||
#define impl_val(name) __impl_val(name, v3_vnd)
|
#define impl_val(name) __impl_val(name, v4_vnd)
|
||||||
|
|
||||||
struct dyn_img_vnd_v3 : public dyn_img_hdr_vendor {
|
struct dyn_img_vnd_v3 : public dyn_img_hdr_vendor {
|
||||||
impl_cls(vnd_v3)
|
impl_cls(vnd_v3)
|
||||||
@ -518,12 +522,9 @@ struct dyn_img_vnd_v3 : public dyn_img_hdr_vendor {
|
|||||||
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
|
// Make API compatible
|
||||||
char *extra_cmdline() override { return &v3_vnd->cmdline[BOOT_ARGS_SIZE]; }
|
char *extra_cmdline() override { return &v4_vnd->cmdline[BOOT_ARGS_SIZE]; }
|
||||||
};
|
};
|
||||||
|
|
||||||
#undef impl_val
|
|
||||||
#define impl_val(name) __impl_val(name, v4_vnd)
|
|
||||||
|
|
||||||
struct dyn_img_vnd_v4 : public dyn_img_vnd_v3 {
|
struct dyn_img_vnd_v4 : public dyn_img_vnd_v3 {
|
||||||
impl_cls(vnd_v4)
|
impl_cls(vnd_v4)
|
||||||
};
|
};
|
||||||
@ -616,4 +617,5 @@ struct boot_img {
|
|||||||
~boot_img();
|
~boot_img();
|
||||||
|
|
||||||
void parse_image(uint8_t *addr, format_t type);
|
void parse_image(uint8_t *addr, format_t type);
|
||||||
|
dyn_img_hdr *create_hdr(uint8_t *addr, format_t type);
|
||||||
};
|
};
|
||||||
|
Loading…
x
Reference in New Issue
Block a user