让你的香橙派5不再吃灰——超低功耗AIB爆改记录

引言

熟悉我的朋友们都知道,我在23年3月拿大创经费报销了一块香橙派5,当时rk3588是瑞芯微的主打产品,又是吹8nm工艺,又是吹性能强,不亚于主流手机。我看着那烧个windows arm巨卡无比的树莓派4B心里直痒痒,所以就买了一块,本来想放在实验室当服务器用,奈何当时生态太拉跨,且实验室有xa的电脑一直不关机,也用不上我搭服务器了,于是就吃灰到现在。现在我工作了,租了自己的房子,老家有黑群晖NAS,而租的房子为了省电,电脑不天天开着,需要一台服务器方便我随时连回去,所以就把吃灰的香橙派翻出来,让他物尽其用吧。看看两年过去了,瑞芯微的生态发展的怎么样了,两天爆肝万字长文(一个汉字占两个字符)把香橙派5打造成全能低功耗AIB

省流助手:还那b样,但是比全志强

安装系统

选择系统

首先,不要选择官方的系统,不要选择官方的系统,不要选择官方的系统

官方系统的内核严重落后,不提供更新,而且最重要的一点是它用的是arm的闭源gpu驱动,只支持opengl es,不支持opengl,所以很多东西都跑不起来

考虑到对rk3588的支持已经进入armbian主线,所以在无特殊需求的情况下,Linux优先推荐armbian,Android优先推荐fyde(openfyde也行)

但是,总有人会像我一样,就是喜欢折腾,选择了ubuntu-rockchip,这个系统胜在和armbian相比适配Ubuntu适配的比较好,更接近于原生Ubuntu的体验,而问题在于维护不是很积极,且使用的人太少,例如下面搭建Android容器就需要自己编译内核,没法用现成的

我安装的是Ubuntu 24.04,按照香橙派手册中的方法和官方系统镜像一样直接烧录即可

https://github.com/Joshua-Riek/ubuntu-rockchip/releases/tag/v2.3.2

不插显示器远程控制(配置多用户)

就像Windows一样,Ubuntu也内置了一套远程桌面服务,不仅支持VNC还支持RDP连接,如果你是日常连显示器鼠标键盘用电脑,只在临时需要远程连接的时候连,那么这套方案已经完全足够了

但如果只通过远程连接,gnome自带的远程桌面就显现出局限性了,gnome考虑到安全性,他的远程桌面只能在主机正在运行桌面系统且已解锁时连接,如果是一个无头的服务器,未启动桌面环境或用户未登录,远程桌面就无法连接了

很显然这样是不行的,我希望香橙派作为一个服务器能随时远程过去,甚至多用户能同时开不同的session,那么gnome自带的远程桌面就做不到了,需要寻找其他解决方案

① 修改gnome远程桌面配置(未成功)

我的第一个想法是看看gnome远程桌面的文档,看能不能允许从远程桌面登录,结果搞了好长时间没搞成功

https://gitlab.gnome.org/GNOME/gnome-remote-desktop

然后又在StackOverflow搜到要装一个插件禁用掉不允许通过远程登录的特性:Allow Locked Remote Desktop – GNOME Shell Extensions,但是还是不行

② HDMI诱骗器(香橙派不支持)

然后zsf提醒了我,那搞个HDMI诱骗器,让香橙派默认能进桌面不就能远程了,所以我到某宝买了个便宜的,结果插上一看,嘿,i2c报错,hdmi不认,开机之前插会kernel panic,开机之后来回拔插也会kernel panic,但是插到电脑是是正常的,后来搜发现rk3588就是会有一些显示器无法识别的问题,疑似是vop2驱动有问题,遂放弃,还是找软件解决方案吧

③ 使用TigerVNC的无头模式(成功)

最后我在网上搜到了一篇文章,说vnc有无头模式,可以在远程桌面连接时自动起一个session,并只在该session中显示桌面系统,这不正好符合我要做服务器的需求,于是赶快尝试一下

Ubuntu Desktop 实践 25、多用户、多桌面、远程桌面和虚拟桌面 – 知乎

成功!而且启动桌面session后gnome的rdp远程桌面服务也能用,就是比tigervnc卡多了,所以我又给关掉了

和直接显示器接板子相比,这种方式启动的桌面环境似乎是软件渲染的,所以有些卡,但好在rk3588 cpu够强,所以也没有那么卡,况且我只是用来当服务器,卡点问题也不大

后来发现TigerVNC起的session是X11,不是Wayland

其他问题

远程桌面进入的session无论怎么设置都是英文,无法改为中文,经过一番研究发现LANG环境变量一直都是C,然后发现我没装en_US语言包,装了之后LANG会被设成en_US.UTF-8,但是还是设不为zh_CN.UTF-8,所以干脆在.xsessionrc里强制把LANG设成中文好了

$ echo "export LANG=zh_CN.UTF-8" > ~/.xsessionrc

救砖

在折腾这些东西的过程中,尤其是配置内核相关的东西的时候,我把系统干崩了无数次,所以很有必要总结下我的救砖经验,供后人参考

瑞芯微soc的启动流程

maskrom--->spi flash->sd card/emmc/nvme/sata/usb...
        \
         ->bootloader->烧录

maskrom是固化在芯片rom中的启动程序,无法修改,他会在上电后自动运行spi flash中的程序(对香橙派来说,如果你是别的板子还可能是nand之类的),如果按住了板子上的maskrom键再上电则会进入maskrom模式,该模式下会等待电脑端上位机RKDevTool发送bootloader,将bootloader放到内存中并执行,所以rk3588的启动流程是一个典型的二阶段加载SSB(似乎国产芯片都这样?)

因此我们需要备份的就是spi flash和你使用的存储器里的内容,这里我使用的是nvme固态硬盘

ubuntu-rockchip的镜像格式

ubuntu-rockchip也很有意思,为了方便随时更换系统无需使用RKDevTool烧写flash,这个ubuntu镜像并非像官方的镜像一样,把uboot烧录在spi flash中,把整个系统分区烧录在存储器中,而是在存储器开头16MB放置了uboot的镜像,后面是一个ext4格式的EFI分区(真的是EFI),启动时会先从maskrom跳转到spi flash里的rkspi_loader,然后跳转到存储器中的uboot分区,再从ext4分区中加载系统内核,最后启动

所以需要注意的是备份系统时不要忘记备份和恢复uboot分区,不然起不来啦

备份和还原整块硬盘

这个简单,dd整块硬盘就行,dd是直接按扇区复制的,没有压缩,所以电脑上记得留充足的空间

可以使用fdisk工具查看系统使用的存储设备名
$ fdisk -l
直接复制到文件
$ dd if=/dev/<存储设备名> of=ubuntu_backup.img bs=4M status=progress
只备份uboot分区
$ dd if=/dev/<存储设备名> of=uboot_backup.img bs=512 count=32
也可以在复制时用管道进行压缩
$ dd if=/dev/<存储设备名> bs=4M | gzip > ubuntu_backup.img.gz

从镜像恢复
$ dd if=ubuntu_backup.img of=/dev/<存储设备名>
只恢复uboot分区
$ dd if=uboot_backup.img of=/dev/<存储设备名>
从压缩的镜像恢复
$ gzip -dc ubuntu_backup.img.gz | dd of=/dev/<存储设备名>

备份和还原文件

因为我的硬盘是256GB的,而且是块19年的三星硬盘,发热量巨大,我就只备份了装系统的分区

还是用fdisk工具查看分区名
$ fdisk -l
挂载分区
$ mkdir -p /mnt/media
$ sudo mount /dev/nvmexnxpx /mnt/media

备份分区所有文件
$ cd /mnt/media
$ tar --acls --xattrs -cpvf ~/rootfs_backup.tar ./
还原分区所有文件
$ tar --acls --xattrs -xpvf ~/rootfs_backup.tar -C /mnt/media

结果实际恢复之后系统起不来,有一大堆坑,以后还是老老实实备份硬盘吧,如果你也和我一样不幸只备份了文件,然后重新烧录了镜像并恢复了文件,那就接着看下一节吧

我忘了备份uboot,怎么办QAQ

首先说结论,其实只备份和还原文件最终是能起来的,只是需要像电脑一样修复一下引导,但是由于arm架构的soc没有UEFI(虽然有edk2的移植,但是还不完善,我没用),也没有grub,更没有livecd,导致修引导极其地费劲。而且内存盘的命令行还只显示在屏幕上,调试串口中没有,导致我一度以为内核挂死修不好了,折腾了好几天

最关键的一点其实在于重装系统后分区的UUID会变,而恢复根文件系统后的/boot/extlinux/extlinux.conf启动配置中还是旧的分区的UUID,导致内核找不到要启动的分区,从而只能进到initramfs的命令行中

这里似乎还有驱动bug,如果我没在进入initramfs前接显示器并切换过去,那无论怎么敲回车屏幕都没有画面,这也是我以为内核挂死的原因之一

首先在命令行中输入exit可以获取系统启动失败的原因,我的原因就是找不到指定UUID的分区

然后使用blkid查看当前各分区的UUID

$ blkid
/dev/nvme0n1p1: LABEL="desktop-rootfs" UUID="977077f9-5d15-4766-802f-99dd34d4f78a" BLOCK_SIZE="4096" TYPE="ext4" PARTLABEL="primary" PARTUUID="7d82bd51-86d5-4adf-b37c-5eb3d5efb1af"

从输出的信息中可以看到系统分区的UUID为977077f9-5d15-4766-802f-99dd34d4f78a,把他记下来,然后把硬盘换到一台装了linux系统的电脑上(windows和mac也行,能想办法打开ext4分区就行)

编辑/boot/extlinux/extlinux.conf/etc/fstab,把分区的UUID全换成刚才的那个,然后硬盘插回去就能成功启动了

最后别忘了sudo u-boot-update更新一下extlinux.conf

部署服务

我打算充分压榨(划掉)利用香橙派的每一份算力,所以打算在上面跑一大堆服务,这些服务单独跑很简单,但要让他们同时正常工作在一个arm架构的soc上还是太吃实力了,遇到了很多坑啊,光重装系统就不下几十次

基础设施

1. Docker

apt install docker docker-compose

最简单的一集

docker desktop商业化太重了,所以管理界面本来打算用podman来着,但是没研究明白,后来改用面板的容器管理功能了

2. Win11虚拟机

使用了bvm,门槛很低,基本上是一键配置,就是很卡

https://github.com/Botspot/bvm

3. WINE/box86

win11虚拟机太卡了,装b用可以,真要跑windows程序还得是wine或者box86这种转译

参考:在 openFyde 和 FydeOS ARM64 设备上安装 Box86、Steam 和 Wine | FydeOS 帮助中心

sudo apt install gcc-arm-linux-gnueabihf libc6-dev-armhf-cross
git clone https://github.com/ptitSeb/box86
cd box86
mkdir build && cd build
cmake .. -DRK3588=1 -DCMAKE_BUILD_TYPE=RelWithDebInfo
make -j4
sudo make install
# 打包deb
DEB_BUILD_OPTIONS=nostrip dpkg-buildpackage -us -uc -nc
sudo apt install binfmt-support
git clone https://github.com/ptitSeb/box64
cd box64
mkdir build && cd build
cmake .. -D ARM_DYNAREC=ON -D RK3588=1 -D CMAKE_BUILD_TYPE=RelWithDebInfo -D BOX32=ON -D BOX32_BINFMT=ON
make -j4
sudo make install
sudo systemctl restart systemd-binfmt
# 打包deb
DEB_BUILD_OPTIONS=nostrip dpkg-buildpackage -us -uc -nc
$ sudo vi /usr/share/binfmts/box86
package box86
interpreter /usr/local/bin/box86
magic \x7fELF\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x03\x00
mask \xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff

$ sudo vi /usr/share/binfmts/box64
package box64
interpreter /usr/local/bin/box64
magic \x7fELF\x02\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x3e\x00
mask \xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff

$ sudo update-binfmts --import
$ sudo update-binfmts --enable box86
$ sudo update-binfmts --enable box64
$ sudo update-binfmts --display
$ sudo systemctl restart systemd-binfmt
echo 'export STEAMOS=1
export STEAM_RUNTIME=1
export DOTNET_SYSTEM_GLOBALIZATION_INVARIANT=1' | sudo tee /etc/profile.d/steam.sh
source /etc/profile.d/steam.sh
./box86/install_steam.sh
sudo apt install libx11-6:armhf libgl-dev:armhf libxrandr2:armhf
sudo apt install libayatana-appindicator3-1 libglib2.0-0t64 libgtk-3-0t64 # libappindicator1
steam

killall -9 steam steamwebhelper
rm -rf ~/.local/share/Steam/

事实上我并没有成功,暂时放弃了,等以后有空了再研究

4. Android容器

为了做某个已经停更的游戏的每日任务,我希望跑一个Android容器,每天自动化执行挂机任务

在试了一大堆Android容器后,发现最好用的还是CNflysky/redroid-rk3588,但是这个容器依赖自定义的linux内核,如果是armbian有大佬编好的直接拿来用即可,而用ubuntu-rockchip的就只能好好折腾一番了

① 编译内核

需要按照CNflysky/redroid-rk3588的README所述,调整内核选项,如果内核版本是6.1还要打dma-buf驱动的补丁,考虑到这个步骤比较繁琐,我已经把我验证过的内核代码上传到了github,直接编译即可

https://github.com/DawningW/linux-rockchip

然后按照linux-rockchip文档的步骤编译内核

https://github.com/Joshua-Riek/linux-rockchip/wiki#building-the-kernel

export $(dpkg-architecture -aarm64)
export CROSS_COMPILE=aarch64-linux-gnu-
export CC=aarch64-linux-gnu-gcc
export LANG=C

fakeroot debian/rules clean binary-headers binary-rockchip do_mainline_build=true

编译完毕后会在上一级目录中生成含有内核模块的deb包,直接用apt安装即可

如果懒得编译或者实在编译不过可以下载我编好的内核

https://github.com/DawningW/linux-rockchip/releases/tag/6.1.0-1027.27%2Bredroid.2

参考:https://www.nyanners.moe/post/fix-rk3588-redroid-azur-lane-crash.html

② 安装容器

把CNflysky/redroid-rk3588拉到本地,修改下docker-compose.yml里的配置,然后

sudo docker-compose up

③ 原神启动 修复其他环境问题

再装个adb和scrcpy,然后就可以启动了…吗

事实上,如果直接启动我玩的某游戏,开屏界面后会闪退,logcat报以下错误:

The property "ro.build.fingerprint" has a value with length 95 that is too large for __system_property_get()/__system_property_read(); use __system_property_read_callback() instead.

这是因为游戏使用了__system_property_get接口读取指纹属性,而这个接口最大只能读95个字符,镜像默认的指纹是redroid/redroid_arm64/redroid_arm64:13/TQ3A.230901.001/eng.flysky.20241107.005346:user/dev-keys,超过了95个字符

但是这是一个只读属性,直接用setprop改会失败,怎么办呢

诶,我灵机一动,这个镜像里有magisk,也就是说镜像已经root了,正好magisk提供了一个resetprop的命令用于修改任何属性,用它改不就行了,一试结果还真行

https://github.com/topjohnwu/Magisk/blob/master/docs/tools.md#resetprop

$ su
# resetprop ro.build.fingerprint redroid/redroid_rk/redroid:13/TQ3A.230901.001/flysky.20241107.005346:user/dev-keys

游戏顺利启动,性能也不错,居然能跑满60帧,挂机脚本也能流畅运行 🙂

应用服务

1. 面板

研究了许多面板,最后发现市面上能用的还是只有宝塔和1panel,宝塔是php写的直接排除,那就来装1panel吧

按官方文档一键安装即可:https://1panel.cn/docs/v2/installation/online_installation/

bash -c "$(curl -sSL https://resource.fit2cloud.com/1panel/package/v2/quick_start.sh)"

进程守护功能需要安装supervisor

sudo apt install supervisor

最后再通过1panel的定时任务功能定时执行挂机脚本(所以我装个面板只是为了定时任务和进程守护吗

2. DDNS

经典ddns-go

3. tailscale

sudo apt install tailscale

4. HomeAssistant

我现在租的房子有小米全屋智能,那当然得接入一下HA了

我选择了通过docker-compose方式安装:https://www.home-assistant.io/installation/alternative/#docker-compose

services:
  homeassistant:
    container_name: homeassistant
    image: "ghcr.io/home-assistant/home-assistant:stable"
    volumes:
      - <你的homeassistant配置目录>:/config
      - /etc/localtime:/etc/localtime:ro
      - /run/dbus:/run/dbus:ro
    restart: unless-stopped
    privileged: true
    network_mode: host

然后启动

$ sudo docker-compose up -d

打开 http://<host>:8123 并进行配置

添加 Home Assistant Community Store 源:https://hacs.xyz/docs/use/download/download/#to-download-hacs-container

$ sudo docker exec -it homeassistant bash
wget -O - https://get.hacs.xyz | bash -

然后在集成中添加HACS

安装官方米家集成:https://github.com/XiaoMi/ha_xiaomi_home/blob/main/doc/README_zh.md

HACS > 在搜索框中输入 Xiaomi Home > 点击 Xiaomi Home ,进入集成详情页 > DOWNLOAD

然后在集成中添加Xiaomi Home,再登录小米账号即可

用vivo智慧生活控制HA:https://github.com/vivo/ha_vivohomebridge

安装后在集成中添加vivohomebridge,然后用vivo智慧生活添加HA中控即可

添加MQTT设备:TODO

添加ESPHome设备:TODO

换更好看的主题:TODO

5. Gitea Runner

按照官方文档按照act runner,因为我是想直接在香橙派本机上跑测试,需要用到sensor等外设,所以没有使用容器部署的方式,而是直接运行,通过1panel的进程守护功能在后台运行(实际是supervisor)

https://docs.gitea.com/zh-cn/usage/actions/act-runner

不过我跑执行器是为了给OurIPC跑门禁,那就需要在板端支持sensor和isp server,ubuntu-rockchip默认并没有开启这些功能,毕竟一般人用不到,下面将介绍如何通过dtbo(设备树覆盖)来实现加载sensor驱动并启动rkisp-server

https://github.com/Joshua-Riek/ubuntu-rockchip/wiki/Ubuntu-24.04-LTS#system-customization

首先加载sensor的设备树,我用的是ov13855,接在cam1上,所以进入到/lib/firmware/$(uname -r)/device-tree/rockchip/overlay目录中找对应的dtbo,经过一番查找,我需要加载的dtbo是orangepi-5-ov13855-c1.dtbo

编辑/etc/default/u-boot,将U_BOOT_FDT_OVERLAYS_DIR设置为"/lib/firmware/",将U_BOOT_FDT_OVERLAYS设置为"device-tree/rockchip/overlay/orangepi-5-ov13855-c1.dtbo",最后运行sudo u-boot-update更新/boot/extlinux/extlinux.conf启动配置

如果需要修改内核启动参数,可以编辑/etc/kernel/cmdline,在里面加上你需要的启动参数,最后别忘了u-boot-update

重启后使用gstreamer已经能够预览sensor的视频流,但因为没有过isp,图像是发绿的,几乎什么都看不清,所以接下来还需要安装并启动瑞芯微的rkaiq_3A_server

$ apt search rkaiq
camera-engine-rkaiq-rk3588/noble,now 6.0x6.1-3~noble arm64
3A libraries match Rockchip rkisp v30(rk3588).
$ sudo apt install camera-engine-rkaiq-rk3588
$ sudo systemctl enable rkaiq_3A.service
$ sudo systemctl start rkaiq_3A.service

然后就可以用gstreamer从isp的节点拉流,图像就正常啦,你可以用gstreamer甚至自己写个程序把香橙派变成一个IPC,这实在是太酷啦!

其他操作,如3A算法参数调节等可以参考瑞芯微官方提供的手册

6. rkllm

rk3588的一大特点就是有算力高达6T的NPU,那能不能用来跑一些小大模型呢,诶,当然是可以的,官方推出了针对大语言模型优化的rkllm库以及预转换好的模型,我们可以直接拿来用

https://github.com/airockchip/rknn-llm

ubuntu-rockchip的5.10和6.1内核中都应该已经自带了RKNPU的内核驱动,且默认开启,应该不需要任何配置就能工作,我们只需要将rknn-llm克隆到板端,下载模型,运行例程即可使用

下面运行推理使用DeepSeek-R1蒸馏的Qwen-7B模型(int8量化)效果如下(我的版本有点旧了,现在库上最新版本可能目录结构有区别,以官方文档为准)

$ cd rknn-llm/examples/DeepSeek-R1-Distill-Qwen-1.5B_Demo/deploy
$ ./build-linux.sh
$ cd install/demo_Linux_aarch64
$ export LD_LIBRARY_PATH=$(pwd)/lib
$ ./llm_demo <下载的模型目录>/DeepSeek_R1_Distill/DeepSeek-R1-Distill-Qwen-7B_W8A8_RK3588.rkllm 1024 4096
rkllm init start
I rkllm: rkllm-runtime version: 1.1.4, rknpu driver version: 0.9.7, platform: RK3588
rkllm init success
**********************可输入以下问题对应序号获取回答/或自定义输入********************

[0] 现有一笼子,里面有鸡和兔子若干只,数一数,共有头14个,腿38条,求鸡和兔子各有多少只?
[1] 有28位小朋友排成一行,从左边开始数第10位是学豆,从右边开始数他是第几位?

*************************************************************************

user: hello
robot: <think>

</think>

Hello! How can I assist you today? 😊

user: 你是谁
robot: <think>

</think>

您好!我是由中国的深度求索(DeepSeek)公司开发的智能助手DeepSeek-R1。如您有任何任何问题,我会尽我所能为您提供帮助。

user: ^C程序即将退出

输出token的速度好慢,我们有没有什么办法查看NPU的使用率呢,有的兄弟有的,rknpu驱动在sysfs下提供了几个用于查看NPU占用率的设备

$ sudo cat /sys/kernel/debug/rknpu/load
NPU load: Core0: 0%, Core1: 0%, Core2: 0%,

如果想要持续观测可以使用watch命令

watch -n 1.0 sudo cat /sys/kernel/debug/rknpu/load

除了NPU占用率,温度也是需要关注的,可以通过以下命令获取

$ cat /sys/class/thermal/thermal_zone*/type
pe
soc-thermal
bigcore0-thermal
bigcore1-thermal
littlecore-thermal
center-thermal
gpu-thermal
npu-thermal
$ cat /sys/class/thermal/thermal_zone*/temp
mp
46230
47153
47153
46230
44384
43461
44384

获取的温度值是乘了1000的,例如上述的46230是46.23°C,可以看到我的香橙派温度还行

如果想要更以人类可读的方式查看传感器温度,可以安装lm-sensors库来查看

$ sudo apt install lm-sensors
$ sensors

那如果想要可视化地查看NPU占用率呢,正好我前段时间在GitHub逛的时候发现了一个脚本,用起来还行

https://github.com/Tang-JingWei/watchload-for-rk3588

直接克隆到本地安装依赖后即可运行

$ git clone https://github.com/Tang-JingWei/watchload-for-rk3588.git
$ cd watchload-for-rk3588
$ pip install -r requirements.txt
$ ./watchload

这个脚本除了TUI外还支持使用matplotlib绘制NPU占用率曲线图,很有意思

上述的例程只能在命令行中输入对话,怎么作为服务对接聊天机器人或各类LLM工具呢,答案是GitHub上有个毛子写的Python脚本,为rkllm推理套了一层openai的api接口

由于原脚本很长时间没有维护了,这里选择了他的一个汉化分支,并在该分支基础上修改:https://github.com/kylin7226/rkllm_server_openai_api

这样就能使用任何兼容openai api接口的客户端使用rkllm进行推理啦~

7. napcat(?)

Docker镜像部署:https://github.com/NapNeko/NapCat-Docker

暂时不跑,有空再搬过去

未来展望

等到rk36883788甚至3888是不是就可以上虚拟化了,虽然现在rk3588已经有移植的esxi,但是不够完善,且rk3588性能还是太差,如果能上虚拟化,且算力足够,就能取代x86的AIO,实现一个集软路由、NAS、各种服务、虚拟机、NVR、大模型推理于一体的超级AIO,且功耗对x86有显著优势

现在是幻想时间
标题: 让你的香橙派5不再吃灰——超低功耗AIB爆改记录
作者: QingChenW
链接: https://dawncraft.cc/2025/10/602/
本文遵循 署名-非商业性使用-相同方式共享 4.0 国际 (CC BY-NC-SA 4.0) 许可
禁止商用, 非商业转载请注明作者及来源!
上一篇
隐藏