mirror of
https://github.com/topjohnwu/Magisk.git
synced 2025-04-16 05:01:25 +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')
|
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):
|
def cleanup(args):
|
||||||
support_targets = {'native', 'java'}
|
support_targets = {'native', 'java'}
|
||||||
if args.target:
|
if args.target:
|
||||||
@ -470,13 +452,54 @@ def setup_avd(args):
|
|||||||
|
|
||||||
abi = cmd_out([adb_path, 'shell', 'getprop', 'ro.product.cpu.abi'])
|
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',
|
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:
|
if proc.returncode != 0:
|
||||||
error('adb push failed!')
|
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:
|
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):
|
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)
|
stub_parser.set_defaults(func=build_stub)
|
||||||
|
|
||||||
avd_parser = subparsers.add_parser(
|
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)
|
avd_parser.set_defaults(func=setup_avd)
|
||||||
|
|
||||||
# Need to bind mount snet sources on top of stub folder
|
avd_patch_parser = subparsers.add_parser(
|
||||||
# Note: source code for the snet extension is *NOT* public
|
'avd_patch', help='patch AVD ramdisk.img')
|
||||||
snet_parser = subparsers.add_parser('snet', help='build snet extension')
|
avd_patch_parser.add_argument('ramdisk', help='path to ramdisk.img')
|
||||||
snet_parser.set_defaults(func=build_snet)
|
avd_patch_parser.set_defaults(func=patch_avd_ramdisk)
|
||||||
|
|
||||||
clean_parser = subparsers.add_parser('clean', help='cleanup')
|
clean_parser = subparsers.add_parser('clean', help='cleanup')
|
||||||
clean_parser.add_argument(
|
clean_parser.add_argument(
|
||||||
|
@ -180,6 +180,8 @@ void BootConfig::set(const kv_pairs &kv) {
|
|||||||
strlcpy(hardware_plat, value.data(), sizeof(hardware_plat));
|
strlcpy(hardware_plat, value.data(), sizeof(hardware_plat));
|
||||||
} else if (key == "androidboot.fstab_suffix") {
|
} else if (key == "androidboot.fstab_suffix") {
|
||||||
strlcpy(fstab_suffix, value.data(), sizeof(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("fstab_suffix=[%s]\n", fstab_suffix);
|
||||||
LOGD("hardware=[%s]\n", hardware);
|
LOGD("hardware=[%s]\n", hardware);
|
||||||
LOGD("hardware.platform=[%s]\n", hardware_plat);
|
LOGD("hardware.platform=[%s]\n", hardware_plat);
|
||||||
|
LOGD("emulator=[%d]\n", emulator);
|
||||||
}
|
}
|
||||||
|
|
||||||
#define read_dt(name, key) \
|
#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 {
|
parse_prop_file("/.backup/.magisk", [=](auto key, auto value) -> bool {
|
||||||
if (key == "RECOVERYMODE" && value == "true") {
|
if (key == "RECOVERYMODE" && value == "true") {
|
||||||
LOGD("Running in recovery mode, waiting for key...\n");
|
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 false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
@ -6,6 +6,7 @@ struct BootConfig {
|
|||||||
bool skip_initramfs;
|
bool skip_initramfs;
|
||||||
bool force_normal_boot;
|
bool force_normal_boot;
|
||||||
bool rootwait;
|
bool rootwait;
|
||||||
|
bool emulator;
|
||||||
char slot[3];
|
char slot[3];
|
||||||
char dt_dir[64];
|
char dt_dir[64];
|
||||||
char fstab_suffix[32];
|
char fstab_suffix[32];
|
||||||
@ -66,6 +67,10 @@ protected:
|
|||||||
mmap_data magisk_config;
|
mmap_data magisk_config;
|
||||||
std::string custom_rules_dir;
|
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();
|
void mount_with_dt();
|
||||||
bool patch_sepolicy(const char *file);
|
bool patch_sepolicy(const char *file);
|
||||||
void setup_tmp(const char *path);
|
void setup_tmp(const char *path);
|
||||||
|
@ -158,12 +158,19 @@ void MagiskInit::mount_with_dt() {
|
|||||||
for (const auto &entry : fstab) {
|
for (const auto &entry : fstab) {
|
||||||
if (is_lnk(entry.mnt_point.data()))
|
if (is_lnk(entry.mnt_point.data()))
|
||||||
continue;
|
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
|
// Derive partname from dev
|
||||||
sprintf(blk_info.partname, "%s%s", basename(entry.dev.data()), config->slot);
|
sprintf(blk_info.partname, "%s%s", basename(entry.dev.data()), config->slot);
|
||||||
setup_block(true);
|
setup_block(true);
|
||||||
xmkdir(entry.mnt_point.data(), 0755);
|
xmkdir(entry.mnt_point.data(), 0755);
|
||||||
xmount(blk_info.block_dev, entry.mnt_point.data(), entry.type.data(), MS_RDONLY, nullptr);
|
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);
|
xmkdir("/dev", 0755);
|
||||||
xmount("tmpfs", "/dev", "tmpfs", 0, "mode=755");
|
xmount("tmpfs", "/dev", "tmpfs", 0, "mode=755");
|
||||||
mount_list.emplace_back("/dev");
|
mount_list.emplace_back("/dev");
|
||||||
|
avd_hack = config->emulator;
|
||||||
mount_with_dt();
|
mount_with_dt();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -399,7 +407,7 @@ bool SecondStageInit::prepare() {
|
|||||||
void BaseInit::exec_init() {
|
void BaseInit::exec_init() {
|
||||||
// Unmount in reverse order
|
// Unmount in reverse order
|
||||||
for (auto &p : reversed(mount_list)) {
|
for (auto &p : reversed(mount_list)) {
|
||||||
if (xumount(p.data()) == 0)
|
if (xumount2(p.data(), MNT_DETACH) == 0)
|
||||||
LOGD("Unmount [%s]\n", p.data());
|
LOGD("Unmount [%s]\n", p.data());
|
||||||
}
|
}
|
||||||
execv("/init", argv);
|
execv("/init", argv);
|
||||||
|
@ -234,6 +234,10 @@ void SARBase::patch_rootdir() {
|
|||||||
make_pair(SPLIT_PLAT_CIL, "xxx"), /* Force loading monolithic sepolicy */
|
make_pair(SPLIT_PLAT_CIL, "xxx"), /* Force loading monolithic sepolicy */
|
||||||
make_pair(MONOPOLICY, sepol) /* Redirect /sepolicy to custom path */
|
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);
|
xmkdir(ROOTOVL, 0);
|
||||||
int dest = xopen(ROOTOVL "/init", O_CREAT | O_WRONLY | O_CLOEXEC, 0);
|
int dest = xopen(ROOTOVL "/init", O_CREAT | O_WRONLY | O_CLOEXEC, 0);
|
||||||
xwrite(dest, init.buf, init.sz);
|
xwrite(dest, init.buf, init.sz);
|
||||||
|
@ -6,14 +6,17 @@
|
|||||||
# Support emulator ABI: x86_64 and arm64
|
# Support emulator ABI: x86_64 and arm64
|
||||||
# Support API level: 23 - 31 (21 and 22 images do not have SELinux)
|
# 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
|
# This script will stop zygote, simulate the Magisk start up process
|
||||||
# that would've happened before zygote was started, and finally
|
# that would've happened before zygote was started, and finally
|
||||||
# restart zygote. This is useful for setting up the emulator for
|
# restart zygote. This is useful for setting up the emulator for
|
||||||
# developing Magisk, testing modules, and developing root apps using
|
# developing Magisk, testing modules, and developing root apps using
|
||||||
# the official Android emulator (AVD) instead of a real device.
|
# the official Android emulator (AVD) instead of a real device.
|
||||||
#
|
#
|
||||||
# This only covers the "core" features of Magisk. Testing magiskinit
|
# This only covers the "core" features of Magisk. For testing
|
||||||
# and magiskboot require additional setups that are not covered here.
|
# 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…
x
Reference in New Issue
Block a user