mirror of
https://github.com/topjohnwu/Magisk.git
synced 2024-11-21 15:05:28 +00:00
parent
3b27de3715
commit
5ac7dc0b37
2
.gitignore
vendored
2
.gitignore
vendored
@ -13,7 +13,7 @@ native/out
|
|||||||
# Android Studio / Gradle
|
# Android Studio / Gradle
|
||||||
*.iml
|
*.iml
|
||||||
.gradle
|
.gradle
|
||||||
|
.idea
|
||||||
/local.properties
|
/local.properties
|
||||||
/.idea
|
|
||||||
/build
|
/build
|
||||||
/captures
|
/captures
|
||||||
|
@ -7,6 +7,7 @@ use cfg_if::cfg_if;
|
|||||||
use cxx::private::c_char;
|
use cxx::private::c_char;
|
||||||
use libc::mode_t;
|
use libc::mode_t;
|
||||||
|
|
||||||
|
use crate::files::map_file_at;
|
||||||
pub(crate) use crate::xwrap::*;
|
pub(crate) use crate::xwrap::*;
|
||||||
use crate::{
|
use crate::{
|
||||||
clone_attr, cstr, fclone_attr, fd_path, map_fd, map_file, slice_from_ptr, CxxResultExt,
|
clone_attr, cstr, fclone_attr, fd_path, map_fd, map_file, slice_from_ptr, CxxResultExt,
|
||||||
@ -61,6 +62,14 @@ pub(crate) fn map_file_for_cxx(path: &Utf8CStr, rw: bool) -> &'static mut [u8] {
|
|||||||
map_file(path, rw).log_cxx().unwrap_or(&mut [])
|
map_file(path, rw).log_cxx().unwrap_or(&mut [])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) fn map_file_at_for_cxx(fd: RawFd, path: &Utf8CStr, rw: bool) -> &'static mut [u8] {
|
||||||
|
unsafe {
|
||||||
|
map_file_at(BorrowedFd::borrow_raw(fd), path, rw)
|
||||||
|
.log_cxx()
|
||||||
|
.unwrap_or(&mut [])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub(crate) fn map_fd_for_cxx(fd: RawFd, sz: usize, rw: bool) -> &'static mut [u8] {
|
pub(crate) fn map_fd_for_cxx(fd: RawFd, sz: usize, rw: bool) -> &'static mut [u8] {
|
||||||
unsafe {
|
unsafe {
|
||||||
map_fd(BorrowedFd::borrow_raw(fd), sz, rw)
|
map_fd(BorrowedFd::borrow_raw(fd), sz, rw)
|
||||||
|
@ -117,6 +117,14 @@ mmap_data::mmap_data(const char *name, bool rw) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mmap_data::mmap_data(int dirfd, const char *name, bool rw) {
|
||||||
|
auto slice = rust::map_file_at(dirfd, name, rw);
|
||||||
|
if (!slice.empty()) {
|
||||||
|
_buf = slice.data();
|
||||||
|
_sz = slice.size();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
mmap_data::mmap_data(int fd, size_t sz, bool rw) {
|
mmap_data::mmap_data(int fd, size_t sz, bool rw) {
|
||||||
auto slice = rust::map_fd(fd, sz, rw);
|
auto slice = rust::map_fd(fd, sz, rw);
|
||||||
if (!slice.empty()) {
|
if (!slice.empty()) {
|
||||||
|
@ -26,6 +26,7 @@ struct mmap_data : public byte_data {
|
|||||||
ALLOW_MOVE_ONLY(mmap_data)
|
ALLOW_MOVE_ONLY(mmap_data)
|
||||||
|
|
||||||
explicit mmap_data(const char *name, bool rw = false);
|
explicit mmap_data(const char *name, bool rw = false);
|
||||||
|
mmap_data(int dirfd, const char *name, bool rw = false);
|
||||||
mmap_data(int fd, size_t sz, bool rw = false);
|
mmap_data(int fd, size_t sz, bool rw = false);
|
||||||
~mmap_data();
|
~mmap_data();
|
||||||
};
|
};
|
||||||
|
@ -856,6 +856,14 @@ impl MappedFile {
|
|||||||
Ok(MappedFile(map_file(path, true)?))
|
Ok(MappedFile(map_file(path, true)?))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn openat<T: AsFd>(dir: &T, path: &Utf8CStr) -> io::Result<MappedFile> {
|
||||||
|
Ok(MappedFile(map_file_at(dir.as_fd(), path, false)?))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn openat_rw<T: AsFd>(dir: &T, path: &Utf8CStr) -> io::Result<MappedFile> {
|
||||||
|
Ok(MappedFile(map_file_at(dir.as_fd(), path, true)?))
|
||||||
|
}
|
||||||
|
|
||||||
pub fn create(fd: BorrowedFd, sz: usize, rw: bool) -> io::Result<MappedFile> {
|
pub fn create(fd: BorrowedFd, sz: usize, rw: bool) -> io::Result<MappedFile> {
|
||||||
Ok(MappedFile(map_fd(fd, sz, rw)?))
|
Ok(MappedFile(map_fd(fd, sz, rw)?))
|
||||||
}
|
}
|
||||||
@ -888,6 +896,14 @@ extern "C" {
|
|||||||
|
|
||||||
// We mark the returned slice static because it is valid until explicitly unmapped
|
// We mark the returned slice static because it is valid until explicitly unmapped
|
||||||
pub(crate) fn map_file(path: &Utf8CStr, rw: bool) -> io::Result<&'static mut [u8]> {
|
pub(crate) fn map_file(path: &Utf8CStr, rw: bool) -> io::Result<&'static mut [u8]> {
|
||||||
|
unsafe { map_file_at(BorrowedFd::borrow_raw(libc::AT_FDCWD), path, rw) }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn map_file_at(
|
||||||
|
dirfd: BorrowedFd,
|
||||||
|
path: &Utf8CStr,
|
||||||
|
rw: bool,
|
||||||
|
) -> io::Result<&'static mut [u8]> {
|
||||||
#[cfg(target_pointer_width = "64")]
|
#[cfg(target_pointer_width = "64")]
|
||||||
const BLKGETSIZE64: u32 = 0x80081272;
|
const BLKGETSIZE64: u32 = 0x80081272;
|
||||||
|
|
||||||
@ -895,18 +911,22 @@ pub(crate) fn map_file(path: &Utf8CStr, rw: bool) -> io::Result<&'static mut [u8
|
|||||||
const BLKGETSIZE64: u32 = 0x80041272;
|
const BLKGETSIZE64: u32 = 0x80041272;
|
||||||
|
|
||||||
let flag = if rw { O_RDWR } else { O_RDONLY };
|
let flag = if rw { O_RDWR } else { O_RDONLY };
|
||||||
let file = FsPath::from(path).open(flag | O_CLOEXEC)?;
|
let fd = unsafe {
|
||||||
|
OwnedFd::from_raw_fd(
|
||||||
|
libc::openat(dirfd.as_raw_fd(), path.as_ptr(), flag | O_CLOEXEC).check_os_err()?,
|
||||||
|
)
|
||||||
|
};
|
||||||
|
|
||||||
let attr = fd_get_attr(file.as_raw_fd())?;
|
let attr = fd_get_attr(fd.as_raw_fd())?;
|
||||||
let sz = if attr.is_block_device() {
|
let sz = if attr.is_block_device() {
|
||||||
let mut sz = 0_u64;
|
let mut sz = 0_u64;
|
||||||
unsafe { ioctl(file.as_raw_fd(), BLKGETSIZE64, &mut sz) }.as_os_err()?;
|
unsafe { ioctl(fd.as_raw_fd(), BLKGETSIZE64, &mut sz) }.as_os_err()?;
|
||||||
sz
|
sz
|
||||||
} else {
|
} else {
|
||||||
attr.st.st_size as u64
|
attr.st.st_size as u64
|
||||||
};
|
};
|
||||||
|
|
||||||
map_fd(file.as_fd(), sz as usize, rw)
|
map_fd(fd.as_fd(), sz as usize, rw)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn map_fd(fd: BorrowedFd, sz: usize, rw: bool) -> io::Result<&'static mut [u8]> {
|
pub(crate) fn map_fd(fd: BorrowedFd, sz: usize, rw: bool) -> io::Result<&'static mut [u8]> {
|
||||||
|
@ -61,6 +61,8 @@ pub mod ffi {
|
|||||||
fn fd_path_for_cxx(fd: i32, buf: &mut [u8]) -> isize;
|
fn fd_path_for_cxx(fd: i32, buf: &mut [u8]) -> isize;
|
||||||
#[cxx_name = "map_file"]
|
#[cxx_name = "map_file"]
|
||||||
fn map_file_for_cxx(path: Utf8CStrRef, rw: bool) -> &'static mut [u8];
|
fn map_file_for_cxx(path: Utf8CStrRef, rw: bool) -> &'static mut [u8];
|
||||||
|
#[cxx_name = "map_file_at"]
|
||||||
|
fn map_file_at_for_cxx(fd: i32, path: Utf8CStrRef, rw: bool) -> &'static mut [u8];
|
||||||
#[cxx_name = "map_fd"]
|
#[cxx_name = "map_fd"]
|
||||||
fn map_fd_for_cxx(fd: i32, sz: usize, rw: bool) -> &'static mut [u8];
|
fn map_fd_for_cxx(fd: i32, sz: usize, rw: bool) -> &'static mut [u8];
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
#include <bit>
|
#include <bit>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
#include <span>
|
||||||
|
|
||||||
#include <base.hpp>
|
#include <base.hpp>
|
||||||
|
|
||||||
@ -61,6 +62,8 @@ void dyn_img_hdr::print() const {
|
|||||||
fprintf(stderr, "%-*s [%u]\n", PADDING, "RECOV_DTBO_SZ", recovery_dtbo_size());
|
fprintf(stderr, "%-*s [%u]\n", PADDING, "RECOV_DTBO_SZ", recovery_dtbo_size());
|
||||||
if (ver == 2 || is_vendor())
|
if (ver == 2 || is_vendor())
|
||||||
fprintf(stderr, "%-*s [%u]\n", PADDING, "DTB_SZ", dtb_size());
|
fprintf(stderr, "%-*s [%u]\n", PADDING, "DTB_SZ", dtb_size());
|
||||||
|
if (ver == 4 && is_vendor())
|
||||||
|
fprintf(stderr, "%-*s [%u]\n", PADDING, "BOOTCONFIG_SZ", bootconfig_size());
|
||||||
|
|
||||||
if (uint32_t os_ver = os_version()) {
|
if (uint32_t os_ver = os_version()) {
|
||||||
int a,b,c,y,m = 0;
|
int a,b,c,y,m = 0;
|
||||||
@ -273,8 +276,7 @@ static format_t check_fmt_lg(const uint8_t *buf, unsigned sz) {
|
|||||||
|
|
||||||
#define CMD_MATCH(s) BUFFER_MATCH(h->cmdline, s)
|
#define CMD_MATCH(s) BUFFER_MATCH(h->cmdline, s)
|
||||||
|
|
||||||
const pair<const uint8_t *, dyn_img_hdr *>
|
pair<const uint8_t *, dyn_img_hdr *> boot_img::create_hdr(const uint8_t *addr, format_t type) {
|
||||||
boot_img::create_hdr(const uint8_t *addr, format_t type) {
|
|
||||||
if (type == AOSP_VENDOR) {
|
if (type == AOSP_VENDOR) {
|
||||||
fprintf(stderr, "VENDOR_BOOT_HDR\n");
|
fprintf(stderr, "VENDOR_BOOT_HDR\n");
|
||||||
auto h = reinterpret_cast<const boot_img_hdr_vnd_v3*>(addr);
|
auto h = reinterpret_cast<const boot_img_hdr_vnd_v3*>(addr);
|
||||||
@ -346,10 +348,23 @@ const pair<const uint8_t *, dyn_img_hdr *>
|
|||||||
addr += ACCLAIM_PRE_HEADER_SZ;
|
addr += ACCLAIM_PRE_HEADER_SZ;
|
||||||
}
|
}
|
||||||
|
|
||||||
// addr could be adjusted
|
|
||||||
return make_pair(addr, make_hdr(addr));
|
return make_pair(addr, make_hdr(addr));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static const char *vendor_ramdisk_type(int type) {
|
||||||
|
switch (type) {
|
||||||
|
case VENDOR_RAMDISK_TYPE_PLATFORM:
|
||||||
|
return "platform";
|
||||||
|
case VENDOR_RAMDISK_TYPE_RECOVERY:
|
||||||
|
return "recovery";
|
||||||
|
case VENDOR_RAMDISK_TYPE_DLKM:
|
||||||
|
return "dlkm";
|
||||||
|
case VENDOR_RAMDISK_TYPE_NONE:
|
||||||
|
default:
|
||||||
|
return "none";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#define assert_off() \
|
#define assert_off() \
|
||||||
if ((base_addr + off) > (map.buf() + map.sz())) { \
|
if ((base_addr + off) > (map.buf() + map.sz())) { \
|
||||||
fprintf(stderr, "Corrupted boot image!\n"); \
|
fprintf(stderr, "Corrupted boot image!\n"); \
|
||||||
@ -362,14 +377,6 @@ off += hdr->name##_size(); \
|
|||||||
off = align_to(off, hdr->page_size()); \
|
off = align_to(off, hdr->page_size()); \
|
||||||
assert_off();
|
assert_off();
|
||||||
|
|
||||||
#define get_ignore(name) \
|
|
||||||
if (hdr->name##_size()) { \
|
|
||||||
auto blk_sz = align_to(hdr->name##_size(), hdr->page_size()); \
|
|
||||||
off += blk_sz; \
|
|
||||||
} \
|
|
||||||
assert_off();
|
|
||||||
|
|
||||||
|
|
||||||
bool boot_img::parse_image(const uint8_t *p, format_t type) {
|
bool boot_img::parse_image(const uint8_t *p, format_t type) {
|
||||||
auto [base_addr, hdr] = create_hdr(p, type);
|
auto [base_addr, hdr] = create_hdr(p, type);
|
||||||
if (hdr == nullptr) {
|
if (hdr == nullptr) {
|
||||||
@ -395,15 +402,12 @@ bool boot_img::parse_image(const uint8_t *p, format_t type) {
|
|||||||
get_block(extra);
|
get_block(extra);
|
||||||
get_block(recovery_dtbo);
|
get_block(recovery_dtbo);
|
||||||
get_block(dtb);
|
get_block(dtb);
|
||||||
|
get_block(signature);
|
||||||
auto ignore_addr = base_addr + off;
|
get_block(vendor_ramdisk_table);
|
||||||
get_ignore(signature)
|
get_block(bootconfig);
|
||||||
get_ignore(vendor_ramdisk_table)
|
|
||||||
get_ignore(bootconfig)
|
|
||||||
|
|
||||||
payload = byte_view(base_addr, off);
|
payload = byte_view(base_addr, off);
|
||||||
auto tail_addr = 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);
|
tail = byte_view(tail_addr, map.buf() + map.sz() - tail_addr);
|
||||||
|
|
||||||
if (auto size = hdr->kernel_size()) {
|
if (auto size = hdr->kernel_size()) {
|
||||||
@ -458,13 +462,28 @@ bool boot_img::parse_image(const uint8_t *p, format_t type) {
|
|||||||
fprintf(stderr, "%-*s [%s]\n", PADDING, "KERNEL_FMT", fmt2name[k_fmt]);
|
fprintf(stderr, "%-*s [%s]\n", PADDING, "KERNEL_FMT", fmt2name[k_fmt]);
|
||||||
}
|
}
|
||||||
if (auto size = hdr->ramdisk_size()) {
|
if (auto size = hdr->ramdisk_size()) {
|
||||||
if (hdr->is_vendor() && hdr->header_version() >= 4) {
|
if (vendor_ramdisk_table != nullptr) {
|
||||||
// v4 vendor boot contains multiple ramdisks
|
// v4 vendor boot contains multiple ramdisks
|
||||||
// Do not try to mess with it for now
|
using table_entry = const vendor_ramdisk_table_entry_v4;
|
||||||
r_fmt = UNKNOWN;
|
if (hdr->vendor_ramdisk_table_entry_size() != sizeof(table_entry)) {
|
||||||
|
fprintf(stderr,
|
||||||
|
"! Invalid vendor image: vendor_ramdisk_table_entry_size != %zu\n",
|
||||||
|
sizeof(table_entry));
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
span<table_entry> table(
|
||||||
|
reinterpret_cast<table_entry *>(vendor_ramdisk_table),
|
||||||
|
hdr->vendor_ramdisk_table_entry_num());
|
||||||
|
for (auto &it : table) {
|
||||||
|
format_t fmt = check_fmt_lg(ramdisk + it.ramdisk_offset, it.ramdisk_size);
|
||||||
|
fprintf(stderr,
|
||||||
|
"%-*s name=[%s] type=[%s] size=[%u] fmt=[%s]\n", PADDING, "VND_RAMDISK",
|
||||||
|
it.ramdisk_name, vendor_ramdisk_type(it.ramdisk_type),
|
||||||
|
it.ramdisk_size, fmt2name[fmt]);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
r_fmt = check_fmt_lg(ramdisk, size);
|
r_fmt = check_fmt_lg(ramdisk, size);
|
||||||
}
|
|
||||||
if (r_fmt == MTK) {
|
if (r_fmt == MTK) {
|
||||||
fprintf(stderr, "MTK_RAMDISK_HDR\n");
|
fprintf(stderr, "MTK_RAMDISK_HDR\n");
|
||||||
flags[MTK_RAMDISK] = true;
|
flags[MTK_RAMDISK] = true;
|
||||||
@ -477,6 +496,7 @@ bool boot_img::parse_image(const uint8_t *p, format_t type) {
|
|||||||
}
|
}
|
||||||
fprintf(stderr, "%-*s [%s]\n", PADDING, "RAMDISK_FMT", fmt2name[r_fmt]);
|
fprintf(stderr, "%-*s [%s]\n", PADDING, "RAMDISK_FMT", fmt2name[r_fmt]);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if (auto size = hdr->extra_size()) {
|
if (auto size = hdr->extra_size()) {
|
||||||
e_fmt = check_fmt_lg(extra, size);
|
e_fmt = check_fmt_lg(extra, size);
|
||||||
fprintf(stderr, "%-*s [%s]\n", PADDING, "EXTRA_FMT", fmt2name[e_fmt]);
|
fprintf(stderr, "%-*s [%s]\n", PADDING, "EXTRA_FMT", fmt2name[e_fmt]);
|
||||||
@ -561,7 +581,30 @@ int unpack(const char *image, bool skip_decomp, bool hdr) {
|
|||||||
dump(boot.kernel_dtb.buf(), boot.kernel_dtb.sz(), KER_DTB_FILE);
|
dump(boot.kernel_dtb.buf(), boot.kernel_dtb.sz(), KER_DTB_FILE);
|
||||||
|
|
||||||
// Dump ramdisk
|
// Dump ramdisk
|
||||||
if (!skip_decomp && COMPRESSED(boot.r_fmt)) {
|
if (boot.vendor_ramdisk_table != nullptr) {
|
||||||
|
using table_entry = const vendor_ramdisk_table_entry_v4;
|
||||||
|
span<table_entry> table(
|
||||||
|
reinterpret_cast<table_entry *>(boot.vendor_ramdisk_table),
|
||||||
|
boot.hdr->vendor_ramdisk_table_entry_num());
|
||||||
|
|
||||||
|
xmkdir(VND_RAMDISK_DIR, 0755);
|
||||||
|
owned_fd dirfd = xopen(VND_RAMDISK_DIR, O_RDONLY | O_CLOEXEC);
|
||||||
|
for (auto &it : table) {
|
||||||
|
char file_name[40];
|
||||||
|
if (it.ramdisk_name[0] == '\0') {
|
||||||
|
strscpy(file_name, RAMDISK_FILE, sizeof(file_name));
|
||||||
|
} else {
|
||||||
|
ssprintf(file_name, sizeof(file_name), "%s.cpio", it.ramdisk_name);
|
||||||
|
}
|
||||||
|
owned_fd fd = xopenat(dirfd, file_name, O_CREAT | O_TRUNC | O_WRONLY | O_CLOEXEC, 0644);
|
||||||
|
format_t fmt = check_fmt_lg(boot.ramdisk + it.ramdisk_offset, it.ramdisk_size);
|
||||||
|
if (!skip_decomp && COMPRESSED(fmt)) {
|
||||||
|
decompress(fmt, fd, boot.ramdisk + it.ramdisk_offset, it.ramdisk_size);
|
||||||
|
} else {
|
||||||
|
xwrite(fd, boot.ramdisk + it.ramdisk_offset, it.ramdisk_size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (!skip_decomp && COMPRESSED(boot.r_fmt)) {
|
||||||
if (boot.hdr->ramdisk_size() != 0) {
|
if (boot.hdr->ramdisk_size() != 0) {
|
||||||
int fd = creat(RAMDISK_FILE, 0644);
|
int fd = creat(RAMDISK_FILE, 0644);
|
||||||
decompress(boot.r_fmt, fd, boot.ramdisk, boot.hdr->ramdisk_size());
|
decompress(boot.r_fmt, fd, boot.ramdisk, boot.hdr->ramdisk_size());
|
||||||
@ -591,6 +634,9 @@ int unpack(const char *image, bool skip_decomp, bool hdr) {
|
|||||||
// Dump dtb
|
// Dump dtb
|
||||||
dump(boot.dtb, boot.hdr->dtb_size(), DTB_FILE);
|
dump(boot.dtb, boot.hdr->dtb_size(), DTB_FILE);
|
||||||
|
|
||||||
|
// Dump bootconfig
|
||||||
|
dump(boot.bootconfig, boot.hdr->bootconfig_size(), BOOTCONFIG_FILE);
|
||||||
|
|
||||||
return boot.flags[CHROMEOS_FLAG] ? 2 : 0;
|
return boot.flags[CHROMEOS_FLAG] ? 2 : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -620,6 +666,7 @@ void repack(const char *src_img, const char *out_img, bool skip_comp) {
|
|||||||
hdr->ramdisk_size() = 0;
|
hdr->ramdisk_size() = 0;
|
||||||
hdr->second_size() = 0;
|
hdr->second_size() = 0;
|
||||||
hdr->dtb_size() = 0;
|
hdr->dtb_size() = 0;
|
||||||
|
hdr->bootconfig_size() = 0;
|
||||||
|
|
||||||
if (access(HEADER_FILE, R_OK) == 0)
|
if (access(HEADER_FILE, R_OK) == 0)
|
||||||
hdr->load_hdr_file();
|
hdr->load_hdr_file();
|
||||||
@ -703,7 +750,40 @@ void repack(const char *src_img, const char *out_img, bool skip_comp) {
|
|||||||
// Copy MTK headers
|
// Copy MTK headers
|
||||||
xwrite(fd, boot.r_hdr, sizeof(mtk_hdr));
|
xwrite(fd, boot.r_hdr, sizeof(mtk_hdr));
|
||||||
}
|
}
|
||||||
if (access(RAMDISK_FILE, R_OK) == 0) {
|
|
||||||
|
using table_entry = vendor_ramdisk_table_entry_v4;
|
||||||
|
vector<table_entry> ramdisk_table;
|
||||||
|
|
||||||
|
if (boot.vendor_ramdisk_table) {
|
||||||
|
// Create a copy so we can modify it
|
||||||
|
auto entry_start = reinterpret_cast<const table_entry *>(boot.vendor_ramdisk_table);
|
||||||
|
ramdisk_table.insert(
|
||||||
|
ramdisk_table.begin(),
|
||||||
|
entry_start, entry_start + boot.hdr->vendor_ramdisk_table_entry_num());
|
||||||
|
|
||||||
|
owned_fd dirfd = xopen(VND_RAMDISK_DIR, O_RDONLY | O_CLOEXEC);
|
||||||
|
uint32_t ramdisk_offset = 0;
|
||||||
|
for (auto &it : ramdisk_table) {
|
||||||
|
char file_name[64];
|
||||||
|
if (it.ramdisk_name[0] == '\0') {
|
||||||
|
strscpy(file_name, RAMDISK_FILE, sizeof(file_name));
|
||||||
|
} else {
|
||||||
|
ssprintf(file_name, sizeof(file_name), "%s.cpio", it.ramdisk_name);
|
||||||
|
}
|
||||||
|
mmap_data m(dirfd, file_name);
|
||||||
|
format_t fmt = check_fmt_lg(boot.ramdisk + it.ramdisk_offset, it.ramdisk_size);
|
||||||
|
it.ramdisk_offset = ramdisk_offset;
|
||||||
|
if (!skip_comp && !COMPRESSED_ANY(check_fmt(m.buf(), m.sz())) && COMPRESSED(fmt)) {
|
||||||
|
it.ramdisk_size = compress(fmt, fd, m.buf(), m.sz());
|
||||||
|
} else {
|
||||||
|
it.ramdisk_size = xwrite(fd, m.buf(), m.sz());
|
||||||
|
}
|
||||||
|
ramdisk_offset += it.ramdisk_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
hdr->ramdisk_size() = ramdisk_offset;
|
||||||
|
file_align();
|
||||||
|
} else if (access(RAMDISK_FILE, R_OK) == 0) {
|
||||||
mmap_data m(RAMDISK_FILE);
|
mmap_data m(RAMDISK_FILE);
|
||||||
auto r_fmt = boot.r_fmt;
|
auto r_fmt = boot.r_fmt;
|
||||||
if (!skip_comp && !hdr->is_vendor() && hdr->header_version() == 4 && r_fmt != LZ4_LEGACY) {
|
if (!skip_comp && !hdr->is_vendor() && hdr->header_version() == 4 && r_fmt != LZ4_LEGACY) {
|
||||||
@ -754,10 +834,22 @@ void repack(const char *src_img, const char *out_img, bool skip_comp) {
|
|||||||
file_align();
|
file_align();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Directly copy ignored blobs
|
// Copy boot signature
|
||||||
if (boot.ignore.sz()) {
|
if (boot.hdr->signature_size()) {
|
||||||
// ignore.sz() should already be aligned
|
xwrite(fd, boot.signature, boot.hdr->signature_size());
|
||||||
xwrite(fd, boot.ignore.buf(), boot.ignore.sz());
|
file_align();
|
||||||
|
}
|
||||||
|
|
||||||
|
// vendor ramdisk table
|
||||||
|
if (!ramdisk_table.empty()) {
|
||||||
|
xwrite(fd, ramdisk_table.data(), sizeof(table_entry) * ramdisk_table.size());
|
||||||
|
file_align();
|
||||||
|
}
|
||||||
|
|
||||||
|
// bootconfig
|
||||||
|
if (access(BOOTCONFIG_FILE, R_OK) == 0) {
|
||||||
|
hdr->bootconfig_size() = restore(fd, BOOTCONFIG_FILE);
|
||||||
|
file_align();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Proprietary stuffs
|
// Proprietary stuffs
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <cstdint>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
#include <bitset>
|
#include <bitset>
|
||||||
#include <cxx.h>
|
#include <cxx.h>
|
||||||
@ -111,15 +111,21 @@ struct AvbVBMetaImageHeader {
|
|||||||
#define VENDOR_RAMDISK_NAME_SIZE 32
|
#define VENDOR_RAMDISK_NAME_SIZE 32
|
||||||
#define VENDOR_RAMDISK_TABLE_ENTRY_BOARD_ID_SIZE 16
|
#define VENDOR_RAMDISK_TABLE_ENTRY_BOARD_ID_SIZE 16
|
||||||
|
|
||||||
/* When the boot image header has a version of 0 - 2, the structure of the boot
|
#define VENDOR_RAMDISK_TYPE_NONE 0
|
||||||
|
#define VENDOR_RAMDISK_TYPE_PLATFORM 1
|
||||||
|
#define VENDOR_RAMDISK_TYPE_RECOVERY 2
|
||||||
|
#define VENDOR_RAMDISK_TYPE_DLKM 3
|
||||||
|
|
||||||
|
/*
|
||||||
|
* When the boot image header has a version of 0 - 2, the structure of the boot
|
||||||
* image is as follows:
|
* image is as follows:
|
||||||
*
|
*
|
||||||
* +-----------------+
|
* +-----------------+
|
||||||
* | boot header | 1 page
|
* | boot header | 1 page
|
||||||
* +-----------------+
|
* +-----------------+
|
||||||
* | kernel | n pages
|
* | kernel | m pages
|
||||||
* +-----------------+
|
* +-----------------+
|
||||||
* | ramdisk | m pages
|
* | ramdisk | n pages
|
||||||
* +-----------------+
|
* +-----------------+
|
||||||
* | second stage | o pages
|
* | second stage | o pages
|
||||||
* +-----------------+
|
* +-----------------+
|
||||||
@ -130,8 +136,8 @@ struct AvbVBMetaImageHeader {
|
|||||||
* | dtb | q pages
|
* | dtb | q pages
|
||||||
* +-----------------+
|
* +-----------------+
|
||||||
*
|
*
|
||||||
* n = (kernel_size + page_size - 1) / page_size
|
* m = (kernel_size + page_size - 1) / page_size
|
||||||
* m = (ramdisk_size + page_size - 1) / page_size
|
* n = (ramdisk_size + page_size - 1) / page_size
|
||||||
* o = (second_size + page_size - 1) / page_size
|
* o = (second_size + page_size - 1) / page_size
|
||||||
* p = (recovery_dtbo_size + page_size - 1) / page_size
|
* p = (recovery_dtbo_size + page_size - 1) / page_size
|
||||||
* q = (dtb_size + page_size - 1) / page_size
|
* q = (dtb_size + page_size - 1) / page_size
|
||||||
@ -211,7 +217,8 @@ struct boot_img_hdr_pxa : public boot_img_hdr_v0_common {
|
|||||||
char extra_cmdline[BOOT_EXTRA_ARGS_SIZE];
|
char extra_cmdline[BOOT_EXTRA_ARGS_SIZE];
|
||||||
} __attribute__((packed));
|
} __attribute__((packed));
|
||||||
|
|
||||||
/* When the boot image header has a version of 3 - 4, the structure of the boot
|
/*
|
||||||
|
* When the boot image header has a version of 3 - 4, the structure of the boot
|
||||||
* image is as follows:
|
* image is as follows:
|
||||||
*
|
*
|
||||||
* +---------------------+
|
* +---------------------+
|
||||||
@ -329,7 +336,7 @@ struct vendor_ramdisk_table_entry_v4 {
|
|||||||
uint32_t ramdisk_size; /* size in bytes for the ramdisk image */
|
uint32_t ramdisk_size; /* size in bytes for the ramdisk image */
|
||||||
uint32_t ramdisk_offset; /* offset to the ramdisk image in vendor ramdisk section */
|
uint32_t ramdisk_offset; /* offset to the ramdisk image in vendor ramdisk section */
|
||||||
uint32_t ramdisk_type; /* type of the ramdisk */
|
uint32_t ramdisk_type; /* type of the ramdisk */
|
||||||
uint8_t ramdisk_name[VENDOR_RAMDISK_NAME_SIZE]; /* asciiz ramdisk name */
|
char ramdisk_name[VENDOR_RAMDISK_NAME_SIZE]; /* asciiz ramdisk name */
|
||||||
|
|
||||||
// Hardware identifiers describing the board, soc or platform which this
|
// Hardware identifiers describing the board, soc or platform which this
|
||||||
// ramdisk is intended to be loaded on.
|
// ramdisk is intended to be loaded on.
|
||||||
@ -376,8 +383,12 @@ struct dyn_img_hdr {
|
|||||||
|
|
||||||
// v4 specific
|
// v4 specific
|
||||||
decl_val(signature_size, 32)
|
decl_val(signature_size, 32)
|
||||||
|
|
||||||
|
// v4 vendor specific
|
||||||
decl_val(vendor_ramdisk_table_size, 32)
|
decl_val(vendor_ramdisk_table_size, 32)
|
||||||
decl_val(bootconfig_size, 32)
|
decl_val(vendor_ramdisk_table_entry_num, 32)
|
||||||
|
decl_val(vendor_ramdisk_table_entry_size, 32)
|
||||||
|
decl_var(bootconfig_size, 32)
|
||||||
|
|
||||||
virtual ~dyn_img_hdr() {
|
virtual ~dyn_img_hdr() {
|
||||||
free(raw);
|
free(raw);
|
||||||
@ -554,7 +565,9 @@ struct dyn_img_vnd_v4 : public dyn_img_vnd_v3 {
|
|||||||
impl_cls(vnd_v4)
|
impl_cls(vnd_v4)
|
||||||
|
|
||||||
impl_val(vendor_ramdisk_table_size)
|
impl_val(vendor_ramdisk_table_size)
|
||||||
impl_val(bootconfig_size)
|
impl_val(vendor_ramdisk_table_entry_num)
|
||||||
|
impl_val(vendor_ramdisk_table_entry_size)
|
||||||
|
impl_var(bootconfig_size)
|
||||||
};
|
};
|
||||||
|
|
||||||
#undef __impl_cls
|
#undef __impl_cls
|
||||||
@ -591,7 +604,7 @@ struct boot_img {
|
|||||||
const mmap_data map;
|
const mmap_data map;
|
||||||
|
|
||||||
// Android image header
|
// Android image header
|
||||||
const dyn_img_hdr *hdr;
|
const dyn_img_hdr *hdr = nullptr;
|
||||||
|
|
||||||
// Flags to indicate the state of current boot image
|
// Flags to indicate the state of current boot image
|
||||||
std::bitset<BOOT_FLAGS_MAX> flags;
|
std::bitset<BOOT_FLAGS_MAX> flags;
|
||||||
@ -607,9 +620,9 @@ struct boot_img {
|
|||||||
|
|
||||||
// Layout of the memory mapped region
|
// Layout of the memory mapped region
|
||||||
// +---------+
|
// +---------+
|
||||||
// | head | Vendor specific. Should be empty for standard AOSP boot images.
|
// | head | Vendor specific. Should not exist for standard AOSP boot images.
|
||||||
// +---------+
|
// +---------+
|
||||||
// | payload | The actual boot image, including the AOSP boot image header.
|
// | payload | The actual entire AOSP boot image, including the boot image header.
|
||||||
// +---------+
|
// +---------+
|
||||||
// | tail | Data after payload. Usually contains signature/AVB information.
|
// | tail | Data after payload. Usually contains signature/AVB information.
|
||||||
// +---------+
|
// +---------+
|
||||||
@ -618,8 +631,8 @@ struct boot_img {
|
|||||||
byte_view tail;
|
byte_view tail;
|
||||||
|
|
||||||
// MTK headers
|
// MTK headers
|
||||||
const mtk_hdr *k_hdr;
|
const mtk_hdr *k_hdr = nullptr;
|
||||||
const mtk_hdr *r_hdr;
|
const mtk_hdr *r_hdr = nullptr;
|
||||||
|
|
||||||
// The pointers/values after parse_image
|
// The pointers/values after parse_image
|
||||||
// +---------------+
|
// +---------------+
|
||||||
@ -629,23 +642,26 @@ struct boot_img {
|
|||||||
// +---------------+
|
// +---------------+
|
||||||
// | z_info.tail | z_info.tail.sz()
|
// | z_info.tail | z_info.tail.sz()
|
||||||
// +---------------+
|
// +---------------+
|
||||||
const zimage_hdr *z_hdr;
|
const zimage_hdr *z_hdr = nullptr;
|
||||||
struct {
|
struct {
|
||||||
uint32_t hdr_sz;
|
uint32_t hdr_sz;
|
||||||
byte_view tail;
|
byte_view tail;
|
||||||
} z_info;
|
} z_info;
|
||||||
|
|
||||||
// AVB structs
|
// AVB structs
|
||||||
const AvbFooter *avb_footer;
|
const AvbFooter *avb_footer = nullptr;
|
||||||
const AvbVBMetaImageHeader *vbmeta;
|
const AvbVBMetaImageHeader *vbmeta = nullptr;
|
||||||
|
|
||||||
// Pointers to blocks defined in header
|
// Pointers to blocks defined in header
|
||||||
const uint8_t *kernel;
|
const uint8_t *kernel = nullptr;
|
||||||
const uint8_t *ramdisk;
|
const uint8_t *ramdisk = nullptr;
|
||||||
const uint8_t *second;
|
const uint8_t *second = nullptr;
|
||||||
const uint8_t *extra;
|
const uint8_t *extra = nullptr;
|
||||||
const uint8_t *recovery_dtbo;
|
const uint8_t *recovery_dtbo = nullptr;
|
||||||
const uint8_t *dtb;
|
const uint8_t *dtb = nullptr;
|
||||||
|
const uint8_t *signature = nullptr;
|
||||||
|
const uint8_t *vendor_ramdisk_table = nullptr;
|
||||||
|
const uint8_t *bootconfig = nullptr;
|
||||||
|
|
||||||
// dtb embedded in kernel
|
// dtb embedded in kernel
|
||||||
byte_view kernel_dtb;
|
byte_view kernel_dtb;
|
||||||
@ -657,7 +673,7 @@ struct boot_img {
|
|||||||
~boot_img();
|
~boot_img();
|
||||||
|
|
||||||
bool parse_image(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);
|
std::pair<const uint8_t *, dyn_img_hdr *> create_hdr(const uint8_t *addr, format_t type);
|
||||||
|
|
||||||
// Rust FFI
|
// Rust FFI
|
||||||
rust::Slice<const uint8_t> get_payload() const { return payload; }
|
rust::Slice<const uint8_t> get_payload() const { return payload; }
|
||||||
|
@ -7,11 +7,13 @@
|
|||||||
#define HEADER_FILE "header"
|
#define HEADER_FILE "header"
|
||||||
#define KERNEL_FILE "kernel"
|
#define KERNEL_FILE "kernel"
|
||||||
#define RAMDISK_FILE "ramdisk.cpio"
|
#define RAMDISK_FILE "ramdisk.cpio"
|
||||||
|
#define VND_RAMDISK_DIR "vendor_ramdisk"
|
||||||
#define SECOND_FILE "second"
|
#define SECOND_FILE "second"
|
||||||
#define EXTRA_FILE "extra"
|
#define EXTRA_FILE "extra"
|
||||||
#define KER_DTB_FILE "kernel_dtb"
|
#define KER_DTB_FILE "kernel_dtb"
|
||||||
#define RECV_DTBO_FILE "recovery_dtbo"
|
#define RECV_DTBO_FILE "recovery_dtbo"
|
||||||
#define DTB_FILE "dtb"
|
#define DTB_FILE "dtb"
|
||||||
|
#define BOOTCONFIG_FILE "bootconfig"
|
||||||
#define NEW_BOOT "new-boot.img"
|
#define NEW_BOOT "new-boot.img"
|
||||||
|
|
||||||
int unpack(const char *image, bool skip_decomp = false, bool hdr = false);
|
int unpack(const char *image, bool skip_decomp = false, bool hdr = false);
|
||||||
|
Loading…
Reference in New Issue
Block a user