记一次对W527的第三方内核编写(一)

SoraNeko 发布于 23 天前 78 次阅读


记一次对w527的内核适配

前言

高三的时候整了一块w527的手表 s100这屏幕的确很诱人 以至于到了大学我还是很想用这块屏幕做小板子

https://e.tb.cn/h.8EY5ZKgedemAujA?tk=n0M2TO1KWNA

大概这个样样 多好看 全面屏 480*480

不过他用的ic不一样 是icn3312 一个没有任何驱动的奇怪ic

包括快充芯片也是eta6947这个奇怪东西 现在应该你在github上找到的都是我当时写的

这就很难办了 当时社区里也没有合适的内核 甚至内核驱动有些也是孤品

所以我选择了用别人的0.1成品内核作为底稿

剩下的...那就只能自己写了 oops

那 总结一下配置

soc:w527(ums312)
pmic:sc2730
charge:eta6947
screen:icn3312
audio:asoc
gravity:da217
touchscreen:hynts
kernel:4.14.98

第一 最基本的编译启动

emm 紫光总是很奇怪的 我起初不理解为什么用过那么多紫光4.14全是gcc4.9.x

所以我第一次选择了头铁用clang/Ubuntu自带的gcc

毕竟一开始怎么配置工具链都配置不好 所以用本机gcc自然是很好的选择

当然啦 最大的前提还没说呢 就是紫光真的好好写了代码 而不是一堆雷霆指针配高版本gcc的雷霆优化 把很多的指针写入变成了一坨大便

      - name: Install dependencies
        run: |
          sudo apt update
          sudo apt install -y git make bc bison flex libssl-dev build-essential \
                              gcc-aarch64-linux-gnu clang libyaml-dev

      - name: Build kernel
        run: |
          export ARCH=arm64
          export CROSS_COMPILE=aarch64-linux-gnu-
          export CC=clang
          export LD=aarch64-linux-gnu-ld

          # 加载 defconfig
          make sprd_sharkl5_s100_defconfig

方便维护和在学校做 所以我选择了ghactions

这一段看起来人畜无害的东西 也编出来了一个看着没什么问题的内核

但是!一刷入问题就来了

[   35.415455] c0 Internal error: Oops: 96000061 [#1] PREEMPT SMP
[   35.418097] c3 init: starting service 'bootanim'...
[   35.421196] c0 dump_die_cb in.
[   35.429063] c0 dump_die_cb save pregs_die_g ok .
[   35.433647] c0 dump_die_cb out.
[   35.436764] c0 Modules linked in: sprd_fm(O) sprdbt_tty(O) pvrsrvkm(O) cyttsp5_i2c_ts(O) flash_ic_aw3642(O) flash_ic_ocp8137(O) flash_ic_sc2703(O) mmdvfs(O) sprd_cpp(O) sprd_flash_drv(O) sprd_sensor(O)
[   35.454603] c0 CPU: 0 PID: 741 Comm: HwBinder:661_1 Tainted: G S      W  O    4.14.98-KawaiiSoraNeko #1
[   35.463938] c0 Hardware name: Unisoc UWS6152 1H10 board (DT)
[   35.469562] c0 task: ffffffc0d1c28000 task.stack: ffffff8013d08000
[   35.475714] c0 PC is at dpu_init+0xb0/0x4dc
[   35.479864] c0 LR is at sprd_crtc_atomic_enable+0x13c/0x160
[   35.485398] c0 pc : [
<ffffff80084a8618>] lr : [<ffffff800849dbe0>] pstate: 40400045
[   35.493013] c0 sp : ffffff8013d0b970
[   35.496569] c0 x29: ffffff8013d0b9c0 x28: ffffffc0f9ebd700 
[   35.506341] c0 x27: ffffffc0d180df10 x26: ffffffc0de9d2800 
[   35.511878] c0 x25: ffffff80089be790 x24: 0000000000000038 
[   35.517416] c0 x23: ffffff80090c3638 x22: ffffff80090c366c 
[   35.522955] c0 x21: ffffffc0f9ebd7e0 x20: ffffffc0f9ebd788 
[   35.528493] c0 x19: 0000000000000000 x18: 0000000000000000 
[   35.534032] c0 x17: 0000007f34ba6bc4 x16: ffffff8008209494 
[   35.539570] c0 x15: 000000000000000a x14: 0000000000f42400 
[   35.545109] c0 x13: ffffffffffffffff x12: ffffff8009067000 
[   35.550648] c0 x11: 0000000000040000 x10: ffffff80091d2012 
[   35.556186] c0 x9 : 000000000000005c x8 : 0000000000000000 
[   35.561723] c0 x7 : 0000000000000001 x6 : ffffff80091d1000 
[   35.567263] c0 x5 : 0000000000000000 x4 : 000000000000000c 
[   35.572800] c0 x3 : 0000000000440000 x2 : 0000ffff00000000 
[   35.578339] c0 x1 : ffffff8009791000 x0 : ffffff8009791800 
[   35.583883] c0 
[   35.583883] c0 PC: 0xffffff80084a8598:
[   35.589329] c0 8598  394046e4 f9478422 f90027e2 d2800002 f9400001 b9002c3f b9403003 b9404002
[   35.597723] c0 85b8  b900083f 2a024062 39404ae3 29040822 394052e2 531c6c63 2a023062 39404ee3
[   35.606118] c0 85d8  2a032083 2a030042 52a00883 2a030042 b9000c22 52880042 72a00022 b9001022
[   35.606138] c0 85f8  39407c02 34000042 97fff9e4 91200020 b908003f d2dfffe2 9100d2f6 d2800013
[   35.606158] c0 8618  f803c002 f8044002 12bfffc0 b9080c20 529fffe0 b901e420 f9400295 b902d2b3
[   35.606177] c0 8638  d28218e0 9411e538 78737ac0 91000673 b902d6a0 f104027f 54ffff21 900028d6
[   35.606205] c0 8658 
[   35.618762] c0  9105a2d6 9104a2d8 f0003b20 aa1803e1 91003800 97f16356 d0007ca0 912ff013
[   35.618781] c0 8678  b940a261 36000161 b94bfc02 aa1803e1 b9400663 2a034040 b90026a0 d0003b20
[   35.666620] c0 
[   35.666620] c0 LR: 0xffffff800849db60:
[   35.672070] c0 db60  f9442260 b40000a0 f9400401 b4000061 aa1403e0 d63f0020 39407e80 340000e0
[   35.680467] c0 db80  f9442260 b40000a0 f9400c01 b4000061 aa1403e0 d63f0020 f9441e60 b40000a0
[   35.688860] c0 dba0  f9400401 b4000061 aa1403e0 d63f0020 f9441e60 b40000a0 f9400c01 b4000061
[   35.697256] c0 dbc0  aa1403e0 d63f0020 f9441a60 b40000a0 f9400801 b4000061 aa1403e0 d63f0020
[   35.705648] c0 dbe0  f9441a60 b40000a0 f9402401 b4000061 aa1403e0 d63f0020 52800020 39007a80
[   35.714043] c0 dc00  17ffffc7 2a0003e1 7100141f 54000129 a9bf7bfd 90003b80 91037c00 910003fd
[   35.714063] c0 dc20  97f18de9 d2800000 a8c17bfd d65f03c0 f0007ce0 911da000 f861d800 d65f03c0
[   35.714083] c0 dc40  a9bf7bfd f0007ce0 911da000 910003fd b0006121 91370021 a9007c1f a9017c1f
[   35.743472] c0 
[   35.743472] c0 SP: 0xffffff8013d0b8f0:
[   35.748918] c0 b8f0  00000038 00000000 089be790 ffffff80 de9d2800 ffffffc0 d180df10 ffffffc0
[   35.757312] c0 b910  f9ebd700 ffffffc0 13d0b9c0 ffffff80 0849dbe0 ffffff80 13d0b970 ffffff80
[   35.765707] c0 b930  084a8618 ffffff80 40400045 00000000 f9f02c00 ffffffc0 00000040 00000000
[   35.774101] c0 b950  ffffffff 0000007f 0943fd00 ffffff80 13d0b9c0 ffffff80 084a8618 ffffff80
[   35.782496] c0 b970  f9f0f100 ffffffc0 00000040 00000000 f92bf480 ffffffc0 0943fd00 ffffff80
[   35.790889] c0 b990  13d0b9c0 ffffff80 0841834c ffffff80 f9f0f100 ffffffc0 00000040 00000000
[   35.799283] c0 b9b0  13d0b9c0 ffffff80 ddc27f00 bf5c3499 13d0ba20 ffffff80 0849dbe0 ffffff80
[   35.807677] c0 b9d0  f9ebd018 ffffffc0 f9ebd788 ffffffc0 f9ebd7e0 ffffffc0 08c086ac ffffff80
[   35.816082] c0 
[   36.803330] c0 Process HwBinder:661_1 (pid: 741, stack limit = 0xffffff8013d08000)
[   36.803333] c0 Call trace:
[   36.803339] c0 Exception stack(0xffffff8013d0b830 to 0xffffff8013d0b970)
[   36.803346] c0 b820:                                   ffffff8009791800 ffffff8009791000
[   36.803357] c0 b840: 0000ffff00000000 0000000000440000 000000000000000c 0000000000000000
[   36.850644] c0 b860: ffffff80091d1000 0000000000000001 0000000000000000 000000000000005c
[   36.858693] c0 b880: ffffff80091d2012 0000000000040000 ffffff8009067000 ffffffffffffffff
[   36.866741] c0 b8a0: 0000000000f42400 000000000000000a ffffff8008209494 0000007f34ba6bc4
[   36.874789] c0 b8c0: 0000000000000000 0000000000000000 ffffffc0f9ebd788 ffffffc0f9ebd7e0
[   36.882838] c0 b8e0: ffffff80090c366c ffffff80090c3638 0000000000000038 ffffff80089be790
[   36.890885] c0 b900: ffffffc0de9d2800 ffffffc0d180df10 ffffffc0f9ebd700 ffffff8013d0b9c0
[   36.898933] c0 b920: ffffff800849dbe0 ffffff8013d0b970 ffffff80084a8618 0000000040400045
[   36.906981] c0 b940: ffffffc0f9f02c00 0000000000000040 0000007fffffffff ffffff800943fd00
[   36.915027] c0 b960: ffffff8013d0b9c0 ffffff80084a8618
[   36.915040] c0 [
<ffffff80084a8618>] dpu_init+0xb0/0x4dc
[   36.915047] c0 [
<ffffff800849dbe0>] sprd_crtc_atomic_enable+0x13c/0x160
[   36.915056] c0 [
<ffffff800846d86c>] drm_atomic_helper_commit_modeset_enables+0xac/0x18c
[   36.915065] c0 [
<ffffff800849b0f0>] sprd_atomic_commit_tail+0x2c/0x5c
[   36.915073] c0 [
<ffffff800849b564>] sprd_commit_tail+0x40/0x7c
[   36.915080] c0 [
<ffffff800849b8d4>] sprd_atomic_commit+0x31c/0x39c
[   36.915097] c0 [
<ffffff800848ada4>] drm_atomic_commit+0x50/0x5c
[   36.968339] c0 [
<ffffff800848b290>] drm_atomic_connector_commit_dpms+0xd0/0xfc
[   36.975522] c0 [
<ffffff800848fdac>] drm_mode_obj_set_property_ioctl+0xd0/0x250
[   36.982705] c0 [
<ffffff800848e9f0>] drm_mode_connector_property_set_ioctl+0x34/0x5c
[   36.990320] c0 [
<ffffff800847b18c>] drm_ioctl_kernel+0x80/0xc4
[   36.996114] c0 [
<ffffff800847b4e0>] drm_ioctl+0x2ec/0x378
[   37.001484] c0 [
<ffffff8008208b9c>] vfs_ioctl+0x24/0x40
[   37.006674] c0 [
<ffffff8008208d58>] do_vfs_ioctl+0xb4/0x7f0
[   37.012215] c0 [
<ffffff80082094f0>] SyS_ioctl+0x5c/0x8c
[   37.017402] c0 Exception stack(0xffffff8013d0bec0 to 0xffffff8013d0c000)
[   37.024069] c0 bec0: 0000000000000006 00000000c01064ab 0000007c9fece288 0000000000000000
[   37.024076] c0 bee0: 0000000000000000 0000000000000040 0000007f363a4000 00000000000038ce
[   37.024084] c0 bf00: 000000000000001d 0000007c9fece200 0000007c9fece200 0000007c9fece1d0
[   37.024093] c0 bf20: ffffff80ffffffd0 000000000000003a 0030a32beb081480 00000f37484e962e
[   37.060501] c0 bf40: 0000007ca18fcd90 0000007f34ba6bc4 0000007c9fb6a000 0000007c9fecf008
[   37.068551] c0 bf60: 00000000c01064ab 0000000000000006 0000000000000006 0000007df45ae2f0
[   37.076597] c0 bf80: 000000000000004f 0000007f349bc038 0000000000000000 00000000000fb000
[   37.084645] c0 bfa0: 0000007c9fdd7000 0000007c9fece230 0000007f34ba6c64 0000007c9fece150
[   37.092693] c0 bfc0: 0000007f34beb318 0000000080000000 0000000000000006 000000000000001d
[   37.100741] c0 bfe0: 0000000000000000 0000000000000000 0000000000000000 0000000000000000
[   37.108791] c0 [
<ffffff80080832c0>] el0_svc_naked+0x34/0x38
[   37.114330] c0 Code: b908003f d2dfffe2 9100d2f6 d2800013 (f803c002) 
[   37.120643] c0 ---[ end trace 2a21c748f1c53e95 ]---
[   37.145152] c0 Kernel panic - not syncing: Fatal exception
[   37.150546] c0 (sprd_debug_save_context) context saved(CPU:0)
[   37.156337] c0 SMP: stopping secondary CPUs

哎呀 kernel panic了

如果你是聪明的小猫的话 你就会发现他在PC:dpu_init+0xb0处崩溃了

这时候正好是一个

f803c002 → str x2, [x0], #60

六十四位写

是不是很眼熟

· x0:0xffffff8009781800(上一份 0xffffff8009791800)

· x1:0xffffff8009781000(上一份 0xffffff8009791000)

· x2:0x0000ffff00000000

x2 的来历:dpu_init 中相邻的 MMU 初始化代码:

reg->mmu_min_ppn1 = 0;        // 低32位填0
reg->mmu_ppn_range1 = 0xffff; // 高32位填0xffff

编译器把这两个该死的三十二位写合并成了一个六十四位写。

但这里要注意:崩溃时写的地址是 base + 0x800,也就是 mmu_en 的位置,而不是 mmu_min_ppn1(偏移 0x83C)。

指令里的后索引 #60(0x3C)说明编译器打算先写 0x800,然后 x0 += 0x3C 跳到 0x83C 继续写。

但由于第一条写 0x800 就崩了,因为实际映射的寄存器区域可能只有 0x800 长(或者 IOMMU 占了 0x20300800 导致 DPU 映射被截断),总之 0x800 在崩溃时不可写。

我们回顾dpu_lite_r2p0.c里的dpuinit

static int dpu_init(struct dpu_context *ctx)
{
    struct dpu_reg *reg = (struct dpu_reg *)ctx->base;
    u32 size;

    /* set bg color */
    reg->bg_color = 0;

    /* set dpu output size */
    size = (ctx->vm.vactive << 16) | ctx->vm.hactive;
    reg->panel_size = size;
    reg->blend_size = size;

    reg->dpu_cfg0 = 0;
    reg->dpu_cfg1 = (qos_cfg.awqos_high << 12) |
        (qos_cfg.awqos_low << 8) |
        (qos_cfg.arqos_high << 4) |
        (qos_cfg.arqos_low) | BIT(18) | BIT(22);
    reg->dpu_cfg2 = 0x14002;

    if (ctx->is_stopped)
        dpu_clean_all(ctx);

    reg->mmu_en = 0;
    reg->mmu_min_ppn1 = 0;
    reg->mmu_ppn_range1 = 0xffff;
    reg->mmu_min_ppn2 = 0;
    reg->mmu_ppn_range2 = 0xffff;
    reg->mmu_vpn_range = 0x1ffff;

    reg->dpu_int_clr = 0xffff;

    dpu_enhance_reload(ctx);

    dpu_write_back_config(ctx);

    INIT_WORK(&ctx->dvfs_work, dpu_dvfs_work_func);

    return 0;
}

dpu_init 函数(位于 dpu_lite_r2p0.c)的主要流程:

  1. 通过 ctx->base 获取硬件寄存器基址 reg
  2. 配置 DPU 基础寄存器(背景色、输出尺寸、QoS 等)
  3. 调用 dpu_enhance_reload(ctx) 重载增强模块参数
  4. 调用 dpu_write_back_config(ctx) 配置 Write-Back 功能
  5. 使用 INIT_WORK 初始化 dvfs_work 工作队列

其实,到最后发现是紫光的驱动没有用 volatile / writel 来访问 MMIO,reg 只是一个普通指针,编译器(高版本 GCC 或 Clang)就放心大胆地合并、重排这些写操作,结果合并出的 64 位写用后索引跳地址时踩到了未映射区域,导致了 kernel panic。

解决问题不算难也不算简单 我选了最简单的办法 也就是降级回gcc4.9.x

如果你头铁 也可以重写drm这坨答辩 当然 重写的成本就可能是重构整个kernel了

题外话

我在编译的时候遇到了一个问题 也挺神秘的

arch/arm64/Makefile:57: Detected assembler with broken .inst; disassembly will be unreliable
  CHK     include/config/kernel.release
Cannot use CONFIG_CC_STACKPROTECTOR_STRONG: -fstack-protector-strong not supported by compiler
make: *** [Makefile:1206: prepare-compiler-check] Error 1
make: *** Waiting for unfinished jobs....
  UPD     include/config/kernel.release
arch/arm64/Makefile:49: LSE atomics not supported by binutils
arch/arm64/Makefile:57: Detected assembler with broken .inst; disassembly will be unreliable
  CHK     include/config/kernel.release

呃 对 栈保护炸了 但我查了很久 gcc4.9.0就引入了栈保护 那这就奇怪了 4.9.x显而易见超过了4.9.0 为什么会炸呢

emm 引入一下

在内核Makefile的prepare-compiler-check 阶段会检测编译器各个功能的可用性

$(CC) -fstack-protector-strong -c empty.c

大概这样检测

问题就出在这个上。gcc 在编译时,如果需要进行汇编,会自动调用 as(汇编器)来生成目标文件。内核的这个探测命令,恰好会触发这个调用。

Android 预编译的 GCC 4.9 工具链,其 gcc 和 as 是分开存放的,并且 gcc 自身可能并不携带“要去哪里找 as”的完整信息。它通常依赖 PATH 环境变量,或者一系列复杂的 wrapper 脚本来定位同目录下的 as。

解释: 在CI 环境中 gcc在尝试汇编时就会找不到 aarch64-linux-android-as 从而退而求其次 去调用宿主机的 /usr/bin/as。当然 我这里只部署了gcc 所以自然就没有工具链as

显而易见 宿主机是x86as 他压根不知道arm指令

booom!

懂了吧 但是gcc4.9是支持的 所以其实根本没啥影响 关掉这个检测就行

prepare-compiler-check: FORCE
# Skip check
# ifdef CONFIG_CC_STACKPROTECTOR_STRONG
#   @if ! $(CC) -fstack-protector-strong -x c -c /dev/null -o /dev/null >/dev/null 2>&1; then \
#       echo 'Cannot use CONFIG_CC_STACKPROTECTOR_STRONG: -fstack-protector-strong not supported by compiler'; \
#       false; \
#   fi
# endif

那这样就好了 接下来编译就正常了

所以 第一步 他终于不缺符号的卡在了第一屏

并开启了adb

顺带贴一下我的完整ghactions捏

name: Build Pure Kernel (gcc 4.9)

on:
  workflow_dispatch:

permissions:
  contents: write

jobs:
  build:
    runs-on: ubuntu-22.04
    steps:
      - name: Checkout kernel source
        uses: actions/checkout@v4
        with:
          ref: ${{ github.ref_name }}
          submodules: true

      - name: Install dependencies
        run: |
          sudo apt update
          sudo apt install -y git make bc bison flex libssl-dev build-essential \
                              libyaml-dev

      - name: Download and setup GCC 4.9 toolchain
        run: |
          mkdir -p $HOME/toolchains
          cd $HOME/toolchains
          git clone --depth=1 --branch=W20.13.3 \
            --filter=blob:none --no-checkout \
            https://github.com/deadman96385/jingpad_android_bsp.git toolchain-tmp
          cd toolchain-tmp
          git sparse-checkout init --cone
          git sparse-checkout set toolchain/prebuilts/gcc/linux-x86/aarch64/aarch64-linux-android-4.9
          git checkout
          mv toolchain/prebuilts/gcc/linux-x86/aarch64/aarch64-linux-android-4.9 \
             ../aarch64-linux-android-4.9
          cd ..
          rm -rf toolchain-tmp
          chmod -R a+x $HOME/toolchains/aarch64-linux-android-4.9/bin
          echo "$HOME/toolchains/aarch64-linux-android-4.9/bin" >> $GITHUB_PATH

      - name: Verify toolchain
        run: |
          aarch64-linux-android-gcc --version
          aarch64-linux-android-gcc -fstack-protector-strong -c -x c /dev/null -o /dev/null

      - name: Test Telegram connection (text message)
        run: |
          curl -s -X POST "https://api.telegram.org/bot${{ secrets.TELEGRAM_TOKEN }}/sendMessage" \
            -d "chat_id=${{ secrets.TELEGRAM_TO }}" \
            -d "text= GitHub Actions: Build started at $(date -u '+%Y-%m-%d %H:%M:%S UTC')." | tee /dev/stderr
          echo "If the message above shows 'ok:true', your bot can send messages to the chat."

      - name: Unshallow KernelSU submodule
        run: |
          cd KernelSU
          git fetch --unshallow
          git fetch --tags

      - name: Build kernel
        run: |
          export ARCH=arm64
          export CROSS_COMPILE=aarch64-linux-android-

          # ===== 1. 配置 & 编译内核本体 =====
          make sprd_sharkl5_s100_defconfig
          scripts/config --disable CONFIG_APPENDED_DTB
          scripts/config --disable CONFIG_EFI
          scripts/config --disable CONFIG_EFI_STUB
          sed -i '/yamltree\.o/d' scripts/dtc/Makefile
          sed -i 's/dt_to_yaml(/\/\/ dt_to_yaml(/g' scripts/dtc/dtc.c
          sed -i '/ifdef CONFIG_CC_STACKPROTECTOR_STRONG/{n;s/stackp-flag :=.*/stackp-flag := -fstack-protector-strong/}' Makefile
          sed -i '/ifdef stackp-name/,/endif/{s/exit 1/true/}' Makefile
          sed -i '/ifdef stackp-check/,/endif/{s/exit 1/true/}' Makefile
          make olddefconfig
          KCFLAGS="-Wno-error=sizeof-pointer-memaccess -Wno-error=array-bounds -Wno-error=missing-braces -Wno-error=format"
          make -j$(nproc) KCFLAGS="$KCFLAGS" 2>&1 | tee build.log

          # ===== 2. 编译内核内部模块 =====
          make modules 2>&1 | tee -a build.log
          make modules_install INSTALL_MOD_PATH=./modules_out 2>&1 | tee -a build.log

          # ===== 3. 编译外部相机模块(所有需要的子模块) =====
          EXTERNAL_MODULES="modules/common/camera/core \
                            modules/common/camera/sensor \
                            modules/common/camera/flash/flash_drv \
                            modules/common/camera/flash/ocp8137 \
                            modules/common/camera/flash/sc2703s \
                            modules/common/camera/mmdvfs \
                            modules/common/camera/fd"

          # 所有宏(目录名必须和源码实际目录一致)
          EXTRA_ARGS="BSP_BOARD_CAMERA_MODULE_ISP_VERSION=isp2.6"
          EXTRA_ARGS="$EXTRA_ARGS BSP_BOARD_CAMERA_MODULE_CSI_VERSION=receiver_r2p1"
          EXTRA_ARGS="$EXTRA_ARGS BSP_BOARD_CAMERA_MODULE_ISP_ADAPT_VERSION=sharkl5"
          EXTRA_ARGS="$EXTRA_ARGS BSP_BOARD_CAMERA_MODULE_DVFS=sharkl5"
          EXTRA_ARGS="$EXTRA_ARGS BSP_BOARD_CAMERA_MODULE_CPP_VERSION=lite_r4p0"
          EXTRA_ARGS="$EXTRA_ARGS BSP_BOARD_CAMERA_MODULE_FD_VERSION=fd2.0"

          for dir in $EXTERNAL_MODULES; do
            if [ -f "$dir/Kbuild" ] || [ -f "$dir/Makefile" ]; then
              echo "Building external module: $dir"
              make -C . M="$dir" $EXTRA_ARGS modules 2>&1 | tee -a build.log
              make -C . M="$dir" modules_install INSTALL_MOD_PATH=./modules_out 2>&1 | tee -a build.log
            fi
          done

      - name: Locate pure kernel image
        id: find_kernel
        continue-on-error: true
        run: |
          if [ -f arch/arm64/boot/Image.gz ]; then
            echo "kernel_path=arch/arm64/boot/Image.gz" >> $GITHUB_OUTPUT
          elif [ -f arch/arm64/boot/Image ]; then
            echo "kernel_path=arch/arm64/boot/Image" >> $GITHUB_OUTPUT
          else
            echo "No kernel image found!"
            exit 1
          fi

      - name: Send build.log if kernel image not found
        if: steps.find_kernel.outcome == 'failure'
        env:
          BOT_TOKEN: ${{ secrets.TELEGRAM_TOKEN }}
          CHAT_ID: ${{ secrets.TELEGRAM_TO }}
        run: |
          curl -s -F document=@build.log \
            -F "caption= Build failed: kernel image not found. See build.log for details." \
            "https://api.telegram.org/bot${BOT_TOKEN}/sendDocument?chat_id=${CHAT_ID}"
          exit 1

      - name: Package modules
        run: |
          KERNEL_RELEASE=$(make -s kernelrelease 2>/dev/null | grep -v '^#' | tail -1)
          if [ -z "$KERNEL_RELEASE" ]; then
            echo "Error: Could not get kernel release"
            exit 1
          fi
          echo "Kernel release: $KERNEL_RELEASE"

          echo "KERNEL_RELEASE=$(echo $KERNEL_RELEASE | xargs)" >> $GITHUB_ENV

          MODULES_DIR="modules_out/lib/modules/$KERNEL_RELEASE"
          if [ ! -d "$MODULES_DIR" ]; then
            echo "Error: Modules directory not found at $MODULES_DIR"
            exit 1
          fi
          cd "$MODULES_DIR"
          rm -f source build
          tar -czf ../../../../modules.tar.gz .
          zip -r ../../../../modules.zip .
          cd ../../../..
          ls -lh modules.tar.gz modules.zip

      - name: Prepare AnyKernel3 (flattened modules)
        env:
          KERNEL_RELEASE: ${{ env.KERNEL_RELEASE }}
        run: |
          git clone --depth=1 https://github.com/ZeroDreamCat/sprd_ak3.git anykernel
          rm -rf anykernel/.git anykernel/{README.md,ramdisk,patch}
          rm -rf anykernel/modules/system

          cp "${{ steps.find_kernel.outputs.kernel_path }}" anykernel/

          MODULES_FLAT="anykernel/modules/vendor/lib/modules"
          mkdir -p "${MODULES_FLAT}"
          find modules_out/lib/modules/${KERNEL_RELEASE} -name "*.ko" \
            -exec cp {} "${MODULES_FLAT}/" \;

          cd anykernel
          zip -r9 ../AnyKernel3.zip .
          cd ..

      - name: gzip vmlinux
        run: gzip -9 vmlinux

      - name: Package all artifacts for Telegram (exclude vmlinux.gz)
        run: |
          mkdir -p telegram_artifacts
          cp ${{ steps.find_kernel.outputs.kernel_path }} telegram_artifacts/
          cp modules.tar.gz modules.zip telegram_artifacts/ 2>/dev/null || true
          cp System.map Module.symvers build.log telegram_artifacts/ 2>/dev/null || true
          cp AnyKernel3.zip telegram_artifacts/
          cd telegram_artifacts
          zip -9 ../all_artifacts.zip *
          cd ..
          echo "Created all_artifacts.zip (without vmlinux.gz)"
          ls -lh all_artifacts.zip

      - name: Create Release and Upload Artifacts
        uses: softprops/action-gh-release@v1
        with:
          tag_name: build-${{ github.run_id }}
          name: Build - ${{ github.sha }} (${{ github.ref_name }})
          files: |
            ${{ steps.find_kernel.outputs.kernel_path }}
            modules.tar.gz
            modules.zip
            AnyKernel3.zip
            build.log
            System.map
            Module.symvers
            vmlinux.gz
          draft: false
          prerelease: true
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

      - name: Send artifacts to Telegram (lightweight + Release link)
        env:
          BOT_TOKEN: ${{ secrets.TELEGRAM_TOKEN }}
          CHAT_ID: ${{ secrets.TELEGRAM_TO }}
          KERNEL_RELEASE: ${{ env.KERNEL_RELEASE }}
        run: |
          COMMIT_MSG=$(git log -1 --pretty=%s)
          export COMMIT_MSG
          python3 -c "
          import os, requests

          bot_token = os.environ['BOT_TOKEN']
          chat_id = os.environ['CHAT_ID']
          kernel_release = os.environ.get('KERNEL_RELEASE', 'unknown').strip()
          commit_msg = os.environ.get('COMMIT_MSG', 'unknown').strip()
          repo = os.environ.get('GITHUB_REPOSITORY', 'unknown')
          ref = os.environ.get('GITHUB_REF_NAME', 'unknown')
          sha = os.environ.get('GITHUB_SHA', 'unknown')[:7]
          run_id = os.environ.get('GITHUB_RUN_ID', 'unknown')

          release_url = f'https://github.com/{repo}/releases/tag/build-{run_id}'

          zip_file = 'all_artifacts.zip'
          if not os.path.exists(zip_file):
              print(f' {zip_file} not found')
              exit(1)

          size = os.path.getsize(zip_file)
          print(f' Sending {zip_file} ({size} bytes)...')

          caption = (
              f' Build completed!\n'
              f' Kernel version: {kernel_release}\n'
              f' Commit: {commit_msg} ({sha})\n'
              f' Branch: {ref}\n'
              f' Repo: {repo}\n'
              f' Artifacts attached: kernel image, modules, System.map, build.log\n'
              f' Full release (including vmlinux.gz):\n{release_url}'
          )

          with open(zip_file, 'rb') as f:
              resp = requests.post(
                  f'https://api.telegram.org/bot{bot_token}/sendDocument',
                  data={'chat_id': chat_id, 'caption': caption},
                  files={'document': f}
              )
          print(resp.text)
          if resp.ok and resp.json().get('ok'):
              print(' Telegram notification sent successfully!')
          else:
              print(' Failed to send Telegram.')
              exit(1)
          "
此作者没有提供个人介绍。
最后更新于 2026-09-26