website: add Traditional Chinese (#429)

Also README_TW added, hope it works :)
This commit is contained in:
Kung-chih
2023-04-23 18:54:33 +08:00
committed by GitHub
parent 925206f9c8
commit fe1cd4b27a
16 changed files with 1077 additions and 2 deletions

View File

@@ -1,4 +1,4 @@
**English** | [中文](README_CN.md) **English** | [简体中文](README_CN.md) | [繁體中文](README_TW.md)
# KernelSU # KernelSU

View File

@@ -1,4 +1,4 @@
[English](README.md) | **中文** [English](README.md) | **简体中文** | [繁體中文](README_TW.md)
# KernelSU # KernelSU

42
README_TW.md Normal file
View File

@@ -0,0 +1,42 @@
[English](README.md) | [简体中文](README_CN.md) | **繁體中文**
# KernelSU
一個基於核心的 Android 裝置 Root 解決方案
## 功能
- 基於核心的 Su 和 Root 存取權管理。
- 基於 Overlayfs 的模組系統。
## 相容性狀態
KernelSU 官方支援 Android GKI 2.0 的裝置 (核心版本 5.10+);舊版核心同樣相容 (最低 4.14+),但需要自行編譯核心。
WSA 和執行在容器中的 Android 也可以與 KernelSU 一同運作。
目前支援架構:`arm64-v8a``x86_64`
## 使用方法
[安裝教學](https://kernelsu.org/zh_TW/guide/installation.html)
## 建置
[如何建置?](https://kernelsu.org/zh_TW/guide/how-to-build.html)
### 討論
- Telegram[@KernelSU](https://t.me/KernelSU)
## 授權
- 目錄 `kernel` 下所有檔案為 [GPL-2](https://www.gnu.org/licenses/old-licenses/gpl-2.0.en.html)
-`kernel` 目錄的其他部分均為 [GPL-3](https://www.gnu.org/licenses/gpl-3.0.html)
## 致謝
- [kernel-assisted-superuser](https://git.zx2c4.com/kernel-assisted-superuser/about/)KernelSU 的靈感。
- [true](https://github.com/brevent/genuine/)apk v2 簽章驗證。
- [Diamorphine](https://github.com/m0nad/Diamorphine):一些 rootkit 技巧。
- [Magisk](https://github.com/topjohnwu/Magisk)sepolicy 實作。

View File

@@ -1,6 +1,7 @@
import { defineConfig } from 'vitepress' import { defineConfig } from 'vitepress'
import en from './en' import en from './en'
import zh_CN from './zh_CN' import zh_CN from './zh_CN'
import zh_TW from './zh_TW'
import vi_VN from './vi_VN' import vi_VN from './vi_VN'
import id_ID from './id_ID' import id_ID from './id_ID'
@@ -18,6 +19,12 @@ export default defineConfig({
themeConfig: zh_CN.themeConfig, themeConfig: zh_CN.themeConfig,
description: zh_CN.description description: zh_CN.description
}, },
zh_TW: {
label: '繁體中文',
lang: zh_TW.lang,
themeConfig: zh_TW.themeConfig,
description: zh_TW.description
},
vi_VN: { vi_VN: {
label: 'Tiếng Việt', label: 'Tiếng Việt',
lang: vi_VN.lang, lang: vi_VN.lang,

View File

@@ -0,0 +1,60 @@
import { createRequire } from 'module'
import { defineConfig } from 'vitepress'
const require = createRequire(import.meta.url)
const pkg = require('vitepress/package.json')
export default defineConfig({
lang: 'zh-TW',
description: '一個以核心為基礎,適用於 Android GKI 的 Root 解決方案。',
themeConfig: {
nav: nav(),
lastUpdatedText: '上次更新',
sidebar: {
'/zh_TW/guide/': sidebarGuide()
},
socialLinks: [
{ icon: 'github', link: 'https://github.com/tiann/KernelSU' }
],
footer: {
message: '係依據 GPL3 授權發行。',
copyright: 'Copyright © 2022-目前 KernelSU 開發人員'
},
editLink: {
pattern: 'https://github.com/tiann/KernelSU/edit/main/website/docs/:path',
text: '在 GitHub 中編輯本頁面'
}
}
})
function nav() {
return [
{ text: '指南', link: '/zh_TW/guide/what-is-kernelsu' },
{ text: 'Github', link: 'https://github.com/tiann/KernelSU' }
]
}
function sidebarGuide() {
return [
{
text: 'Guide',
items: [
{ text: '什麼是 KernelSU', link: '/zh_TW/guide/what-is-kernelsu' },
{ text: '安裝', link: '/zh_TW/guide/installation' },
{ text: '如何建置?', link: '/zh_TW/guide/how-to-build' },
{ text: '如何為非 GKI 核心整合 KernelSU', link: '/zh_TW/guide/how-to-integrate-for-non-gki'},
{ text: '非官方支援裝置', link: '/zh_TW/guide/unofficially-support-devices.md' },
{ text: '模組指南', link: '/zh_TW/guide/module.md' },
{ text: '搶救開機迴圈', link: '/zh_TW/guide/rescue-from-bootloop.md' },
{ text: '常見問題', link: '/zh_TW/guide/faq' },
{ text: '隱藏功能', link: '/zh_TW/guide/hidden-features' },
]
}
]
}

View File

@@ -0,0 +1,26 @@
# KernelSU 模組與 Magisk 的差異 {#title}
儘管 KernelSU 模組和 Magisk 模組之間有許多相似之處,但由於它們完全不同的實作機制,不可避免地存在一些差異;如果您想讓您的模組同時在 Magisk 和 KernelSU 上運作,那麼您必須瞭解這些差異。
## 相同之處 {#similarities}
- 模組檔案格式:都以 Zip 的格式組織模組,並且模組的格式幾乎相同
- 模組安裝目錄:都位於 `/data/adb/modules`
- Systemless都支援透過模組的形式以 systemless 修改 /system
- `post-fs-data.sh`:執行時間和語義完全相同
- `service.sh`:執行時間和語義完全相同
- `system.prop`:完全相同
- `sepolicy.rule`:完全相同
- BusyBox指令碼在 BusyBox 中以「獨立模式」執行
## 不同之處 {#differences}
在瞭解不同之處之前,您需要知道如何區分您的模組是在 KernelSU 還是 Magisk 中執行;在所有可以執行模組指令碼的位置 (`customize.sh`, `post-fs-data.sh`, `service.sh`),您都可以使用環境變數 `KSU` 來區分,在 KernelSU 中,這個環境變數將被設定為 `true`
以下是一些不同之處:
1. KernelSU 的模組不支援在 Recovery 中安裝。
2. KernelSU 的模組沒有內建的 Zygisk 支援 (但您可以透過 [ZygiskOnKernelSU](https://github.com/Dr-TSNG/ZygiskOnKernelSU) 來使用 Zygisk 模組)。
3. KernelSU 模組取代或刪除檔案與 Magisk 完全不同。KernelSU 不支援 `.replace` 方法,相反,您需要透過 `mknod filename c 0 0` 建立相同名稱的資料夾以刪除對應檔案。
4. BusyBox 的目錄不同KernelSU 內建的 BusyBox 在 `/data/adb/ksu/bin/busybox` 而 Magisk 在 `/data/adb/magisk/busybox`**注意此為 KernelSU 內部行為,未來可能會變更!**
5. KernelSU 不支援 `.replace` 檔案;但 KernelSU 支援 `REPLACE``REMOVE` 變數以移除或取代檔案 (資料夾)。

View File

@@ -0,0 +1,67 @@
# 常見問題
## KernelSU 是否支援我的裝置?
首先,您的裝置應該能解鎖 Bootloader。如果不能則不支援。
然後在您的裝置上安裝 KernelSU 管理員並開啟它,如果它顯示 `不支援`,那麼您的裝置沒有官方支援的開箱即用的 Boot 映像;但您可以自行建置核心來源並整合 KernelSU 以繼續使用。
## KernelSU 是否需要解鎖 Bootloader
當然需要。
## KernelSU 是否支援模組?
支援,但它是早期版本,可能存在問題。請等候它逐漸穩定 :)
## KernelSU 是否支援 Xposed
支援。[Dreamland](https://github.com/canyie/Dreamland) 和 [TaiChi](https://taichi.cool) 可以正常運作。LSPosed 可以在 [Zygisk on KernelSU](https://github.com/Dr-TSNG/ZygiskOnKernelSU) 的支援下正常運作。
## KernelSU 支援 Zygisk 嗎?
KernelSU 沒有內建 Zygisk 支援,但是您可以用 [Zygisk on KernelSU](https://github.com/Dr-TSNG/ZygiskOnKernelSU) 來使用 Zygisk 模組。
## KernelSU 與 Magisk 相容嗎?
KernelSU 的模組系統與 Magisk 的 magic mount 存在衝突,如果在 KernelSU 中啟用了任何模組,那麼整個 Magisk 將無法正常運作。
但是如果您只使用 KernelSU 的 `su`,那么它會和 Magisk 一同運作KernelSU 修改 `kernel` 、 Magisk 修改 `ramdisk`,它們可以搭配使用。
## KernelSU 会取代 Magisk 嗎?
我們不這樣認為這也不是我們的目標。Magisk 對於使用者空間 Root 解決方案來說已經足夠優秀了它會存在很長一段時間。KernelSU 的目標是為使用者提供核心介面,而非取代 Magisk。
## KernelSU 可以支援非 GKI 裝置嗎?
可以。但是您應該下載核心來源並整合 KernelSU 至來源樹狀結構並自行編譯核心。
## KernelSU 支援 Android 12 以下的裝置嗎?
影響 KernelSU 相容性的是裝置的核心版本,它與 Android 版本並無直接關係。唯一有關聯的是:**原廠** Android 12 的裝置,一定是 5.10 或更高的核心 (GKI 裝置);因此結論如下:
1. 原廠 Android 12 的裝置必定支援 (GKI 裝置)
2. 舊版核心的裝置 (即使是 Android 12也可能是舊版核心) 是相容的 (您需要自行建置核心)
## KernelSU 可以支援舊版核心嗎?
可以,目前最低支援到 4.14;更低的版本您需要手動移植它,歡迎 PR
## 如何為舊版核心整合 KernelSU
請參閱[指南](how-to-integrate-for-non-gki)
## 為何我的 Android 版本為 13但核心版本卻是 "android12-5.10"
核心版本與 Android 版本無關,如果您要刷新 KernelSU請一律使用**核心版本**而非 Android 版本,如果你為 "android12-5.10" 的裝置刷新 Android 13 的核心,等候您的將會是開機迴圈。
## KernelSU 支援 --mount-master/全域掛接命名空間嗎?
目前沒有 (未來可能會支援),但實際上有很多種方法手動進入全域命名空間,無需 Su 內建支援,比如:
1. `nsenter -t 1 -m sh` 可以取得一個全域 mount namespace 的 shell.
2. 在您要執行的命令前新增 `nsenter --mount=/proc/1/ns/mnt` 即可使此命令在全域 mount namespace 下執行。KernelSU 本身也使用了 [這種方法](https://github.com/tiann/KernelSU/blob/77056a710073d7a5f7ee38f9e77c9fd0b3256576/manager/app/src/main/java/me/weishu/kernelsu/ui/util/KsuCli.kt#L115)
## 我是 GKI1.0,能用 KernelSU 嗎?
GKI1 與 GKI2 完全不同,所以您需要自行編譯核心。

View File

@@ -0,0 +1,7 @@
# 隱藏功能
## ksurc
預設狀況下,`/system/bin/sh` 會載入 `/system/etc/mkshrc`
可以透過建立 `/data/adb/ksu/.ksurc` 檔案來讓 Su 載入此檔案而非 `/system/etc/mkshrc`

View File

@@ -0,0 +1,65 @@
# 如何建置 KernelSU?
首先,您需要閱讀核心建置的 Android 官方文件:
1. [建置核心](https://source.android.com/docs/setup/build/building-kernels)
2. [標準核心映像 (GKI) 發行組建](https://source.android.com/docs/core/architecture/kernel/gki-release-builds)
::: warning
此文件適用於 GKI 裝置,如果您是舊版核心,請參閱[如何為非 GKI 裝置整合 KernelSU](how-to-integrate-for-non-gki)
:::
## 建置核心
### 同步核心原始碼
```sh
repo init -u https://android.googlesource.com/kernel/manifest
mv <kernel_manifest.xml> .repo/manifests
repo init -m manifest.xml
repo sync
```
`<kernel_manifest.xml>` 是一個可以唯一確定組建的資訊清單檔案,您可以使用這個資訊清單進行可重新預測的組建。您需要從[標準核心映像 (GKI) 發行組建](https://source.android.com/docs/core/architecture/kernel/gki-release-builds) 下載資訊清單檔案
### 建置
請先查看[官方文件](https://source.android.com/docs/setup/build/building-kernels)。
例如,我們需要建置 aarch64 核心映像:
```sh
LTO=thin BUILD_CONFIG=common/build.config.gki.aarch64 build/build.sh
```
不要忘記新增 `LTO=thin`,否則,如果您的電腦記憶體小於 24GB建置可能會失敗。
從 Android 13 開始,核心由 `bazel` 建置:
```sh
tools/bazel build --config=fast //common:kernel_aarch64_dist
```
## 使用 KernelSU 建置核心
如果您可以成功建置核心,那麼建置 KernelSU 就會非常輕鬆,依自己的需求在核心原始碼根目錄中執行以下任一命令:
- 最新 tag (穩定版本)
```sh
curl -LSs "https://raw.githubusercontent.com/tiann/KernelSU/main/kernel/setup.sh" | bash -
```
- main 分支 (開發版本)
```sh
curl -LSs "https://raw.githubusercontent.com/tiann/KernelSU/main/kernel/setup.sh" | bash -s main
```
- 選取 tag (例如 v0.5.2)
```sh
curl -LSs "https://raw.githubusercontent.com/tiann/KernelSU/main/kernel/setup.sh" | bash -s v0.5.2
```
然後重新建置核心,您將會得到一個帶有 KernelSU 的核心映像!

View File

@@ -0,0 +1,240 @@
# 如何為非 GKI 核心整合 KernelSU {#introduction}
KernelSU 可以被整合到非 GKI 核心中,現在它最低支援到核心 4.14 版本;理論上也可以支援更低的版本。
由於非 GKI 核心的片段化極其嚴重,因此通常沒有統一的方法來建置它,所以我們也無法為非 GKI 裝置提供 Boot 映像。但您完全可以自行整合 KernelSU 並建置核心以繼續使用。
首先,您必須有能力從您裝置的核心原始碼建置出一個可以開機並且能夠正常使用的核心,如果核心並非開放原始碼,這通常難以做到。
如果您已經做好了上述準備,那有兩個方法來將 KernelSU 整合至您的核心之中。
1. 藉助 `kprobe` 自動整合
2. 手動修改核心原始碼
## 使用 kprobe 整合 {#using-kprobes}
KernelSU 使用 kprobe 機制來處理核心的相關 hook如果 *kprobe* 可以在您建置的核心中正常運作,那麼建議使用這個方法進行整合。
首先,把 KernelSU 新增至您的核心來源樹狀結構,再核心的根目錄執行以下命令:
- 最新 tag (稳定版本)
```sh
curl -LSs "https://raw.githubusercontent.com/tiann/KernelSU/main/kernel/setup.sh" | bash -
```
- main 分支(開發版本)
```sh
curl -LSs "https://raw.githubusercontent.com/tiann/KernelSU/main/kernel/setup.sh" | bash -s main
```
- 選取 tag (例如 v0.5.2)
```sh
curl -LSs "https://raw.githubusercontent.com/tiann/KernelSU/main/kernel/setup.sh" | bash -s v0.5.2
```
然後,您需要檢查您的核心是否啟用 *kprobe* 相關組態,如果未啟用,則需要新增以下組態:
```
CONFIG_KPROBES=y
CONFIG_HAVE_KPROBES=y
CONFIG_KPROBE_EVENTS=y
```
最後,重新建置您的核心即可。
如果您發現 KPROBES 仍未生效,很有可能是因為它的相依性 `CONFIG_MODULES` 並未被啟用 (如果還是未生效請輸入 `make menuconfig` 搜尋 KPROBES 的其他相依性並啟用)
如果您在整合 KernelSU 之後手機無法啟動,那麼很可能您的核心中 **kprobe 無法正常運作**,您需要修正這個錯誤,或者使用第二種方法。
:::tip 如何檢查 kprobe 是否損毀?
`KernelSU/kernel/ksu.c` 中的 `ksu_enable_sucompat()``ksu_enable_ksud()` 取消註解,如果正常開機,即 kprobe 已損毀;或者您可以手動嘗試使用 kprobe 功能,如果不正常,手機會直接重新啟動。
:::
## 手動修改核心原始碼 {#modify-kernel-source-code}
如果 kprobe 無法正常運作 (可能是上游的錯誤或核心版本過低),那您可以嘗試這種方法:
首先,將 KernelSU 新增至您的原始碼樹狀結構,再核心的根目錄執行以下命令:
```sh
curl -LSs "https://raw.githubusercontent.com/tiann/KernelSU/main/kernel/setup.sh" | bash -
```
然後,手動修改核心原始碼,您可以參閱下方的 patch
```diff
diff --git a/fs/exec.c b/fs/exec.c
index ac59664eaecf..bdd585e1d2cc 100644
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -1890,11 +1890,14 @@ static int __do_execve_file(int fd, struct filename *filename,
return retval;
}
+extern int ksu_handle_execveat(int *fd, struct filename **filename_ptr, void *argv,
+ void *envp, int *flags);
static int do_execveat_common(int fd, struct filename *filename,
struct user_arg_ptr argv,
struct user_arg_ptr envp,
int flags)
{
+ ksu_handle_execveat(&fd, &filename, &argv, &envp, &flags);
return __do_execve_file(fd, filename, argv, envp, flags, NULL);
}
diff --git a/fs/open.c b/fs/open.c
index 05036d819197..965b84d486b8 100644
--- a/fs/open.c
+++ b/fs/open.c
@@ -348,6 +348,8 @@ SYSCALL_DEFINE4(fallocate, int, fd, int, mode, loff_t, offset, loff_t, len)
return ksys_fallocate(fd, mode, offset, len);
}
+extern int ksu_handle_faccessat(int *dfd, const char __user **filename_user, int *mode,
+ int *flags);
/*
* access() needs to use the real uid/gid, not the effective uid/gid.
* We do this by temporarily clearing all FS-related capabilities and
@@ -355,6 +357,7 @@ SYSCALL_DEFINE4(fallocate, int, fd, int, mode, loff_t, offset, loff_t, len)
*/
long do_faccessat(int dfd, const char __user *filename, int mode)
{
+ ksu_handle_faccessat(&dfd, &filename, &mode, NULL);
const struct cred *old_cred;
struct cred *override_cred;
struct path path;
diff --git a/fs/read_write.c b/fs/read_write.c
index 650fc7e0f3a6..55be193913b6 100644
--- a/fs/read_write.c
+++ b/fs/read_write.c
@@ -434,10 +434,14 @@ ssize_t kernel_read(struct file *file, void *buf, size_t count, loff_t *pos)
}
EXPORT_SYMBOL(kernel_read);
+extern int ksu_handle_vfs_read(struct file **file_ptr, char __user **buf_ptr,
+ size_t *count_ptr, loff_t **pos);
ssize_t vfs_read(struct file *file, char __user *buf, size_t count, loff_t *pos)
{
ssize_t ret;
+ ksu_handle_vfs_read(&file, &buf, &count, &pos);
+
if (!(file->f_mode & FMODE_READ))
return -EBADF;
if (!(file->f_mode & FMODE_CAN_READ))
diff --git a/fs/stat.c b/fs/stat.c
index 376543199b5a..82adcef03ecc 100644
--- a/fs/stat.c
+++ b/fs/stat.c
@@ -148,6 +148,8 @@ int vfs_statx_fd(unsigned int fd, struct kstat *stat,
}
EXPORT_SYMBOL(vfs_statx_fd);
+extern int ksu_handle_stat(int *dfd, const char __user **filename_user, int *flags);
+
/**
* vfs_statx - Get basic and extra attributes by filename
* @dfd: A file descriptor representing the base dir for a relative filename
@@ -170,6 +172,7 @@ int vfs_statx(int dfd, const char __user *filename, int flags,
int error = -EINVAL;
unsigned int lookup_flags = LOOKUP_FOLLOW | LOOKUP_AUTOMOUNT;
+ ksu_handle_stat(&dfd, &filename, &flags);
if ((flags & ~(AT_SYMLINK_NOFOLLOW | AT_NO_AUTOMOUNT |
AT_EMPTY_PATH | KSTAT_QUERY_FLAGS)) != 0)
return -EINVAL;
```
主要修改四個項目:
1. do_faccessat通常位於 `fs/open.c`
2. do_execveat_common通常位於 `fs/exec.c`
3. vfs_read通常位於 `fs/read_write.c`
4. vfs_statx通常位於 `fs/stat.c`
如果您的核心沒有 `vfs_statx`,使用 `vfs_fstatat` 將其取代:
```diff
diff --git a/fs/stat.c b/fs/stat.c
index 068fdbcc9e26..5348b7bb9db2 100644
--- a/fs/stat.c
+++ b/fs/stat.c
@@ -87,6 +87,8 @@ int vfs_fstat(unsigned int fd, struct kstat *stat)
}
EXPORT_SYMBOL(vfs_fstat);
+extern int ksu_handle_stat(int *dfd, const char __user **filename_user, int *flags);
+
int vfs_fstatat(int dfd, const char __user *filename, struct kstat *stat,
int flag)
{
@@ -94,6 +96,8 @@ int vfs_fstatat(int dfd, const char __user *filename, struct kstat *stat,
int error = -EINVAL;
unsigned int lookup_flags = 0;
+ ksu_handle_stat(&dfd, &filename, &flag);
+
if ((flag & ~(AT_SYMLINK_NOFOLLOW | AT_NO_AUTOMOUNT |
AT_EMPTY_PATH)) != 0)
goto out;
```
對於早於 4.17 的核心,如果沒有 `do_faccessat`,可以直接找到 `faccessat` 系統呼叫的定義並進行修改:
```diff
diff --git a/fs/open.c b/fs/open.c
index 2ff887661237..e758d7db7663 100644
--- a/fs/open.c
+++ b/fs/open.c
@@ -355,6 +355,9 @@ SYSCALL_DEFINE4(fallocate, int, fd, int, mode, loff_t, offset, loff_t, len)
return error;
}
+extern int ksu_handle_faccessat(int *dfd, const char __user **filename_user, int *mode,
+ int *flags);
+
/*
* access() needs to use the real uid/gid, not the effective uid/gid.
* We do this by temporarily clearing all FS-related capabilities and
@@ -370,6 +373,8 @@ SYSCALL_DEFINE3(faccessat, int, dfd, const char __user *, filename, int, mode)
int res;
unsigned int lookup_flags = LOOKUP_FOLLOW;
+ ksu_handle_faccessat(&dfd, &filename, &mode, NULL);
+
if (mode & ~S_IRWXO) /* where's F_OK, X_OK, W_OK, R_OK? */
return -EINVAL;
```
若要啟用 KernelSU 內建的安全模式,您還需要修改 `drivers/input/input.c` 中的 `input_handle_event` 方法:
:::tip
強烈建議啟用此功能,如果遇到開機迴圈,這將會非常有用!
:::
```diff
diff --git a/drivers/input/input.c b/drivers/input/input.c
index 45306f9ef247..815091ebfca4 100755
--- a/drivers/input/input.c
+++ b/drivers/input/input.c
@@ -367,10 +367,13 @@ static int input_get_disposition(struct input_dev *dev,
return disposition;
}
+extern int ksu_handle_input_handle_event(unsigned int *type, unsigned int *code, int *value);
+
static void input_handle_event(struct input_dev *dev,
unsigned int type, unsigned int code, int value)
{
int disposition = input_get_disposition(dev, type, code, &value);
+ ksu_handle_input_handle_event(&type, &code, &value);
if (disposition != INPUT_IGNORE_EVENT && type != EV_SYN)
add_input_randomness(type, code, value);
```
最後再次建置您的核心KernelSU 將會如期運作。

View File

@@ -0,0 +1,169 @@
# 安裝 {#title}
## 檢查您的裝置是否受支援 {#check-if-supported}
從 [GitHub Releases](https://github.com/tiann/KernelSU/releases) 或 [酷安](https://www.coolapk.com/apk/me.weishu.kernelsu) 下載 KernelSU 管理員應用程式,然後將應用程式安裝至裝置並開啟:
- 如果應用程式顯示「不支援」,則表示您的裝置不支援 KernelSU您需要自行編譯核心才能繼續使用KernelSU 官方也永遠不會為您提供一個可以刷新的 Boot 映像。
- 如果應用程式顯示「未安裝」,那麼 KernelSU 支援您的裝置;可以進行下一步作業。
:::info
對於顯示「不支援」的裝置,這裡有一個[非官方支援裝置清單](unofficially-support-devices.md),您可以使用這個清單裡的核心自行編譯。
:::
## 備份您的原廠 boot.img {#backup-boot-image}
在進行刷新作業前,您必須預先備份您的原廠 boot.img。如果您在後續刷新作業中出現了任何問題您都可以透過使用 Fastboot 刷新回到原廠 Boot 以還原系統。
::: warning
刷新作業可能會造成資料遺失,請確保做好這一步再繼續進行下一步作業!!必要時您還可以備份您手機的所有資料。
:::
## 必要知識 {#acknowage}
### ADB 和 Fastboot {#adb-and-fastboot}
預設狀況下,您將會使用 ADB 和 Fastboot 工具,如果您不知道它們,建議使用搜尋引擎先瞭解相關內容。
### KMI
KMI 全稱 Kernel Module Interface相同 KMI 的核心版本是**相容的** 這也是 GKI 中「標準」的涵義所在;反之,如果 KMI 不同,那麼這些核心之間無法彼此相容,刷新與您裝置 KMI 不同的核心映像可能會導致開機迴圈。
具體來講,對 GKI 的裝置,其核心版本格式應該如下:
```txt
KernelRelease :=
Version.PatchLevel.SubLevel-AndroidRelease-KmiGeneration-suffix
w .x .y -zzz -k -something
```
其中,`w.x-zzz-k` 為 KMI 版本。例如,一部裝置核心版本為 `5.10.101-android12-9-g30979850fc20`,那麼它的 KMI 為 `5.10-android12-9`;理論上刷新其他這個 KMI 的核心也能正常開機。
::: tip
請注意,核心版本中的 SubLevel 並非 KMI 的一部分!也就是說 `5.10.101-android12-9-g30979850fc20``5.10.137-android12-9-g30979850fc20` 的 KMI 相同!
:::
### 核心版本與 Android 版本 {#kernel-version-vs-android-version}
請注意:**核心版本與 Android 版本並不一定相同!**
如果您發現您的核心版本是 `android12-5.10.101`,然而您 Android 系統的版本為 Android 13 或者其他;請不要覺得奇怪,因為 Android 系統的版本與 Linux 核心的版本號碼並非一致Linux 核心的版本號碼一般與**裝置出廠時隨附的 Android 系統的版本一致**,如果後續 Android 系統更新,核心版本一般不會發生變化。如果您需要刷新,**請以核心版本為準!!**
## 安裝簡介 {#installation-introduction}
KernelSU 的安裝方法有以下幾種,各自適用於不同的場景,請視需要選擇:
1. 使用自訂 Recovery (如 TWRP) 安裝
2. 使用核心刷新應用程式 (例如 Franco Kernel Manager) 安裝
3. 使用 KernelSU 提供的 boot.img 透過 Fastboot 安裝
4. 手動修補 boot.img 並安裝
## 使用自訂 Recovery 安裝 {#install-by-recovery}
先決條件:您的裝置必須有自訂的 Recovery例如 TWRP如果沒有或者只有官方 Recovery請使用其他方法。
步驟:
1. 在 KernelSU 的 [Release 頁面](https://github.com/tiann/KernelSU/releases) 下載與您手機版本相符的以 AnyKernel3 開頭的 Zip 套件;例如,手機核心版本為 `android12-5.10.66`,那麼您應該下載 `AnyKernel3-android12-5.10.66_yyyy-MM.zip` 這個檔案 (其中 `yyyy` 為年份,`MM` 為月份)。
2. 重新開機手機至 TWRP。
3. 使用 Adb 將 AnyKernel3-*.zip 放置到手機 /sdcard 然後在 TWRP 圖形使用者介面選擇並安裝;或者您也可以直接 `adb sideload AnyKernel-*.zip` 安裝。
PS. 這種方法適用於任何狀況下的安裝 (不限於初次安裝或後續更新),只要您用 TWRP 就可以進行作業。
## 使用核心刷新應用程式安裝 {#install-by-kernel-flasher}
先決條件:您的裝置必須已經 Root。例如您已經安裝了 Magisk 並取得 Root 存取權,或者您已經安裝了舊版本的 KernelSU 需升級到其他版本的 KernelSU如果您的裝置並未 Root請嘗試其他方法。
步驟:
1. 下載 AnyKernel3 的 Zip 檔案;請參閱 *使用自訂 Recovery 安裝* 章節的内容。
2. 開啟核心刷新應用程式提供的 AnyKernel3 Zip 檔案進行刷新。
如果您先前並未使用過核心刷新應用程式,可以嘗試下面幾個方法:
1. [Kernel Flasher](https://github.com/capntrips/KernelFlasher/releases)
2. [Franco Kernel Manager](https://play.google.com/store/apps/details?id=com.franco.kernel)
3. [Ex Kernel Manager](https://play.google.com/store/apps/details?id=flar2.exkernelmanager)
PS. 這種方法在更新 KernelSU 時比較方便,無需電腦即可完成 (注意備份!)。
## 使用 KernelSU 提供的 boot.img 安裝 {#install-by-kernelsu-boot-image}
這種方法無需您有 TWRP也無需您的手機有 Root 權限;適用於您初次安裝 KernelSU。
### 找到合適的 boot.img {#found-propery-image}
KernelSU 為 GKI 裝置提供了標準 boot.img您需要將 boot.img 刷新至裝置的 Boot 分割區。
您可以從 [GitHub Release](https://github.com/tiann/KernelSU/releases) 下載 boot.img請注意您應該使用正確版本的 boot.img。例如如果您的裝置顯示核心是 `android12-5.10.101`,需要下載 `android-5.10.101_yyyy-MM.boot-<format>.img`.
其中 `<format>` 指的是您的官方 boot.img 的核心壓縮格式,請檢查您原有 boot.img 的核心壓縮格式,您應該使用正確的格式,例如 `lz4``gz`;如果使用不正確的壓縮格式,刷新 Boot 後可能無法開機。
::: info
1. 您可以透過 magiskboot 以取得您的原始 Boot 的壓縮格式;當然,您也可以詢問與您相同型號的其他更有經驗的使用者。另外,核心的壓縮格式通常部會出現變更,如果您使用的某個壓縮格式成功開機,後續可以優先嘗試這個格式。
2. 小米裝置通常 `gz` 或者 **不壓縮**
3. Pixel 裝置有些特殊,請遵循下方的指示。
:::
### 將 boot.img 刷新至裝置 {#flash-boot-image}
使用 `adb` 連接您的裝置,然後執行 `adb reboot bootloader` 進入 fastboot 模式,然後使用此命令刷新 KernelSU
```sh
fastboot flash boot boot.img
```
::: info
如果您的裝置支援 `fastboot boot`,可以先使用 `fastboot boot boot.img` 來先嘗試使用 boot.img 開機進入系統,如果出現意外,重新啟動即可開機。
:::
### 重新開機 {#reboot}
刷新完成後,您應該重新啟動您的裝置:
```sh
fastboot reboot
```
## 手動修補 boot.img {#patch-boot-image}
對於某些裝置來說,其 boot.img 格式並不是很常見,比如 `lz4``gz` 和未壓縮;最典型的就是 Pixel它的 boot.img 格式是 `lz4_legacy` 壓縮ramdisk 可能是 `gz` 也可能是 `lz4_legacy` 壓縮;此時如果您直接刷新 KernelSU 提供的 boot.img手機可能無法開機這時您可以透過手動修補 boot.img 來完成。
一般有兩種修補方法:
1. [Android-Image-Kitchen](https://forum.xda-developers.com/t/tool-android-image-kitchen-unpack-repack-kernel-ramdisk-win-android-linux-mac.2073775/)
2. [magiskboot](https://github.com/topjohnwu/Magisk/releases)
其中Android-Image-Kitchen 適用於在電腦上作業magiskboot 需要手機協作。
### 準備 {#patch-preparation}
1. 取得您手機的原廠 boot.img您可以聯絡您的裝置製造商您也可能需要[payload-dumper-go](https://github.com/ssut/payload-dumper-go)
2. 下載 KernelSU 提供的與您的裝置 KMI 一致地 AnyKernel3 Zip 檔案 (可參閱 *使用自訂 Recovery 安裝*)。
3. 解壓縮 AnyKernel3 Zip 檔案,取得其中的 `Image` 檔案,此檔案為 KernelSU 的核心檔案。
### 使用 Android-Image-Kitchen {#using-android-image-kitchen}
1. 下載 Android-Image-Kitchen 至您的電腦。
2. 將手機原廠 boot.img 放置於 Android-Image-Kitchen 根目錄。
3. 在 Android-Image-Kitchen 根目錄執行 `./unpackimg.sh boot.img`;此命令會將 boot.img 解除封裝,您會得到一些檔案。
4.`split_img` 目錄中的 `boot.img-kernel` 取代為您從 AnyKernel3 解壓縮出來的 `Image` (注意名稱變更為 boot.img-kernel)。
5. 在 Android-Image-Kitchecn 根目錄執行 `./repackimg.sh`;此時您會得到一個 `image-new.img` 檔案;使用此 boot.img 透過 fastboot 刷新即可 (刷新方法請參閱上一章節)。
### 使用 magiskboot {#using magiskboot}
1. 在 Magisk 的 [Release 頁面](https://github.com/topjohnwu/Magisk/releases) 下載最新的 Magisk 安裝套件。
2. 將 Magisk-*.apk 重新命名為 Magisk-vesion.zip 然後解壓縮。
3. 將解壓縮後的 `Magisk-v25.2/lib/arm64-v8a/libmagiskboot.so` 檔案,使用 Adb 推入至手機:`adb push Magisk-v25.2/lib/arm64-v8a/libmagiskboot.so /data/local/tmp/magiskboot`
4. 使用 Adb 將原廠 boot.img 和 AnyKernel3 中的 Image 推入至手機。
5. adb shell 進入 /data/local/tmp/ 目錄,然後賦予先前推入檔案的可執行權限 `chmod +x magiskboot`
6. adb shell 進入 /data/local/tmp/ 目錄,執行 `./magiskboot unpack boot.img` 此時會將 `boot.img` 解除封裝,得到一個名為 `kernel` 的檔案,這個檔案是您的原廠核心。
7. 使用 `Image` 取代 `kernel`: `mv -f Image kernel`
8. 執行 `./magiskboot repack boot.img` 重新封裝 img此時您會得到一個 `new-boot.img` 檔案,透過 Fastboot 將這個檔案刷新至裝置即可。
## 其他替代方法 {#other-methods}
其實所有這些安裝方法的主旨只有一個,那就是**將原廠核心取代為 KernelSU 提供的核心**;只要能實現這個目的,就可以安裝;比如以下是其他可行的方法:
1. 首先安裝 Magisk透過 Magisk 取得 Root 權限後使用核心刷新程式刷新 KernelSU 的 AnyKernel Zip。
2. 使用某些 PC 上的刷新工具組刷新 KernelSU 提供的核心。

View File

@@ -0,0 +1,262 @@
# 模組指南 {#introduction}
KernelSU 提供了一個模組機制,它可以在保持系統分割區完整性的同時達到修改系統分割區的效果;這種機制一般被稱為 systemless。
KernelSU 的模組運作機制與 Magisk 幾乎相同,如果您熟悉 Magisk 模組的開發,那麼開發 KernelSU 的模組大同小異,您可以跳過下列有關模組的介紹,只需要瞭解 [KernelSU 模組與 Magisk 模組的異同](difference-with-magisk.md)。
## Busybox
KernelSU 提供了一個完備的 BusyBox 二進位檔案 (包括完整的 SELinux 支援)。可執行檔位於 `/data/adb/ksu/bin/busybox`
KernelSU 的 BusyBox 支援同時執行時可切換的 "ASH Standalone Shell Mode"。
這種讀了模式意味著在執行 BusyBox 的 ash shell 時,每個命令都會直接使用 BusyBox 中內建的應用程式,而不論 PATH 的設定為何。
例如,`ls``rm``chmod` 等命令將不會使用 PATH 中設定的命令 (在 Android 的狀況下,預設狀況下分別為 `/system/bin/ls``/system/bin/rm``/system/bin/chmod`),而是直接呼叫 BusyBox 內建的應用程式。
這確保了指令碼始終在可預測的環境中執行,並始終具有完整的命令套件,不論它執行在哪個 Android 版本上。
要強制下一個命令不使用 BusyBox您必須使用完整路徑呼叫可執行檔。
在 KernelSU 上下文中執行的每個 shell 指令碼都將在 BusyBox 的 ash shell 中以獨立模式執行。對於第三方開發人員相關的內容,包括所有開機指令碼和模組安裝指令碼。
對於想要在 KernelSU 之外使用這個「獨立模式」功能的使用者,有兩種啟用方法:
1. 將環境變數 `ASH_STANDALONE` 設為 `1`。例如:`ASH_STANDALONE=1 /data/adb/ksu/bin/busybox sh <script>`
2. 使用命令列選項切換:`/data/adb/ksu/bin/busybox sh -o standalone <script>`
為了確保所有後續的 `sh` shell 都在獨立模式下執行,第一種是首選方法 (這也是 KernelSU 和 KernelSU 管理員內部使用的方法),因為環境變數會被繼承到子處理程序中。
::: tip 與 Magisk 的差異
KernelSU 的 BusyBox 現在是直接使用 Magisk 專案編譯的二進位檔案,**感謝 Magisk**
因此,您完全不必擔心 BusyBox 指令碼與在 Magisk 和 KernelSU 之間的相容性問題,因為它們完全相同!
:::
## KernelSU 模組 {#kernelsu-modules}
KernelSU 模組是一個放置於 `/data/adb/modules` 且滿足下列結構的資料夾:
```txt
/data/adb/modules
├── .
├── .
|
├── $MODID <--- 模組的資料夾名稱與模組 ID 相同
│ │
│ │ *** 模組識別 ***
│ │
│ ├── module.prop <--- 這個檔案儲存與模組相關的中繼資料,例如模組 ID、版本等
│ │
│ │ *** 主要內容 ***
│ │
│ ├── system <--- 這個資料夾會在 skip_mount 不存在時被掛接至系統
│ │ ├── ...
│ │ ├── ...
│ │ └── ...
│ │
│ │ *** 狀態旗標 ***
│ │
│ ├── skip_mount <--- 如果這個檔案存在,那麼 KernelSU 將不會掛接您的系統資料夾
│ ├── disable <--- 如果這個檔案存在,那麼模組將會被停用
│ ├── remove <--- 如果這個檔案存在,那麼模組將會在下次重新開機時被移除
│ │
│ │ *** 選用檔案 ***
│ │
│ ├── post-fs-data.sh <--- 這個指令碼將會在 post-fs-data 中執行
│ ├── service.sh <--- 這個指令碼將會在 late_start 服務中執行
| ├── uninstall.sh <--- 這個指令碼將會在 KernelSU 移除模組時執行
│ ├── system.prop <--- 這個檔案中指定的屬性將會在系統啟動時透過 resetprop 變更
│ ├── sepolicy.rule <--- 這個檔案中的 SELinux 原則將會在系統開機時載入
│ │
│ │ *** 自動產生的目錄,不要手動建立或修改! ***
│ │
│ ├── vendor <--- A symlink to $MODID/system/vendor
│ ├── product <--- A symlink to $MODID/system/product
│ ├── system_ext <--- A symlink to $MODID/system/system_ext
│ │
│ │ *** 允許的其他額外檔案/資料夾 ***
│ │
│ ├── ...
│ └── ...
|
├── another_module
│ ├── .
│ └── .
├── .
├── .
```
::: tip 與 Magisk 的差異
KernelSU 沒有內建的針對 Zygisk 的支援,因此模組中沒有與 Zygisk 相關的內容,但您可以透過 [ZygiskOnKernelSU](https://github.com/Dr-TSNG/ZygiskOnKernelSU) 以支援 Zygisk 模組,此時 Zygisk 模組的內容與 Magisk 所支援的 Zygisk 完全相同。
:::
### module.prop
module.prop 是一個模組的組態檔案,在 KernelSU 中如果模組中不包含這個檔案,那麼它將不被認為是一個模組;這個檔案的格式如下:
```txt
id=<string>
name=<string>
version=<string>
versionCode=<int>
author=<string>
description=<string>
```
- id 必須與這個規則運算式相符:`^[a-zA-Z][a-zA-Z0-9._-]+$` 例如:✓ `a_module`,✓ `a.module`,✓ `module-101`,✗ `a module`,✗ `1_module`,✗ `-a-module`。這是您的模組的唯一識別碼,發表後將無法變更。
- versionCode 必須是一個整數,用於比較版本。
- 其他未在上方提到的內容可以是任何單行字串。
- 請確保使用 `UNIX (LF)` 分行符號類型,而非 `Windows (CR + LF)``Macintosh (CR)`
### Shell 指令碼 {#shell-scripts}
請閱讀 [開機指令碼](#boot-scripts) 章節,以瞭解 `post-fs-data.sh``service.sh` 之間的差別。對於大多數模組開發人員來說,如果您只需要執行一個開機指令碼,`service.sh` 應該已經足夠了。
在您的模組中的所有指令碼中,請使用 `MODDIR=${0%/*}` 以取得您的模組基本目錄路徑;請不要在指令碼中以硬式編碼的方式加入您的模組路徑。
:::tip 與 Magisk 的差異
您可以透過環境變數 `KSU` 來判斷指令碼是執行在 KernelSU 還是 Magisk 中,如果執行在 KernelSU這個值會被設為 `true`
:::
### `system` 目錄 {#system-directories}
這個目錄的內容會在系統啟動後,以 `overlayfs` 的方式覆疊在系統的 `/system` 分割區之上,這表示:
1. 系統中對應目錄的相同名稱的檔案會被此目錄中的檔案覆寫。
2. 系統中對應目錄的相同名稱的檔案會與此目錄的檔案合併。
如果您想要刪除系統先前的目錄中的某個檔案或資料夾,您需要在模組目錄中透過 `mknod filename c 0 0` 以建立一個 `filename` 的相同名稱的檔案;這樣 overlayfs 系統會自動「whiteout」等效刪除這個檔案 (`/system` 分割區並未被變更)。
您也可以在 `customize.sh` 中宣告一個名為 `REMOVE` 並且包含一系列目錄的變數以執行移除作業KernelSU 會自動為您在模組對應目錄執行 `mknod <TARGET> c 0 0`。例如:
```sh
REMOVE="
/system/app/YouTube
/system/app/Bloatware
"
```
上方的清單將會執行:`mknod $MODPATH/system/app/YouTuBe c 0 0``mknod $MODPATH/system/app/Bloatware c 0 0`;並且 `/system/app/YouTube``/system/app/Bloatware` 將會在模組生效前移除。
如果您想要取代系統的某個目錄,您需要在模組目錄中建立一個相同路徑的目錄,然後為此目錄設定此屬性:`setfattr -n trusted.overlay.opaque -v y <TARGET>`;這樣 overlayfs 系統會自動將對應目錄取代 (`/system` 分割區並未被變更)。
您可以在 `customize.sh` 中宣告一個名為 `REMOVE` 並且包含一系列目錄的變數以執行移除作業KernelSU 會自動為您在模組對應目錄執行相關作業。例如:
```sh
REPLACE="
/system/app/YouTube
/system/app/Bloatware
"
```
上方的清單將會執行:自動建立目錄 `$MODPATH/system/app/YouTube``$MODPATH//system/app/Bloatware`,然後執行 `setfattr -n trusted.overlay.opaque -v y $$MODPATH/system/app/YouTube``setfattr -n trusted.overlay.opaque -v y $$MODPATH/system/app/Bloatware`;並且 `/system/app/YouTube``/system/app/Bloatware` 將會在模組生效後被取代為空白目錄。
::: tip 與 Magisk 的差異
KernelSU 的 systemless 機制透過核心的 overlayfs 實作,而 Magisk 目前則是透過 magic mount (bind mount),兩者的實作方式有很大的差別,但最終的目標是一致的:不修改實際的 `/system` 分割區但修改 `/system` 檔案。
:::
如果您對 overlayfs 感興趣,建議閱讀 Linux Kernel 關於 [overlayfs 的文件](https://docs.kernel.org/filesystems/overlayfs.html)
### system.prop
這個檔案的格式與 `build.prop` 完全相同:每一行都是由 `[key]=[value]` 組成。
### sepolicy.rule
如果您的模組需要一些額外 SELinux 原則修補程式,請將這些原則新增至這個檔案中。這個檔案的每一行都將被視為一個原則陳述。
## 模組安裝程式 {#module-installer}
KernelSU 的模組安裝程式就是一個可以透過 KernelSU 管理員應用程式刷新的 Zip 檔案,這個 Zip 檔案的格式如下:
```txt
module.zip
├── customize.sh <--- (Optional, more details later)
│ This script will be sourced by update-binary
├── ...
├── ... /* 其他模块文件 */
```
:::warning
KernelSU 模組不支援在 Recovery 中安裝!!
:::
### 自訂安裝程序 {#customizing-installation}
如果您想要控制模組的安裝程序,可以在模組的目錄下建立一個名為 `customize.sh` 的檔案,這個檔案將會在模組被解壓縮後**匯入**至目前的 shell 中,如果您的模組需要依據裝置的 API 版本或裝置架構執行一些額外的作業,這個指令碼將非常有用。
如果您想完全控制指令碼的安裝程序,您可以在 `customize.sh` 中宣告 `SKIPUNZIP=1` 以跳過所有的預設安裝步驟;此時,您需要自行處理所有的安裝程序 (例如解壓縮模組、設定權限等)
`customize.sh` 指令碼以「獨立模式」執行在 KernelSU 的 BusyBox `ash` shell 中。您可以使用下列變數和函式:
#### 變數 {#variables}
- `KSU` (bool): 標示此指令碼執行於 KernelSU 環境中,此變數的值將永遠為 `true`,您可以透過它與 Magisk 進行區分。
- `KSU_VER` (string): KernelSU 目前的版本名稱 (例如 `v0.4.0`)
- `KSU_VER_CODE` (int): KernelSU 使用者空間目前的版本代碼 (例如 `10672`)
- `KSU_KERNEL_VER_CODE` (int): KernelSU 核心空間目前的版本代碼 (例如 `10672`)
- `BOOTMODE` (bool): 此變數在 KernelSU 中永遠為 `true`
- `MODPATH` (path): 目前模組的安裝目錄
- `TMPDIR` (path): 可以存放暫存檔的位置
- `ZIPFILE` (path): 目前模組的安裝程式 Zip
- `ARCH` (string): 裝置的 CPU 架構,有這幾種:`arm`, `arm64`, `x86`, or `x64`
- `IS64BIT` (bool): 是否為 64 位元裝置
- `API` (int): 目前裝置的 Android API 版本 (例如 Android 6.0 上為 `23`)
::: warning
`MAGISK_VER_CODE` 在 KernelSU 永遠為 `25200``MAGISK_VER` 則為 `v25.2`,請不要透過這兩個變數來判斷是否為 KernelSU
:::
#### 函式 {#functions}
```txt
ui_print <msg>
print <msg> to console
Avoid using 'echo' as it will not display in custom recovery's console
abort <msg>
print error message <msg> to console and terminate the installation
Avoid using 'exit' as it will skip the termination cleanup steps
set_perm <target> <owner> <group> <permission> [context]
if [context] is not set, the default is "u:object_r:system_file:s0"
this function is a shorthand for the following commands:
chown owner.group target
chmod permission target
chcon context target
set_perm_recursive <directory> <owner> <group> <dirpermission> <filepermission> [context]
if [context] is not set, the default is "u:object_r:system_file:s0"
for all files in <directory>, it will call:
set_perm file owner group filepermission context
for all directories in <directory> (including itself), it will call:
set_perm dir owner group dirpermission context
```
## 開機指令碼 {#boot-scripts}
在 KernelSU 中依據指令碼執行模式的不同分為兩種post-fs-data 模式和 late_start 服務模式。
- post-fs-data 模式
- 這個階段是「封鎖」的。在執行完成之前或 10 秒鐘之後,開機程序會被暫停。
- 指令碼在任何模組被掛接之前執行。這使模組開發人員可以在模組被掛接之前動態調整他們的模組。
- 這個階段發生在 Zygote 啟動之前,這意味著 Android 中的一切。
- 使用 setprop 會導致開機程序死鎖!請使用 `resetprop -n <prop_name> <prop_value>` 替代。
- **僅在必要時在此模式中執行指令碼**。
- late_start 服務模式
- 這個階段是「非封鎖」的。您的指令碼會與其餘的啟動程序**平行**執行。
- **大多数脚本都建议在这种模式下运行**。
在 KernelSU 中,開機指令碼依據存放位置的不同還分為兩種:一般指令碼和模組指令碼。
- 一般指令碼
- 放置於 `/data/adb/post-fs-data.d``/data/adb/service.d` 中。
- 僅有指令碼被設為可執行 (`chmod +x script.sh`) 時才會被執行。
-`post-fs-data.d` 中的指令碼以 post-fs-data 模式執行,在 `service.d` 中的指令碼以 late_start 服務模式執行。
- 模組**不應**在安裝程序中新增一般指令碼。
- 模組指令碼
- 放置於模組自己的資料夾中。
- 僅有在模組啟用時才會執行。
- `post-fs-data.sh` 以 post-fs-data 模式執行,而 `service.sh` 則以 late_start 服務模式執行。
所有启动脚本都将在 KernelSU 的 BusyBox ash shell 中运行,并启用“独立模式”。

View File

@@ -0,0 +1,50 @@
# 搶救開機迴圈 {#intruduction}
在刷新裝置時,我們很可能會遇到裝置「變磚」的狀況,從理論上講,如果您只是使用 Fastboot 刷新 Boot 分割區或者安裝不合適的模組導致裝置無法開機,那麼這都可以透過合適的作業還原您的手機;這個文件提供一些緊急方法可以讓您在「變磚」中還原。
## 刷新 Boot 時變磚
在 KernelSU 中,刷新 boot 時變磚有下列原因:
1. 你刷新了錯誤格式的 Boot 映像。比如您的手機 Boot 格式為 `gz`,但您刷新 `lz4` 格式的映像,那麼此時手機將無法開機。
2. 您的手機需要關閉 AVB 驗證才可正常開機 (這通常需要抹除手機上的所有資料)。
3. 您的核心存在某些錯誤或您的核心並不適合這部手機刷新。
無論哪種狀況,您都可以透過**刷新原廠 Boot**還原;因此,在安裝教學最開始,我們已經強烈建議大家,在刷新之前備份自己的原廠 Boot如果您沒有備份那麼您可以透過其他與您相同裝置的使用者或官方韌體擷取 Boot。
## 刷新模組變磚
刷新模組變磚可能是大家遇到的更常見的狀況,但是這裡要嚴正警示大家:**不要刷新未知來源的模組!!**。因為模組擁有 Root 權限,它能完全對您的裝置造成無法復原的損壞!
### 一般模組
如果大家刷新了某些開放原始碼的或者被證明是安全的模組使手機無法開機,那麼這種狀況在 KernelSU 中非常容易還原也無需擔心。KernelSU 內建了下列兩種機制以搶救您的裝置:
1. AB 更新
2. 透過按下「音量 -」搶救
#### AB 更新 {#ab-update}
KernelSU 的模組借鑒了 Android 系統 OTA 更新時的 AB 更新機制,如果您安裝了新模組或者對現存模組進行了更新作業,不會直接修改目前使用的模組檔案,而是會把所有模組建置為另外一個更新映像;系統重新啟動後,會使用這個更新映像嘗試重新啟動一次,如果 Android 系統成功開機,模組才會真正更新。
因此,最簡單最常用的搶救方法就是:**強制重新開機一次**。如果您在刷新某個模組之後系統無法開機,您可以長按電源按鈕超過 10 秒,系統會自動重新開機;模組會回復為更新前的狀態,先前更新的模組也將會被自動停用。
#### 透過按下「音量 -」搶救 {#volume-down}
如果 AB 更新仍然無法解決,您可以嘗試使用**安全模式**。進入安全模式之後,所有的模組將會被停用。
進入安全模式的方法有兩種:
1. 某些系統內建的安全模式;有些系統是長按「音量 -」,有些系統 (例如 MIUI) 可以在 Recovery 中啟用安全模式。進入系統的安全模式後KernelSU 也會進入安全模式,並自動停用模組。
2. KernelSU 內建的安全模式;作業方法:開機第一個畫面後,**連續按下「音量 -」按鈕超過三次**。注意是按下-抬起、按下-抬起、按下-抬起,並非一直按下。
進入安全模式後KernelSU 管理員的模組頁面的所有模組將會被停用,但您可以執行「解除安裝」作業,將可能存在問題的模組解除安裝。
內建的安全模式在核心中實作,因此不會出現按鍵活動無法攔截的狀況。不過對於非 GKI 核心,可能需要手動整合程式碼,可以參閱官方文件指南。
### 惡意模組
如果以上方法無法搶救您的裝置,那麼很可能您安裝的模組存在惡意作業或透過其他方式損壞了您的裝置,在這種狀況下,只有兩個建議:
1. 抹除資料並刷新官方系統。
2. 諮詢售後服務。

View File

@@ -0,0 +1,30 @@
# 非官方支援裝置
::: warning
本文件列出由其他開發人員維護的支援 KernelSU 的非 GKI 裝置核心
:::
::: warning
本文件仅便於尋找裝置對應原始碼,這並非意味著這些原始碼**被** KernelSU 開發人員**審查**,您應自行承擔風險。
:::
<script setup>
import data from '../../repos.json'
</script>
<table>
<thead>
<tr>
<th>維護者</th>
<th>存放庫</th>
<th>支援裝置</th>
</tr>
</thead>
<tbody>
<tr v-for="repo in data" :key="repo.devices">
<td><a :href="repo.maintainer_link" target="_blank" rel="noreferrer">{{ repo.maintainer }}</a></td>
<td><a :href="repo.kernel_link" target="_blank" rel="noreferrer">{{ repo.kernel_name }}</a></td>
<td>{{ repo.devices }}</td>
</tr>
</tbody>
</table>

View File

@@ -0,0 +1,21 @@
# 什麼是 KernelSU {#introduction}
KernelSU 是 Android GKI 裝置的 Root 解決方案,它以核心模式運作,並直接在核心空間中為使用者空間應用程式授予 Root 權限。
## 功能 {#features}
KernelSU 的主要功能是它是**以核心為基礎的**。 KernelSU 在核心空間中執行,所以它可以向我們提供從未有過的核心介面。例如,我們可以在核心模式中為任何處理程序新增硬體中斷點;我們可以在任何處理程序的實體記憶體中存取,而無人知曉;我們可以在核心空間攔截任何系統呼叫;等等。
KernelSU 還提供了一個以 overlayfs 為基礎的模組系統,允許您將自訂外掛程式載入到系統中。它還提供了一種修改 /system 分割區中檔案的機制。
## 如何使用 {#how-to-use}
請參閱:[安裝](installation)
## 如何建置 {#how-to-build}
请參閱:[如何建置](how-to-build)
## 討論 {#discussion}
- Telegram: [@KernelSU](https://t.me/KernelSU)

View File

@@ -0,0 +1,29 @@
---
layout: home
title: Android 上以核心為基礎的 Root 解決方案
hero:
name: KernelSU
text: Android 上以核心為基礎的 root 解決方案
tagline: ""
image:
src: /logo.png
alt: KernelSU
actions:
- theme: brand
text: 開始瞭解
link: /zh_TW/guide/what-is-kernelsu
- theme: alt
text: 在 GitHub 中檢視
link: https://github.com/tiann/KernelSU
features:
- title: 以核心為基礎
details: KernelSU 以 Linux 核心模式運作,對使用者空間有更強的掌控。
- title: 白名單存取控制
details: 僅有被授予 Root 權限的應用程式才可存取 `su`,而其他應用程式完全無法知悉。
- title: 模組支援
details: KernelSU 支援透過 overlayfs 修改 /system它甚至可以使 /system 可寫入。
- title: 開放原始碼
details: KernelSU 是 GPL-3 授權下的開放原始碼專案。