Move bootimg injecting to the lib, trampoline now has --inject=boot.img

This commit is contained in:
Vojtech Bocek
2015-02-26 15:30:18 +01:00
parent 1887f526e7
commit 959b76d08a
11 changed files with 312 additions and 238 deletions

View File

@@ -109,3 +109,15 @@ ifeq ($(MR_CONTINUOUS_FB_UPDATE),true)
endif
LOCAL_CFLAGS += -DPLATFORM_SDK_VERSION=$(PLATFORM_SDK_VERSION)
ifeq ($(MR_USE_MROM_FSTAB),true)
LOCAL_CFLAGS += -DMR_USE_MROM_FSTAB
endif
ifeq ($(MR_ENCRYPTION),true)
LOCAL_CFLAGS += -DMR_ENCRYPTION
endif
ifneq ($(MR_RD_ADDR),)
LOCAL_CFLAGS += -DMR_RD_ADDR=$(MR_RD_ADDR)
endif

View File

@@ -59,8 +59,6 @@ $(MULTIROM_ZIP_TARGET): multirom trampoline fw_mounter signapk bbootimg mrom_kex
cp -a $(TARGET_OUT_OPTIONAL_EXECUTABLES)/bbootimg $(MULTIROM_INST_DIR)/scripts/
cp $(PWD)/$(MR_FSTAB) $(MULTIROM_INST_DIR)/multirom/mrom.fstab
$(install_zip_path)/extract_boot_dev.sh $(PWD)/$(MR_FSTAB) $(MULTIROM_INST_DIR)/scripts/bootdev
echo $(MR_RD_ADDR) > $(MULTIROM_INST_DIR)/scripts/rd_addr
echo "$(MR_USE_MROM_FSTAB)" > $(MULTIROM_INST_DIR)/scripts/use_mrom_fstab
$(install_zip_path)/make_updater_script.sh $(TARGET_DEVICE) $(MULTIROM_INST_DIR)/META-INF/com/google/android "Installing MultiROM for"
rm -f $(MULTIROM_ZIP_TARGET).zip $(MULTIROM_ZIP_TARGET)-unsigned.zip
cd $(MULTIROM_INST_DIR) && zip -qr ../$(notdir $@)-unsigned.zip *

View File

@@ -1,105 +1,10 @@
#!/sbin/sh
BUSYBOX="/tmp/multirom/busybox"
LZ4="/tmp/multirom/lz4"
BOOT_DEV="$(cat /tmp/bootdev)"
RD_ADDR="$(cat /tmp/rd_addr)"
USE_MROM_FSTAB="$(cat /tmp/use_mrom_fstab)"
CMPR_GZIP=0
CMPR_LZ4=1
if [ ! -e "$BOOT_DEV" ]; then
echo "BOOT_DEV \"$BOOT_DEV\" does not exist!"
return 1
fi
dd if=$BOOT_DEV of=/tmp/boot.img
/tmp/bbootimg -x /tmp/boot.img /tmp/bootimg.cfg /tmp/zImage /tmp/initrd.img /tmp/second.img /tmp/dtb.img
if [ ! -f /tmp/zImage ] ; then
echo "Failed to extract boot.img"
return 1
fi
rm -r /tmp/boot
mkdir /tmp/boot
cd /tmp/boot
rd_cmpr=-1
magic=$($BUSYBOX hexdump -n 4 -v -e '/1 "%02X"' "../initrd.img")
case "$magic" in
1F8B*) # GZIP
$BUSYBOX gzip -d -c "../initrd.img" | $BUSYBOX cpio -i
rd_cmpr=CMPR_GZIP;
;;
02214C18) # LZ4
$LZ4 -d "../initrd.img" stdout | $BUSYBOX cpio -i
rd_cmpr=CMPR_LZ4;
;;
*)
echo "invalid ramdisk magic $magic"
;;
esac
if [ rd_cmpr == -1 ] || [ ! -f /tmp/boot/init ] ; then
echo "Failed to extract ramdisk!"
return 1
fi
# copy trampoline
if [ ! -e /tmp/boot/main_init ] ; then
mv /tmp/boot/init /tmp/boot/main_init
fi
cp /tmp/multirom/trampoline /tmp/boot/init
chmod 750 /tmp/boot/init
# create ueventd and watchdogd symlink
# older versions were changing these to ../main_init, we need to change it back
if [ -L /tmp/boot/sbin/ueventd ] ; then
ln -sf ../init /tmp/boot/sbin/ueventd
fi
if [ -L /tmp/boot/sbin/watchdogd ] ; then
ln -sf ../init /tmp/boot/sbin/watchdogd
fi
# copy MultiROM's fstab if needed, remove old one if disabled
if [ "$USE_MROM_FSTAB" == "true" ]; then
echo "Using MultiROM's fstab"
cp /tmp/multirom/mrom.fstab /tmp/boot/mrom.fstab
elif [ -e /tmp/boot/mrom.fstab ] ; then
rm /tmp/boot/mrom.fstab
fi
# pack the image again
cd /tmp/boot
case $rd_cmpr in
CMPR_GZIP)
find . | $BUSYBOX cpio -o -H newc | $BUSYBOX gzip > "../initrd.img"
;;
CMPR_LZ4)
find . | $BUSYBOX cpio -o -H newc | $LZ4 stdin "../initrd.img"
;;
esac
echo "bootsize = 0x0" >> /tmp/bootimg.cfg
if [ -n "$RD_ADDR" ]; then
echo "Using ramdisk addr $RD_ADDR"
echo "ramdiskaddr = $RD_ADDR" >> /tmp/bootimg.cfg
fi
cd /tmp
dtb_cmd=""
if [ -f "dtb.img" ]; then
dtb_cmd="-d dtb.img"
fi
/tmp/bbootimg --create newboot.img -f bootimg.cfg -k zImage -r initrd.img $dtb_cmd
if [ ! -e "/tmp/newboot.img" ] ; then
echo "Failed to inject boot.img!"
return 1
fi
echo "Writing new boot.img..."
dd bs=4096 if=/tmp/newboot.img of=$BOOT_DEV
/tmp/multirom/trampoline --inject="$BOOT_DEV" --mrom_dir="/tmp_multirom" -f
return $?

View File

@@ -10,6 +10,7 @@ common_SRC_FILES := \
framebuffer_png.c \
framebuffer_truetype.c \
fstab.c \
inject.c \
input.c \
listview.c \
keyboard.c \
@@ -24,7 +25,8 @@ common_SRC_FILES := \
common_C_INCLUDES := $(multirom_local_path)/lib \
external/libpng \
external/zlib \
external/freetype/include
external/freetype/include \
system/extras/libbootimg/include \
# With these, GCC optimizes aggressively enough so full-screen alpha blending
# is quick enough to be done in an animation

232
lib/inject.c Normal file
View File

@@ -0,0 +1,232 @@
/*
* This file is part of MultiROM.
*
* MultiROM is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* MultiROM is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with MultiROM. If not, see <http://www.gnu.org/licenses/>.
*/
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdint.h>
#include <stdio.h>
#include "inject.h"
#include "mrom_data.h"
#include "log.h"
#include "util.h"
#include "../version.h"
// clone libbootimg to /system/extras/ from
// https://github.com/Tasssadar/libbootimg.git
#include <libbootimg.h>
#if LIBBOOTIMG_VERSION < 0x000200
#error "libbootimg version 0.2.0 or higher is required. Please update libbootimg."
#endif
#define TMP_RD_UNPACKED_DIR "/mrom_rd"
static int get_img_trampoline_ver(struct bootimg *img)
{
int ver = 0;
if(strncmp((char*)img->hdr.name, "tr_ver", 6) == 0)
ver = atoi((char*)img->hdr.name + 6);
return ver;
}
static int copy_rd_files(const char *path, const char *busybox_path)
{
char buf[256];
if (access(TMP_RD_UNPACKED_DIR"/main_init", F_OK) < 0 &&
rename(TMP_RD_UNPACKED_DIR"/init", TMP_RD_UNPACKED_DIR"/main_init") < 0)
{
ERROR("Failed to move /init to /main_init!");
return -1;
}
snprintf(buf, sizeof(buf), "%s/trampoline", mrom_dir());
if(copy_file(buf, TMP_RD_UNPACKED_DIR"/init") < 0)
{
ERROR("Failed to copy trampoline to /init!");
return -1;
}
chmod(TMP_RD_UNPACKED_DIR"/init", 0750);
#ifdef MR_USE_MROM_FSTAB
snprintf(buf, "%s/mrom.fstab", mrom_dir());
copy_file(buf, TMP_RD_UNPACKED_DIR"/mrom.fstab");
#else
remove(TMP_RD_UNPACKED_DIR"/mrom.fstab");
#endif
#ifdef MR_ENCRYPTION
remove_dir(TMP_RD_UNPACKED_DIR"/mrom_enc");
char *cmd[] = { busybox_path, "sh", "-c", buf, NULL };
snprintf(buf, sizeof(buf), "\"%s\" cp -a \"%s/enc\" \"%s/mrom_enc\"", busybox_path, mrom_dir(), TMP_RD_UNPACKED_DIR);
if(run_cmd(cmd) != 0)
{
ERROR("Failed to copy encryption files!");
return -1;
}
#endif
return 0;
}
#define RD_GZIP 1
#define RD_LZ4 2
static int inject_rd(const char *path)
{
int result = -1;
uint32_t magic = 0;
FILE *f = fopen(path, "r");
if(!f)
{
ERROR("Couldn't open %s!\n", path);
return -1;
}
fread(&magic, sizeof(magic), 1, f);
fclose(f);
remove_dir(TMP_RD_UNPACKED_DIR);
mkdir(TMP_RD_UNPACKED_DIR, 0755);
// Decompress initrd
int type;
char buff[256];
char busybox_path[256];
snprintf(busybox_path, sizeof(busybox_path), "%s/busybox", mrom_dir());
char *cmd[] = { busybox_path, "sh", "-c", buff, NULL };
if((magic & 0xFFFF) == 0x8B1F)
{
type = RD_GZIP;
snprintf(buff, sizeof(buff), "B=\"%s\"; cd \"%s\"; \"$B\" gzip -d -c \"%s\" | \"$B\" cpio -i", busybox_path, TMP_RD_UNPACKED_DIR, path);
}
else if(magic == 0x184C2102)
{
type = RD_LZ4;
snprintf(buff, sizeof(buff), "cd \"%s\"; \"%s/lz4\" -d \"%s\" stdout | \"%s\" cpio -i", TMP_RD_UNPACKED_DIR, mrom_dir(), path, busybox_path);
}
else
{
ERROR("Unknown ramdisk magic 0x%08X, can't update trampoline\n", magic);
goto success;
}
int r = run_cmd(cmd);
if(r != 0)
{
ERROR("Failed to unpack ramdisk!\n");
goto fail;
}
// Update files
if(copy_rd_files(path, busybox_path) < 0)
goto fail;
// Pack initrd again
switch(type)
{
case RD_GZIP:
snprintf(buff, sizeof(buff), "B=\"%s\"; cd \"%s\"; \"$B\" find . | \"$B\" cpio -o -H newc | \"$B\" gzip > \"%s\"", busybox_path, TMP_RD_UNPACKED_DIR, path);
break;
case RD_LZ4:
snprintf(buff, sizeof(buff), "B=\"%s\"; cd \"%s\"; \"$B\" find . | \"$B\" cpio -o -H newc | \"%s/lz4\" stdin \"%s\"", busybox_path, TMP_RD_UNPACKED_DIR, mrom_dir(), path);
break;
}
r = run_cmd(cmd);
if(r != 0)
{
ERROR("Failed to pack ramdisk!\n");
goto fail;
}
success:
result = 0;
fail:
remove_dir(TMP_RD_UNPACKED_DIR);
return result;
}
int inject_bootimg(const char *img_path, int force)
{
int res = -1;
struct bootimg img;
int img_ver;
char initrd_path[256];
static const char *initrd_tmp_name = "/inject-initrd.img";
if(libbootimg_init_load(&img, img_path, LIBBOOTIMG_LOAD_ALL) < 0)
{
ERROR("Could not open boot image (%s)!", img_path);
return -1;
}
img_ver = get_img_trampoline_ver(&img);
if(!force && img_ver >= VERSION_TRAMPOLINE)
{
INFO("No need to update trampoline.");
res = 0;
goto exit;
}
INFO("Updating trampoline from ver %d to %d", img_ver, VERSION_TRAMPOLINE);
if(libbootimg_dump_ramdisk(&img, initrd_tmp_name) < 0)
{
ERROR("Failed to dump ramdisk to %s!", initrd_path);
goto exit;
}
if(inject_rd(initrd_tmp_name) >= 0)
{
// Update the boot.img
snprintf((char*)img.hdr.name, BOOT_NAME_SIZE, "tr_ver%d", VERSION_TRAMPOLINE);
#ifdef MR_RD_ADDR
img.hdr.ramdisk_addr = MR_RD_ADDR;
#endif
if(libbootimg_load_ramdisk(&img, initrd_tmp_name) < 0)
{
ERROR("Failed to load ramdisk from %s!", initrd_tmp_name);
goto exit;
}
char tmp[256];
strcpy(tmp, img_path);
strcat(tmp, ".new");
if(libbootimg_write_img(&img, tmp) >= 0)
{
INFO("Writing boot.img updated with trampoline v%d\n", VERSION_TRAMPOLINE);
if(copy_file(tmp, img_path) < 0)
ERROR("Failed to copy %s to %s!", tmp, img_path);
else
res = 0;
remove(tmp);
}
else
ERROR("Failed to libbootimg_write_img!");
}
exit:
libbootimg_destroy(&img);
remove("/inject-initrd.img");
return res;
}

23
lib/inject.h Normal file
View File

@@ -0,0 +1,23 @@
/*
* This file is part of MultiROM.
*
* MultiROM is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* MultiROM is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with MultiROM. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef INJECT_H
#define INJECT_H
int inject_bootimg(const char *img_path, int force);
#endif

View File

@@ -633,6 +633,11 @@ char *strtoupper(const char *str)
return res;
}
int strstartswith(const char *haystack, const char *needle)
{
return strncmp(haystack, needle, strlen(needle)) == 0;
}
int create_loop_device(const char *dev_path, const char *img_path, int loop_num, int loop_chmod)
{
int file_fd, device_fd, res = -1;

View File

@@ -33,6 +33,7 @@ int make_link(const char *oldpath, const char *newpath);
void remove_link(const char *oldpath, const char *newpath);
int wait_for_file(const char *filename, int timeout);
int copy_file(const char *from, const char *to);
int copy_dir(const char *from, const char *to);
int mkdir_with_perms(const char *path, mode_t mode, const char *owner, const char *group);
int write_file(const char *path, const char *value);
int remove_dir(const char *dir);
@@ -55,5 +56,6 @@ inline int in_rect(int x, int y, int rx, int ry, int rw, int rh);
inline void *mzalloc(size_t size); // alloc and fill with 0s
char *strtoupper(const char *str);
int strstartswith(const char *haystack, const char *needle);
#endif

View File

@@ -39,6 +39,7 @@
#include "lib/containers.h"
#include "lib/framebuffer.h"
#include "lib/inject.h"
#include "lib/input.h"
#include "lib/log.h"
#include "lib/util.h"
@@ -1669,6 +1670,14 @@ int multirom_fill_kexec_android(struct multirom_status *s, struct multirom_rom *
char img_path[256];
sprintf(img_path, "%s/boot.img", rom->base_path);
// Trampolines in ROM boot images may get out of sync, so we need to check it and
// update if needed. I can't do that during ZIP installation because of USB drives.
if(inject_bootimg(img_path, 0) < 0)
{
ERROR("Failed to inject bootimg!");
return -1;
}
struct bootimg img;
if(libbootimg_init_load(&img, img_path, LIBBOOTIMG_LOAD_ALL) < 0)
{
@@ -1692,36 +1701,6 @@ int multirom_fill_kexec_android(struct multirom_status *s, struct multirom_rom *
kexec_add_arg(kexec, "--dtb");
#endif
// Trampolines in ROM boot images may get out of sync, so we need to check it and
// update if needed. I can't do that during ZIP installation because of USB drives.
// That header.name is added by recovery.
int ver = 0;
if(strncmp((char*)img.hdr.name, "tr_ver", 6) == 0)
ver = atoi((char*)img.hdr.name + 6);
if(ver < multirom_get_trampoline_ver())
{
if(multirom_update_rd_trampoline("/initrd.img") != 0)
goto exit;
else
{
// Update the boot.img
snprintf((char*)img.hdr.name, BOOT_NAME_SIZE, "tr_ver%d", multirom_get_trampoline_ver());
if(libbootimg_load_ramdisk(&img, "/initrd.img") >= 0)
{
char tmp[256];
strcpy(tmp, img_path);
strcat(tmp, ".new");
if(libbootimg_write_img(&img, tmp) >= 0)
{
INFO("Writing boot.img updated with trampoline v%d\n", multirom_get_trampoline_ver());
rename(tmp, img_path);
}
}
}
}
char cmdline[1536];
strcpy(cmdline, "--command-line=");
@@ -2524,114 +2503,6 @@ int multirom_run_scripts(const char *type, struct multirom_rom *rom)
return 0;
}
#define RD_GZIP 1
#define RD_LZ4 2
int multirom_update_rd_trampoline(const char *path)
{
int result = -1;
uint32_t magic = 0;
FILE *f = fopen(path, "r");
if(!f)
{
ERROR("Couldn't open %s!\n", path);
return -1;
}
fread(&magic, sizeof(magic), 1, f);
fclose(f);
remove_dir("/mrom_rd");
mkdir("/mrom_rd", 0755);
// Decompress initrd
int type;
char buff[256];
char *cmd[] = { busybox_path, "sh", "-c", buff, NULL };
if((magic & 0xFFFF) == 0x8B1F)
{
type = RD_GZIP;
snprintf(buff, sizeof(buff), "B=\"%s\"; cd /mrom_rd; \"$B\" gzip -d -c \"%s\" | \"$B\" cpio -i", busybox_path, path);
}
else if(magic == 0x184C2102)
{
type = RD_LZ4;
snprintf(buff, sizeof(buff), "cd /mrom_rd; \"%s/lz4\" -d \"%s\" stdout | \"%s\" cpio -i", mrom_dir(), path, busybox_path);
}
else
{
ERROR("Unknown ramdisk magic 0x%08X, can't update trampoline\n", magic);
goto success;
}
int r = run_cmd(cmd);
if(r != 0)
{
ERROR("Failed to unpack ramdisk!\n");
goto fail;
}
if(access("/mrom_rd/init", F_OK) < 0 || access("/mrom_rd/main_init", F_OK) < 0)
{
ERROR("This ramdisk is not injected, skipping\n");
goto success;
}
// Check version
char *cmd_t[] = { "/mrom_rd/init", "-v", NULL };
char *res = run_get_stdout(cmd_t);
int ver = 0;
if(res)
{
ver = atoi(res);
free(res);
}
else
{
ERROR("Failed to run trampoline!\n");
goto fail;
}
if(ver >= multirom_get_trampoline_ver())
{
INFO("No need to update trampoline for this rd\n");
goto success;
}
INFO("Updating trampoline in %s from ver %d to %d\n", path, ver, multirom_get_trampoline_ver());
if(copy_file("/init", "/mrom_rd/init") < 0)
{
ERROR("Failed to update trampoline\n");
goto fail;
}
chmod("/mrom_rd/init", 0755);
// Pack initrd again
switch(type)
{
case RD_GZIP:
snprintf(buff, sizeof(buff), "B=\"%s\"; cd /mrom_rd; \"$B\" find . | \"$B\" cpio -o -H newc | \"$B\" gzip > \"%s\"", busybox_path, path);
break;
case RD_LZ4:
snprintf(buff, sizeof(buff), "B=\"%s\"; cd /mrom_rd; \"$B\" find . | \"$B\" cpio -o -H newc | \"%s/lz4\" stdin \"%s\"", busybox_path, mrom_dir(), path);
break;
}
r = run_cmd(cmd);
if(r != 0)
{
ERROR("Failed to pack ramdisk!\n");
goto fail;
}
success:
result = 0;
fail:
remove_dir("/mrom_rd");
return result;
}
#define IC_TYPE_PREDEF 0
#define IC_TYPE_USER 1
#define USER_IC_PATH "../Android/data/com.tassadar.multirommgr/files"

View File

@@ -12,7 +12,7 @@ LOCAL_MODULE_TAGS := eng
LOCAL_MODULE_PATH := $(TARGET_ROOT_OUT)
LOCAL_UNSTRIPPED_PATH := $(TARGET_ROOT_OUT_UNSTRIPPED)
LOCAL_STATIC_LIBRARIES := libcutils libc libmultirom_static
LOCAL_STATIC_LIBRARIES := libcutils libc libmultirom_static libbootimg
LOCAL_FORCE_STATIC_EXECUTABLE := true
ifeq ($(MR_INIT_DEVICES),)

View File

@@ -29,6 +29,7 @@
#include "../lib/log.h"
#include "../lib/util.h"
#include "../lib/fstab.h"
#include "../lib/inject.h"
#include "../version.h"
#include "adb.h"
#include "../hooks.h"
@@ -240,6 +241,9 @@ int main(int argc, char *argv[])
int i, res;
static char *const cmd[] = { "/init", NULL };
struct fstab *fstab = NULL;
char *inject_path = NULL;
char *mrom_dir = NULL;
int force_inject = 0;
for(i = 1; i < argc; ++i)
{
@@ -249,6 +253,26 @@ int main(int argc, char *argv[])
fflush(stdout);
return 0;
}
else if(strstartswith(argv[i], "--inject="))
inject_path = argv[i] + strlen("--inject=");
else if(strstartswith(argv[i], "--mrom_dir="))
mrom_dir = argv[i] + strlen("--mrom_dir=");
else if(strcmp(argv[i], "-f") == 0)
force_inject = 1;
}
if(inject_path)
{
if(!mrom_dir)
{
printf("--mrom_dir=[path to multirom's data dir] needs to be specified!\n");
fflush(stdout);
return 1;
}
mrom_set_dir(mrom_dir);
mrom_set_log_tag("trampoline_inject");
return inject_bootimg(inject_path, force_inject);
}
umask(000);