mirror of
https://github.com/topjohnwu/Magisk.git
synced 2024-12-25 00:57:48 +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;
|
||||
}
|
||||
|
||||
#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)
|
||||
|
||||
void boot_img::parse_image(uint8_t *addr, format_t type) {
|
||||
auto h = reinterpret_cast<boot_img_hdr_v0*>(addr);
|
||||
dyn_img_hdr *boot_img::create_hdr(uint8_t *addr, format_t type) {
|
||||
if (type == AOSP_VENDOR) {
|
||||
fprintf(stderr, "VENDOR_BOOT_HDR\n");
|
||||
auto h = reinterpret_cast<boot_img_hdr_vnd_v3*>(addr);
|
||||
hdr_addr = addr;
|
||||
switch (h->header_version) {
|
||||
case 4:
|
||||
hdr = new dyn_img_vnd_v4(addr);
|
||||
break;
|
||||
case 3:
|
||||
return new dyn_img_vnd_v4(addr);
|
||||
default:
|
||||
hdr = 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;
|
||||
return new dyn_img_vnd_v3(addr);
|
||||
}
|
||||
}
|
||||
|
||||
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()) {
|
||||
for (int i = SHA_DIGEST_SIZE + 4; i < SHA256_DIGEST_SIZE; ++i) {
|
||||
if (id[i]) {
|
||||
@ -305,7 +310,6 @@ void boot_img::parse_image(uint8_t *addr, format_t type) {
|
||||
hdr->print();
|
||||
|
||||
size_t off = hdr->hdr_space();
|
||||
hdr_addr = addr;
|
||||
get_block(kernel);
|
||||
get_block(ramdisk);
|
||||
get_block(second);
|
||||
|
@ -151,7 +151,15 @@ struct 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 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
|
||||
// However, on some devices like Samsung, this field is used to store DTB
|
||||
@ -374,13 +382,10 @@ struct dyn_img_hdr {
|
||||
|
||||
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_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_pxa *hdr_pxa; /* Samsung PXA header */
|
||||
void *raw; /* Raw pointer */
|
||||
};
|
||||
dyn_img_hdr(bool b) : is_vendor(b) {}
|
||||
@ -394,31 +399,33 @@ private:
|
||||
#undef decl_var
|
||||
#undef decl_val
|
||||
|
||||
#define __impl_cls(name, hdr) \
|
||||
protected: name() = default; \
|
||||
public: \
|
||||
name(void *ptr) { \
|
||||
raw = xmalloc(sizeof(hdr)); \
|
||||
memcpy(raw, ptr, sizeof(hdr)); \
|
||||
} \
|
||||
size_t hdr_size() override { return sizeof(hdr); } \
|
||||
dyn_img_hdr *clone() override { \
|
||||
auto p = new name(this->raw); \
|
||||
#define __impl_cls(name, hdr) \
|
||||
protected: name() = default; \
|
||||
public: \
|
||||
name(void *ptr) { \
|
||||
raw = xmalloc(sizeof(hdr)); \
|
||||
memcpy(raw, ptr, sizeof(hdr)); \
|
||||
} \
|
||||
size_t hdr_size() override { \
|
||||
return sizeof(hdr); \
|
||||
} \
|
||||
dyn_img_hdr *clone() override { \
|
||||
auto p = new name(raw); \
|
||||
p->kernel_dt_size = kernel_dt_size; \
|
||||
return p; \
|
||||
return p; \
|
||||
};
|
||||
|
||||
#define __impl_val(name, hdr_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 {
|
||||
protected:
|
||||
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 {
|
||||
impl_val(kernel_size)
|
||||
impl_val(ramdisk_size)
|
||||
@ -469,7 +476,7 @@ struct dyn_img_pxa : public dyn_img_common {
|
||||
};
|
||||
|
||||
#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 {
|
||||
impl_cls(v3)
|
||||
@ -483,15 +490,12 @@ struct dyn_img_v3 : public dyn_img_hdr_boot {
|
||||
|
||||
// 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]; }
|
||||
char *extra_cmdline() override { return &v4_hdr->cmdline[BOOT_ARGS_SIZE]; }
|
||||
|
||||
private:
|
||||
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 {
|
||||
impl_cls(v4)
|
||||
};
|
||||
@ -502,7 +506,7 @@ protected:
|
||||
};
|
||||
|
||||
#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 {
|
||||
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); }
|
||||
|
||||
// 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 {
|
||||
impl_cls(vnd_v4)
|
||||
};
|
||||
@ -616,4 +617,5 @@ struct boot_img {
|
||||
~boot_img();
|
||||
|
||||
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