-
VirtualBox 建立机器,选择 Linux 2.6 / 3.x / 4.x 64-bit,CPU 核数、内存、磁盘、显存拉高,加载 Bliss OS 安装镜像,图像驱动器选 VBoxVGA,3D 加速不要勾选。可按需增加一个 Bridged Adapter 或者 Host-only Adapter,方便之后网络连接。
-
使用 VBoxManager 命令行工具增加一个视频模式:
VBoxManage setextradata "<虚拟机名称>" "CustomVideoMode1" "640x1080x32"640x1080x32 中分辨率可以自行设置,但最后的色彩位数一定要置为 32。
-
安装过程同安装 Android x86 的过程,中间有几个点要注意的。
-
启动后先进 debug mode
cd /mnt/grub
cp menu.lst menu.lst.bak
vi menu.lst
# 主启动项上加参数 vga=864,去掉 quiet。如 864 不对,加 vga=ask 后进系统确认下数字,再 16 进制转成 10 进制。
sync后Host键 + R- 进系统后,安装必要软件(可连接 VirtWifi 后,通过 10.0.2.2 访问宿主机)。使用以下脚本传输 ADB 公钥到系统:(调出软键盘按 Alt+F1 可以进 root 命令行,Alt+F7 切回来)
#!/bin/sh
# receive-adb-key.sh
# 后续可将整个文件部署至 Magisk 的 service.d
# 再将 ip addr 的这句移至 post-fs-data.d
nohup sh -c 'while true; do if [ "$(getprop sys.boot_completed)" = "1" ]; then break ; fi ; sleep 2 ; done ; ip addr add 192.168.68.121/24 dev eth1;' > /dev/null &
THIS_SCRIPT_PATH="$(realpath "$0")"
if [ "$1" = "worker" ]; then
exec 2>&1
echo -e Please input content from file "\"adbkey.pub\":""\r" >&2
echo -e ==================="\r" >&2
read INPUT_ADB_KEY
echo "$INPUT_ADB_KEY" >> /data/misc/adb/adb_keys
chown system:shell /data/misc/adb/adb_keys
chmod 0640 /data/misc/adb/adb_keys
stop adbd
setprop service.adb.tcp.port 5555
setprop persist.adb.tcp.port 5555
start adbd
echo -e ==================="\r" >&2
echo -e Done."\r" >&2
exit
fi
stop adbd
setprop service.adb.tcp.port 5555
setprop persist.adb.tcp.port 5555
start adbd
while true; do
busybox nc -l -p 15555 -e sh "$THIS_SCRIPT_PATH" worker
sleep 1
done
- 修改 Magisk。checkout 8aaa45c62(修改过版本号的 23.0,注意不要直接 checkout tag v23.0)
diff --git a/app/build.gradle.kts b/app/build.gradle.kts
index 4c50bed2b..33999e6c4 100644
--- a/app/build.gradle.kts
+++ b/app/build.gradle.kts
@@ -27,7 +27,7 @@ android {
vectorDrawables.useSupportLibrary = true
versionName = Config.version
versionCode = Config.versionCode
- ndk.abiFilters("armeabi-v7a", "arm64-v8a", "x86", "x86_64")
+ ndk.abiFilters("x86")
}
buildTypes {
@@ -100,10 +100,10 @@ val createStubLibs by tasks.registering {
doLast {
val arm64 = project.file("src/main/jniLibs/arm64-v8a/libstub.so")
arm64.parentFile.mkdirs()
- arm64.createNewFile()
+ // arm64.createNewFile()
val x64 = project.file("src/main/jniLibs/x86_64/libstub.so")
x64.parentFile.mkdirs()
- x64.createNewFile()
+ // x64.createNewFile()
}
}
diff --git a/app/src/main/java/com/topjohnwu/magisk/core/Const.kt b/app/src/main/java/com/topjohnwu/magisk/core/Const.kt
index 5ddb8c148..386f80e0a 100644
--- a/app/src/main/java/com/topjohnwu/magisk/core/Const.kt
+++ b/app/src/main/java/com/topjohnwu/magisk/core/Const.kt
@@ -8,8 +8,8 @@ import java.io.File
@Suppress("DEPRECATION")
object Const {
- val CPU_ABI: String = Build.SUPPORTED_ABIS[0]
- val CPU_ABI_32: String = Build.SUPPORTED_32_BIT_ABIS.firstOrNull() ?: CPU_ABI
+ val CPU_ABI: String = "x86_64"
+ val CPU_ABI_32: String = "x86"
// Paths
lateinit var MAGISKTMP: String
diff --git a/native/jni/Application.mk b/native/jni/Application.mk
index e1d65f416..c4c214e17 100644
--- a/native/jni/Application.mk
+++ b/native/jni/Application.mk
@@ -12,7 +12,7 @@ endif
# Build 64 bit binaries
ifdef B_64BIT
-APP_ABI += arm64-v8a x86_64
+APP_ABI += arm64-v8a
endif
# Busybox should use stock libc.a
diff --git a/native/jni/core/bootstages.cpp b/native/jni/core/bootstages.cpp
index 336a4b0ea..7f869c96d 100644
--- a/native/jni/core/bootstages.cpp
+++ b/native/jni/core/bootstages.cpp
@@ -3,6 +3,7 @@
#include <sys/sysmacros.h>
#include <linux/input.h>
#include <libgen.h>
+#include <dirent.h>
#include <vector>
#include <string>
@@ -26,20 +27,49 @@ static bool safe_mode = false;
#define MNT_DIR_IS(dir) (me->mnt_dir == string_view(dir))
#define SETMIR(b, part) sprintf(b, "%s/" MIRRDIR "/" #part, MAGISKTMP.data())
#define SETBLK(b, part) sprintf(b, "%s/" BLOCKDIR "/" #part, MAGISKTMP.data())
+#define SETTMPBLK(b, part) sprintf(b, "%s/tmpblk_" #part, MAGISKTMP.data())
+#define SETTMPMNT(b, part) sprintf(b, "%s/tmpmnt_" #part, MAGISKTMP.data())
-#define do_mount_mirror(part, flag) {\
+#define do_mount_mirror(part, flag, is_loop) {\
SETMIR(buf1, part); \
SETBLK(buf2, part); \
unlink(buf2); \
- mknod(buf2, S_IFBLK | 0600, st.st_dev); \
+ if (is_loop) {\
+ SETTMPBLK(buf3, part); \
+ mknod(buf3, S_IFBLK | 0600, st.st_dev); \
+ tmp_dev_fd = open(buf3, O_RDWR); \
+ if (tmp_dev_fd < -1) { LOGE("%s tmp_dev_fd fail\n", buf1); return false; } \
+ loop_dev_fd = open("/dev/block/loop6", O_RDWR); \
+ if (loop_dev_fd < -1) { LOGE("%s loop_dev_fd fail\n", buf1); return false; } \
+ if (ioctl(loop_dev_fd, 0x4C00 /* LOOP_SET_FD */, tmp_dev_fd) < 0) { LOGE("%s ioctl fail\n", buf1); return false; } \
+ close(tmp_dev_fd); \
+ if (fstat(loop_dev_fd, &loop_st) < 0) { LOGE("%s fstat fail\n", buf1); return false; } \
+ close(loop_dev_fd); \
+ mknod(buf2, S_IFBLK | 0600, loop_st.st_rdev); \
+ } else { \
+ mknod(buf2, S_IFBLK | 0600, st.st_dev); \
+ } \
xmkdir(buf1, 0755); \
- xmount(buf2, buf1, me->mnt_type, flag, nullptr); \
+ if (flag & MS_BIND) { \
+ /* shunf4: for BlissOS's /data partition, we need to mount the subdirectory "/bliss-x86-11.13/data" of the block device, thus MS_BIND. */ \
+ SETTMPMNT(buf3, part); \
+ xmkdir(buf3, 0755); \
+ xmount(buf2, buf3, me->mnt_type, flag & ~MS_BIND, nullptr); \
+ tmp_data_root = opendir(buf3); \
+ if (!tmp_data_root) { LOGE("%s opendir fail\n", buf1); return false; } \
+ buf4[0] = '\0'; \
+ while ((tmp_data_dirent = readdir(tmp_data_root)) != NULL) { if (strncmp(tmp_data_dirent->d_name, "bliss-", 6) == 0) { sprintf(buf4, "%s/%s/data", buf3, tmp_data_dirent->d_name); break; } } \
+ closedir(tmp_data_root); \
+ if (buf4[0] == '\0') { LOGE("%s bliss dir not found\n", buf1); return false; } \
+ xmount(buf4, buf1, 0, MS_BIND, nullptr); \
+ } else \
+ xmount(buf2, buf1, me->mnt_type, flag, nullptr); \
LOGI("mount: %s\n", buf1); \
}
-#define mount_mirror(part, flag) \
+#define mount_mirror(part, flag, is_loop) \
else if (MNT_DIR_IS("/" #part) && me->mnt_type != "tmpfs"sv && lstat(me->mnt_dir, &st) == 0) \
- do_mount_mirror(part, flag)
+ do_mount_mirror(part, flag, is_loop)
#define link_mirror(part) \
SETMIR(buf1, part); \
@@ -61,17 +91,24 @@ else if (MNT_DIR_IS(dir) && me->mnt_type != "tmpfs"sv) { \
static void mount_mirrors() {
char buf1[4096];
char buf2[4096];
+ char buf3[4096];
+ char buf4[4096];
+ int tmp_dev_fd;
+ int loop_dev_fd;
+ struct stat loop_st;
+ DIR* tmp_data_root;
+ struct dirent* tmp_data_dirent;
LOGI("* Mounting mirrors\n");
parse_mnt("/proc/mounts", [&](mntent *me) {
struct stat st;
if (0) {}
- mount_mirror(system, MS_RDONLY)
- mount_mirror(vendor, MS_RDONLY)
- mount_mirror(product, MS_RDONLY)
- mount_mirror(system_ext, MS_RDONLY)
- mount_mirror(data, 0)
+ mount_mirror(system, MS_RDONLY, 1)
+ mount_mirror(vendor, MS_RDONLY, 0)
+ mount_mirror(product, MS_RDONLY, 0)
+ mount_mirror(system_ext, MS_RDONLY, 0)
+ mount_mirror(data, MS_BIND, 0)
link_orig(cache)
link_orig(metadata)
link_orig(persist)
@@ -88,7 +125,7 @@ static void mount_mirrors() {
parse_mnt("/proc/mounts", [&](mntent *me) {
struct stat st;
if (MNT_DIR_IS("/") && me->mnt_type != "rootfs"sv && stat("/", &st) == 0) {
- do_mount_mirror(system_root, MS_RDONLY)
+ do_mount_mirror(system_root, MS_RDONLY, 0)
return false;
}
return true;
This is my build (Download and rename extension to .zip):
https://user-images.githubusercontent.com/20991618/147526309-be931ff0-744d-4169-8414-cc67f4c47210.gif
- 安装修改版本后的 Magisk: https://web.archive.org/web/20210228102356/https://wiki.blissroms.org/index.php?title=Bliss_OS/Extras
- 目前使用 Magisk 23.0 正式版,因为需要在隐藏 Root 的情况下 hook,因此 MagiskHide 必不可少。
但 Magisk 23.0 的 APK 无法在 x86_64 下处理 boot.img(提示失败),因此在 Shell 下解包 Magisk 的 APK,手动调用 boot_patch.sh。修改后的 Magisk 23.0 已经可以按原教程正常使用。- 重启后进 debug 模式部署三个文件,记得删掉两处的 su 二进制文件。没有 SuperUser APP, 无需删除。 多打几次 sync 总没坏处。
将 /data/app/com.topj..../lib/arm 下的 lib*.so 文件全部换成 x86 版本。修改后的 Magisk 无需这步。- 再重启到系统,进 Magisk,应提示已经安装,无任何错误。
但切换到 log 标签页看不到日志,检查 /cache/magisk.log 发现启动时出现了 busybox 错误,原因是 /sbin/.magisk/busybox/busybox 链接到了 ARM 版本的 busybox。做 Snapshot 后替换,将 /data/adb/magisk/ 下有关二进制全部链向 x86 的版本,重启。修改后的 Magisk 无需这步。- 现在可以启动 MagiskHide、隐藏 Magisk App、安装 receive-adb-key 服务、安装各种模块了。
- 其他调整:
- Settings - Display - Smallest width 改为 480dp,可以调整 DPI。
VBoxManage modifyvm "<VM Name>" --defaultfrontend headless