mirror of
https://github.com/topjohnwu/Magisk.git
synced 2024-11-21 15:05:28 +00:00
Add new build command avd_patch
This commit is contained in:
parent
f443cbaa2b
commit
20ef724fad
75
build.py
75
build.py
@ -383,24 +383,6 @@ def build_stub(args):
|
||||
build_apk(args, 'stub')
|
||||
|
||||
|
||||
def build_snet(args):
|
||||
if not op.exists(op.join('stub', 'src', 'main', 'java', 'com', 'topjohnwu', 'snet')):
|
||||
error('snet sources have to be bind mounted on top of the stub folder')
|
||||
header('* Building snet extension')
|
||||
proc = execv([gradlew, 'stub:assembleRelease'])
|
||||
if proc.returncode != 0:
|
||||
error('Build snet extention failed!')
|
||||
source = op.join('stub', 'build', 'outputs', 'apk',
|
||||
'release', 'stub-release.apk')
|
||||
target = op.join(config['outdir'], 'snet.jar')
|
||||
# Extract classes.dex
|
||||
with zipfile.ZipFile(target, 'w', compression=zipfile.ZIP_DEFLATED, allowZip64=False) as zout:
|
||||
with zipfile.ZipFile(source) as zin:
|
||||
zout.writestr('classes.dex', zin.read('classes.dex'))
|
||||
rm(source)
|
||||
header('Output: ' + target)
|
||||
|
||||
|
||||
def cleanup(args):
|
||||
support_targets = {'native', 'java'}
|
||||
if args.target:
|
||||
@ -470,13 +452,54 @@ def setup_avd(args):
|
||||
|
||||
abi = cmd_out([adb_path, 'shell', 'getprop', 'ro.product.cpu.abi'])
|
||||
proc = execv([adb_path, 'push', f'native/out/{abi}/busybox', 'out/app-debug.apk',
|
||||
'scripts/emulator.sh', '/data/local/tmp'])
|
||||
'scripts/avd_magisk.sh', '/data/local/tmp'])
|
||||
if proc.returncode != 0:
|
||||
error('adb push failed!')
|
||||
|
||||
proc = execv([adb_path, 'shell', 'sh', '/data/local/tmp/emulator.sh'])
|
||||
proc = execv([adb_path, 'shell', 'sh', '/data/local/tmp/avd_magisk.sh'])
|
||||
if proc.returncode != 0:
|
||||
error('emulator.sh failed!')
|
||||
error('avd_magisk.sh failed!')
|
||||
|
||||
|
||||
def patch_avd_ramdisk(args):
|
||||
build_binary(args)
|
||||
build_app(args)
|
||||
|
||||
header('* Patching emulator ramdisk.img')
|
||||
|
||||
# Create a backup to prevent accidental overwrites
|
||||
backup = args.ramdisk + '.bak'
|
||||
if not op.exists(backup):
|
||||
cp(args.ramdisk, backup)
|
||||
|
||||
ini = op.join(op.dirname(args.ramdisk), 'advancedFeatures.ini')
|
||||
with open(ini, 'r') as f:
|
||||
adv_ft = f.read()
|
||||
|
||||
# Need to turn off system as root
|
||||
if 'SystemAsRoot = on' in adv_ft:
|
||||
# Create a backup
|
||||
cp(ini, ini + '.bak')
|
||||
adv_ft = adv_ft.replace('SystemAsRoot = on', 'SystemAsRoot = off')
|
||||
with open(ini, 'w') as f:
|
||||
f.write(adv_ft)
|
||||
|
||||
abi = cmd_out([adb_path, 'shell', 'getprop', 'ro.product.cpu.abi'])
|
||||
proc = execv([adb_path, 'push', f'native/out/{abi}/busybox', 'out/app-debug.apk',
|
||||
'scripts/avd_patch.sh', '/data/local/tmp'])
|
||||
if proc.returncode != 0:
|
||||
error('adb push failed!')
|
||||
proc = execv([adb_path, 'push', backup, '/data/local/tmp/ramdisk.cpio.gz'])
|
||||
if proc.returncode != 0:
|
||||
error('adb push failed!')
|
||||
|
||||
proc = execv([adb_path, 'shell', 'sh', '/data/local/tmp/avd_patch.sh'])
|
||||
if proc.returncode != 0:
|
||||
error('avd_patch.sh failed!')
|
||||
|
||||
proc = execv([adb_path, 'pull', '/data/local/tmp/ramdisk.cpio.gz', args.ramdisk])
|
||||
if proc.returncode != 0:
|
||||
error('adb pull failed!')
|
||||
|
||||
|
||||
def build_all(args):
|
||||
@ -512,13 +535,13 @@ stub_parser = subparsers.add_parser('stub', help='build the stub app')
|
||||
stub_parser.set_defaults(func=build_stub)
|
||||
|
||||
avd_parser = subparsers.add_parser(
|
||||
'emulator', help='build and setup AVD for development')
|
||||
'emulator', help='setup AVD for development')
|
||||
avd_parser.set_defaults(func=setup_avd)
|
||||
|
||||
# Need to bind mount snet sources on top of stub folder
|
||||
# Note: source code for the snet extension is *NOT* public
|
||||
snet_parser = subparsers.add_parser('snet', help='build snet extension')
|
||||
snet_parser.set_defaults(func=build_snet)
|
||||
avd_patch_parser = subparsers.add_parser(
|
||||
'avd_patch', help='patch AVD ramdisk.img')
|
||||
avd_patch_parser.add_argument('ramdisk', help='path to ramdisk.img')
|
||||
avd_patch_parser.set_defaults(func=patch_avd_ramdisk)
|
||||
|
||||
clean_parser = subparsers.add_parser('clean', help='cleanup')
|
||||
clean_parser.add_argument(
|
||||
|
@ -180,6 +180,8 @@ void BootConfig::set(const kv_pairs &kv) {
|
||||
strlcpy(hardware_plat, value.data(), sizeof(hardware_plat));
|
||||
} else if (key == "androidboot.fstab_suffix") {
|
||||
strlcpy(fstab_suffix, value.data(), sizeof(fstab_suffix));
|
||||
} else if (key == "qemu") {
|
||||
emulator = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -193,6 +195,7 @@ void BootConfig::print() {
|
||||
LOGD("fstab_suffix=[%s]\n", fstab_suffix);
|
||||
LOGD("hardware=[%s]\n", hardware);
|
||||
LOGD("hardware.platform=[%s]\n", hardware_plat);
|
||||
LOGD("emulator=[%d]\n", emulator);
|
||||
}
|
||||
|
||||
#define read_dt(name, key) \
|
||||
@ -230,7 +233,7 @@ void load_kernel_info(BootConfig *config) {
|
||||
parse_prop_file("/.backup/.magisk", [=](auto key, auto value) -> bool {
|
||||
if (key == "RECOVERYMODE" && value == "true") {
|
||||
LOGD("Running in recovery mode, waiting for key...\n");
|
||||
config->skip_initramfs = !check_key_combo();
|
||||
config->skip_initramfs = config->emulator || !check_key_combo();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
|
@ -6,6 +6,7 @@ struct BootConfig {
|
||||
bool skip_initramfs;
|
||||
bool force_normal_boot;
|
||||
bool rootwait;
|
||||
bool emulator;
|
||||
char slot[3];
|
||||
char dt_dir[64];
|
||||
char fstab_suffix[32];
|
||||
@ -66,6 +67,10 @@ protected:
|
||||
mmap_data magisk_config;
|
||||
std::string custom_rules_dir;
|
||||
|
||||
// When this boolean is set, this means we are currently
|
||||
// running magiskinit on legacy SAR AVD emulator
|
||||
bool avd_hack = false;
|
||||
|
||||
void mount_with_dt();
|
||||
bool patch_sepolicy(const char *file);
|
||||
void setup_tmp(const char *path);
|
||||
|
@ -158,12 +158,19 @@ void MagiskInit::mount_with_dt() {
|
||||
for (const auto &entry : fstab) {
|
||||
if (is_lnk(entry.mnt_point.data()))
|
||||
continue;
|
||||
// When we force AVD to disable SystemAsRoot, it will always add system
|
||||
// to dt fstab, which we actually have already mounted as root
|
||||
if (avd_hack && entry.mnt_point == "/system")
|
||||
continue;
|
||||
// Derive partname from dev
|
||||
sprintf(blk_info.partname, "%s%s", basename(entry.dev.data()), config->slot);
|
||||
setup_block(true);
|
||||
xmkdir(entry.mnt_point.data(), 0755);
|
||||
xmount(blk_info.block_dev, entry.mnt_point.data(), entry.type.data(), MS_RDONLY, nullptr);
|
||||
mount_list.push_back(entry.mnt_point);
|
||||
// When avd_hack is true, do not add any early mount partitions to mount_list
|
||||
// as we will actually forcefully disable original init's early mount
|
||||
if (!avd_hack)
|
||||
mount_list.push_back(entry.mnt_point);
|
||||
}
|
||||
}
|
||||
|
||||
@ -372,6 +379,7 @@ void SARInit::early_mount() {
|
||||
xmkdir("/dev", 0755);
|
||||
xmount("tmpfs", "/dev", "tmpfs", 0, "mode=755");
|
||||
mount_list.emplace_back("/dev");
|
||||
avd_hack = config->emulator;
|
||||
mount_with_dt();
|
||||
}
|
||||
}
|
||||
@ -399,7 +407,7 @@ bool SecondStageInit::prepare() {
|
||||
void BaseInit::exec_init() {
|
||||
// Unmount in reverse order
|
||||
for (auto &p : reversed(mount_list)) {
|
||||
if (xumount(p.data()) == 0)
|
||||
if (xumount2(p.data(), MNT_DETACH) == 0)
|
||||
LOGD("Unmount [%s]\n", p.data());
|
||||
}
|
||||
execv("/init", argv);
|
||||
|
@ -234,6 +234,10 @@ void SARBase::patch_rootdir() {
|
||||
make_pair(SPLIT_PLAT_CIL, "xxx"), /* Force loading monolithic sepolicy */
|
||||
make_pair(MONOPOLICY, sepol) /* Redirect /sepolicy to custom path */
|
||||
});
|
||||
if (avd_hack) {
|
||||
// Force disable early mount on original init
|
||||
init.patch({ make_pair("android,fstab", "xxx") });
|
||||
}
|
||||
xmkdir(ROOTOVL, 0);
|
||||
int dest = xopen(ROOTOVL "/init", O_CREAT | O_WRONLY | O_CLOEXEC, 0);
|
||||
xwrite(dest, init.buf, init.sz);
|
||||
|
@ -6,14 +6,17 @@
|
||||
# Support emulator ABI: x86_64 and arm64
|
||||
# Support API level: 23 - 31 (21 and 22 images do not have SELinux)
|
||||
#
|
||||
# With an emulator booted and accessible via ADB, usage:
|
||||
# ./build.py emulator
|
||||
#
|
||||
# This script will stop zygote, simulate the Magisk start up process
|
||||
# that would've happened before zygote was started, and finally
|
||||
# restart zygote. This is useful for setting up the emulator for
|
||||
# developing Magisk, testing modules, and developing root apps using
|
||||
# the official Android emulator (AVD) instead of a real device.
|
||||
#
|
||||
# This only covers the "core" features of Magisk. Testing magiskinit
|
||||
# and magiskboot require additional setups that are not covered here.
|
||||
# This only covers the "core" features of Magisk. For testing
|
||||
# magiskinit, please checkout avd_init.sh.
|
||||
#
|
||||
#####################################################################
|
||||
|
81
scripts/avd_patch.sh
Normal file
81
scripts/avd_patch.sh
Normal file
@ -0,0 +1,81 @@
|
||||
#!/usr/bin/env bash
|
||||
#####################################################################
|
||||
# AVD MagiskInit Setup
|
||||
#####################################################################
|
||||
#
|
||||
# Support emulator ABI: x86_64 and arm64
|
||||
# Support API level: 23 - 31 (21 and 22 images do not have SELinux)
|
||||
#
|
||||
# With an emulator booted and accessible via ADB, usage:
|
||||
# ./build.py avd_patch path/to/booted/avd-image/ramdisk.img
|
||||
#
|
||||
# The purpose of this script is to patch AVD ramdisk.img and do a
|
||||
# full integration test of magiskinit under several circumstances.
|
||||
# After patching ramdisk.img, close the emulator, then select
|
||||
# "Cold Boot Now" in AVD Manager to force a full reboot.
|
||||
#
|
||||
#####################################################################
|
||||
# AVD Init Configurations:
|
||||
#
|
||||
# rootfs w/o early mount: API 23 - 25
|
||||
# rootfs with early mount: API 26 - 27
|
||||
# Legacy system-as-root: API 28
|
||||
# 2 stage init: API 29 - 31
|
||||
#####################################################################
|
||||
|
||||
if [ ! -f /system/build.prop ]; then
|
||||
# Running on PC
|
||||
echo 'Please run `./build.py avd_patch` instead of directly executing the script!'
|
||||
exit 1
|
||||
fi
|
||||
|
||||
cd /data/local/tmp
|
||||
chmod 755 busybox
|
||||
|
||||
if [ -z "$FIRST_STAGE" ]; then
|
||||
export FIRST_STAGE=1
|
||||
export ASH_STANDALONE=1
|
||||
# Re-exec script with busybox
|
||||
exec ./busybox sh $0
|
||||
fi
|
||||
|
||||
# Extract files from APK
|
||||
unzip -oj app-debug.apk 'assets/util_functions.sh'
|
||||
. ./util_functions.sh
|
||||
|
||||
api_level_arch_detect
|
||||
|
||||
unzip -oj app-debug.apk "lib/$ABI/*" "lib/$ABI32/libmagisk32.so" -x "lib/$ABI/busybox.so"
|
||||
for file in lib*.so; do
|
||||
chmod 755 $file
|
||||
mv "$file" "${file:3:${#file}-6}"
|
||||
done
|
||||
|
||||
gzip -d ramdisk.cpio.gz
|
||||
cp ramdisk.cpio ramdisk.cpio.orig
|
||||
|
||||
touch config
|
||||
|
||||
# For API 28, we also patch advancedFeatures.ini to disable SAR
|
||||
# Manually override skip_initramfs by setting RECOVERYMODE=true
|
||||
[ $API = "28" ] && echo 'RECOVERYMODE=true' >> config
|
||||
|
||||
./magiskboot compress=xz magisk32 magisk32.xz
|
||||
./magiskboot compress=xz magisk64 magisk64.xz
|
||||
|
||||
export KEEPVERITY=false
|
||||
export KEEPFORCEENCRYPT=true
|
||||
|
||||
./magiskboot cpio ramdisk.cpio \
|
||||
"add 0750 init magiskinit" \
|
||||
"mkdir 0750 overlay.d" \
|
||||
"mkdir 0750 overlay.d/sbin" \
|
||||
"add 0644 overlay.d/sbin/magisk32.xz magisk32.xz" \
|
||||
"add 0644 overlay.d/sbin/magisk64.xz magisk64.xz" \
|
||||
"patch" \
|
||||
"backup ramdisk.cpio.orig" \
|
||||
"mkdir 000 .backup" \
|
||||
"add 000 .backup/.magisk config"
|
||||
|
||||
rm -f ramdisk.cpio.orig config magisk*.xz
|
||||
gzip -9 ramdisk.cpio
|
Loading…
Reference in New Issue
Block a user