mirror of
				https://github.com/topjohnwu/Magisk.git
				synced 2025-10-31 08:44:07 +00:00 
			
		
		
		
	Add new build command avd_patch
This commit is contained in:
		
							
								
								
									
										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 | ||||||
		Reference in New Issue
	
	Block a user
	 topjohnwu
					topjohnwu