diff --git a/.github/workflows/build-minimal.yml b/.github/workflows/build-minimal.yml
new file mode 100644
index 0000000..8143b73
--- /dev/null
+++ b/.github/workflows/build-minimal.yml
@@ -0,0 +1,180 @@
+name: Build minimal
+
+on:
+ workflow_dispatch:
+ repository_dispatch:
+ types: [minimal]
+
+jobs:
+ build:
+ name: Build ${{ matrix.model }}-${{ matrix.tag.version }}
+ runs-on: ubuntu-24.04
+ defaults:
+ run:
+ shell: bash
+ strategy:
+ fail-fast: false
+ matrix:
+ model:
+ - nanopi-r4s
+ - nanopi-r5s
+ - x86_64
+ - netgear_r8500
+ tag:
+ - type: rc2
+ version: openwrt-23.05
+
+ steps:
+ - name: Setup variables
+ run: |
+ sudo timedatectl set-timezone 'Asia/Shanghai'
+ git config --global user.name 'actions'
+ git config --global user.email 'action@github.com'
+ echo build_dir="/builder" >> "$GITHUB_ENV"
+
+ - name: Show system
+ run: |
+ echo -e "\n\e[1;32mCPU:\e[0m"
+ echo "$(grep 'model name' /proc/cpuinfo | head -1 | awk -F ': ' '{print $2}') ($(grep 'cpu MHz' /proc/cpuinfo | head -1 | awk -F ': ' '{print $2}')MHz) x $(grep processor /proc/cpuinfo | wc -l)"
+ echo -e "\n\e[1;32mMemory:\e[0m"
+ free -h
+ echo -e "\n\e[1;32mStorage:\e[0m"
+ df -Th / /mnt
+ echo -e "\n\e[1;32mSystem:\e[0m"
+ lsb_release -a
+ echo -e "\n\e[1;32mKernel:\e[0m"
+ uname -a
+ echo
+
+ - name: Free disk space
+ uses: sbwml/actions@free-disk
+ with:
+ build-mount-path: /builder
+
+ - name: Build System Setup
+ uses: sbwml/actions@openwrt-build-setup
+
+ - name: Compile OpenWrt
+ id: compile
+ continue-on-error: true
+ working-directory: /builder
+ env:
+ git_password: ${{ secrets.ftp_password }}
+ run: |
+ [ "${{ matrix.model }}" != "netgear_r8500" ] && export KERNEL_CLANG_LTO=y
+ export BUILD_FAST=y ENABLE_OTA=y ENABLE_BPF=y ENABLE_LTO=y ENABLE_LRNG=y MINIMAL_BUILD=y USE_GCC15=y ENABLE_MOLD=y
+ bash <(curl -sS ${{ secrets.script_url_general }}) ${{ matrix.tag.type }} ${{ matrix.model }}
+ cd openwrt
+ tags=$(git describe --abbrev=0 --tags)
+ echo "latest_release=$tags" >>$GITHUB_ENV
+
+ - name: Extensive logs after a failed compilation
+ if: steps.compile.outcome == 'failure'
+ working-directory: /builder
+ run: |
+ cd openwrt
+ make V=s IGNORE_ERRORS="n m"
+
+ - name: Prepare Firmware Files
+ working-directory: /builder
+ run: |
+ mkdir -p rom info
+ if [ "${{ matrix.model }}" = "nanopi-r4s" ]; then
+ cp -a openwrt/bin/targets/rockchip/*/*.img.gz rom/
+ cp -a openwrt/bin/targets/rockchip/*/*-r4s.manifest info/manifest.txt
+ cp -a openwrt/bin/targets/rockchip/*/config.buildinfo info/config.buildinfo
+ cd rom && sha256sum * > ../info/sha256sums.txt
+ elif [ "${{ matrix.model }}" = "nanopi-r5s" ]; then
+ cp -a openwrt/bin/targets/rockchip/*/*.img.gz rom/
+ cp -a openwrt/bin/targets/rockchip/*/*.manifest info/manifest.txt
+ cp -a openwrt/bin/targets/rockchip/*/config.buildinfo info/config.buildinfo
+ cd rom && sha256sum * > ../info/sha256sums.txt
+ elif [ "${{ matrix.model }}" = "x86_64" ]; then
+ cp -a openwrt/bin/targets/x86/*/*-ext4-combined-efi.img.gz rom/
+ cp -a openwrt/bin/targets/x86/*/*-squashfs-combined-efi.img.gz rom/
+ cp -a openwrt/bin/targets/x86/*/*-generic-rootfs.tar.gz rom/
+ cp -a openwrt/bin/targets/x86/*/*-x86-64-generic.manifest info/manifest.txt
+ cp -a openwrt/bin/targets/x86/*/config.buildinfo info/config.buildinfo
+ cd rom && sha256sum * > ../info/sha256sums.txt
+ elif [ "${{ matrix.model }}" = "netgear_r8500" ]; then
+ cp -a openwrt/bin/targets/bcm53xx/generic/*-bcm53xx-generic-netgear_r8500-squashfs.chk rom/
+ cp -a openwrt/bin/targets/bcm53xx/generic/*.manifest info/manifest.txt
+ cp -a openwrt/bin/targets/bcm53xx/generic/config.buildinfo info/config.buildinfo
+ cd rom && sha256sum * > ../info/sha256sums.txt
+ fi
+ cd ..
+ tar zcf rom/buildinfo_${{ matrix.model }}.tar.gz info
+
+ - name: Install aliyunpan & login
+ working-directory: /builder
+ timeout-minutes: 1
+ run: |
+ if [ "${{ matrix.model }}" = "nanopi-r4s" ]; then
+ device_id=${{ secrets.device_id_r4s_minimal }}
+ elif [ "${{ matrix.model }}" = "nanopi-r5s" ]; then
+ device_id=${{ secrets.device_id_r5s_minimal }}
+ elif [ "${{ matrix.model }}" = "x86_64" ]; then
+ device_id=${{ secrets.device_id_x86_minimal }}
+ elif [ "${{ matrix.model }}" = "netgear_r8500" ]; then
+ device_id=${{ secrets.device_id_netgear_minimal }}
+ fi
+ sudo wget -q ${{ secrets.aliyunpan_go }} -O /bin/aliyunpan
+ sudo chmod 0755 /bin/aliyunpan
+ sudo sh -c 'echo "${{ secrets.aliyunpan_us_node }} api.alipan.com auth.alipan.com www.alipan.com" >> /etc/hosts'
+ export ALIYUNPAN_CONFIG_DIR="$(pwd)/.aliyunpan"
+ aliyun_token=`curl -s ${{ secrets.aliyun_token }} | openssl enc -aes-256-cfb -pbkdf2 -a -d -k ${{ secrets.token_dec }}`
+ aliyunpan config set -device_id=$device_id >/dev/null 2>&1
+ echo
+ echo $aliyun_token | aliyunpan login
+
+ - name: Upload artifacts
+ uses: actions/upload-artifact@v4
+ with:
+ name: ${{ matrix.model }}-${{ matrix.tag.version }}
+ path: ${{ env.build_dir }}/rom/*.*
+
+ - name: Upload Firmware - Minimal
+ working-directory: /builder
+ timeout-minutes: 45
+ run: |
+ export ALIYUNPAN_CONFIG_DIR="$(pwd)/.aliyunpan"
+ version=$(cat openwrt/version.txt)
+ if [ "${{ matrix.model }}" = "nanopi-r4s" ]; then
+ aliyunpan upload --timeout 30 --retry 10 --ow info/config.buildinfo openwrt/nanopi-r4s/minimal/${{ matrix.tag.version }}/$version/
+ aliyunpan upload --timeout 30 --retry 10 --ow info/manifest.txt openwrt/nanopi-r4s/minimal/${{ matrix.tag.version }}/$version/
+ aliyunpan upload --timeout 30 --retry 10 --ow info/sha256sums.txt openwrt/nanopi-r4s/minimal/${{ matrix.tag.version }}/$version/
+ aliyunpan upload --timeout 30 --retry 10 --ow rom/*-r4s-ext4-sysupgrade.img.gz openwrt/nanopi-r4s/minimal/${{ matrix.tag.version }}/$version/
+ aliyunpan upload --timeout 30 --retry 10 --ow rom/*-r4s-squashfs-sysupgrade.img.gz openwrt/nanopi-r4s/minimal/${{ matrix.tag.version }}/$version/
+ elif [ "${{ matrix.model }}" = "nanopi-r5s" ]; then
+ aliyunpan upload --timeout 30 --retry 10 --ow info/config.buildinfo openwrt/nanopi-r5s/minimal/${{ matrix.tag.version }}/$version/
+ aliyunpan upload --timeout 30 --retry 10 --ow info/manifest.txt openwrt/nanopi-r5s/minimal/${{ matrix.tag.version }}/$version/
+ aliyunpan upload --timeout 30 --retry 10 --ow info/sha256sums.txt openwrt/nanopi-r5s/minimal/${{ matrix.tag.version }}/$version/
+ aliyunpan upload --timeout 30 --retry 10 --ow rom/*-r5c-ext4-sysupgrade.img.gz openwrt/nanopi-r5s/minimal/${{ matrix.tag.version }}/$version/
+ aliyunpan upload --timeout 30 --retry 10 --ow rom/*-r5c-squashfs-sysupgrade.img.gz openwrt/nanopi-r5s/minimal/${{ matrix.tag.version }}/$version/
+ aliyunpan upload --timeout 30 --retry 10 --ow rom/*-r5s-ext4-sysupgrade.img.gz openwrt/nanopi-r5s/minimal/${{ matrix.tag.version }}/$version/
+ aliyunpan upload --timeout 30 --retry 10 --ow rom/*-r5s-squashfs-sysupgrade.img.gz openwrt/nanopi-r5s/minimal/${{ matrix.tag.version }}/$version/
+ elif [ "${{ matrix.model }}" = "x86_64" ]; then
+ aliyunpan upload --timeout 30 --retry 10 --ow info/config.buildinfo openwrt/x86_64/minimal/${{ matrix.tag.version }}/$version/
+ aliyunpan upload --timeout 30 --retry 10 --ow info/manifest.txt openwrt/x86_64/minimal/${{ matrix.tag.version }}/$version/
+ aliyunpan upload --timeout 30 --retry 10 --ow info/sha256sums.txt openwrt/x86_64/minimal/${{ matrix.tag.version }}/$version/
+ aliyunpan upload --timeout 30 --retry 10 --ow rom/*-generic-rootfs.tar.gz openwrt/x86_64/minimal/${{ matrix.tag.version }}/$version/
+ aliyunpan upload --timeout 30 --retry 10 --ow rom/*-ext4-combined-efi.img.gz openwrt/x86_64/minimal/${{ matrix.tag.version }}/$version/
+ aliyunpan upload --timeout 30 --retry 10 --ow rom/*-squashfs-combined-efi.img.gz openwrt/x86_64/minimal/${{ matrix.tag.version }}/$version/
+ elif [ "${{ matrix.model }}" = "netgear_r8500" ]; then
+ aliyunpan upload --timeout 30 --retry 10 --ow info/config.buildinfo openwrt/netgear-r8500/minimal/${{ matrix.tag.version }}/$version/
+ aliyunpan upload --timeout 30 --retry 10 --ow info/manifest.txt openwrt/netgear-r8500/minimal/${{ matrix.tag.version }}/$version/
+ aliyunpan upload --timeout 30 --retry 10 --ow info/sha256sums.txt openwrt/netgear-r8500/minimal/${{ matrix.tag.version }}/$version/
+ aliyunpan upload --timeout 30 --retry 10 --ow rom/*.chk openwrt/netgear-r8500/minimal/${{ matrix.tag.version }}/$version/
+ fi
+ aliyunpan recycle delete -all
+ echo y | aliyunpan logout
+
+ - name: Release OTA
+ uses: SamKirkland/FTP-Deploy-Action@v4.3.5
+ with:
+ username: openwrt
+ server: ${{ secrets.ftp_address }}
+ password: ${{ secrets.ftp_password }}
+ server-dir: minimal/${{ matrix.model }}/
+ local-dir: ${{ env.build_dir }}/openwrt/ota/
+ dangerous-clean-slate: true
diff --git a/.github/workflows/build-release.yml b/.github/workflows/build-release.yml
new file mode 100644
index 0000000..ce22693
--- /dev/null
+++ b/.github/workflows/build-release.yml
@@ -0,0 +1,264 @@
+name: Build releases
+
+on:
+ workflow_dispatch:
+ repository_dispatch:
+ types: [release]
+
+jobs:
+ build:
+ name: Build ${{ matrix.model }}-${{ matrix.tag.version }}
+ runs-on: ubuntu-24.04
+ defaults:
+ run:
+ shell: bash
+ strategy:
+ fail-fast: false
+ matrix:
+ model:
+ - armv8
+ - nanopi-r4s
+ - nanopi-r5s
+ - x86_64
+ - netgear_r8500
+ tag:
+ - type: rc2
+ version: openwrt-23.05
+
+ steps:
+ - name: Setup variables
+ run: |
+ sudo timedatectl set-timezone 'Asia/Shanghai'
+ git config --global user.name 'actions'
+ git config --global user.email 'action@github.com'
+ echo build_dir="/builder" >> "$GITHUB_ENV"
+ if [[ ${{ matrix.model }} != "nanopi-r4s" ]]; then
+ echo "release_kmod=true" >> "$GITHUB_ENV"
+ fi
+ if [ "${{ matrix.model }}" = "nanopi-r5s" ]; then
+ echo "kmod_repo=kmod-aarch64" >> "$GITHUB_ENV"
+ elif [ "${{ matrix.model }}" = "x86_64" ]; then
+ echo "kmod_repo=kmod-x86_64" >> "$GITHUB_ENV"
+ elif [ "${{ matrix.model }}" = "netgear_r8500" ]; then
+ echo "kmod_repo=kmod-bcm53xx" >> "$GITHUB_ENV"
+ elif [ "${{ matrix.model }}" = "armv8" ]; then
+ echo "kmod_repo=kmod-armsr-armv8" >> "$GITHUB_ENV"
+ fi
+
+ - name: Show system
+ run: |
+ echo -e "\n\e[1;32mCPU:\e[0m"
+ echo "$(grep 'model name' /proc/cpuinfo | head -1 | awk -F ': ' '{print $2}') ($(grep 'cpu MHz' /proc/cpuinfo | head -1 | awk -F ': ' '{print $2}')MHz) x $(grep processor /proc/cpuinfo | wc -l)"
+ echo -e "\n\e[1;32mMemory:\e[0m"
+ free -h
+ echo -e "\n\e[1;32mStorage:\e[0m"
+ df -Th / /mnt
+ echo -e "\n\e[1;32mSystem:\e[0m"
+ lsb_release -a
+ echo -e "\n\e[1;32mKernel:\e[0m"
+ uname -a
+ echo
+
+ - name: Free disk space
+ uses: sbwml/actions@free-disk
+ with:
+ build-mount-path: /builder
+
+ - name: Build System Setup
+ uses: sbwml/actions@openwrt-build-setup
+
+ - name: Compile OpenWrt
+ id: compile
+ continue-on-error: true
+ working-directory: /builder
+ env:
+ git_password: ${{ secrets.ftp_password }}
+ private_url: ${{ secrets.private_url }}
+ run: |
+ [ "${{ matrix.model }}" != "netgear_r8500" ] && export KERNEL_CLANG_LTO=y
+ export BUILD_FAST=y ENABLE_OTA=y ENABLE_BPF=y ENABLE_LTO=y ENABLE_LRNG=y USE_GCC15=y ENABLE_MOLD=y
+ bash <(curl -sS ${{ secrets.script_url_general }}) ${{ matrix.tag.type }} ${{ matrix.model }}
+ cd openwrt
+ tags=$(git describe --abbrev=0 --tags)
+ echo "latest_release=$tags" >>$GITHUB_ENV
+
+ - name: Extensive logs after a failed compilation
+ if: steps.compile.outcome == 'failure'
+ working-directory: /builder
+ run: |
+ cd openwrt
+ make V=s IGNORE_ERRORS="n m"
+
+ - name: Prepare Firmware Files
+ working-directory: /builder
+ run: |
+ mkdir -p rom info
+ if [ "${{ matrix.model }}" = "nanopi-r4s" ]; then
+ cp -a openwrt/bin/targets/rockchip/*/*.img.gz rom/
+ cp -a openwrt/bin/targets/rockchip/*/*-r4s.manifest info/manifest.txt
+ cp -a openwrt/bin/targets/rockchip/*/config.buildinfo info/config.buildinfo
+ cd rom && sha256sum * > ../info/sha256sums.txt
+ elif [ "${{ matrix.model }}" = "nanopi-r5s" ]; then
+ cp -a openwrt/bin/targets/rockchip/*/*.img.gz rom/
+ cp -a openwrt/bin/targets/rockchip/*/*.manifest info/manifest.txt
+ cp -a openwrt/bin/targets/rockchip/*/config.buildinfo info/config.buildinfo
+ cd rom && sha256sum * > ../info/sha256sums.txt
+ elif [ "${{ matrix.model }}" = "x86_64" ]; then
+ cp -a openwrt/bin/targets/x86/*/*-ext4-combined-efi.img.gz rom/
+ cp -a openwrt/bin/targets/x86/*/*-squashfs-combined-efi.img.gz rom/
+ cp -a openwrt/bin/targets/x86/*/*-generic-rootfs.tar.gz rom/
+ cp -a openwrt/bin/targets/x86/*/*-x86-64-generic.manifest info/manifest.txt
+ cp -a openwrt/bin/targets/x86/*/config.buildinfo info/config.buildinfo
+ cd rom && sha256sum * > ../info/sha256sums.txt
+ elif [ "${{ matrix.model }}" = "netgear_r8500" ]; then
+ cp -a openwrt/bin/targets/bcm53xx/generic/*-bcm53xx-generic-netgear_r8500-squashfs.chk rom/
+ cp -a openwrt/bin/targets/bcm53xx/generic/*.manifest info/manifest.txt
+ cp -a openwrt/bin/targets/bcm53xx/generic/config.buildinfo info/config.buildinfo
+ cd rom && sha256sum * > ../info/sha256sums.txt
+ elif [ "${{ matrix.model }}" = "armv8" ]; then
+ tar zcf rom/u-boot-qemu_armv8.tar.gz -C openwrt/bin/targets/armsr/armv8*/ ./u-boot-qemu_armv8
+ cp -a openwrt/bin/targets/armsr/armv8*/*-generic-initramfs-kernel.bin rom/
+ cp -a openwrt/bin/targets/armsr/armv8*/*-generic-kernel.bin rom/
+ cp -a openwrt/bin/targets/armsr/armv8*/*-generic-ext4-combined-efi.img.gz rom/
+ cp -a openwrt/bin/targets/armsr/armv8*/*-generic-squashfs-combined-efi.img.gz rom/
+ cp -a openwrt/bin/targets/armsr/armv8*/*-rootfs.tar.gz rom/
+ cp -a openwrt/bin/targets/armsr/armv8*/*.manifest info/manifest.txt
+ cp -a openwrt/bin/targets/armsr/armv8*/config.buildinfo info/config.buildinfo
+ cd rom && sha256sum * > ../info/sha256sums.txt
+ fi
+ cd ..
+ tar zcf rom/buildinfo_${{ matrix.model }}.tar.gz info
+
+ - name: Create virtual machine images
+ if: ${{ matrix.model == 'x86_64' }}
+ working-directory: /builder
+ run: |
+ mkdir -p virtual_images
+ cp -a openwrt/bin/targets/x86/*/*-generic-squashfs-combined-efi.img.gz virtual_images/
+ gzip -dq virtual_images/*-generic-squashfs-combined-efi.img.gz || true
+ cd virtual_images
+ image_name=$(basename -s .img *.img)
+ qemu-img convert -f raw -O qcow2 *.img $image_name.qcow2
+ qemu-img convert -f raw -O vpc *.img $image_name.vhd
+ qemu-img convert -f raw -O vmdk *.img $image_name.vmdk
+ rm -f *.img
+ sha256sum * > sha256sums.txt
+ echo "
x86_64 虚拟机平台镜像
" > README.md
+
+ - name: Create release
+ uses: ncipollo/release-action@v1.14.0
+ with:
+ name: OpenWrt-${{ env.latest_release }}
+ allowUpdates: true
+ tag: ${{ env.latest_release }}
+ commit: main
+ replacesArtifacts: true
+ token: ${{ secrets.workflow_token }}
+ artifacts: |
+ ${{ env.build_dir }}/rom/*
+
+ - name: Release kernel modules
+ if: ${{ matrix.model != 'nanopi-r4s' }}
+ uses: ncipollo/release-action@v1.14.0
+ with:
+ name: OpenWrt-${{ env.latest_release }}
+ allowUpdates: true
+ tag: ${{ env.latest_release }}
+ commit: main
+ replacesArtifacts: true
+ token: ${{ secrets.workflow_token }}
+ artifacts: |
+ ${{ env.build_dir }}/openwrt/*-*.tar.gz
+
+ - name: Sync kernel modules
+ if: env.release_kmod == 'true'
+ uses: peter-evans/repository-dispatch@v3
+ with:
+ token: ${{ secrets.workflow_token }}
+ repository: sbwml/${{ env.kmod_repo }}
+ event-type: sync
+
+ - name: Install aliyunpan & login
+ if: ${{ matrix.model != 'armv8' }}
+ continue-on-error: true
+ working-directory: /builder
+ timeout-minutes: 1
+ run: |
+ if [ "${{ matrix.model }}" = "nanopi-r4s" ]; then
+ device_id=${{ secrets.device_id_r4s }}
+ elif [ "${{ matrix.model }}" = "nanopi-r5s" ]; then
+ device_id=${{ secrets.device_id_r5s }}
+ elif [ "${{ matrix.model }}" = "x86_64" ]; then
+ device_id=${{ secrets.device_id_x86 }}
+ elif [ "${{ matrix.model }}" = "netgear_r8500" ]; then
+ device_id=${{ secrets.device_id_netgear }}
+ fi
+ sudo wget -q ${{ secrets.aliyunpan_go }} -O /bin/aliyunpan
+ sudo chmod 0755 /bin/aliyunpan
+ sudo sh -c 'echo "${{ secrets.aliyunpan_us_node }} api.alipan.com auth.alipan.com www.alipan.com" >> /etc/hosts'
+ export ALIYUNPAN_CONFIG_DIR="$(pwd)/.aliyunpan"
+ aliyun_token=`curl -s ${{ secrets.aliyun_token }} | openssl enc -aes-256-cfb -pbkdf2 -a -d -k ${{ secrets.token_dec }}`
+ aliyunpan config set -device_id=$device_id >/dev/null 2>&1
+ echo
+ echo $aliyun_token | aliyunpan login
+
+ - name: Upload Firmware - releases
+ if: ${{ matrix.model != 'armv8' }}
+ id: upload
+ continue-on-error: true
+ working-directory: /builder
+ timeout-minutes: 40
+ run: |
+ export ALIYUNPAN_CONFIG_DIR="$(pwd)/.aliyunpan"
+ version=$(cat openwrt/version.txt)
+ if [ "${{ matrix.model }}" = "nanopi-r4s" ]; then
+ aliyunpan upload --timeout 20 --retry 10 --ow info/config.buildinfo openwrt/nanopi-r4s/releases/${{ matrix.tag.version }}/$version/
+ aliyunpan upload --timeout 20 --retry 10 --ow info/manifest.txt openwrt/nanopi-r4s/releases/${{ matrix.tag.version }}/$version/
+ aliyunpan upload --timeout 20 --retry 10 --ow info/sha256sums.txt openwrt/nanopi-r4s/releases/${{ matrix.tag.version }}/$version/
+ aliyunpan upload --timeout 20 --retry 10 --ow rom/*-r4s-ext4-sysupgrade.img.gz openwrt/nanopi-r4s/releases/${{ matrix.tag.version }}/$version/
+ aliyunpan upload --timeout 20 --retry 10 --ow rom/*-r4s-squashfs-sysupgrade.img.gz openwrt/nanopi-r4s/releases/${{ matrix.tag.version }}/$version/
+ elif [ "${{ matrix.model }}" = "nanopi-r5s" ]; then
+ aliyunpan upload --timeout 20 --retry 10 --ow info/config.buildinfo openwrt/nanopi-r5s/releases/${{ matrix.tag.version }}/$version/
+ aliyunpan upload --timeout 20 --retry 10 --ow info/manifest.txt openwrt/nanopi-r5s/releases/${{ matrix.tag.version }}/$version/
+ aliyunpan upload --timeout 20 --retry 10 --ow info/sha256sums.txt openwrt/nanopi-r5s/releases/${{ matrix.tag.version }}/$version/
+ aliyunpan upload --timeout 20 --retry 10 --ow rom/*-r5c-ext4-sysupgrade.img.gz openwrt/nanopi-r5s/releases/${{ matrix.tag.version }}/$version/
+ aliyunpan upload --timeout 20 --retry 10 --ow rom/*-r5c-squashfs-sysupgrade.img.gz openwrt/nanopi-r5s/releases/${{ matrix.tag.version }}/$version/
+ aliyunpan upload --timeout 20 --retry 10 --ow rom/*-r5s-ext4-sysupgrade.img.gz openwrt/nanopi-r5s/releases/${{ matrix.tag.version }}/$version/
+ aliyunpan upload --timeout 20 --retry 10 --ow rom/*-r5s-squashfs-sysupgrade.img.gz openwrt/nanopi-r5s/releases/${{ matrix.tag.version }}/$version/
+ elif [ "${{ matrix.model }}" = "x86_64" ]; then
+ aliyunpan upload --timeout 30 --retry 10 --ow info/config.buildinfo openwrt/x86_64/releases/${{ matrix.tag.version }}/$version/
+ aliyunpan upload --timeout 30 --retry 10 --ow info/manifest.txt openwrt/x86_64/releases/${{ matrix.tag.version }}/$version/
+ aliyunpan upload --timeout 30 --retry 10 --ow info/sha256sums.txt openwrt/x86_64/releases/${{ matrix.tag.version }}/$version/
+ aliyunpan upload --timeout 30 --retry 10 --ow rom/*-generic-rootfs.tar.gz openwrt/x86_64/releases/${{ matrix.tag.version }}/$version/
+ aliyunpan upload --timeout 30 --retry 10 --ow rom/*-ext4-combined-efi.img.gz openwrt/x86_64/releases/${{ matrix.tag.version }}/$version/
+ aliyunpan upload --timeout 30 --retry 10 --ow rom/*-squashfs-combined-efi.img.gz openwrt/x86_64/releases/${{ matrix.tag.version }}/$version/
+ # virtual machine images
+ aliyunpan upload --timeout 30 --retry 10 --ow virtual_images/README.md openwrt/x86_64/releases/${{ matrix.tag.version }}/$version/virtual_machine_images/
+ aliyunpan upload --timeout 30 --retry 10 --ow virtual_images/sha256sums.txt openwrt/x86_64/releases/${{ matrix.tag.version }}/$version/virtual_machine_images/
+ aliyunpan upload --timeout 30 --retry 10 --ow virtual_images/*.vmdk openwrt/x86_64/releases/${{ matrix.tag.version }}/$version/virtual_machine_images/
+ aliyunpan upload --timeout 30 --retry 10 --ow virtual_images/*.vhd openwrt/x86_64/releases/${{ matrix.tag.version }}/$version/virtual_machine_images/
+ aliyunpan upload --timeout 30 --retry 10 --ow virtual_images/*.qcow2 openwrt/x86_64/releases/${{ matrix.tag.version }}/$version/virtual_machine_images/
+ elif [ "${{ matrix.model }}" = "netgear_r8500" ]; then
+ aliyunpan upload --timeout 20 --retry 10 --ow info/config.buildinfo openwrt/netgear-r8500/releases/${{ matrix.tag.version }}/$version/
+ aliyunpan upload --timeout 20 --retry 10 --ow info/manifest.txt openwrt/netgear-r8500/releases/${{ matrix.tag.version }}/$version/
+ aliyunpan upload --timeout 20 --retry 10 --ow info/sha256sums.txt openwrt/netgear-r8500/releases/${{ matrix.tag.version }}/$version/
+ aliyunpan upload --timeout 20 --retry 10 --ow rom/*.chk openwrt/netgear-r8500/releases/${{ matrix.tag.version }}/$version/
+ fi
+ aliyunpan recycle delete -all
+ echo y | aliyunpan logout
+
+ - name: Retry Upload Firmware - releases
+ if: steps.upload.outcome == 'failure'
+ run: |
+ sshpass -p ${{ secrets.user_password }} ssh -o StrictHostKeyChecking=no root@${{ secrets.ftp_address }} >/dev/null 2>&1
+ sshpass -p ${{ secrets.user_password }} ssh root@${{ secrets.ftp_address }} "/opt/sbin/fw-upload ${{ matrix.model }}"
+
+ - name: Release OTA
+ uses: SamKirkland/FTP-Deploy-Action@v4.3.5
+ with:
+ username: openwrt
+ server: ${{ secrets.ftp_address }}
+ password: ${{ secrets.ftp_password }}
+ server-dir: release/${{ matrix.model }}/
+ local-dir: ${{ env.build_dir }}/openwrt/ota/
+ dangerous-clean-slate: true
diff --git a/.github/workflows/build-snapshots.yml b/.github/workflows/build-snapshots.yml
new file mode 100644
index 0000000..948d625
--- /dev/null
+++ b/.github/workflows/build-snapshots.yml
@@ -0,0 +1,198 @@
+name: Build SNAPSHOT
+
+on:
+ workflow_dispatch:
+ schedule:
+ - cron: 0 16 * * *
+
+jobs:
+ build:
+ name: Build ${{ matrix.model }}-${{ matrix.tag.version }}
+ runs-on: ubuntu-24.04
+ defaults:
+ run:
+ shell: bash
+ strategy:
+ fail-fast: false
+ matrix:
+ model:
+ - armv8
+ - nanopi-r4s
+ - nanopi-r5s
+ - x86_64
+ - netgear_r8500
+ tag:
+ - type: dev
+ version: openwrt-24.10
+
+ steps:
+ - name: Setup variables
+ run: |
+ sudo timedatectl set-timezone 'Asia/Shanghai'
+ git config --global user.name 'actions'
+ git config --global user.email 'action@github.com'
+ echo build_dir="/builder" >> "$GITHUB_ENV"
+
+ - name: Show system
+ run: |
+ echo -e "\n\e[1;32mCPU:\e[0m"
+ echo "$(grep 'model name' /proc/cpuinfo | head -1 | awk -F ': ' '{print $2}') ($(grep 'cpu MHz' /proc/cpuinfo | head -1 | awk -F ': ' '{print $2}')MHz) x $(grep processor /proc/cpuinfo | wc -l)"
+ echo -e "\n\e[1;32mMemory:\e[0m"
+ free -h
+ echo -e "\n\e[1;32mStorage:\e[0m"
+ df -Th / /mnt
+ echo -e "\n\e[1;32mSystem:\e[0m"
+ lsb_release -a
+ echo -e "\n\e[1;32mKernel:\e[0m"
+ uname -a
+ echo
+
+ - name: Free disk space
+ uses: sbwml/actions@free-disk
+ with:
+ build-mount-path: /builder
+
+ - name: Build System Setup
+ uses: sbwml/actions@openwrt-build-setup
+
+ - name: Compile OpenWrt
+ id: compile
+ continue-on-error: true
+ working-directory: /builder
+ env:
+ git_password: ${{ secrets.ftp_password }}
+ private_url: ${{ secrets.private_url }}
+ run: |
+ [ "${{ matrix.model }}" != "netgear_r8500" ] && export KERNEL_CLANG_LTO=y
+ export BUILD_FAST=y ENABLE_BPF=y ENABLE_LTO=y ENABLE_LRNG=y USE_GCC15=y ENABLE_MOLD=y
+ bash <(curl -sS ${{ secrets.script_url_general }}) ${{ matrix.tag.type }} ${{ matrix.model }}
+ build_date=$(date "+%Y-%m-%d")
+ echo "build_date=$build_date" >> $GITHUB_ENV
+
+ - name: Extensive logs after a failed compilation
+ if: steps.compile.outcome == 'failure'
+ working-directory: /builder
+ run: |
+ cd openwrt
+ make V=s IGNORE_ERRORS="n m"
+
+ - name: Assemble Artifact
+ working-directory: /builder
+ run: |
+ mkdir -p rom info
+ if [ "${{ matrix.model }}" = "nanopi-r4s" ]; then
+ cp -a openwrt/bin/targets/rockchip/*/*.img.gz rom/
+ cp -a openwrt/bin/targets/rockchip/*/*-r4s.manifest info/manifest.txt
+ cp -a openwrt/bin/targets/rockchip/*/config.buildinfo info/config.buildinfo
+ cd rom && sha256sum *gz > ../info/sha256sums.txt
+ elif [ "${{ matrix.model }}" = "nanopi-r5s" ]; then
+ cp -a openwrt/bin/targets/rockchip/*/*.img.gz rom/
+ cp -a openwrt/bin/targets/rockchip/*/*.manifest info/manifest.txt
+ cp -a openwrt/bin/targets/rockchip/*/config.buildinfo info/config.buildinfo
+ cd rom && sha256sum *gz > ../info/sha256sums.txt
+ elif [ "${{ matrix.model }}" = "x86_64" ]; then
+ cp -a openwrt/bin/targets/x86/*/*-ext4-combined-efi.img.gz rom/
+ cp -a openwrt/bin/targets/x86/*/*-squashfs-combined-efi.img.gz rom/
+ cp -a openwrt/bin/targets/x86/*/*-generic-rootfs.tar.gz rom/
+ cp -a openwrt/bin/targets/x86/*/*-x86-64-generic.manifest info/manifest.txt
+ cp -a openwrt/bin/targets/x86/*/config.buildinfo info/config.buildinfo
+ cd rom && sha256sum *gz > ../info/sha256sums.txt
+ elif [ "${{ matrix.model }}" = "netgear_r8500" ]; then
+ cp -a openwrt/bin/targets/bcm53xx/generic/*-bcm53xx-generic-netgear_r8500-squashfs.chk rom/
+ cp -a openwrt/bin/targets/bcm53xx/generic/*.manifest info/manifest.txt
+ cp -a openwrt/bin/targets/bcm53xx/generic/config.buildinfo info/config.buildinfo
+ cd rom && sha256sum * > ../info/sha256sums.txt
+ elif [ "${{ matrix.model }}" = "armv8" ]; then
+ tar zcf rom/u-boot-qemu_armv8.tar.gz -C openwrt/bin/targets/armsr/armv8*/ ./u-boot-qemu_armv8
+ cp -a openwrt/bin/targets/armsr/armv8*/*-generic-initramfs-kernel.bin rom/
+ cp -a openwrt/bin/targets/armsr/armv8*/*-generic-kernel.bin rom/
+ cp -a openwrt/bin/targets/armsr/armv8*/*-generic-ext4-combined-efi.img.gz rom/
+ cp -a openwrt/bin/targets/armsr/armv8*/*-generic-squashfs-combined-efi.img.gz rom/
+ cp -a openwrt/bin/targets/armsr/armv8*/*-rootfs.tar.gz rom/
+ cp -a openwrt/bin/targets/armsr/armv8*/*.manifest info/manifest.txt
+ cp -a openwrt/bin/targets/armsr/armv8*/config.buildinfo info/config.buildinfo
+ cd rom && sha256sum * > ../info/sha256sums.txt
+ fi
+
+ - name: Upload artifacts
+ uses: actions/upload-artifact@v4
+ with:
+ name: ${{ env.build_date }}-${{ matrix.model }}-${{ matrix.tag.version }}
+ path: ${{ env.build_dir }}/rom/*.*
+
+ - name: Install aliyunpan & login
+ if: ${{ matrix.model != 'armv8' }}
+ working-directory: /builder
+ continue-on-error: true
+ run: |
+ if [ "${{ matrix.model }}" = "nanopi-r4s" ]; then
+ device_id=${{ secrets.device_id_r4s_dev }}
+ elif [ "${{ matrix.model }}" = "nanopi-r5s" ]; then
+ device_id=${{ secrets.device_id_r5s_dev }}
+ elif [ "${{ matrix.model }}" = "x86_64" ]; then
+ device_id=${{ secrets.device_id_x86_dev }}
+ elif [ "${{ matrix.model }}" = "netgear_r8500" ]; then
+ device_id=${{ secrets.device_id_netgear_dev }}
+ fi
+ sudo wget -q ${{ secrets.aliyunpan_go }} -O /bin/aliyunpan
+ sudo chmod 0755 /bin/aliyunpan
+ sudo sh -c 'echo "${{ secrets.aliyunpan_us_node }} api.alipan.com auth.alipan.com www.alipan.com" >> /etc/hosts'
+ export ALIYUNPAN_CONFIG_DIR="$(pwd)/.aliyunpan"
+ aliyun_token=`curl -s ${{ secrets.aliyun_token }} | openssl enc -aes-256-cfb -pbkdf2 -a -d -k ${{ secrets.token_dec }}`
+ aliyunpan config set -device_id=$device_id >/dev/null 2>&1
+ echo
+ echo $aliyun_token | aliyunpan login
+
+ - name: Upload Firmware - snapshots
+ if: ${{ matrix.model != 'armv8' }}
+ working-directory: /builder
+ timeout-minutes: 20
+ continue-on-error: true
+ run: |
+ export ALIYUNPAN_CONFIG_DIR="$(pwd)/.aliyunpan"
+ DATE=$(date "+%Y-%m-%d")
+ branch=24.10-SNAPSHOT
+ if [ "${{ matrix.model }}" = "nanopi-r4s" ]; then
+ aliyunpan upload --timeout 30 --retry 10 --ow info/config.buildinfo openwrt/nanopi-r4s/snapshots/$branch/$DATE/
+ aliyunpan upload --timeout 30 --retry 10 --ow info/manifest.txt openwrt/nanopi-r4s/snapshots/$branch/$DATE/
+ aliyunpan upload --timeout 30 --retry 10 --ow info/sha256sums.txt openwrt/nanopi-r4s/snapshots/$branch/$DATE/
+ aliyunpan upload --timeout 30 --retry 10 --ow rom/*-r4s-ext4-sysupgrade.img.gz openwrt/nanopi-r4s/snapshots/$branch/$DATE/
+ aliyunpan upload --timeout 30 --retry 10 --ow rom/*-r4s-squashfs-sysupgrade.img.gz openwrt/nanopi-r4s/snapshots/$branch/$DATE/
+ elif [ "${{ matrix.model }}" = "nanopi-r5s" ]; then
+ aliyunpan upload --timeout 30 --retry 10 --ow info/config.buildinfo openwrt/nanopi-r5s/snapshots/$branch/$DATE/
+ aliyunpan upload --timeout 30 --retry 10 --ow info/manifest.txt openwrt/nanopi-r5s/snapshots/$branch/$DATE/
+ aliyunpan upload --timeout 30 --retry 10 --ow info/sha256sums.txt openwrt/nanopi-r5s/snapshots/$branch/$DATE/
+ aliyunpan upload --timeout 30 --retry 10 --ow rom/*-r5c-ext4-sysupgrade.img.gz openwrt/nanopi-r5s/snapshots/$branch/$DATE/
+ aliyunpan upload --timeout 30 --retry 10 --ow rom/*-r5c-squashfs-sysupgrade.img.gz openwrt/nanopi-r5s/snapshots/$branch/$DATE/
+ aliyunpan upload --timeout 30 --retry 10 --ow rom/*-r5s-ext4-sysupgrade.img.gz openwrt/nanopi-r5s/snapshots/$branch/$DATE/
+ aliyunpan upload --timeout 30 --retry 10 --ow rom/*-r5s-squashfs-sysupgrade.img.gz openwrt/nanopi-r5s/snapshots/$branch/$DATE/
+ elif [ "${{ matrix.model }}" = "x86_64" ]; then
+ aliyunpan upload --timeout 30 --retry 10 --ow info/config.buildinfo openwrt/x86_64/snapshots/$branch/$DATE/
+ aliyunpan upload --timeout 30 --retry 10 --ow info/manifest.txt openwrt/x86_64/snapshots/$branch/$DATE/
+ aliyunpan upload --timeout 30 --retry 10 --ow info/sha256sums.txt openwrt/x86_64/snapshots/$branch/$DATE/
+ aliyunpan upload --timeout 30 --retry 10 --ow rom/*-generic-rootfs.tar.gz openwrt/x86_64/snapshots/$branch/$DATE/
+ aliyunpan upload --timeout 30 --retry 10 --ow rom/*-ext4-combined-efi.img.gz openwrt/x86_64/snapshots/$branch/$DATE/
+ aliyunpan upload --timeout 30 --retry 10 --ow rom/*-squashfs-combined-efi.img.gz openwrt/x86_64/snapshots/$branch/$DATE/
+ elif [ "${{ matrix.model }}" = "netgear_r8500" ]; then
+ aliyunpan upload --timeout 30 --retry 10 --ow info/config.buildinfo openwrt/netgear-r8500/snapshots/$branch/$DATE/
+ aliyunpan upload --timeout 30 --retry 10 --ow info/manifest.txt openwrt/netgear-r8500/snapshots/$branch/$DATE/
+ aliyunpan upload --timeout 30 --retry 10 --ow info/sha256sums.txt openwrt/netgear-r8500/snapshots/$branch/$DATE/
+ aliyunpan upload --timeout 30 --retry 10 --ow rom/*.chk openwrt/netgear-r8500/snapshots/$branch/$DATE/
+ fi
+ aliyunpan recycle delete -all
+ echo y | aliyunpan logout
+
+ - name: Copy build info
+ working-directory: /builder
+ run: |
+ cp -a info/* rom/
+
+ - name: Upload Firmware - FTP
+ uses: SamKirkland/FTP-Deploy-Action@v4.3.5
+ with:
+ dangerous-clean-slate: true
+ username: snapshot
+ server: ${{ secrets.ftp_address }}
+ password: ${{ secrets.ftp_password }}
+ server-dir: ${{ matrix.model }}/
+ local-dir: ${{ env.build_dir }}/rom/
diff --git a/.github/workflows/build-snapshots_core.yml b/.github/workflows/build-snapshots_core.yml
new file mode 100644
index 0000000..7cf99a0
--- /dev/null
+++ b/.github/workflows/build-snapshots_core.yml
@@ -0,0 +1,97 @@
+name: Build SNAPSHOT Core
+
+on:
+ workflow_dispatch:
+
+jobs:
+ build:
+ name: Build ${{ matrix.model }} Core
+ runs-on: ubuntu-24.04
+ defaults:
+ run:
+ shell: bash
+ strategy:
+ fail-fast: false
+ matrix:
+ model:
+ - armv8
+ - nanopi-r5s
+ - x86_64
+ - netgear_r8500
+ tag:
+ - type: dev
+
+ steps:
+ - name: Setup variables
+ run: |
+ sudo timedatectl set-timezone 'Asia/Shanghai'
+ git config --global user.name 'actions'
+ git config --global user.email 'action@github.com'
+ echo build_dir="/builder" >> "$GITHUB_ENV"
+
+ - name: Show system
+ run: |
+ echo -e "\n\e[1;32mCPU:\e[0m"
+ echo "$(grep 'model name' /proc/cpuinfo | head -1 | awk -F ': ' '{print $2}') ($(grep 'cpu MHz' /proc/cpuinfo | head -1 | awk -F ': ' '{print $2}')MHz) x $(grep processor /proc/cpuinfo | wc -l)"
+ echo -e "\n\e[1;32mMemory:\e[0m"
+ free -h
+ echo -e "\n\e[1;32mStorage:\e[0m"
+ df -Th / /mnt
+ echo -e "\n\e[1;32mSystem:\e[0m"
+ lsb_release -a
+ echo -e "\n\e[1;32mKernel:\e[0m"
+ uname -a
+ echo
+
+ - name: Free disk space
+ uses: sbwml/actions@free-disk
+ with:
+ build-mount-path: /builder
+
+ - name: Build System Setup
+ uses: sbwml/actions@openwrt-build-setup
+
+ - name: Compile OpenWrt
+ id: compile
+ continue-on-error: true
+ working-directory: /builder
+ env:
+ git_password: ${{ secrets.ftp_password }}
+ run: |
+ [ "${{ matrix.model }}" != "netgear_r8500" ] && export KERNEL_CLANG_LTO=y
+ export BUILD_FAST=y ENABLE_OTA=y ENABLE_BPF=y ENABLE_LTO=y ENABLE_LRNG=y USE_GCC15=y ENABLE_MOLD=y MINIMAL_BUILD=y
+ bash <(curl -sS ${{ secrets.script_url_general }}) ${{ matrix.tag.type }} ${{ matrix.model }}
+
+ - name: Extensive logs after a failed compilation
+ if: steps.compile.outcome == 'failure'
+ working-directory: /builder
+ run: |
+ cd openwrt
+ make V=s IGNORE_ERRORS="n m"
+
+ - name: Prepare files
+ working-directory: /builder
+ run: |
+ base_name=$(basename ${{ env.build_dir }}/openwrt/*-*.tar.gz)
+ kmod_name=$(echo $base_name | sed 's/~/-/g')
+ mv ${{ env.build_dir }}/openwrt/*-*.tar.gz ${{ env.build_dir }}/openwrt/$kmod_name
+
+ - name: Release kernel modules
+ uses: ncipollo/release-action@v1.14.0
+ with:
+ name: kmod-snapshot
+ allowUpdates: true
+ prerelease: true
+ tag: snapshot
+ commit: main
+ replacesArtifacts: true
+ token: ${{ secrets.workflow_token }}
+ artifacts: |
+ ${{ env.build_dir }}/openwrt/*-*.tar.gz
+
+ - name: Sync kernel modules
+ uses: peter-evans/repository-dispatch@v3
+ with:
+ token: ${{ secrets.workflow_token }}
+ repository: sbwml/openwrt_core
+ event-type: sync
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..499061f
--- /dev/null
+++ b/README.md
@@ -0,0 +1,292 @@
+
+
+
+
+OpenWrt for FriendlyElec NanoPi R4S / R5S & X86_64 & Netgear R8500
+
+
+
+
+
+
+ 基于原生 OpenWrt 更改与优化的固件,提供高效、稳定的使用体验!
+
+
+-------
+
+## 固件下载
+
+**NanoPi R4S: https://r4s.cooluc.com**
+
+**NanoPi R5S: https://r5s.cooluc.com**
+
+**X86_64: https://x86.cooluc.com**
+
+**Netgear R8500: https://r8500.cooluc.com**
+
+**Snapshot-24.10: https://snapshot.cooluc.com**
+
+## 版本信息
+
+**[Releases](https://r5s.cooluc.com/releases):正式版 - 基于 [OpenWrt](https://github.com/openwrt/openwrt/releases) 最新 Releases 源代码和软件包编译(推荐) - [Linux 6.6 LTS](https://kernel.org/)**
+
+**[Snapshots](https://r5s.cooluc.com/snapshots):开发版 - 基于 [OpenWrt](https://github.com/openwrt/openwrt/tree/openwrt-23.05) 最新 openwrt-23.05 分支源代码和软件包编译 - [Linux 6.12 LTS](https://kernel.org/)(每夜构建)**
+
+**[Minimal](https://r5s.cooluc.com/minimal):轻量版 - 基于 [OpenWrt](https://github.com/openwrt/openwrt/releases) 最新 Releases 源代码和软件包编译,无内置插件(不推荐) - [Linux 6.6 LTS](https://kernel.org/)**
+
+------
+
+## 默认信息
+
+- **管理地址:[http://10.0.0.1](http://10.0.0.1) 或 [http://openwrt.lan](http://openwrt.lan)**
+- **账户:root**
+- **密码:无**
+
+------
+
+## 基本状况
+
+| 基本 | 状态 | 基本 | 状态 |
+|:-------------------------------------------------:|:----:|:----------------------------:|:----:|
+| kmod 内核模块安装 | ✅ | 全锥型 NAT(NFT、BCM 双方案)| ✅ |
+| SS AES 硬件加速 | ✅ | 构建优化(O3、LTO) | ✅ |
+| GPU 硬件加速 | ✅ | 内核/模块 优化(LLVM LTO) | ✅ |
+| HDMI 终端输出 | ✅ | 在线 OTA 升级(squashfs) | ✅ |
+| RTC 时钟 (HYM8563) | ✅ | 固件重置(squashfs) | ✅ |
+| BBRv3 拥塞控制 | ✅ | LLVM-BPF 支持 | ✅ |
+| KVM 虚拟化加速 | ✅ | Shortcut-FE(支持 UDP 入站) | ✅ |
+| NGINX & CURL HTTP3/QUIC 支持 | ✅ | LRNG(v54) | ✅ |
+| TCP Brutal 拥塞控制 | ✅ | | |
+
+| 内置插件 | 状态 | 内置插件 | 状态 |
+|:------------------------:|:----:|:----------------:|:----:|
+| PassWall | ✅ | Docker | ✅ |
+| ShadowSocksR Plus+ | ✅ | TTY 终端 | ✅ |
+| HomeProxy | ✅ | NetData 监控 | ✅ |
+| FileBrowser | ✅ | DiskMan 磁盘管理 | ✅ |
+| qBittorrent | ✅ | CPU 性能调节 | ✅ |
+| MosDNS | ✅ | SQM 列队管理 | ✅ |
+| 动态 DNS | ✅ | nlbw 宽带监控 | ✅ |
+| Watchcat | ✅ | Socat | ✅ |
+| KMS 服务器 | ✅ | 应用过滤 | ✅ |
+| FRP 客户端 | ✅ | 访问控制 | ✅ |
+| 网络唤醒 | ✅ | UPnP | ✅ |
+| 网络共享(Samba) | ✅ | IP 限速 | ✅ |
+| 锐捷认证 | ✅ | WireGuard | ✅ |
+| Aria2 | ✅ | L2TP | ✅ |
+| Alist 文件列表 | ✅ | ZeroTier | ✅ |
+| USB 打印服务器 | ✅ | GoWebDav | ✅ |
+| AirConnect | ✅ | AirPlay 2 | ✅ |
+| 自定义命令 | ✅ | 网速测试 | ✅ |
+
+✅ 可用
+
+❌ 不可用
+
+⏳ 计划中
+
+特别说明:
+
+* *AirPlay 2:一款简单易用的 AirPlay 音频播放器,需要外接 USB 声卡使用。*
+* *Shortcut-FE:当使用 “Shortcut-FE 流量分载” 时,请先关闭 “软件流量分载”。*
+
+
+LuCI 菜单概览
+
+├── 状态
+ ├── 概览
+ ├── 路由
+ ├── 防火墙
+ ├── 路由表
+ ├── 系统日志
+ ├── 系统进程
+ ├── 实时信息
+ ├── 实时监控
+ ├── 在线用户
+ ├── WireGuard
+ └── 释放内存
+
+
+├── 系统
+ ├── 系统
+ ├── 管理权
+ ├── 软件包
+ ├── 启动项
+ ├── 计划任务
+ ├── 挂载点
+ ├── 终端
+ ├── 磁盘管理
+ ├── LED 配置
+ ├── 在线升级
+ ├── 备份/升级
+ ├── 自定义命令
+ ├── 定时重启
+ ├── Argon 主题设置
+ ├── CPU 性能调节
+ └── 重启
+
+
+├── 服务
+ ├── PassWall
+ ├── HomeProxy
+ ├── qBittorrent
+ ├── MosDNS
+ ├── 动态 DNS(DDNS)
+ ├── Watchcat
+ ├── 文件浏览器
+ ├── KMS 服务器
+ ├── 隔空播放
+ ├── AirPlay 2 播放器
+ ├── Aria2
+ ├── FRP 客户端
+ ├── 锐捷认证
+ ├── 网络共享
+ ├── 网络唤醒
+ └── ZeroTier
+
+
+├── Docker
+ ├── 概览
+ ├── 容器
+ ├── 镜像
+ ├── 网络
+ ├── 卷标
+ ├── 事件
+ └── 配置
+
+
+├── 网络存储
+ ├── Alist 文件列表
+ ├── USB 打印服务器
+ └── GoWebDav
+
+
+├── 网络
+ ├── 接口
+ ├── 路由
+ ├── DHCP/DNS
+ ├── 网络诊断
+ ├── SQM 队列管理
+ ├── 防火墙
+ ├── UPnP
+ ├── 带宽监控
+ ├── 网速测试
+ ├── 应用过滤
+ ├── Socat
+ ├── 访问控制
+ └── IP 限速
+
+ └── 退出
+
+
+------
+
+## 固件格式
+
+**固件分为两个文件系统,[SquashFS](https://zh.wikipedia.org/wiki/SquashFS) 和 [Ext4](https://zh.wikipedia.org/wiki/Ext4)。**
+
+**SquashFS(推荐):固件文件名带有 “squashfs”,SquashFS 为只读文件系统,支持系统重置,更能避免 SD 卡文件系统触发写保护,支持在线 OTA 升级,适合绝大部分用户使用。**
+
+**Ext4:固件文件名带有 “ext4”,Ext4 文件系统具备整个分区可读写性质,更适合熟悉 Linux 系统的用户使用,但意外断电有几率造成分区写入保护。**
+
+
+------
+
+## NanoPi R4S/R5S 固件烧写(SD)
+
+**推荐工具:**
+
+**SD卡容量:2GB 或更多**
+
+*固件文件无需解压,直接使用工具写入 microSD 卡*
+
+------
+
+## 固件烧写(NanoPi R5S eMMC)
+
+### 准备工具
+
+- **电脑(Windows),其它操作系统自行搜索相关工具**
+- **数据线:USB-A to USB-A 或 Type-C to USB-A**
+- **瑞芯微开发工具:**RKDevTool_Release_v2.84.zip
+
+- **Mask 设备驱动:**DriverAssitant_v5.1.1.zip
+
+### 准备固件
+
+- **下载固件文件,并解压出 .img**
+
+### 操作过程
+
+- **安装 Mask 设备驱动**
+
+- **Mask 模式连接电脑(R5S 断电状态下,取下 SD 卡,使用数据线连接电脑。长按 “Mask” 按钮,接通 R5S 电源直至电脑发现新设备后释放 “Mask” 按钮)**
+
+
+
+
+
+- **打开 瑞芯微开发工具:正常状态:(发现一个Maskrom设备) 缺少驱动:(没有发现设备)**
+
+ **安装步骤:**
+
+ **① 点击 “system” 路径选择按钮(选择 zip 解压出来的 IMG 文件)**
+
+
+
+
+
+ **② 点击 “执行”(固件写入完成后会自动重启进入 OpenWrt 系统)**
+
+
+
+- ***注意:通过电脑烧写固件请使用本站下载的 [瑞芯微开发工具](https://media.cooluc.com/%E8%BD%AF%E4%BB%B6/RKDevTool/RKDevTool_Release_v2.84.zip)。***
+
+------
+
+## 固件烧写(SD to eMMC)
+
+```shell
+# 通过 SD 卡启动后,上传固件文件到路由器任意目录(需要空间大于2G),比如 /tmp 目录,并执行以下命令将固件写入到 eMMC 存储
+# 可以使用 SFTP 工具上传固件到 /tmp 目录,或通过终端 wget 在线下载固件到 /tmp 目录
+
+# 进入 tmp 目录
+cd /tmp
+
+# 解压 img 固件(请根据实际文件名称)
+gzip -d openwrt-23.05.3-rockchip-armv8-friendlyarm_nanopi-r5s-squashfs-sysupgrade.img.gz
+
+# 写入 img 固件到 eMMC 存储(of=/dev/mmcblk1 改成你的 eMMC 存储实际路径,fdisk -l 命令可查看具体路径)
+dd if=openwrt-23.05.3-rockchip-armv8-friendlyarm_nanopi-r5s-squashfs-sysupgrade.img of=/dev/mmcblk1 bs=1M oflag=dsync
+
+```
+
+**固件写入完成后,取下 SD 卡,手动断电重启即可完成。**
+
+------
+
+## RTC 硬件时钟(HYM8563)
+
+**本固件支持 RTC 硬件时钟读取/同步,当设备断电时,重新通电启动系统时间不会错乱** *(注意:设备需要安装 RTC 电池后使用)*
+
+**首次安装 RTC 电池写入时间命令**
+
+```shell
+hwclock -w -f /dev/rtc1
+```
+
+**测试时间读取(返回当前时间表示正常)**
+
+```shell
+hwclock -f /dev/rtc1
+```
+
+------
+
+## 开源地址
+
+**构建脚本:** [https://init2.cooluc.com](https://init2.cooluc.com)
+
+**构建脚本(存档):** [https://github.com/sbwml/r4s_build_script](https://github.com/sbwml/r4s_build_script)
+
+**构建来源:** [https://github.com/sbwml/builder](https://github.com/sbwml/builder)