mirror of
https://github.com/topjohnwu/Magisk.git
synced 2024-12-22 07:57:39 +00:00
Segment memory mapped boot image region
This commit is contained in:
parent
4caed73fe0
commit
c97ab690b6
@ -211,7 +211,7 @@ class byte_channel;
|
||||
struct heap_data : public byte_data {
|
||||
ALLOW_MOVE_ONLY(heap_data)
|
||||
|
||||
explicit heap_data(size_t sz) : byte_data(malloc(sz), sz) {}
|
||||
explicit heap_data(size_t sz) : byte_data(calloc(sz, 1), sz) {}
|
||||
~heap_data() { free(_buf); }
|
||||
|
||||
// byte_channel needs to reallocate the internal buffer
|
||||
|
@ -169,8 +169,9 @@ boot_img::boot_img(const char *image) : map(image) {
|
||||
break;
|
||||
case AOSP:
|
||||
case AOSP_VENDOR:
|
||||
parse_image(addr, fmt);
|
||||
if (parse_image(addr, fmt))
|
||||
return;
|
||||
// fallthrough
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@ -231,16 +232,16 @@ static format_t check_fmt_lg(const uint8_t *buf, unsigned sz) {
|
||||
|
||||
#define CMD_MATCH(s) BUFFER_MATCH(h->cmdline, s)
|
||||
|
||||
dyn_img_hdr *boot_img::create_hdr(const uint8_t *addr, format_t type) {
|
||||
const pair<const uint8_t *, dyn_img_hdr *>
|
||||
boot_img::create_hdr(const uint8_t *addr, format_t type) {
|
||||
if (type == AOSP_VENDOR) {
|
||||
fprintf(stderr, "VENDOR_BOOT_HDR\n");
|
||||
auto h = reinterpret_cast<const boot_img_hdr_vnd_v3*>(addr);
|
||||
hdr_addr = addr;
|
||||
switch (h->header_version) {
|
||||
case 4:
|
||||
return new dyn_img_vnd_v4(addr);
|
||||
return make_pair(addr, new dyn_img_vnd_v4(addr));
|
||||
default:
|
||||
return new dyn_img_vnd_v3(addr);
|
||||
return make_pair(addr, new dyn_img_vnd_v3(addr));
|
||||
}
|
||||
}
|
||||
|
||||
@ -248,12 +249,14 @@ dyn_img_hdr *boot_img::create_hdr(const uint8_t *addr, format_t type) {
|
||||
|
||||
if (h->page_size >= 0x02000000) {
|
||||
fprintf(stderr, "PXA_BOOT_HDR\n");
|
||||
hdr_addr = addr;
|
||||
return new dyn_img_pxa(addr);
|
||||
return make_pair(addr, new dyn_img_pxa(addr));
|
||||
}
|
||||
|
||||
auto make_hdr = [](const uint8_t *ptr) -> dyn_img_hdr * {
|
||||
auto h = reinterpret_cast<const boot_img_hdr_v0*>(ptr);
|
||||
if (memcmp(h->magic, BOOT_MAGIC, BOOT_MAGIC_SIZE) != 0)
|
||||
return nullptr;
|
||||
|
||||
switch (h->header_version) {
|
||||
case 1:
|
||||
return new dyn_img_v1(ptr);
|
||||
@ -278,12 +281,14 @@ dyn_img_hdr *boot_img::create_hdr(const uint8_t *addr, format_t type) {
|
||||
|
||||
// The real header is shifted, copy to temporary buffer
|
||||
h = reinterpret_cast<const boot_img_hdr_v0*>(addr + AMONET_MICROLOADER_SZ);
|
||||
auto real_hdr_sz = h->page_size - AMONET_MICROLOADER_SZ;
|
||||
auto buf = make_unique<uint8_t[]>(h->page_size);
|
||||
memcpy(buf.get(), h, real_hdr_sz);
|
||||
if (memcmp(h->magic, BOOT_MAGIC, BOOT_MAGIC_SIZE) != 0)
|
||||
return make_pair(addr, nullptr);
|
||||
|
||||
hdr_addr = addr;
|
||||
return make_hdr(buf.get());
|
||||
auto real_hdr_sz = h->page_size - AMONET_MICROLOADER_SZ;
|
||||
heap_data copy(h->page_size);
|
||||
memcpy(copy.buf(), h, real_hdr_sz);
|
||||
|
||||
return make_pair(addr, make_hdr(copy.buf()));
|
||||
}
|
||||
|
||||
if (CMD_MATCH(NOOKHD_RL_MAGIC) ||
|
||||
@ -301,26 +306,37 @@ dyn_img_hdr *boot_img::create_hdr(const uint8_t *addr, format_t type) {
|
||||
}
|
||||
|
||||
// addr could be adjusted
|
||||
hdr_addr = addr;
|
||||
return make_hdr(addr);
|
||||
return make_pair(addr, make_hdr(addr));
|
||||
}
|
||||
|
||||
#define assert_off() \
|
||||
if ((base_addr + off) > (map.buf() + map.sz())) { \
|
||||
fprintf(stderr, "Corrupted boot image!\n"); \
|
||||
return false; \
|
||||
}
|
||||
|
||||
#define get_block(name) \
|
||||
name = hdr_addr + off; \
|
||||
name = base_addr + off; \
|
||||
off += hdr->name##_size(); \
|
||||
off = align_to(off, hdr->page_size());
|
||||
off = align_to(off, hdr->page_size()); \
|
||||
assert_off();
|
||||
|
||||
#define get_ignore(name) \
|
||||
if (hdr->name##_size()) { \
|
||||
auto blk_sz = align_to(hdr->name##_size(), hdr->page_size()); \
|
||||
ignore_size += blk_sz; \
|
||||
off += blk_sz; \
|
||||
} \
|
||||
assert_off();
|
||||
|
||||
|
||||
bool boot_img::parse_image(const uint8_t *p, format_t type) {
|
||||
auto [base_addr, hdr] = create_hdr(p, type);
|
||||
if (hdr == nullptr) {
|
||||
fprintf(stderr, "Invalid boot image header!\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
void boot_img::parse_image(const uint8_t *addr, format_t type) {
|
||||
auto hdr = create_hdr(addr, type);
|
||||
|
||||
if (char *id = hdr->id()) {
|
||||
if (const char *id = hdr->id()) {
|
||||
for (int i = SHA_DIGEST_SIZE + 4; i < SHA256_DIGEST_SIZE; ++i) {
|
||||
if (id[i]) {
|
||||
flags[SHA256_FLAG] = true;
|
||||
@ -339,17 +355,21 @@ void boot_img::parse_image(const uint8_t *addr, format_t type) {
|
||||
get_block(recovery_dtbo);
|
||||
get_block(dtb);
|
||||
|
||||
ignore = hdr_addr + off;
|
||||
auto ignore_addr = base_addr + off;
|
||||
get_ignore(signature)
|
||||
get_ignore(vendor_ramdisk_table)
|
||||
get_ignore(bootconfig)
|
||||
|
||||
payload = byte_view(base_addr, off);
|
||||
auto tail_addr = base_addr + off;
|
||||
ignore = byte_view(ignore_addr, tail_addr - ignore_addr);
|
||||
tail = byte_view(tail_addr, map.buf() + map.sz() - tail_addr);
|
||||
|
||||
if (auto size = hdr->kernel_size()) {
|
||||
if (int dtb_off = find_dtb_offset(kernel, size); dtb_off > 0) {
|
||||
kernel_dtb = kernel + dtb_off;
|
||||
hdr->kernel_dt_size = size - dtb_off;
|
||||
kernel_dtb = byte_view(kernel + dtb_off, size - dtb_off);
|
||||
hdr->kernel_size() = dtb_off;
|
||||
fprintf(stderr, "%-*s [%u]\n", PADDING, "KERNEL_DTB_SZ", hdr->kernel_dt_size);
|
||||
fprintf(stderr, "%-*s [%zu]\n", PADDING, "KERNEL_DTB_SZ", kernel_dtb.sz());
|
||||
}
|
||||
|
||||
k_fmt = check_fmt_lg(kernel, hdr->kernel_size());
|
||||
@ -365,9 +385,9 @@ void boot_img::parse_image(const uint8_t *addr, format_t type) {
|
||||
}
|
||||
if (k_fmt == ZIMAGE) {
|
||||
z_hdr = reinterpret_cast<const zimage_hdr *>(kernel);
|
||||
if (void *gzip_offset = memmem(kernel, hdr->kernel_size(), GZIP1_MAGIC "\x08\x00", 4)) {
|
||||
if (const void *gzip = memmem(kernel, hdr->kernel_size(), GZIP1_MAGIC "\x08\x00", 4)) {
|
||||
fprintf(stderr, "ZIMAGE_KERNEL\n");
|
||||
z_info.hdr_sz = (uint8_t *) gzip_offset - kernel;
|
||||
z_info.hdr_sz = (const uint8_t *) gzip - kernel;
|
||||
|
||||
// Find end of piggy
|
||||
uint32_t zImage_size = z_hdr->end - z_hdr->start;
|
||||
@ -385,8 +405,7 @@ void boot_img::parse_image(const uint8_t *addr, format_t type) {
|
||||
fprintf(stderr, "! Could not find end of zImage piggy, keeping raw kernel\n");
|
||||
} else {
|
||||
flags[ZIMAGE_KERNEL] = true;
|
||||
z_info.tail = kernel + piggy_end;
|
||||
z_info.tail_sz = hdr->kernel_size() - piggy_end;
|
||||
z_info.tail = byte_view(kernel + piggy_end, hdr->kernel_size() - piggy_end);
|
||||
kernel += z_info.hdr_sz;
|
||||
hdr->kernel_size() = piggy_end - z_info.hdr_sz;
|
||||
k_fmt = check_fmt_lg(kernel, hdr->kernel_size());
|
||||
@ -422,25 +441,22 @@ void boot_img::parse_image(const uint8_t *addr, format_t type) {
|
||||
fprintf(stderr, "%-*s [%s]\n", PADDING, "EXTRA_FMT", fmt2name[e_fmt]);
|
||||
}
|
||||
|
||||
if (addr + off < map.buf() + map.sz()) {
|
||||
tail = addr + off;
|
||||
tail_size = map.buf() + map.sz() - tail;
|
||||
|
||||
if (tail.sz()) {
|
||||
// Check special flags
|
||||
if (tail_size >= 16 && BUFFER_MATCH(tail, SEANDROID_MAGIC)) {
|
||||
if (tail.sz() >= 16 && BUFFER_MATCH(tail.buf(), SEANDROID_MAGIC)) {
|
||||
fprintf(stderr, "SAMSUNG_SEANDROID\n");
|
||||
flags[SEANDROID_FLAG] = true;
|
||||
} else if (tail_size >= 16 && BUFFER_MATCH(tail, LG_BUMP_MAGIC)) {
|
||||
} else if (tail.sz() >= 16 && BUFFER_MATCH(tail.buf(), LG_BUMP_MAGIC)) {
|
||||
fprintf(stderr, "LG_BUMP_IMAGE\n");
|
||||
flags[LG_BUMP_FLAG] = true;
|
||||
}
|
||||
|
||||
// Find AVB footer
|
||||
const void *footer = tail + tail_size - sizeof(AvbFooter);
|
||||
const void *footer = tail.buf() + tail.sz() - sizeof(AvbFooter);
|
||||
if (BUFFER_MATCH(footer, AVB_FOOTER_MAGIC)) {
|
||||
avb_footer = reinterpret_cast<const AvbFooter*>(footer);
|
||||
// Double check if meta header exists
|
||||
const void *meta = hdr_addr + __builtin_bswap64(avb_footer->vbmeta_offset);
|
||||
const void *meta = base_addr + __builtin_bswap64(avb_footer->vbmeta_offset);
|
||||
if (BUFFER_MATCH(meta, AVB_MAGIC)) {
|
||||
fprintf(stderr, "VBMETA\n");
|
||||
flags[AVB_FLAG] = true;
|
||||
@ -450,6 +466,7 @@ void boot_img::parse_image(const uint8_t *addr, format_t type) {
|
||||
}
|
||||
|
||||
this->hdr = hdr;
|
||||
return true;
|
||||
}
|
||||
|
||||
int split_image_dtb(const char *filename) {
|
||||
@ -490,7 +507,7 @@ int unpack(const char *image, bool skip_decomp, bool hdr) {
|
||||
}
|
||||
|
||||
// Dump kernel_dtb
|
||||
dump(boot.kernel_dtb, boot.hdr->kernel_dt_size, KER_DTB_FILE);
|
||||
dump(boot.kernel_dtb.buf(), boot.kernel_dtb.sz(), KER_DTB_FILE);
|
||||
|
||||
// Dump ramdisk
|
||||
if (!skip_decomp && COMPRESSED(boot.r_fmt)) {
|
||||
@ -552,7 +569,6 @@ void repack(const char *src_img, const char *out_img, bool skip_comp) {
|
||||
hdr->ramdisk_size() = 0;
|
||||
hdr->second_size() = 0;
|
||||
hdr->dtb_size() = 0;
|
||||
hdr->kernel_dt_size = 0;
|
||||
|
||||
if (access(HEADER_FILE, R_OK) == 0)
|
||||
hdr->load_hdr_file();
|
||||
@ -577,7 +593,7 @@ void repack(const char *src_img, const char *out_img, bool skip_comp) {
|
||||
|
||||
// Copy raw header
|
||||
off.header = lseek(fd, 0, SEEK_CUR);
|
||||
xwrite(fd, boot.hdr_addr, hdr->hdr_space());
|
||||
xwrite(fd, boot.payload.buf(), hdr->hdr_space());
|
||||
|
||||
// kernel
|
||||
off.kernel = lseek(fd, 0, SEEK_CUR);
|
||||
@ -622,7 +638,7 @@ void repack(const char *src_img, const char *out_img, bool skip_comp) {
|
||||
if (boot.flags[ZIMAGE_KERNEL]) {
|
||||
// Copy zImage tail and adjust size accordingly
|
||||
hdr->kernel_size() += boot.z_info.hdr_sz;
|
||||
hdr->kernel_size() += xwrite(fd, boot.z_info.tail, boot.z_info.tail_sz);
|
||||
hdr->kernel_size() += xwrite(fd, boot.z_info.tail.buf(), boot.z_info.tail.sz());
|
||||
}
|
||||
|
||||
// kernel dtb
|
||||
@ -688,9 +704,9 @@ void repack(const char *src_img, const char *out_img, bool skip_comp) {
|
||||
}
|
||||
|
||||
// Directly copy ignored blobs
|
||||
if (boot.ignore_size) {
|
||||
// ignore_size should already be aligned
|
||||
xwrite(fd, boot.ignore, boot.ignore_size);
|
||||
if (boot.ignore.sz()) {
|
||||
// ignore.sz() should already be aligned
|
||||
xwrite(fd, boot.ignore.buf(), boot.ignore.sz());
|
||||
}
|
||||
|
||||
// Proprietary stuffs
|
||||
|
@ -365,7 +365,6 @@ struct dyn_img_hdr {
|
||||
decl_str(cmdline)
|
||||
decl_str(id)
|
||||
decl_str(extra_cmdline)
|
||||
uint32_t kernel_dt_size = 0;
|
||||
|
||||
// v1/v2 specific
|
||||
decl_var(recovery_dtbo_size, 32)
|
||||
@ -425,7 +424,6 @@ size_t hdr_size() const override { \
|
||||
} \
|
||||
dyn_img_hdr *clone() const override { \
|
||||
auto p = new name(raw); \
|
||||
p->kernel_dt_size = kernel_dt_size; \
|
||||
return p; \
|
||||
};
|
||||
|
||||
@ -604,6 +602,18 @@ struct boot_img {
|
||||
* Following pointers points within the read-only mmap region
|
||||
*************************************************************/
|
||||
|
||||
// Layout of the memory mapped region
|
||||
// +---------+
|
||||
// | head | Vendor specific. Should be empty for standard AOSP boot images.
|
||||
// +---------+
|
||||
// | payload | The actual boot image, including the AOSP boot image header.
|
||||
// +---------+
|
||||
// | tail | Data after payload. Usually contains signature/AVB information.
|
||||
// +---------+
|
||||
|
||||
byte_view payload;
|
||||
byte_view tail;
|
||||
|
||||
// MTK headers
|
||||
const mtk_hdr *k_hdr;
|
||||
const mtk_hdr *r_hdr;
|
||||
@ -614,28 +624,19 @@ struct boot_img {
|
||||
// +---------------+
|
||||
// | kernel | hdr->kernel_size()
|
||||
// +---------------+
|
||||
// | z_info.tail | z_info.tail_sz
|
||||
// | z_info.tail | z_info.tail.sz()
|
||||
// +---------------+
|
||||
const zimage_hdr *z_hdr;
|
||||
struct {
|
||||
uint32_t hdr_sz;
|
||||
uint32_t tail_sz = 0;
|
||||
const uint8_t *tail = nullptr;
|
||||
byte_view tail;
|
||||
} z_info;
|
||||
|
||||
// Pointer to dtb that is embedded in kernel
|
||||
const uint8_t *kernel_dtb;
|
||||
|
||||
// Pointer to end of image
|
||||
const uint8_t *tail;
|
||||
size_t tail_size = 0;
|
||||
|
||||
// AVB structs
|
||||
const AvbFooter *avb_footer;
|
||||
const AvbVBMetaImageHeader *vbmeta;
|
||||
|
||||
// Pointers to blocks defined in header
|
||||
const uint8_t *hdr_addr;
|
||||
const uint8_t *kernel;
|
||||
const uint8_t *ramdisk;
|
||||
const uint8_t *second;
|
||||
@ -643,13 +644,15 @@ struct boot_img {
|
||||
const uint8_t *recovery_dtbo;
|
||||
const uint8_t *dtb;
|
||||
|
||||
// Pointer to blocks defined in header, but we do not care
|
||||
const uint8_t *ignore;
|
||||
size_t ignore_size = 0;
|
||||
// dtb embedded in kernel
|
||||
byte_view kernel_dtb;
|
||||
|
||||
// Blocks defined in header but we do not care
|
||||
byte_view ignore;
|
||||
|
||||
boot_img(const char *);
|
||||
~boot_img();
|
||||
|
||||
void parse_image(const uint8_t *addr, format_t type);
|
||||
dyn_img_hdr *create_hdr(const uint8_t *addr, format_t type);
|
||||
bool parse_image(const uint8_t *addr, format_t type);
|
||||
const std::pair<const uint8_t *, dyn_img_hdr *> create_hdr(const uint8_t *addr, format_t type);
|
||||
};
|
||||
|
Loading…
x
Reference in New Issue
Block a user