Merge pull request #834 from liangzhuohua/feat/nanokvm-data-initd

feat(kvm): add NanoKVM data and init scripts
This commit is contained in:
Guoguo
2026-07-07 17:30:48 +08:00
committed by GitHub
17 changed files with 1707 additions and 607 deletions

4
.gitignore vendored
View File

@@ -3,6 +3,10 @@
*.o
*.ko
*.d
# keep init.d directory
!kvm/init.d/*
!buildroot/board/cvitek/SG200X/overlay/etc/init.d/
!buildroot/board/cvitek/SG200X/overlay/etc/init.d/*
host-tools/
host-tools
*.sqfs

677
README.md
View File

@@ -1,60 +1,671 @@
# LicheeRV-Nano-Build
# 构建 NanoKVM 镜像
# download source
完整的 NanoKVM 镜像由两部分组成:
1. `LicheeRV-Nano` 的 Linux 系统镜像。
2. `NanoKVM APP`,也就是设备启动后运行的 KVM 应用、Web 前端、后端服务和硬件辅助组件。
整体流程是:先编译 `LicheeRV-Nano Linux` 镜像,再编译 `NanoKVM APP`,最后把 `kvmapp` 合并进系统镜像。
## 0. 路径约定
为避免后续构建、复制和挂载命令中的路径混乱,本文固定使用下面的目录结构。所有源码都放在用户目录下的 `LicheeRV_NanoKVM` 文件夹中:
```text
~/LicheeRV_NanoKVM/
├── LicheeRV-Nano-Build/ # SDK 和系统镜像构建目录
└── NanoKVM/ # NanoKVM APP 源码目录
```
git clone https://github.com/sipeed/LicheeRV-Nano-Build --depth=1
cd LicheeRV-Nano-Build
先在终端里定义这几个固定路径变量,后续命令都基于它们执行:
```shell
export WORKDIR="$HOME/LicheeRV_NanoKVM"
export SDK_DIR="$WORKDIR/LicheeRV-Nano-Build"
export APP_DIR="$WORKDIR/NanoKVM"
```
首次构建前创建工作目录:
```shell
mkdir -p "$WORKDIR"
```
不要把 `LicheeRV-Nano-Build` 和 `NanoKVM` 分散到其他目录,否则后文的复制、合并镜像命令需要同步调整。新开终端后需要重新执行上面的变量定义。
## 1. 构建 LicheeRV-Nano Linux 镜像
### 1.1 源码和分支
- SDK 仓库:<https://github.com/sipeed/LicheeRV-Nano-Build>
- SDK 分支:`NanoKVM`
- 工具链仓库:<https://github.com/sophgo/host-tools>
`host-tools` 中包含 `riscv64-unknown-linux-musl-gcc`,后续编译 `NanoKVM APP` 的后端服务也会用到同一套工具链。
### 1.2 拉取源码
```shell
cd "$WORKDIR"
git clone -b NanoKVM https://github.com/sipeed/LicheeRV-Nano-Build --depth=1
cd "$SDK_DIR"
git clone https://github.com/sophgo/host-tools --depth=1
```
## host environment
如果源码已经存在,可以跳过 clone,直接进入目录:
you can use container:
```
cd host/ubuntu
docker build -t licheervnano-build-ubuntu .
docker run --name licheervnano-build-ubuntu licheervnano-build-ubuntu
docker export licheervnano-build-ubuntu | sqfstar licheervnano-build-ubuntu.sqfs
singularity shell -e licheervnano-build-ubuntu.sqfs
```shell
cd "$SDK_DIR"
```
# build it
### 1.3 编译系统镜像
```
进入 SDK 目录并加载编译环境:
```shell
cd "$SDK_DIR"
source build/cvisetup.sh
# C906:
```
执行后会注册 `defconfig`、`build_all`、`clean_all` 等命令,并打印当前 SDK 支持的板型配置说明。
选择 `LicheeRV Nano` 的板级配置:
```shell
defconfig sg2002_licheervnano_sd
# A53:
# defconfig sg2002_licheea53nano_sd
```
如果要编译 A53 版本,可以改用:
```shell
defconfig sg2002_licheea53nano_sd
```
开始完整编译:
```shell
build_all
```
# build fail
`build_all` 会依次编译 `U-Boot`、`Kernel`、`ramdisk/rootfs`、驱动、第三方库、中间件,并打包最终镜像。
on some system, qt5svg or qt5base will build failed on first build, please retry command:
如果需要从干净状态重新完整编译,可以执行:
```
```shell
cd "$SDK_DIR"
source build/cvisetup.sh
defconfig sg2002_licheervnano_sd
clean_all
build_all
```
# how to modify image after build:
不要在另一个 `build_all` 还在运行时执行 `clean_all`。
```
# first partition
touch wifi.sta
mcopy -i install/xxx/xxx.img@@1s wifi.sta ::/
### 1.4 WSL 下的 PATH 问题
# second partition
./host/mount_ext4.sh install/xxx/xxx.img mountpoint
cd mountpoint
touch xxx
如果在 WSL 中编译,可能会遇到类似错误:
```text
Your PATH contains spaces, TABs, and/or newline (\n) characters.
This doesn't work. Fix you PATH.
make: *** [support/dependencies/dependencies.mk:27: dependencies] Error 1
```
# logo
这是因为 `PATH` 里混入了带空格的 Windows 路径,Buildroot 不允许 `PATH` 包含空格、Tab 或换行。可以在当前终端临时过滤掉这些路径后再重新编译:
```shell
export PATH="$(printf '%s' "$PATH" | tr ':' '\n' | grep -v '[[:space:]]' | paste -sd: -)"
```
./host/make_logo.sh input.jpeg logo.jpeg
mcopy -i install/xxx/xxx.img@@1s logo.jpeg ::/
### 1.5 编译产物
编译成功后,产物通常位于:
```shell
"$SDK_DIR/install/soc_sg2002_licheervnano_sd/"
```
镜像文件通常在:
```shell
"$SDK_DIR/install/soc_sg2002_licheervnano_sd/images/"
```
常见产物包括:
```text
fip.bin
boot.sd
rootfs.sd
system.sd
upgrade.zip
*.img
```
查看最新生成的整盘镜像:
```shell
ls -lh "$SDK_DIR"/install/soc_sg2002_licheervnano_sd/images/*.img
```
如果编译过程中停在下载进度位置,例如 `Buildroot` 正在下载 `Pillow`、`qt5base`、`qt5svg` 等源码包,通常是网络较慢,不一定是编译卡死。可以观察对应的临时下载文件大小是否仍在增长。
如果首次构建在 `qt5svg` 或 `qt5base` 附近失败,可以先重新执行:
```shell
build_all
```
## 2. 构建 NanoKVM APP
### 2.1 拉取源码
```shell
cd "$WORKDIR"
git clone https://github.com/sipeed/NanoKVM.git --depth=1
cd "$APP_DIR"
```
这里的 `kvmapp` 是 NanoKVM 设备上的应用目录,不是完整烧录镜像。完整系统镜像还需要依赖前面编译出的 `LicheeRV-Nano Linux` 镜像。
`NanoKVM` 仓库的主要目录如下:
```text
NanoKVM/
├── server/ # Go 后端服务
├── web/ # 前端页面
├── support/sg2002/ # kvm_system 等硬件辅助组件
├── kvmapp/ # 本地应用包目录
└── Makefile # Docker builder 编译入口
```
最终 `kvmapp` 中至少需要这些关键内容:
```text
kvmapp/server/NanoKVM-Server
kvmapp/server/dl_lib/
kvmapp/server/web/
kvmapp/kvm_system/kvm_system
kvmapp/kvm_system/kvm_stream
kvmapp/system/init.d/S95nanokvm
```
需要编译或更新的组件主要是:
- `server/`:Go 后端,生成 `NanoKVM-Server`。
- `web/`:前端页面,生成 `dist/` 后放入 `kvmapp/server/web/`。
- `support/sg2002/kvm_system`:硬件辅助进程,生成 `kvm_system`。
通常不需要单独编译的内容:
- `kvmapp/system/init.d/`:启动脚本,直接复制。
- `kvmapp/picoclaw/`:运行时配置和技能文件,`picoclaw` 二进制由设备侧安装或下载逻辑处理。
- `kvmapp/jpg_stream/`:旧版本升级兼容文件,保留即可。
- `tools/logo_generator/`:Python 辅助脚本,不参与 `kvmapp` 主流程编译。
按需编译的内容:
- `support/sg2002/kvm_vision`:只有修改图像采集或编码动态库时才需要重新编译。
- `tools/nanokvm_update_edid`:EDID 更新工具。如果后续从 SDK 镜像挂载目录里的 `mnt/system/tool/` 补齐,可以不重新编译。
### 2.2 准备 Go 环境
`server/` 是 Go 后端项目,编译 `NanoKVM-Server` 需要本机安装 Go。项目 `server/go.mod` 使用:
```go
go 1.24.0
```
先检查当前电脑是否已经有 Go:
```shell
which go
go version
```
期望 Go 版本为 `1.24.0` 或更高,例如:
```text
/usr/local/go/bin/go
go version go1.24.0 linux/amd64
```
如果提示 `go: command not found`,或者版本低于 `1.24.0`,可以安装官方 Go:
```shell
cd /tmp
wget https://go.dev/dl/go1.24.0.linux-amd64.tar.gz
sudo rm -rf /usr/local/go
sudo tar -C /usr/local -xzf go1.24.0.linux-amd64.tar.gz
echo 'export PATH=/usr/local/go/bin:$PATH' >> ~/.bashrc
source ~/.bashrc
hash -r
which go
go version
```
如果 `which go` 指向 `/usr/bin/go`,或者执行 `go mod tidy` 时出现:
```text
invalid go version '1.24.0': must match format 1.23
```
说明当前 Go 太旧,或者用到了 Ubuntu 自带的 `gccgo`。确认 `/usr/local/go/bin` 已经排在 `PATH` 前面,然后重新执行:
```shell
hash -r
go version
```
如果 Go 依赖下载很慢,可以设置代理:
```shell
go env -w GOPROXY=https://goproxy.cn,direct
go env -w GOSUMDB=sum.golang.google.cn
```
### 2.3 准备 server 编译依赖
除了 Go,`server/build.sh` 还需要:
- `patchelf`
- `riscv64-unknown-linux-musl-gcc`
检查依赖:
```shell
which patchelf
which riscv64-unknown-linux-musl-gcc
```
安装 `patchelf`:
```shell
sudo apt update
sudo apt install -y patchelf
```
如果 RISC-V 工具链没有加入 `PATH`,可以使用 SDK 里的 `host-tools`:
```shell
export PATH="$SDK_DIR/host-tools/gcc/riscv64-linux-musl-x86_64/bin:$PATH"
which riscv64-unknown-linux-musl-gcc
riscv64-unknown-linux-musl-gcc -v
```
### 2.4 编译后端 server
推荐使用仓库里的脚本,因为它会自动设置 `RPATH`:
```shell
cd "$APP_DIR/server"
go mod tidy
./build.sh
```
成功后生成:
```text
server/NanoKVM-Server
```
确认架构和 `RPATH`:
```shell
file NanoKVM-Server
patchelf --print-rpath NanoKVM-Server
```
期望输出包含:
```text
ELF 64-bit ... RISC-V ...
$ORIGIN/dl_lib
```
如果看到类似警告:
```text
warning: libopencv_video.so.409, needed by .../libkvm.so, not found
```
但同时看到:
```text
[SUCCESS] Binary 'NanoKVM-Server' created successfully.
[DONE] Build script completed successfully!
```
说明 `server` 已经编译成功。这个警告表示本机交叉链接时没有找到某个运行时库,后续需要确认设备或 `kvmapp/server/dl_lib` 中有对应库。
把后端放入本地 `kvmapp`:
```shell
cd "$APP_DIR"
mkdir -p kvmapp/server
cp server/NanoKVM-Server kvmapp/server/NanoKVM-Server
cp -a server/dl_lib kvmapp/server/
```
### 2.5 编译前端 web
进入前端目录:
```shell
cd "$APP_DIR/web"
pnpm install
pnpm build
```
如果执行 `pnpm install` 时报错:
```text
ERROR packages field missing or empty
```
说明当前 `pnpm` 版本识别到了 `web/pnpm-workspace.yaml`,但这个文件里缺少 `packages` 字段。可以给 `pnpm-workspace.yaml` 补上当前目录作为 workspace 包:
```yaml
packages:
- "."
allowBuilds:
bufferutil: true
es5-ext: true
esbuild: true
msw: true
utf-8-validate: true
```
修改后重新执行:
```shell
pnpm install
pnpm build
```
成功后生成:
```text
web/dist
```
放入本地 `kvmapp`:
```shell
cd "$APP_DIR/web"
rm -rf "$APP_DIR/kvmapp/server/web"
mkdir -p "$APP_DIR/kvmapp/server"
cp -a dist "$APP_DIR/kvmapp/server/web"
```
检查前端文件:
```shell
ls "$APP_DIR/kvmapp/server/web"
ls "$APP_DIR/kvmapp/server/web/assets"
```
应包含:
```text
index.html
assets/
sipeed.ico
```
### 2.6 编译 support 组件
仓库顶层 `Makefile` 使用 Docker builder 编译 support 组件,需要 Docker 已安装并运行。
检查 Docker:
```shell
docker --version
```
构建 builder 镜像:
```shell
cd "$APP_DIR"
make builder-image
```
编译 support:
```shell
make support
```
`make support` 会在 Docker 中使用 `MaixCDK` 编译 `support/sg2002/kvm_system`,并执行:
```text
./build kvm_system
./build kvm_system add_to_kvmapp
```
生成或更新:
```text
kvmapp/kvm_system/kvm_system
```
如果修改过图像采集或编码相关动态库,可以按需编译 `kvm_vision`:
```shell
cd "$APP_DIR/support/sg2002"
./build kvm_vision
./build kvm_vision add_to_kvmapp
```
这会把 `kvm_vision_test/dist/kvm_vision_test_release/dl_lib/` 更新到 `kvmapp/server/dl_lib/`。没有修改这部分时,通常直接使用仓库或镜像中已有的 `dl_lib/` 即可。
注意:顶层 `make all` 等于:
```text
make app
make support
```
但是 `make all` 不会编译前端 `web`,并且 `make app` 没有执行 `patchelf --add-rpath '$ORIGIN/dl_lib'`。因此 `server` 更推荐使用 `server/build.sh` 编译。
### 2.7 可选:编译 EDID 更新工具
如果不从 SDK 镜像挂载目录里的 `mnt/system/tool/` 复制 EDID 工具,可以手动编译:
```shell
cd "$APP_DIR/tools/nanokvm_update_edid"
make
cd "$APP_DIR"
mkdir -p kvmapp/system/tool
cp tools/nanokvm_update_edid/nanokvm_update_edid kvmapp/system/tool/
cp tools/nanokvm_update_edid/E21_NanoKVM.bin kvmapp/system/tool/
```
如果板子烧录的是当前 SDK 编译出的镜像,更推荐后续从 `mountpoint` 补齐,避免工具版本和镜像不一致。
### 2.8 补充 version 文件
在 `kvmapp` 目录中写入应用版本号:
```shell
cd "$APP_DIR/kvmapp"
echo 2.4.3 > version
```
### 2.9 检查 kvmapp 文件
构建完后的 `kvmapp` 目录应该包含以下关键文件。不同版本的文件数量可能略有差异,但这些核心路径应当存在:
```text
kvmapp
├── jpg_stream
│ ├── S95nanokvm
│ └── jpg_stream
├── kvm_new_app
├── kvm_system
│ ├── kvm_stream
│ └── kvm_system
├── picoclaw
│ ├── AGENT.md
│ ├── AGENT_KVM.md
│ └── skills
│ └── kvm-control
├── server
│ ├── NanoKVM-Server
│ ├── dl_lib
│ └── web
│ ├── assets
│ ├── index.html
│ ├── mockServiceWorker.js
│ └── sipeed.ico
├── system
│ ├── init.d
│ │ ├── S00kmod
│ │ ├── S01fs
│ │ ├── S03usbdev
│ │ ├── S03usbhid
│ │ ├── S15kvmhwd
│ │ ├── S30eth
│ │ ├── S30wifi
│ │ ├── S50avahi-daemon
│ │ ├── S50ssdpd
│ │ ├── S50sshd
│ │ ├── S80dnsmasq
│ │ ├── S95nanokvm
│ │ ├── S96picoclaw
│ │ └── S98tailscaled
│ ├── ko
│ │ └── soph_mipi_rx.ko
│ └── update-nanokvm.py
└── version
```
可以用下面的命令快速检查关键文件:
```shell
test -x "$APP_DIR/kvmapp/server/NanoKVM-Server"
test -d "$APP_DIR/kvmapp/server/dl_lib"
test -f "$APP_DIR/kvmapp/server/web/index.html"
test -x "$APP_DIR/kvmapp/kvm_system/kvm_system"
test -f "$APP_DIR/kvmapp/system/init.d/S95nanokvm"
test -f "$APP_DIR/kvmapp/version"
```
## 3. 合并系统镜像和 NanoKVM APP
SDK 的 `kvm/merge_nanokvm_app.sh` 脚本可以自动完成合并流程,包括:
- 从 `NanoKVM/kvmapp` 复制应用文件到 SDK 的 `kvm/kvmapp`。
- 自动选择最新生成的原始 `.img`,或者使用你手动指定的镜像。
- 默认复制出一个新的 `*-nanokvm.img`,只修改这个输出镜像,不原地修改原始镜像。
- 挂载镜像的 ext4 分区。
- 写入 `kvmapp`、`frpc`、`tailscale`、`tailscaled`、内核模块、启动脚本、默认数据和默认 KVM 配置。
- 每个关键步骤后检查挂载状态或目标文件,并校验第二分区之前的 boot 区域没有变化;失败时打印具体失败步骤并终止。
- 写入完成后自动卸载镜像。
### 3.1 默认用法
确认目录结构符合本文约定:
```text
~/LicheeRV_NanoKVM/
├── LicheeRV-Nano-Build/
└── NanoKVM/
```
然后进入 SDK 目录执行:
```shell
cd "$SDK_DIR"
./kvm/merge_nanokvm_app.sh
```
默认情况下,脚本会:
- 从 `"$APP_DIR/kvmapp"` 复制应用文件。
- 使用 `"$SDK_DIR/install/soc_sg2002_licheervnano_sd/images/"` 中最新的原始 `.img`。
- 生成同目录下的 `*-nanokvm.img` 作为输出镜像。
- 使用 `"$SDK_DIR/mountpoint"` 作为临时挂载目录。
执行完成后,终端会打印已经写入 NanoKVM APP 的镜像路径,例如:
```text
NanoKVM APP has been merged into:
/home/xxx/LicheeRV_NanoKVM/LicheeRV-Nano-Build/install/soc_sg2002_licheervnano_sd/images/xxx-nanokvm.img
```
把这个 `.img` 烧录到 SD 卡即可。
### 3.2 指定镜像文件
如果你不想使用最新镜像,可以用 `-i` 指定某一个 `.img`:
```shell
cd "$SDK_DIR"
./kvm/merge_nanokvm_app.sh -i install/soc_sg2002_licheervnano_sd/images/your-image-name.img
```
脚本默认会生成 `your-image-name-nanokvm.img`。如果想指定输出路径,可以使用 `-o`:
```shell
./kvm/merge_nanokvm_app.sh \
-i install/soc_sg2002_licheervnano_sd/images/your-image-name.img \
-o install/soc_sg2002_licheervnano_sd/images/your-output-name.img
```
如果输出镜像已经存在,需要加 `-f` 覆盖:
```shell
./kvm/merge_nanokvm_app.sh -i your-image-name.img -o your-output-name.img -f
```
也可以使用绝对路径:
```shell
./kvm/merge_nanokvm_app.sh -i "$SDK_DIR/install/soc_sg2002_licheervnano_sd/images/your-image-name.img"
```
### 3.3 指定 NanoKVM 源码目录
如果 `NanoKVM` 源码没有放在 `~/LicheeRV_NanoKVM/NanoKVM`,可以用 `-a` 指定:
```shell
cd "$SDK_DIR"
./kvm/merge_nanokvm_app.sh -a /path/to/NanoKVM
```
不过为了减少路径错误,仍然推荐按本文约定放置源码。
### 3.4 使用已有的 SDK kvm/kvmapp
如果你已经手动准备好了 `"$SDK_DIR/kvm/kvmapp"`,不想让脚本重新从 `NanoKVM/kvmapp` 覆盖它,可以加 `--skip-copy-kvmapp`:
```shell
cd "$SDK_DIR"
./kvm/merge_nanokvm_app.sh --skip-copy-kvmapp
```
这种方式会直接使用现有的 `kvm/kvmapp` 写入镜像。
### 3.5 查看脚本帮助
脚本支持的参数可以通过 `--help` 查看:
```shell
cd "$SDK_DIR"
./kvm/merge_nanokvm_app.sh --help
```
### 3.6 注意事项
- 执行脚本前,先确保第 1 节的系统镜像已经编译完成。
- 执行脚本前,先确保第 2 节的 `NanoKVM/kvmapp` 已经准备完整。
- 脚本会覆盖 SDK 目录下的 `kvm/kvmapp`,除非使用 `--skip-copy-kvmapp`。
- 脚本不会原地修改输入 `.img`,而是生成新的输出镜像;烧录时请使用脚本最后打印的 `*-nanokvm.img`。
- 如果脚本提示 `mountpoint` 目录已经挂载,先执行 `umount "$SDK_DIR/mountpoint"` 后再重试。

View File

@@ -0,0 +1,31 @@
#!/bin/sh
if ! command -v i2cget &> /dev/null
then
echo "i2cdetect not find, please install i2c-tools"
exit 1
fi
pmu_version=$(i2cget -y 4 0x34 0x03)
pmu_version=$((pmu_version & 0xCF))
chip_id_1=$(printf "%d" 0x47)
chip_id_2=$(printf "%d" 0x4a)
if [ "$pmu_version" -eq "$chip_id_1" ] || [ "$pmu_version" -eq "$chip_id_2" ]; then
case "$1" in
start)
exec /usr/bin/axp2101
echo "Starting PMU: OK\n"
;;
stop)
runlevel=$(cat /run/runlevel | awk '{ print $1 }')
if [ "$runlevel" = "0" ]; then
printf "Stopping PMU\n"
value=$(i2cget -y 4 0x34 0x10)
value=$((value | 0x01))
i2cset -y 4 0x34 0x10 $value
fi
;;
esac
fi

View File

@@ -0,0 +1,76 @@
#!/bin/sh
if [ "$1" = "start" ]
then
. /etc/profile
printf "copy config file from /boot: "
if [ -e /boot/sshd_config ]
then
cp -vf /boot/sshd_config /etc/ssh/sshd_config
fi
if [ -e /boot/resolv.conf ]
then
rm -rf /etc/resolv.conf
cp -vf /boot/resolv.conf /etc/resolv.conf
fi
if [ -e /boot/input-event-daemon ]
then
if [ ! -e /etc/input-event-daemon.conf ]
then
cp /etc/input-event-daemon.conf.bak /etc/input-event-daemon.conf
fi
else
if [ -e /etc/input-event-daemon.conf ]
then
cp /etc/input-event-daemon.conf /etc/input-event-daemon.conf.bak
rm /etc/input-event-daemon.conf
fi
fi
if [ -e /boot/rc.local ]
then
cp -vf /boot/rc.local /etc/rc.local
fi
if [ -e /boot/ttyGS0_handler.sh ]
then
cp /boot/ttyGS0_handler.sh /etc/ttyGS0_handler.sh
fi
if [ -e /boot/console_handler.sh ]
then
cp /boot/console_handler.sh /etc/console_handler.sh
fi
if [ -e /boot/alpha ]
then
if [ ! -e /mnt/data/sensor_cfg.ini ]
then
cp /mnt/data/sensor_cfg.ini.alpha /mnt/data/sensor_cfg.ini
fi
if [ $(cat /mnt/data/sensor_cfg.ini | wc -l) -eq 0 ]
then
cp /mnt/data/sensor_cfg.ini.beta /mnt/data/sensor_cfg.ini
fi
# MIPI RX 4N PINMUX MCLK0
devmem 0x0300116C 32 0x5
# MIPI RX 0N PINMUX MIPIP RX 0N
devmem 0x0300118C 32 0x3
echo " alpha "
else
if [ ! -e /mnt/data/sensor_cfg.ini ]
then
cp /mnt/data/sensor_cfg.ini.beta /mnt/data/sensor_cfg.ini
fi
if [ $(cat /mnt/data/sensor_cfg.ini | wc -l) -eq 0 ]
then
cp /mnt/data/sensor_cfg.ini.beta /mnt/data/sensor_cfg.ini
fi
# MIPI RX 4N PINMUX MIPI RX 4N
devmem 0x0300116C 32 0x3
# MIPI RX 0N PINMUX MCLK1
devmem 0x0300118C 32 0x5
echo -n " beta "
fi
if [ -e /boot/kvmtest ]
then
cp /mnt/data/sensor_cfg.ini.LT /mnt/data/sensor_cfg.ini
fi
echo "OK"
fi

View File

@@ -0,0 +1,21 @@
#!/bin/sh
if [ "$1" = "start" ]
then
. /etc/profile
if [ -e /boot/fb ]
then
echo "framebuffer enable"
insmod /mnt/system/ko/soph_fb.ko
# we need keep node /dev/fb0 open
# graphic layer will disable after node /dev/fb0 is closed
(
exec 3<>/dev/fb0
while true
do
sleep 65535
done
) &
fi
exit 0
fi

View File

@@ -0,0 +1,62 @@
#!/bin/sh
hex2mac() {
MAC=""
seq 2 2 12 | while read i
do
echo -n ${1} | head -c $i | tail -c 2
if [ $i != 12 ]
then
echo -n ':'
fi
done | tr '[:upper:]' '[:lower:]'
}
if [ "${1}" = start ]
then
prefix=kvm
if [ -e /boot/hostname.prefix ]
then
prefix=$(cat /boot/hostname.prefix)
fi
old_hostname=$(cat /etc/hostname)
new_hostname=${prefix}-$(sha512sum /sys/class/cvi-base/base_uid | head -c 4)
if [ -e /boot/hostname ]
then
new_hostname=$(cat /boot/hostname)
fi
if [ "${old_hostname}" != "${new_hostname}" ]
then
hostname ${new_hostname}
echo ${new_hostname} > /etc/hostname
sed -i -e "s/${old_hostname}/${new_hostname}/g" /etc/hosts
fi
echo "hostname: ${new_hostname}"
if [ -e /boot/eth.mac ]
then
new_ethmac=$(cat /boot/ethmac)
else
new_ethmac=$(hex2mac 48da356f$(sha512sum /sys/class/cvi-base/base_uid | head -c 4))
fi
ifconfig eth0 down
ip link set eth0 address ${new_ethmac}
ifconfig eth0 up
echo "ethernet mac address: ${new_ethmac}"
if [ -e /boot/usb.rndis0 ]
then
if [ -e /boot/usb.rndis0.mac ]
then
new_rndismac=$(cat /boot/usb.rndis0.mac)
else
new_rndismac=$(hex2mac 48da356e$(sha512sum /sys/class/cvi-base/base_uid | head -c 4))
fi
ifconfig usb0 down
ip link set usb0 address ${new_rndismac}
ifconfig usb0 up
echo "rndis mac address: ${new_rndismac}"
fi
fi

View File

@@ -0,0 +1,14 @@
#!/bin/sh
if [ "$1" = "start" ]
then
. /etc/profile
printf "load wifi kernel module: "
cd /mnt/system/ko/
insmod cfg80211.ko
insmod 3rd/aic8800_bsp.ko
insmod 3rd/aic8800_fdrv.ko
insmod 3rd/8733bs.ko
echo "OK"
exit 0
fi

View File

@@ -0,0 +1,70 @@
#!/bin/sh
. /etc/profile
gen_udhcpd_conf() {
interface=${1}
ipv4_prefix=${2}
echo "start ${ipv4_prefix}.100"
echo "end ${ipv4_prefix}.200"
echo "interface ${interface}"
echo "pidfile /var/run/udhcpd.${interface}.pid"
echo "lease_file /var/lib/misc/udhcpd.${interface}.leases"
echo "option subnet 255.255.255.0"
echo "option lease 864000"
}
start() {
if [ -e /boot/usb.rndis0 ]
then
printf "start usb rndis: "
if [ ! -e /boot/rndis.nodhcpd ]
then
if [ -e /boot/rndis.ipv4_prefix ]
then
ipv4_prefix=`cat /boot/rndis.ipv4_prefix`
else
id2=$(printf "%d" 0x$(sha512sum /sys/class/cvi-base/base_uid | head -c 2))
id3=$(printf "%d" 0x$(sha512sum /sys/class/cvi-base/base_uid | head -c 4 | tail -c 2))
if [ "$id2" = "$id3" ]
then
id2=$((id2 + 1))
fi
if [ "$id2" -ge 255 ]
then
id2=253
fi
if [ "$id3" -ge 255 ]
then
id3=254
fi
ipv4_prefix=10.$id2.$id3
fi
gen_udhcpd_conf usb0 "${ipv4_prefix}" > /etc/udhcpd.usb0.conf
ip addr add $ipv4_prefix.1/24 dev usb0
udhcpd -S /etc/udhcpd.usb0.conf
fi
echo "ok"
fi
}
stop() {
kill `cat /var/run/udhcpd.usb0.pid`
rm /var/run/udhcpd.usb0.pid
}
restart() {
start
stop
}
if [ "${1}" = "start" ]
then
start
elif [ "${1}" = "stop" ]
then
stop
elif [ "${1}" = "restart" ]
then
restart
fi

View File

@@ -1,264 +1,196 @@
BR2_riscv=y
BR2_riscv_g=y
BR2_RISCV_ISA_RVC=y
BR2_RISCV_ABI_LP64D=y
BR2_TOOLCHAIN_EXTERNAL=y
BR2_TOOLCHAIN_EXTERNAL_CUSTOM=y
BR2_TOOLCHAIN_EXTERNAL_PREINSTALLED=y
# cvitek vendor toolchain
BR2_TOOLCHAIN_EXTERNAL_CUSTOM_PREFIX="riscv64-unknown-linux-musl"
BR2_TOOLCHAIN_EXTERNAL_CUSTOM_MUSL=y
BR2_TOOLCHAIN_EXTERNAL_GCC_10=y
BR2_TOOLCHAIN_EXTERNAL_HEADERS_5_10=y
BR2_TOOLCHAIN_EXTERNAL_HAS_SSP=y
# BR2_TOOLCHAIN_EXTERNAL_INET_RPC is not set
BR2_TOOLCHAIN_EXTERNAL_CUSTOM_MUSL=y
BR2_TOOLCHAIN_EXTERNAL_CXX=y
# BR2_TOOLCHAIN_EXTERNAL_FORTRAN is not set
BR2_TOOLCHAIN_EXTERNAL_OPENMP=y
BR2_OPTIMIZE_2=y
BR2_TARGET_LDFLAGS="-mcpu=c906fdv -march=rv64imafdcv0p7xthead -mcmodel=medany -mabi=lp64d"
BR2_PACKAGE_GDB=y
BR2_PACKAGE_GDB_SERVER=y
BR2_PACKAGE_GDB_DEBUGGER=y
BR2_PACKAGE_GDB_PYTHON=y
BR2_PACKAGE_GDB_TUI=y
BR2_PACKAGE_HOST_GDB=y
BR2_PACKAGE_HOST_GDB_TUI=y
BR2_PACKAGE_HOST_GDB_PYTHON3=y
BR2_PACKAGE_HOST_GDB_SIM=y
BR2_PACKAGE_HOST_GDB_TUI=y
BR2_GDB_VERSION_13=y
BR2_TARGET_LDFLAGS="-mcpu=c906fdv -march=rv64imafdcv0p7xthead -mcmodel=medany -mabi=lp64d"
BR2_CCACHE=y
BR2_OPTIMIZE_2=y
BR2_REPRODUCIBLE=y
BR2_PER_PACKAGE_DIRECTORIES=y
BR2_TARGET_GENERIC_HOSTNAME="licheervnano"
BR2_TARGET_GENERIC_ISSUE="Welcome to Linux"
BR2_TARGET_GENERIC_ROOT_PASSWD="root"
BR2_PACKAGE_AIC8800_SDIO_FIRMWARE=y
BR2_PACKAGE_CVITEK_RISCV64_MUSL_SYSROOT=y
BR2_INIT_SYSV=y
BR2_ROOTFS_MERGED_USR=y
BR2_ENABLE_LOCALE_WHITELIST="C en_US en_US.utf8"
BR2_ROOTFS_DEVICE_CREATION_DYNAMIC_EUDEV=y
BR2_PACKAGE_BUSYBOX_SHOW_OTHERS=y
BR2_PACKAGE_KMOD=y
# dont rename network card,
# BR2_PACKAGE_EUDEV_RULES_GEN is not set
BR2_PACKAGE_EUDEV_ENABLE_HWDB=y
BR2_PACKAGE_BLUEZ5_UTILS=y
BR2_PACKAGE_BLUEZ5_UTILS_CLIENT=y
BR2_PACKAGE_BLUEZ5_UTILS_TOOLS=y
BR2_PACKAGE_BLUEZ5_UTILS_DEPRECATED=y
BR2_PACKAGE_BLUEZ5_UTILS_PLUGINS_HID=y
BR2_PACKAGE_BLUEZ5_UTILS_PLUGINS_NETWORK=y
BR2_PACKAGE_BLUEZ5_UTILS_TOOLS_HID2HCI=y
BR2_PACKAGE_BLUEZ5_UTILS_MONITOR=y
BR2_PACKAGE_BLUEZ_ALSA=y
BR2_PACKAGE_BLUEZ_ALSA_RFCOMM=y
BR2_PACKAGE_BLUEZ_ALSA_HCITOP=y
BR2_PACKAGE_NTP=y
BR2_PACKAGE_NTP_NTPD=y
BR2_PACKAGE_NTP_NTPDATE=y
BR2_PACKAGE_MACCHANGER=y
BR2_PACKAGE_AVAHI=y
# BR2_PACKAGE_AVAHI_AUTOIPD is not set
BR2_PACKAGE_AVAHI_DAEMON=y
# BR2_PACKAGE_AVAHI_LIBDNSSD_COMPATIBILITY is not set
BR2_PACKAGE_AVAHI_DEFAULT_SERVICES=y
# BR2_PACKAGE_MDNSD is not set
# BR2_PACKAGE_MDNSD_MQUERY is not set
# BR2_PACKAGE_MDNSD_HTTP_SERVICE is not set
# BR2_PACKAGE_MDNSD_SSH_SERVICE is not set
BR2_PACKAGE_WIRELESS_TOOLS=y
BR2_PACKAGE_WIRELESS_TOOLS_IFRENAME=y
BR2_PACKAGE_WIRELESS_TOOLS_IWCONFIG=y
BR2_PACKAGE_WIRELESS_TOOLS_LIB=y
BR2_PACKAGE_AIRCRACK_NG=y
BR2_PACKAGE_UTIL_LINUX_RFKILL=y
BR2_PACKAGE_IPERF3=y
BR2_PACKAGE_IPMITOOL=y
BR2_PACKAGE_IPMITOOL_PEN_REG_URI=y
BR2_PACKAGE_IPMITOOL_LANPLUS=y
BR2_PACKAGE_IPMITOOL_USB=y
BR2_PACKAGE_IPMITOOL_IPMIEVD=y
BR2_PACKAGE_IPMITOOL_IPMISHELL=y
BR2_PACKAGE_ETHTOOL=y
BR2_PACKAGE_DNSMASQ=y
BR2_PACKAGE_DNSMASQ_DHCP=y
BR2_PACKAGE_RSYNC=y
BR2_PACKAGE_SOCAT=y
BR2_PACKAGE_TINC=y
BR2_PACKAGE_WIRELESS_REGDB=y
BR2_PACKAGE_MOSH=y
BR2_PACKAGE_LRZSZ=y
BR2_PACKAGE_IW=y
BR2_PACKAGE_NETCAT=y
BR2_PACKAGE_MTR=y
# BR2_PACKAGE_WIREGUARD=y
BR2_PACKAGE_WIREGUARD_TOOLS=y
# BR2_PACKAGE_WIREGUARD_LINUX_COMPAT=y
BR2_PACKAGE_WPA_SUPPLICANT=y
BR2_PACKAGE_WPA_SUPPLICANT_NL80211=y
BR2_PACKAGE_WPA_SUPPLICANT_WPA3=y
BR2_PACKAGE_WPA_SUPPLICANT_AUTOSCAN=y
BR2_PACKAGE_WPA_SUPPLICANT_AP_SUPPORT=y
BR2_PACKAGE_WPA_SUPPLICANT_OVERRIDES=y
BR2_PACKAGE_WPA_SUPPLICANT_WIFI_DISPLAY=y
BR2_PACKAGE_WPA_SUPPLICANT_MESH_NETWORKING=y
BR2_PACKAGE_WPA_SUPPLICANT_IBSS_RSN=y
BR2_PACKAGE_WPA_SUPPLICANT_WEXT=y
BR2_PACKAGE_WPA_SUPPLICANT_EAP=y
BR2_PACKAGE_WPA_SUPPLICANT_HOTSPOT=y
BR2_PACKAGE_WPA_SUPPLICANT_DEBUG_SYSLOG=y
BR2_PACKAGE_WPA_SUPPLICANT_WPS=y
BR2_PACKAGE_WPA_SUPPLICANT_CLI=y
BR2_PACKAGE_WPA_SUPPLICANT_WPA_CLIENT_SO=y
BR2_PACKAGE_WPA_SUPPLICANT_PASSPHRASE=y
BR2_PACKAGE_WPA_SUPPLICANT_CTRL_IFACE=y
BR2_PACKAGE_WPA_SUPPLICANT_DBUS=y
BR2_PACKAGE_HOSTAPD=y
BR2_PACKAGE_HOSTAPD_DRIVER_HOSTAP=y
BR2_PACKAGE_HOSTAPD_DRIVER_NL80211=y
BR2_PACKAGE_HOSTAPD_ACS=y
BR2_PACKAGE_HOSTAPD_EAP=y
BR2_PACKAGE_HOSTAPD_WPS=y
BR2_PACKAGE_HOSTAPD_WPA3=y
# BR2_PACKAGE_HOSTAPD_VLAN is not set
BR2_PACKAGE_OPENSSH=y
BR2_PACKAGE_OPENSSH_CLIENT=y
BR2_PACKAGE_OPENSSH_SERVER=y
BR2_PACKAGE_OPENSSH_KEY_UTILS=y
BR2_PACKAGE_HAVEGED=y
BR2_PACKAGE_LIBOPENSSL_BIN=y
BR2_PACKAGE_LIBOPENSSL_ENGINES=y
BR2_PACKAGE_PARTED=y
BR2_PACKAGE_MEMTESTER=y
BR2_PACKAGE_CACHE_CALIBRATOR=y
BR2_PACKAGE_DHRYSTONE=y
BR2_PACKAGE_COREMARK=y
BR2_PACKAGE_RAMSPEED=y
BR2_PACKAGE_SPIDEV_TEST=y
BR2_PACKAGE_STRESS_NG=y
BR2_PACKAGE_STRACE=y
BR2_PACKAGE_VMTOUCH=y
BR2_ROOTFS_MERGED_USR=y
BR2_TARGET_GENERIC_ROOT_PASSWD="root"
BR2_ENABLE_LOCALE_WHITELIST="C en_US en_US.utf8"
BR2_TARGET_TZ_INFO=y
BR2_ROOTFS_OVERLAY="$(TOPDIR)/board/cvitek/SG200X/overlay"
BR2_PACKAGE_BUSYBOX_CONFIG_FRAGMENT_FILES="$(TOPDIR)/board/cvitek/SG200X/busybox-extra.config"
BR2_PACKAGE_ALSA_UTILS=y
BR2_PACKAGE_ALSA_UTILS_ALSACTL=y
BR2_PACKAGE_ALSA_UTILS_ALSAMIXER=y
BR2_PACKAGE_ALSA_UTILS_APLAY=y
BR2_PACKAGE_ALSA_UTILS_AMIXER=y
BR2_PACKAGE_ALSA_UTILS_APLAY=y
BR2_PACKAGE_FFMPEG_GPL=y
BR2_PACKAGE_FFMPEG_NONFREE=y
BR2_PACKAGE_FFMPEG_FFPROBE=y
BR2_PACKAGE_FFMPEG_POSTPROC=y
BR2_PACKAGE_MPG123=y
BR2_PACKAGE_BZIP2=y
BR2_PACKAGE_BROTLI=y
BR2_PACKAGE_LRZIP=y
BR2_PACKAGE_LZIP=y
BR2_PACKAGE_LZOP=y
BR2_PACKAGE_P7ZIP=y
BR2_PACKAGE_PIGZ=y
BR2_PACKAGE_PIXZ=y
BR2_PACKAGE_UNRAR=y
BR2_PACKAGE_UNZIP=y
BR2_PACKAGE_ZIP=y
BR2_PACKAGE_ZSTD=y
BR2_PACKAGE_LZOP=y
BR2_PACKAGE_BROTLI=y
BR2_PACKAGE_LIBZIP=y
BR2_PACKAGE_LZ4_PROGS=y
BR2_PACKAGE_SZIP=y
BR2_PACKAGE_CA_CERTIFICATES=y
BR2_PACKAGE_EVTEST=y
BR2_PACKAGE_BASH=y
BR2_PACKAGE_FILE=y
BR2_PACKAGE_EMPTY=y
BR2_PACKAGE_EXFATPROGS=y
BR2_PACKAGE_CACHE_CALIBRATOR=y
BR2_PACKAGE_COREMARK=y
BR2_PACKAGE_DHRYSTONE=y
BR2_PACKAGE_GDB=y
BR2_PACKAGE_GDB_SERVER=y
BR2_PACKAGE_GDB_DEBUGGER=y
BR2_PACKAGE_GDB_TUI=y
BR2_PACKAGE_GDB_PYTHON=y
BR2_PACKAGE_RAMSPEED=y
BR2_PACKAGE_SPIDEV_TEST=y
BR2_PACKAGE_STRACE=y
BR2_PACKAGE_STRESS_NG=y
BR2_PACKAGE_VMTOUCH=y
BR2_PACKAGE_E2FSPROGS=y
BR2_PACKAGE_E2FSPROGS_RESIZE2FS=y
BR2_PACKAGE_TMUX=y
BR2_PACKAGE_HTOP=y
BR2_PACKAGE_LIBCURL=y
BR2_PACKAGE_LIBCURL_CURL=y
BR2_PACKAGE_LIBCURL_VERBOSE=y
BR2_PACKAGE_LIBCURL_PROXY_SUPPORT=y
BR2_PACKAGE_LIBCURL_COOKIES_SUPPORT=y
BR2_PACKAGE_LIBCURL_WEBSOCKETS_SUPPORT=y
BR2_PACKAGE_LIBCURL_EXTRA_PROTOCOLS_FEATURES=y
BR2_PACKAGE_LIBCURL_OPENSSL=y
BR2_PACKAGE_LIBWEBSOCKETS=y
BR2_PACKAGE_WATCHDOG=y
BR2_PACKAGE_EXFATPROGS=y
BR2_PACKAGE_SQUASHFS=y
BR2_PACKAGE_SQUASHFS_GZIP=y
BR2_PACKAGE_SQUASHFS_LZ4=y
BR2_PACKAGE_SQUASHFS_LZMA=y
BR2_PACKAGE_SQUASHFS_LZO=y
BR2_PACKAGE_SQUASHFS_XZ=y
BR2_PACKAGE_SQUASHFS_ZSTD=y
BR2_PACKAGE_LCDTEST=y
BR2_PACKAGE_ASCII_INVADERS=y
BR2_PACKAGE_GNUCHESS=y
BR2_PACKAGE_SL=y
BR2_PACKAGE_XORCURSES=y
BR2_PACKAGE_INPUT_EVENT_DAEMON=y
BR2_PACKAGE_BLUEZ_TOOLS=y
BR2_PACKAGE_TPUDEMO_SG200X=y
BR2_PACKAGE_SG2002_CODEC_FIRMWARE=y
BR2_PACKAGE_TCPDUMP=y
BR2_PACKAGE_SSDP_RESPONDER=y
BR2_PACKAGE_PPPD=y
BR2_PACKAGE_NFTABLES=y
BR2_PACKAGE_BIND=y
BR2_PACKAGE_SYSSTAT=y
BR2_PACKAGE_TRACEROUTE=y
BR2_PACKAGE_IPUTILS=y
BR2_PACKAGE_IPROUTE2=y
BR2_PACKAGE_IPTABLES=y
BR2_PACKAGE_IPTABLES_NFTABLES=y
BR2_PACKAGE_NCURSES_WCHAR=y
BR2_PACKAGE_RTC_TOOLS=y
BR2_PACKAGE_PICOCOM=y
BR2_PACKAGE_FBGRAB=y
BR2_PACKAGE_DBUS_GLIB=y
BR2_PACKAGE_EVTEST=y
BR2_PACKAGE_IPMITOOL=y
BR2_PACKAGE_IPMITOOL_LANPLUS=y
BR2_PACKAGE_IPMITOOL_USB=y
BR2_PACKAGE_IPMITOOL_IPMIEVD=y
BR2_PACKAGE_IPMITOOL_IPMISHELL=y
BR2_PACKAGE_MEMTESTER=y
BR2_PACKAGE_MHZ=y
BR2_PACKAGE_OPENIPMI=y
BR2_PACKAGE_PARTED=y
BR2_PACKAGE_PICOCOM=y
BR2_PACKAGE_RTC_TOOLS=y
BR2_PACKAGE_SETSERIAL=y
BR2_PACKAGE_SYSSTAT=y
BR2_PACKAGE_UBOOT_TOOLS=y
BR2_PACKAGE_UBOOT_TOOLS_FIT_SUPPORT=y
BR2_PACKAGE_UBOOT_TOOLS_MKIMAGE=y
BR2_PACKAGE_UBOOT_TOOLS_DUMPIMAGE=y
# if your sdnand is small, you can delete some package
# BR2_PACKAGE_IMAGEMAGICK is not set
# BR2_PACKAGE_OCRAD is not set
# BR2_PACKAGE_SDL is not set
# BR2_PACKAGE_SDL_FBCON is not set
# BR2_PACKAGE_SDL_GFX is not set
# BR2_PACKAGE_SDL_IMAGE is not set
# BR2_PACKAGE_SDL_IMAGE_BMP is not set
# BR2_PACKAGE_SDL_IMAGE_GIF is not set
# BR2_PACKAGE_SDL_IMAGE_JPEG is not set
# BR2_PACKAGE_SDL_IMAGE_PNG is not set
# BR2_PACKAGE_SDL_IMAGE_WEBP is not set
# BR2_PACKAGE_SDL_MIXER is not set
# BR2_PACKAGE_SDL_NET is not set
# BR2_PACKAGE_SDL_SOUND is not set
# BR2_PACKAGE_SDL_SOUND_PLAYSOUND is not set
# BR2_PACKAGE_LBREAKOUT2 is not set
# BR2_PACKAGE_LBREAKOUT2_AUDIO is not set
# BR2_PACKAGE_LBREAKOUT2_NET is not set
# BR2_PACKAGE_LTRIS is not set
# BR2_PACKAGE_LTRIS_AUDIO is not set
# BR2_PACKAGE_PRBOOM is not set
# BR2_PACKAGE_DOOM_WAD is not set
BR2_PACKAGE_PYTHON3=y
BR2_PACKAGE_PYTHON3_PY_PYC=y
BR2_PACKAGE_PYTHON3_2TO3=y
BR2_PACKAGE_PYTHON3_CURSES=y
BR2_PACKAGE_PYTHON3_READLINE=y
BR2_PACKAGE_PYTHON3_XZ=y
BR2_PACKAGE_PYTHON_AENUM=y
BR2_PACKAGE_PYTHON_ALSAAUDIO=y
BR2_PACKAGE_PYTHON_BEAUTIFULSOUP4=y
BR2_PACKAGE_PYTHON_BROTLI=y
BR2_PACKAGE_PYTHON_BSDIFF4=y
BR2_PACKAGE_PYTHON_CRC16=y
BR2_PACKAGE_PYTHON_CRCMOD=y
BR2_PACKAGE_PYTHON_CRONTAB=y
BR2_PACKAGE_PYTHON_CYCLER=y
BR2_PACKAGE_PYTHON_DBUS_FAST=y
BR2_PACKAGE_PYTHON_DBUS_NEXT=y
BR2_PACKAGE_PYTHON_DJANGO=y
BR2_PACKAGE_PYTHON_EVDEV=y
BR2_PACKAGE_PYTHON_FLASK_BABEL=y
BR2_PACKAGE_PYTHON_FLASK_CORS=y
BR2_PACKAGE_PYTHON_FLASK_JSONRPC=y
BR2_PACKAGE_PYTHON_FLASK_LOGIN=y
BR2_PACKAGE_PYTHON_FLASK_SMOREST=y
BR2_PACKAGE_PYTHON_FLASK_SQLALCHEMY=y
BR2_PACKAGE_PYTHON_FLASK_WTF=y
BR2_PACKAGE_PYTHON_FLATBUFFERS=y
BR2_PACKAGE_PYTHON_HTML5LIB=y
BR2_PACKAGE_PYTHON_HUMANIZE=y
BR2_PACKAGE_PYTHON_HWDATA=y
BR2_PACKAGE_PYTHON_INTELHEX=y
BR2_PACKAGE_PYTHON_IPYTHON=y
BR2_PACKAGE_PYTHON_IPYTHON_GENUTILS=y
BR2_PACKAGE_PYTHON_KIWISOLVER=y
BR2_PACKAGE_PYTHON_LIBEVDEV=y
BR2_PACKAGE_PYTHON_LIBUSB1=y
BR2_PACKAGE_PYTHON_LXML=y
BR2_PACKAGE_PYTHON_MARKDOWN=y
BR2_PACKAGE_PYTHON_MSGPACK=y
BR2_PACKAGE_PYTHON_NETADDR=y
BR2_PACKAGE_PYTHON_NETIFACES=y
BR2_PACKAGE_PYTHON_NETWORKX=y
BR2_PACKAGE_PYTHON_PAHO_MQTT=y
BR2_PACKAGE_PYTHON_PERIPHERY=y
BR2_PACKAGE_PYTHON_PIP=y
BR2_PACKAGE_PYTHON_POSIX_IPC=y
BR2_PACKAGE_PYTHON_PROTOBUF=y
BR2_PACKAGE_PYTHON_PSUTIL=y
BR2_PACKAGE_PYTHON_PYAES=y
BR2_PACKAGE_PYTHON_PYALSA=y
BR2_PACKAGE_PYTHON_PYDEVMEM=y
BR2_PACKAGE_PYTHON_PYLIBFDT=y
BR2_PACKAGE_PYTHON_PYMODBUS=y
BR2_PACKAGE_PYTHON_PYPARSING=y
BR2_PACKAGE_PYTHON_PYQRCODE=y
BR2_PACKAGE_PYTHON_PYSMB=y
BR2_PACKAGE_PYTHON_PYUDEV=y
BR2_PACKAGE_PYTHON_PYUSB=y
BR2_PACKAGE_PYTHON_PYZMQ=y
BR2_PACKAGE_PYTHON_QRCODE=y
BR2_PACKAGE_PYTHON_QRCODE_PIL=y
BR2_PACKAGE_PYTHON_REQUESTS_OAUTHLIB=y
BR2_PACKAGE_PYTHON_REQUESTS_TOOLBELT=y
BR2_PACKAGE_PYTHON_SCAPY=y
BR2_PACKAGE_PYTHON_SELENIUM=y
BR2_PACKAGE_PYTHON_SERIAL_ASYNCIO=y
BR2_PACKAGE_PYTHON_SMBUS_CFFI=y
BR2_PACKAGE_PYTHON_SNAPPY=y
BR2_PACKAGE_PYTHON_SOCKETIO=y
BR2_PACKAGE_PYTHON_SPIDEV=y
BR2_PACKAGE_PYTHON_TINYRPC=y
BR2_PACKAGE_PYTHON_TOML=y
BR2_PACKAGE_PYTHON_TORNADO=y
BR2_PACKAGE_PYTHON_UBJSON=y
BR2_PACKAGE_PYTHON_UHID=y
BR2_PACKAGE_PYTHON_UJSON=y
BR2_PACKAGE_PYTHON_WATCHDOG=y
BR2_PACKAGE_PYTHON_WEBSOCKET_CLIENT=y
BR2_PACKAGE_PYTHON_WEBSOCKETS=y
BR2_PACKAGE_PYTHON_XLSXWRITER=y
BR2_PACKAGE_PYTHON_XLUTILS=y
BR2_PACKAGE_PYTHON_XMODEM=y
BR2_PACKAGE_PYTHON_ZEROCONF=y
BR2_PACKAGE_TCL=y
# BR2_PACKAGE_TCL_SHLIB_ONLY is not set
# BR2_PACKAGE_TCL_DEL_ENCODINGS is not set
# BR2_PACKAGE_TCL_SHLIB_ONLY is not set
BR2_PACKAGE_EXPECT=y
BR2_PACKAGE_TCLLIB=y
BR2_PACKAGE_SBC=y
BR2_PACKAGE_LIBZIP=y
BR2_PACKAGE_LZ4_PROGS=y
BR2_PACKAGE_SZIP=y
BR2_PACKAGE_CA_CERTIFICATES=y
BR2_PACKAGE_LIBOPENSSL_BIN=y
BR2_PACKAGE_LIBOPENSSL_ENGINES=y
BR2_PACKAGE_LIBQRENCODE=y
BR2_PACKAGE_LIBQRENCODE_TOOLS=y
BR2_PACKAGE_OPENCV4=y
BR2_PACKAGE_OPENCV4_LIB_CALIB3D=y
BR2_PACKAGE_OPENCV4_LIB_DNN=y
BR2_PACKAGE_OPENCV4_LIB_HIGHGUI=y
BR2_PACKAGE_OPENCV4_LIB_OBJDETECT=y
BR2_PACKAGE_OPENCV4_LIB_PHOTO=y
BR2_PACKAGE_OPENCV4_LIB_PYTHON=y
BR2_PACKAGE_OPENCV4_LIB_SHAPE=y
BR2_PACKAGE_OPENCV4_LIB_STITCHING=y
BR2_PACKAGE_OPENCV4_LIB_SUPERRES=y
@@ -274,344 +206,85 @@ BR2_PACKAGE_OPENCV4_WITH_TIFF=y
BR2_PACKAGE_OPENCV4_WITH_V4L=y
BR2_PACKAGE_OPENCV4_WITH_WEBP=y
BR2_PACKAGE_OPENCV4_INSTALL_DATA=y
BR2_PACKAGE_LIBQRENCODE=y
BR2_PACKAGE_LIBQRENCODE_TOOLS=y
BR2_PACKAGE_FFMPEG=y
BR2_PACKAGE_FFMPEG_FFMPEG=y
BR2_PACKAGE_FFMPEG_FFPROBE=y
BR2_PACKAGE_FFMPEG_GPL=y
BR2_PACKAGE_FFMPEG_NONFREE=y
BR2_PACKAGE_FFMPEG_POSTPROC=y
# BR2_PACKAGE_MULTICAT is not set
# BR2_PACKAGE_WQY_ZENHEI is not set
# BR2_PACKAGE_DEJAVU is not set
# BR2_PACKAGE_GNUPLOT is not set
# BR2_PACKAGE_TESSERACT_OCR is not set
# BR2_PACKAGE_TESSERACT_OCR_LANG_ENG is not set
# BR2_PACKAGE_TESSERACT_OCR_LANG_CHI_SIM is not set
# BR2_PACKAGE_TESSERACT_OCR_LANG_CHI_TRA is not set
# BR2_PACKAGE_QT5 is not set
# BR2_PACKAGE_QT5BASE_SQLITE_SYSTEM is not set
# BR2_PACKAGE_QT5BASE_GUI is not set
# BR2_PACKAGE_QT5BASE_LINUXFB is not set
# BR2_PACKAGE_QT5BASE_WIDGETS is not set
# BR2_PACKAGE_QT5BASE_DEFAULT_QPA="linuxf is not set
# BR2_PACKAGE_QT5BASE_FONTCONFIG is not set
# BR2_PACKAGE_QT5BASE_GIF is not set
# BR2_PACKAGE_QT5BASE_PNG is not set
# BR2_PACKAGE_QT5BASE_JPEG is not set
# BR2_PACKAGE_QT5BASE_SYSLOG is not set
# BR2_PACKAGE_QT5BASE_DBUS is not set
# BR2_PACKAGE_QT5BASE_TSLIB is not set
# BR2_PACKAGE_QT5BASE_EXAMPLES is not set
# BR2_PACKAGE_QT5BASE_CONCURRENT is not set
# BR2_PACKAGE_QT5CONNECTIVITY is not set
# BR2_PACKAGE_QT5IMAGEFORMATS is not set
# BR2_PACKAGE_QT5MULTIMEDIA is not set
# BR2_PACKAGE_QT5SENSORS is not set
# BR2_PACKAGE_QT5SERIALBUS is not set
# BR2_PACKAGE_QT5CHARTS is not set
# BR2_PACKAGE_QT5COAP is not set
# BR2_PACKAGE_QT5ENGINIO is not set
# BR2_PACKAGE_QT5KNX is not set
# BR2_PACKAGE_QT5LOCATION is not set
# BR2_PACKAGE_QT5MQTT is not set
# BR2_PACKAGE_QT5OPCUA is not set
# BR2_PACKAGE_QT5REMOTEOBJECTS is not set
# BR2_PACKAGE_QT5SPEECH is not set
# BR2_PACKAGE_QT5SVG is not set
# BR2_PACKAGE_QT5WEBSOCKETS is not set
# BR2_PACKAGE_QT5WEBCHANNEL is not set
# BR2_PACKAGE_QEXTSERIALPORT is not set
# BR2_PACKAGE_QT5X11EXTRAS is not set
# BR2_PACKAGE_QT5XMLPATTERNS is not set
# BR2_PACKAGE_QT5BASE_MYSQL is not set
# BR2_PACKAGE_QJSON is not set
# BR2_PACKAGE_QUAZIP is not set
BR2_PACKAGE_OPENCV4_LIB_PYTHON=y
# BR2_PACKAGE_OPENCV4_WITH_QT5 is not set
BR2_PACKAGE_PYTHON3=y
BR2_PACKAGE_PYTHON3_2TO3=y
BR2_PACKAGE_PYTHON3_BZIP2=y
BR2_PACKAGE_PYTHON3_CODECSCJK=y
BR2_PACKAGE_PYTHON3_CURSES=y
BR2_PACKAGE_PYTHON3_READLINE=y
BR2_PACKAGE_PYTHON3_SSL=y
BR2_PACKAGE_PYTHON3_UNICODEDATA=y
BR2_PACKAGE_PYTHON3_SQLITE=y
BR2_PACKAGE_PYTHON3_PYEXPAT=y
BR2_PACKAGE_PYTHON3_XZ=y
BR2_PACKAGE_PYTHON3_ZLIB=y
BR2_PACKAGE_PYTHON3_PY_PYC=y
BR2_PACKAGE_PYTHON_NUMPY=y
BR2_PACKAGE_PYTHON_BSDIFF4=y
BR2_PACKAGE_PYTHON_BEAUTIFULSOUP4=y
BR2_PACKAGE_PYTHON_CFFI=y
BR2_PACKAGE_PYTHON_CRC16=y
BR2_PACKAGE_PYTHON_DBUS_FAST=y
BR2_PACKAGE_PYTHON_DATEUTIL=y
BR2_PACKAGE_PYTHON_DBUS_NEXT=y
BR2_PACKAGE_PYTHON_DJANGO=y
BR2_PACKAGE_PYTHON_FLASK=y
BR2_PACKAGE_PYTHON_EVDEV=y
BR2_PACKAGE_PYTHON_FLASK_BABEL=y
BR2_PACKAGE_PYTHON_FLASK_CORS=y
BR2_PACKAGE_PYTHON_FLASK_JSONRPC=y
BR2_PACKAGE_PYTHON_FLASK_LOGIN=y
BR2_PACKAGE_PYTHON_FLASK_SMOREST=y
BR2_PACKAGE_PYTHON_FLASK_SQLALCHEMY=y
BR2_PACKAGE_PYTHON_FLASK_WTF=y
BR2_PACKAGE_PYTHON_HWDATA=y
BR2_PACKAGE_PYTHON_PIP=y
BR2_PACKAGE_PYTHON_PEXPECT=y
BR2_PACKAGE_PYTHON_PSUTIL=y
BR2_PACKAGE_PYTHON_PYAES=y
BR2_PACKAGE_PYTHON_PYALSA=y
BR2_PACKAGE_PYTHON_PYDEVMEM=y
BR2_PACKAGE_PYTHON_PYUSB=y
BR2_PACKAGE_PYTHON_REQUESTS=y
BR2_PACKAGE_PYTHON_REQUESTS_OAUTHLIB=y
BR2_PACKAGE_PYTHON_REQUESTS_TOOLBELT=y
BR2_PACKAGE_PYTHON_SERIAL=y
BR2_PACKAGE_PYTHON_SERIAL_ASYNCIO=y
BR2_PACKAGE_PYTHON_WEBSOCKETS=y
BR2_PACKAGE_PYTHON_WEBSOCKET_CLIENT=y
BR2_PACKAGE_PYTHON_XMODEM=y
BR2_PACKAGE_PYTHON_PYQT5=y
BR2_PACKAGE_PYTHON_PYQRCODE=y
BR2_PACKAGE_PYTHON_PYLIBFDT=y
BR2_PACKAGE_PYTHON_JEDI=y
BR2_PACKAGE_PYTHON_LIBUSB1=y
BR2_PACKAGE_PYTHON_LXML=y
BR2_PACKAGE_PYTHON_MARKDOWN=y
BR2_PACKAGE_PYTHON_MSGPACK=y
BR2_PACKAGE_PYTHON_PERIPHERY=y
BR2_PACKAGE_PYTHON_PILLOW=y
BR2_PACKAGE_PYTHON_POSIX_IPC=y
BR2_PACKAGE_PYTHON_PROTOBUF=y
BR2_PACKAGE_PYTHON_PYUDEV=y
BR2_PACKAGE_PYTHON_PYYAML=y
BR2_PACKAGE_PYTHON_QRCODE=y
BR2_PACKAGE_PYTHON_QRCODE_PIL=y
BR2_PACKAGE_PYTHON_INTELHEX=y
#
# External python modules
#
BR2_PACKAGE_PYTHON_AENUM=y
BR2_PACKAGE_PYTHON_ALSAAUDIO=y
BR2_PACKAGE_PYTHON_APISPEC=y
BR2_PACKAGE_PYTHON_ARGH=y
BR2_PACKAGE_PYTHON_ASGIREF=y
BR2_PACKAGE_PYTHON_ASTTOKENS=y
BR2_PACKAGE_PYTHON_ASYNC_GENERATOR=y
BR2_PACKAGE_PYTHON_ASYNC_TIMEOUT=y
BR2_PACKAGE_PYTHON_ATTRS=y
BR2_PACKAGE_PYTHON_BABEL=y
BR2_PACKAGE_PYTHON_BACKCALL=y
BR2_PACKAGE_PYTHON_BEAUTIFULSOUP4=y
BR2_PACKAGE_PYTHON_BIDICT=y
BR2_PACKAGE_PYTHON_BLINKER=y
#
# python-bluezero needs a glibc toolchain, gcc >= 4.9, host gcc >= 8
#
BR2_PACKAGE_PYTHON_BROTLI=y
BR2_PACKAGE_PYTHON_BSDIFF4=y
BR2_PACKAGE_PYTHON_CERTIFI=y
BR2_PACKAGE_PYTHON_CFFI=y
BR2_PACKAGE_PYTHON_CHARSET_NORMALIZER=y
BR2_PACKAGE_PYTHON_CLICK=y
BR2_PACKAGE_PYTHON_CRC16=y
BR2_PACKAGE_PYTHON_CRCMOD=y
BR2_PACKAGE_PYTHON_CRONTAB=y
BR2_PACKAGE_PYTHON_CYCLER=y
BR2_PACKAGE_PYTHON_DATEUTIL=y
BR2_PACKAGE_PYTHON_DBUS_FAST=y
BR2_PACKAGE_PYTHON_DBUS_NEXT=y
BR2_PACKAGE_PYTHON_DECORATOR=y
BR2_PACKAGE_PYTHON_DJANGO=y
BR2_PACKAGE_PYTHON_ENGINEIO=y
BR2_PACKAGE_PYTHON_EVDEV=y
BR2_PACKAGE_PYTHON_EXECUTING=y
BR2_PACKAGE_PYTHON_FLASK=y
BR2_PACKAGE_PYTHON_FLASK_BABEL=y
BR2_PACKAGE_PYTHON_FLASK_CORS=y
BR2_PACKAGE_PYTHON_FLASK_JSONRPC=y
BR2_PACKAGE_PYTHON_FLASK_LOGIN=y
BR2_PACKAGE_PYTHON_FLASK_SMOREST=y
BR2_PACKAGE_PYTHON_FLASK_SQLALCHEMY=y
BR2_PACKAGE_PYTHON_FLASK_WTF=y
BR2_PACKAGE_PYTHON_FLATBUFFERS=y
#
# python-gobject needs a glibc toolchain, gcc >= 4.9, host gcc >= 8
#
BR2_PACKAGE_PYTHON_GREENLET_ARCH_SUPPORTS=y
BR2_PACKAGE_PYTHON_H11=y
BR2_PACKAGE_PYTHON_HTML5LIB=y
BR2_PACKAGE_PYTHON_HUMANIZE=y
BR2_PACKAGE_PYTHON_HWDATA=y
BR2_PACKAGE_PYTHON_IDNA=y
BR2_PACKAGE_PYTHON_IFADDR=y
BR2_PACKAGE_PYTHON_INTELHEX=y
BR2_PACKAGE_PYTHON_IPYTHON=y
BR2_PACKAGE_PYTHON_IPYTHON_GENUTILS=y
BR2_PACKAGE_PYTHON_ITSDANGEROUS=y
BR2_PACKAGE_PYTHON_JEDI=y
BR2_PACKAGE_PYTHON_JINJA2=y
BR2_PACKAGE_PYTHON_KIWISOLVER=y
#
# python-libconfig needs a glibc or uClibc toolchain w/ C++, threads
#
BR2_PACKAGE_PYTHON_LIBEVDEV=y
BR2_PACKAGE_PYTHON_LIBUSB1=y
BR2_PACKAGE_PYTHON_LXML=y
BR2_PACKAGE_PYTHON_MARKUPSAFE=y
BR2_PACKAGE_PYTHON_MARSHMALLOW=y
BR2_PACKAGE_PYTHON_MSGPACK=y
BR2_PACKAGE_PYTHON_MYPY_EXTENSIONS=y
BR2_PACKAGE_PYTHON_NETADDR=y
BR2_PACKAGE_PYTHON_NETIFACES=y
BR2_PACKAGE_PYTHON_NETWORKX=y
BR2_PACKAGE_PYTHON_NUMPY_ARCH_SUPPORTS=y
BR2_PACKAGE_PYTHON_NUMPY=y
BR2_PACKAGE_PYTHON_OAUTHLIB=y
BR2_PACKAGE_PYTHON_OUTCOME=y
BR2_PACKAGE_PYTHON_PACKAGING=y
BR2_PACKAGE_PYTHON_PAHO_MQTT=y
BR2_PACKAGE_PYTHON_PARSO=y
BR2_PACKAGE_PYTHON_PATHTOOLS=y
BR2_PACKAGE_PYTHON_PERIPHERY=y
BR2_PACKAGE_PYTHON_PEXPECT=y
BR2_PACKAGE_PYTHON_PICKLESHARE=y
BR2_PACKAGE_PYTHON_PILLOW=y
BR2_PACKAGE_PYTHON_PIP=y
BR2_PACKAGE_PYTHON_POSIX_IPC=y
BR2_PACKAGE_PYTHON_PROMPT_TOOLKIT=y
BR2_PACKAGE_PYTHON_PROTOBUF=y
BR2_PACKAGE_PYTHON_PSUTIL=y
BR2_PACKAGE_PYTHON_PTYPROCESS=y
BR2_PACKAGE_PYTHON_PURE_EVAL=y
BR2_PACKAGE_PYTHON_PYAES=y
BR2_PACKAGE_PYTHON_PYALSA=y
BR2_PACKAGE_PYTHON_PYASN1=y
BR2_PACKAGE_PYTHON_PYCPARSER=y
BR2_PACKAGE_PYTHON_PYDEVMEM=y
BR2_PACKAGE_PYTHON_PYGMENTS=y
BR2_PACKAGE_PYTHON_PYLIBFDT=y
BR2_PACKAGE_PYTHON_PYMODBUS=y
#
# python-pymupdf needs Xorg
#
BR2_PACKAGE_PYTHON_PYPARSING=y
BR2_PACKAGE_PYTHON_PYQRCODE=y
#
# python-pyqt5 needs Qt5
#
BR2_PACKAGE_PYTHON_PYSMB=y
BR2_PACKAGE_PYTHON_PYSOCKS=y
BR2_PACKAGE_PYTHON_PYTZ=y
BR2_PACKAGE_PYTHON_PYUDEV=y
BR2_PACKAGE_PYTHON_PYUSB=y
BR2_PACKAGE_PYTHON_PYYAML=y
BR2_PACKAGE_PYTHON_PYZMQ=y
BR2_PACKAGE_PYTHON_QRCODE=y
BR2_PACKAGE_PYTHON_QRCODE_PIL=y
BR2_PACKAGE_PYTHON_REQUESTS=y
BR2_PACKAGE_PYTHON_REQUESTS_OAUTHLIB=y
BR2_PACKAGE_PYTHON_REQUESTS_TOOLBELT=y
BR2_PACKAGE_PYTHON_SCAPY=y
#
# python-scipy needs glibc or musl toolchain w/ fortran, c++, gcc >= 9, host gcc >= 9
#
BR2_PACKAGE_PYTHON_SELENIUM=y
BR2_PACKAGE_PYTHON_SERIAL=y
BR2_PACKAGE_PYTHON_SERIAL_ASYNCIO=y
BR2_PACKAGE_PYTHON_SETUPTOOLS=y
BR2_PACKAGE_PYTHON_SIX=y
BR2_PACKAGE_PYTHON_SMBUS_CFFI=y
BR2_PACKAGE_PYTHON_SNAPPY=y
BR2_PACKAGE_PYTHON_SNIFFIO=y
BR2_PACKAGE_PYTHON_SOCKETIO=y
BR2_PACKAGE_PYTHON_SORTEDCONTAINERS=y
BR2_PACKAGE_PYTHON_SOUPSIEVE=y
BR2_PACKAGE_PYTHON_SPIDEV=y
BR2_PACKAGE_PYTHON_SQLALCHEMY=y
BR2_PACKAGE_PYTHON_SQLPARSE=y
BR2_PACKAGE_PYTHON_STACK_DATA=y
#
# python-systemd needs systemd
#
BR2_PACKAGE_PYTHON_TINYRPC=y
BR2_PACKAGE_PYTHON_TOML=y
BR2_PACKAGE_PYTHON_TORNADO=y
BR2_PACKAGE_PYTHON_TQDM=y
BR2_PACKAGE_PYTHON_TRAITLETS=y
BR2_PACKAGE_PYTHON_TRIO=y
BR2_PACKAGE_PYTHON_TRIO_WEBSOCKET=y
BR2_PACKAGE_PYTHON_TYPEGUARD=y
BR2_PACKAGE_PYTHON_TYPING_EXTENSIONS=y
BR2_PACKAGE_PYTHON_TYPING_INSPECT=y
BR2_PACKAGE_PYTHON_UBJSON=y
BR2_PACKAGE_PYTHON_UHID=y
BR2_PACKAGE_PYTHON_UJSON=y
BR2_PACKAGE_PYTHON_URLLIB3=y
BR2_PACKAGE_PYTHON_WATCHDOG=y
BR2_PACKAGE_PYTHON_WCWIDTH=y
BR2_PACKAGE_PYTHON_WEBARGS=y
BR2_PACKAGE_PYTHON_WEBENCODINGS=y
BR2_PACKAGE_PYTHON_WEBSOCKET_CLIENT=y
BR2_PACKAGE_PYTHON_WEBSOCKETS=y
BR2_PACKAGE_PYTHON_WERKZEUG=y
BR2_PACKAGE_PYTHON_WSPROTO=y
BR2_PACKAGE_PYTHON_WTFORMS=y
BR2_PACKAGE_PYTHON_XLRD=y
BR2_PACKAGE_PYTHON_XLSXWRITER=y
BR2_PACKAGE_PYTHON_XLUTILS=y
BR2_PACKAGE_PYTHON_XLWT=y
BR2_PACKAGE_PYTHON_XMODEM=y
BR2_PACKAGE_PYTHON_ZEROCONF=y
# BR2_PACKAGE_MGBA is not set
# BR2_PACKAGE_GB_TEST_ROMS is not set
# BR2_PACKAGE_NGINX=y
# BR2_PACKAGE_NGINX_HTTP=y
# BR2_PACKAGE_NGINX_HTTP_DAV_MODULE=y
# BR2_PACKAGE_NGINX_HTTP_MP4_MODULE=y
# BR2_PACKAGE_NGINX_HTTP_FLV_MODULE=y
# BR2_PACKAGE_NGINX_HTTP_GUNZIP_MODULE=y
# BR2_PACKAGE_NGINX_STREAM=y
# BR2_PACKAGE_NGINX_SELECT_MODULE=y
# BR2_PACKAGE_NGINX_HTTP_FASTCGI_MODULE=y
# BR2_PACKAGE_NGINX_HTTP_UWSGI_MODULE=y
# BR2_PACKAGE_NGINX_HTTP_SCGI_MODULE=y
BR2_PACKAGE_VIM=y
BR2_PACKAGE_VIM_RUNTIME=y
BR2_PACKAGE_LIBCURL=y
BR2_PACKAGE_LIBCURL_CURL=y
BR2_PACKAGE_LIBCURL_VERBOSE=y
BR2_PACKAGE_LIBCURL_WEBSOCKETS_SUPPORT=y
BR2_PACKAGE_LIBWEBSOCKETS=y
BR2_PACKAGE_LIBBSD=y
BR2_PACKAGE_NCURSES_WCHAR=y
BR2_PACKAGE_EMPTY=y
BR2_PACKAGE_HAVEGED=y
BR2_PACKAGE_AIRCRACK_NG=y
BR2_PACKAGE_AVAHI=y
# BR2_PACKAGE_AVAHI_AUTOIPD is not set
BR2_PACKAGE_AVAHI_DAEMON=y
BR2_PACKAGE_AVAHI_DEFAULT_SERVICES=y
BR2_PACKAGE_BIND=y
BR2_PACKAGE_DNSMASQ=y
BR2_PACKAGE_ETHTOOL=y
BR2_PACKAGE_HOSTAPD=y
BR2_PACKAGE_HOSTAPD_EAP=y
BR2_PACKAGE_HOSTAPD_WPS=y
BR2_PACKAGE_HOSTAPD_WPA3=y
# BR2_PACKAGE_HOSTAPD_VLAN is not set
BR2_PACKAGE_IPERF3=y
BR2_PACKAGE_IPROUTE2=y
BR2_PACKAGE_IPTABLES=y
BR2_PACKAGE_IPTABLES_NFTABLES=y
BR2_PACKAGE_IPUTILS=y
BR2_PACKAGE_IW=y
BR2_PACKAGE_LRZSZ=y
BR2_PACKAGE_MACCHANGER=y
BR2_PACKAGE_MOSH=y
BR2_PACKAGE_MTR=y
BR2_PACKAGE_NETCAT=y
BR2_PACKAGE_NFTABLES=y
BR2_PACKAGE_NTP=y
BR2_PACKAGE_NTP_NTPDATE=y
BR2_PACKAGE_PPPD=y
BR2_PACKAGE_RSYNC=y
BR2_PACKAGE_SER2NET=y
BR2_PACKAGE_SOCAT=y
BR2_PACKAGE_SSDP_RESPONDER=y
BR2_PACKAGE_TCPDUMP=y
BR2_PACKAGE_TINC=y
BR2_PACKAGE_TRACEROUTE=y
BR2_PACKAGE_WIREGUARD_TOOLS=y
BR2_PACKAGE_WIRELESS_REGDB=y
BR2_PACKAGE_WIRELESS_TOOLS=y
BR2_PACKAGE_WIRELESS_TOOLS_IFRENAME=y
BR2_PACKAGE_WIRELESS_TOOLS_LIB=y
BR2_PACKAGE_WPA_SUPPLICANT=y
BR2_PACKAGE_WPA_SUPPLICANT_WEXT=y
BR2_PACKAGE_WPA_SUPPLICANT_IBSS_RSN=y
BR2_PACKAGE_WPA_SUPPLICANT_AP_SUPPORT=y
BR2_PACKAGE_WPA_SUPPLICANT_WIFI_DISPLAY=y
BR2_PACKAGE_WPA_SUPPLICANT_MESH_NETWORKING=y
BR2_PACKAGE_WPA_SUPPLICANT_OVERRIDES=y
BR2_PACKAGE_WPA_SUPPLICANT_AUTOSCAN=y
BR2_PACKAGE_WPA_SUPPLICANT_HOTSPOT=y
BR2_PACKAGE_WPA_SUPPLICANT_DEBUG_SYSLOG=y
BR2_PACKAGE_WPA_SUPPLICANT_WPS=y
BR2_PACKAGE_WPA_SUPPLICANT_WPA3=y
BR2_PACKAGE_WPA_SUPPLICANT_CLI=y
BR2_PACKAGE_WPA_SUPPLICANT_WPA_CLIENT_SO=y
BR2_PACKAGE_WPA_SUPPLICANT_PASSPHRASE=y
BR2_PACKAGE_WPA_SUPPLICANT_DBUS=y
BR2_PACKAGE_BASH=y
BR2_PACKAGE_FILE=y
BR2_PACKAGE_TMUX=y
BR2_PACKAGE_AXP2101=y
BR2_PACKAGE_HTOP=y
BR2_PACKAGE_UTIL_LINUX_RFKILL=y
BR2_PACKAGE_WATCHDOG=y
BR2_PACKAGE_NANO=y
BR2_PACKAGE_VIM=y
BR2_PACKAGE_AIC8800_SDIO_FIRMWARE=y
BR2_PACKAGE_CVITEK_RISCV64_MUSL_SYSROOT=y
BR2_PACKAGE_LCDTEST=y
BR2_PACKAGE_TPUDEMO_SG200X=y
BR2_PACKAGE_SG2002_CODEC_FIRMWARE=y
BR2_TARGET_ROOTFS_EXT2=y
BR2_TARGET_ROOTFS_EXT2_4=y
BR2_TARGET_ROOTFS_EXT2_SIZE="1536M"
BR2_ROOTFS_OVERLAY="$(TOPDIR)/board/cvitek/SG200X/overlay"
BR2_PACKAGE_BUSYBOX_CONFIG_FRAGMENT_FILES="$(TOPDIR)/board/cvitek/SG200X/busybox-extra.config"
BR2_TARGET_TZ_INFO=y
BR2_TARGET_TZ_ZONELIST="default"
BR2_TARGET_LOCALTIME="Etc/UTC"
BR2_PACKAGE_SER2NET=y
BR2_PACKAGE_NANO=y
BR2_PACKAGE_OPENIPMI=y

View File

@@ -1,31 +0,0 @@
cd kvm
rm -r ./kvmapp
rm -r ./latest
curl -O https://cdn.sipeed.com/nanokvm/latest.zip
unzip latest.zip
rm latest.zip
mv ./latest ./kvmapp
touch ./kvmapp/kvm_new_img
chmod -R +x ./kvmapp
cd ../
./host/mount_ext4.sh $1 mountpoint
cp -r ./kvm/kvmapp/ mountpoint/
cp ./kvm/frp_0.59.0_linux_riscv64/frpc mountpoint/usr/bin/
cp ./kvm/tailscale_1.80.2_riscv64/tailscale mountpoint/usr/bin/
cp ./kvm/tailscale_1.80.2_riscv64/tailscaled mountpoint/usr/sbin/
chmod +x mountpoint/usr/bin/frpc
chmod +x mountpoint/usr/bin/tailscale
chmod +x mountpoint/usr/sbin/tailscaled
cp -f kvm/kvmapp/system/ko/soph_mipi_rx.ko ./mountpoint/mnt/system/ko/
chmod +x mountpoint/mnt/system/ko/soph_mipi_rx.ko
rm -rf mountpoint/etc/init.d
cp -rf kvm/init.d mountpoint/etc/
mkdir mountpoint/etc/kvm/
touch mountpoint/etc/kvm/ssh_stop
umount mountpoint
# ./kvm/NanoKVM_img.sh /home/bugu/LicheeRV-Nano-Build/install/soc_sg2002_licheervnano_sd/images/2025-02-17-19-08-3649fe.img
# cp /home/bugu/LicheeRV-Nano-Build/install/soc_sg2002_licheervnano_sd/images/2025-02-17-19-08-3649fe.img /home/bugu/LicheeRV-Nano-Build/install/soc_sg2002_licheervnano_sd/images/20250217_NanoKVM_Rev1_4_0.img
# xz /home/bugu/LicheeRV-Nano-Build/install/soc_sg2002_licheervnano_sd/images/20250217_NanoKVM_Rev1_4_0.img

34
kvm/data/sensor_cfg.ini Normal file
View File

@@ -0,0 +1,34 @@
[source]
;type = SOURCE_USER_FE
dev_num = 1
; section for sensor
[sensor]
; sensor name
name = LONTIUM_LT6911_2M_60FPS_8BIT
bus_id = 4
sns_i2c_addr = ff
mipi_dev = 0
lane_id = 2, 4, 3, 1, 0
pn_swap = 0, 0, 0, 0, 0
mclk_en = 0
mclk = 0
;port = 0
;pin = 2
;pol = 1
fps = 60

View File

@@ -0,0 +1,34 @@
[source]
;type = SOURCE_USER_FE
dev_num = 1
; section for sensor
[sensor]
; sensor name
name = LONTIUM_LT6911_2M_60FPS_8BIT
bus_id = 4
sns_i2c_addr = ff
mipi_dev = 0
lane_id = 2, 4, 3, 1, 0
pn_swap = 0, 0, 0, 0, 0
mclk_en = 0
mclk = 0
;port = 0
;pin = 2
;pol = 1
fps = 60

34
kvm/data/sensor_cfg.ini.OA Executable file
View File

@@ -0,0 +1,34 @@
[source]
;type = SOURCE_USER_FE
dev_num = 1
; section for sensor
[sensor]
; sensor name
name = OV_OS04A10_MIPI_4M_1440P_30FPS_12BIT
bus_id = 4
sns_i2c_addr = 36
mipi_dev = 0
lane_id = 2, 1, 3, 0, 4
pn_swap = 0, 0, 0, 0, 0
mclk_en = 0
mclk = 0
;port = 0
;pin = 2
;pol = 1
;fps = 30

34
kvm/data/sensor_cfg.ini.SC035 Executable file
View File

@@ -0,0 +1,34 @@
[source]
;type = SOURCE_USER_FE
dev_num = 1
; section for sensor
[sensor]
; sensor name
name = SMS_SC035GS_MIPI_480P_120FPS_12BIT
bus_id = 4
sns_i2c_addr = 30
mipi_dev = 0
lane_id = 4, 3, 2, -1, -1
pn_swap = 0, 0, 0, 0, 0
mclk_en = 1
mclk = 1
;port = 0
;pin = 2
;pol = 1
;fps = 30

View File

@@ -0,0 +1,34 @@
[source]
;type = SOURCE_USER_FE
dev_num = 1
; section for sensor
[sensor]
; sensor name
name = GCORE_GC4653_MIPI_4M_30FPS_10BIT
bus_id = 4
sns_i2c_addr = 29
mipi_dev = 0
lane_id = 2, 1, 0, -1, -1
pn_swap = 0, 0, 0, 0, 0
mclk_en = 1
mclk = 0
;port = 0
;pin = 2
;pol = 1
;fps = 30

View File

@@ -0,0 +1,34 @@
[source]
;type = SOURCE_USER_FE
dev_num = 1
; section for sensor
[sensor]
; sensor name
name = GCORE_GC4653_MIPI_4M_30FPS_10BIT
bus_id = 4
sns_i2c_addr = 29
mipi_dev = 0
lane_id = 4, 3, 2, -1, -1
pn_swap = 0, 0, 0, 0, 0
mclk_en = 1
mclk = 1
;port = 0
;pin = 2
;pol = 1
;fps = 30

365
kvm/merge_nanokvm_app.sh Executable file
View File

@@ -0,0 +1,365 @@
#!/bin/sh
set -eu
set +x
usage() {
cat <<'EOF'
Usage:
kvm/merge_nanokvm_app.sh [options]
Options:
-i, --image FILE Input image. Defaults to the latest non-*-nanokvm.img in
install/soc_sg2002_licheervnano_sd/images/.
-o, --output FILE Output image. Defaults to INPUT-nanokvm.img.
-a, --app-dir DIR NanoKVM source directory. Defaults to ../NanoKVM next to
this SDK directory.
-m, --mount-dir DIR Temporary mount directory. Defaults to ./mountpoint.
--skip-copy-kvmapp Use existing kvm/kvmapp instead of copying from APP_DIR.
-f, --force Overwrite the output image if it already exists.
-h, --help Show this help.
Examples:
./kvm/merge_nanokvm_app.sh
./kvm/merge_nanokvm_app.sh -i install/soc_sg2002_licheervnano_sd/images/out.img
./kvm/merge_nanokvm_app.sh -i base.img -o base-nanokvm.img
./kvm/merge_nanokvm_app.sh -a "$HOME/LicheeRV_NanoKVM/NanoKVM"
EOF
}
die() {
echo "error: $*" >&2
exit 1
}
warn() {
echo "warning: $*" >&2
}
info() {
echo "==> $*"
}
run_step() {
desc=$1
shift
info "$desc"
if "$@"; then
return 0
else
status=$?
die "$desc failed with exit code $status"
fi
}
need_file() {
[ -f "$1" ] || die "missing file: $1"
}
need_exec() {
[ -x "$1" ] || die "missing executable file: $1"
}
need_dir() {
[ -d "$1" ] || die "missing directory: $1"
}
copy_image() {
src=$1
dst=$2
cp --reflink=auto --sparse=always "$src" "$dst" 2>/dev/null || cp "$src" "$dst"
}
partition2_offset_bytes() {
partx -s "$1" | awk '$1 == 2 { print $2 * 512; found = 1 } END { exit !found }'
}
is_mounted() {
if command -v mountpoint >/dev/null 2>&1; then
mountpoint -q "$MOUNT_DIR" && return 0
fi
if command -v findmnt >/dev/null 2>&1; then
findmnt -rn --mountpoint "$MOUNT_DIR" >/dev/null 2>&1 && return 0
fi
if [ -r /proc/mounts ]; then
awk -v dir="$MOUNT_DIR" '$2 == dir { found = 1 } END { exit !found }' /proc/mounts
return $?
fi
return 1
}
write_config() {
name=$1
value=$2
file="$MOUNT_DIR/kvmapp/kvm/$name"
info "write default config: kvm/$name=$value"
if ! printf '%s\n' "$value" > "$file"; then
die "failed to write default config: $file"
fi
need_file "$file"
}
SCRIPT_DIR=$(CDPATH= cd -- "$(dirname -- "$0")" && pwd -P)
SDK_DIR=$(CDPATH= cd -- "$SCRIPT_DIR/.." && pwd -P)
WORKDIR=$(dirname "$SDK_DIR")
APP_DIR="$WORKDIR/NanoKVM"
IMAGE_DIR="$SDK_DIR/install/soc_sg2002_licheervnano_sd/images"
IMAGE_FILE=""
OUTPUT_IMAGE_FILE=""
MOUNT_DIR="$SDK_DIR/mountpoint"
COPY_KVMAPP=1
FORCE_OUTPUT=0
while [ "$#" -gt 0 ]; do
case "$1" in
-i|--image)
[ "$#" -ge 2 ] || die "$1 requires a file path"
IMAGE_FILE=$2
shift 2
;;
-o|--output)
[ "$#" -ge 2 ] || die "$1 requires a file path"
OUTPUT_IMAGE_FILE=$2
shift 2
;;
-a|--app-dir)
[ "$#" -ge 2 ] || die "$1 requires a directory path"
APP_DIR=$2
shift 2
;;
-m|--mount-dir)
[ "$#" -ge 2 ] || die "$1 requires a directory path"
MOUNT_DIR=$2
shift 2
;;
--skip-copy-kvmapp)
COPY_KVMAPP=0
shift
;;
-f|--force)
FORCE_OUTPUT=1
shift
;;
-h|--help)
usage
exit 0
;;
*)
die "unknown argument: $1"
;;
esac
done
case "$IMAGE_FILE" in
"") ;;
/*) ;;
*) IMAGE_FILE="$SDK_DIR/$IMAGE_FILE" ;;
esac
case "$OUTPUT_IMAGE_FILE" in
"") ;;
/*) ;;
*) OUTPUT_IMAGE_FILE="$SDK_DIR/$OUTPUT_IMAGE_FILE" ;;
esac
case "$MOUNT_DIR" in
/*) ;;
*) MOUNT_DIR="$SDK_DIR/$MOUNT_DIR" ;;
esac
command -v partx >/dev/null 2>&1 || die "missing command: partx"
need_exec "$SDK_DIR/host/mount_ext4.sh"
if [ -z "$IMAGE_FILE" ]; then
need_dir "$IMAGE_DIR"
IMAGE_FILE=$(find "$IMAGE_DIR" -maxdepth 1 -type f -name '*.img' ! -name '*-nanokvm.img' -printf '%T@ %p\n' | sort -nr | sed -n '1s/^[^ ]* //p')
[ -n "$IMAGE_FILE" ] || die "no input *.img found in $IMAGE_DIR; build the system image first or pass -i FILE"
fi
need_file "$IMAGE_FILE"
SOURCE_IMAGE_FILE=$IMAGE_FILE
ROOTFS_OFFSET_BYTES=$(partition2_offset_bytes "$SOURCE_IMAGE_FILE") || die "failed to read partition 2 offset from $SOURCE_IMAGE_FILE"
[ "$ROOTFS_OFFSET_BYTES" -gt 0 ] || die "invalid partition 2 offset: $ROOTFS_OFFSET_BYTES"
if [ -z "$OUTPUT_IMAGE_FILE" ]; then
case "$SOURCE_IMAGE_FILE" in
*.img) OUTPUT_IMAGE_FILE=${SOURCE_IMAGE_FILE%.img}-nanokvm.img ;;
*) OUTPUT_IMAGE_FILE=$SOURCE_IMAGE_FILE.nanokvm.img ;;
esac
fi
[ "$OUTPUT_IMAGE_FILE" != "$SOURCE_IMAGE_FILE" ] || die "output image must be different from input image"
if [ -e "$OUTPUT_IMAGE_FILE" ]; then
if [ "$FORCE_OUTPUT" -eq 1 ]; then
run_step "remove old output image" rm -f "$OUTPUT_IMAGE_FILE"
else
die "output image already exists: $OUTPUT_IMAGE_FILE; pass -f to overwrite it"
fi
fi
run_step "copy input image to output image" copy_image "$SOURCE_IMAGE_FILE" "$OUTPUT_IMAGE_FILE"
IMAGE_FILE=$OUTPUT_IMAGE_FILE
if ! cmp -n "$ROOTFS_OFFSET_BYTES" "$SOURCE_IMAGE_FILE" "$IMAGE_FILE" >/dev/null; then
die "output image differs from input before partition 2; aborting before mount"
fi
info "SDK directory: $SDK_DIR"
info "NanoKVM directory: $APP_DIR"
info "input image: $SOURCE_IMAGE_FILE"
info "output image: $IMAGE_FILE"
info "partition 2 offset: $ROOTFS_OFFSET_BYTES bytes"
info "mount directory: $MOUNT_DIR"
run_step "create mount directory" mkdir -p "$MOUNT_DIR"
if is_mounted; then
die "$MOUNT_DIR is already mounted; run: umount \"$MOUNT_DIR\""
fi
if [ "$COPY_KVMAPP" -eq 1 ]; then
need_dir "$APP_DIR/kvmapp"
need_exec "$APP_DIR/kvmapp/server/NanoKVM-Server"
need_exec "$APP_DIR/kvmapp/kvm_system/kvm_system"
need_file "$APP_DIR/kvmapp/system/ko/soph_mipi_rx.ko"
need_file "$APP_DIR/kvmapp/system/init.d/S95nanokvm"
need_file "$APP_DIR/kvmapp/version"
run_step "remove old SDK kvmapp" rm -rf "$SCRIPT_DIR/kvmapp"
run_step "copy NanoKVM app from $APP_DIR/kvmapp" cp -a "$APP_DIR/kvmapp" "$SCRIPT_DIR/"
run_step "create kvm_new_img marker" touch "$SCRIPT_DIR/kvmapp/kvm_new_img"
run_step "make SDK kvmapp files executable" chmod -R +x "$SCRIPT_DIR/kvmapp"
else
info "use existing SDK kvmapp: $SCRIPT_DIR/kvmapp"
fi
need_dir "$SCRIPT_DIR/kvmapp"
need_exec "$SCRIPT_DIR/kvmapp/server/NanoKVM-Server"
need_exec "$SCRIPT_DIR/kvmapp/kvm_system/kvm_system"
need_file "$SCRIPT_DIR/kvmapp/system/ko/soph_mipi_rx.ko"
need_file "$SCRIPT_DIR/kvmapp/system/init.d/S95nanokvm"
need_file "$SCRIPT_DIR/kvmapp/version"
need_dir "$SCRIPT_DIR/data"
need_file "$SCRIPT_DIR/data/sensor_cfg.ini"
FRP_DIR=$(find "$SCRIPT_DIR" -maxdepth 1 -type d -name 'frp_*_linux_riscv64' | sort -V | tail -n 1)
TAILSCALE_DIR=$(find "$SCRIPT_DIR" -maxdepth 1 -type d -name 'tailscale_*_riscv64' | sort -V | tail -n 1)
[ -n "$FRP_DIR" ] || die "missing frp_*_linux_riscv64 directory under $SCRIPT_DIR"
[ -n "$TAILSCALE_DIR" ] || die "missing tailscale_*_riscv64 directory under $SCRIPT_DIR"
need_exec "$FRP_DIR/frpc"
need_exec "$TAILSCALE_DIR/tailscale"
need_exec "$TAILSCALE_DIR/tailscaled"
MOUNTED=0
cleanup() {
status=$?
if [ "$MOUNTED" -eq 1 ]; then
info "cleanup: unmount $MOUNT_DIR"
if ! umount "$MOUNT_DIR"; then
warn "failed to unmount $MOUNT_DIR; please run: umount \"$MOUNT_DIR\""
fi
fi
exit "$status"
}
trap cleanup EXIT HUP INT TERM
info "mount image: $IMAGE_FILE"
if "$SDK_DIR/host/mount_ext4.sh" "$IMAGE_FILE" "$MOUNT_DIR"; then
:
else
status=$?
die "failed to mount image: $IMAGE_FILE; mount_ext4.sh exited with code $status"
fi
MOUNTED=1
if ! is_mounted; then
die "mount command finished, but $MOUNT_DIR is not a mounted filesystem"
fi
need_dir "$MOUNT_DIR/etc"
need_dir "$MOUNT_DIR/usr"
need_dir "$MOUNT_DIR/mnt"
info "mount check passed"
run_step "remove old image kvmapp" rm -rf "$MOUNT_DIR/kvmapp"
run_step "copy kvmapp into image" cp -a "$SCRIPT_DIR/kvmapp" "$MOUNT_DIR/"
need_exec "$MOUNT_DIR/kvmapp/server/NanoKVM-Server"
need_file "$MOUNT_DIR/kvmapp/system/init.d/S95nanokvm"
need_file "$MOUNT_DIR/kvmapp/version"
info "kvmapp install check passed"
run_step "create frp and tailscale target directories" install -d "$MOUNT_DIR/usr/bin" "$MOUNT_DIR/usr/sbin"
run_step "install frpc" install -m 755 "$FRP_DIR/frpc" "$MOUNT_DIR/usr/bin/frpc"
run_step "install tailscale" install -m 755 "$TAILSCALE_DIR/tailscale" "$MOUNT_DIR/usr/bin/tailscale"
run_step "install tailscaled" install -m 755 "$TAILSCALE_DIR/tailscaled" "$MOUNT_DIR/usr/sbin/tailscaled"
need_exec "$MOUNT_DIR/usr/bin/frpc"
need_exec "$MOUNT_DIR/usr/bin/tailscale"
need_exec "$MOUNT_DIR/usr/sbin/tailscaled"
info "frp and tailscale install check passed"
run_step "create kernel module and init target directories" install -d "$MOUNT_DIR/mnt/system/ko" "$MOUNT_DIR/etc/init.d"
run_step "install soph_mipi_rx.ko" install -m 755 "$SCRIPT_DIR/kvmapp/system/ko/soph_mipi_rx.ko" "$MOUNT_DIR/mnt/system/ko/soph_mipi_rx.ko"
need_file "$MOUNT_DIR/mnt/system/ko/soph_mipi_rx.ko"
for script in S00kmod S01fs S03usbdev S15kvmhwd S30eth S30wifi S95nanokvm; do
need_file "$SCRIPT_DIR/kvmapp/system/init.d/$script"
run_step "install init script: $script" install -m 755 "$SCRIPT_DIR/kvmapp/system/init.d/$script" "$MOUNT_DIR/etc/init.d/$script"
need_exec "$MOUNT_DIR/etc/init.d/$script"
done
info "kernel module and init script install check passed"
run_step "create default data and kvm config directories" install -d "$MOUNT_DIR/mnt/data" "$MOUNT_DIR/etc/kvm" "$MOUNT_DIR/kvmapp/kvm"
for data_file in "$SCRIPT_DIR"/data/*; do
[ -f "$data_file" ] || continue
data_name=$(basename "$data_file")
run_step "install default data: $data_name" install -m 644 "$data_file" "$MOUNT_DIR/mnt/data/$data_name"
need_file "$MOUNT_DIR/mnt/data/$data_name"
done
need_file "$MOUNT_DIR/mnt/data/sensor_cfg.ini"
run_step "create ssh_stop marker" touch "$MOUNT_DIR/etc/kvm/ssh_stop"
need_file "$MOUNT_DIR/etc/kvm/ssh_stop"
write_config fps 30
write_config height 1080
write_config now_fps 0
write_config qlty 60
write_config res 0
write_config state 1
write_config type mjpeg
write_config width 1920
info "default data and kvm config install check passed"
info "unmount image"
if umount "$MOUNT_DIR"; then
:
else
status=$?
die "failed to unmount $MOUNT_DIR with exit code $status; make sure no terminal is inside the mount directory, then run: umount \"$MOUNT_DIR\""
fi
MOUNTED=0
if is_mounted; then
die "$MOUNT_DIR is still mounted after umount"
fi
if ! cmp -n "$ROOTFS_OFFSET_BYTES" "$SOURCE_IMAGE_FILE" "$IMAGE_FILE" >/dev/null; then
die "boot area changed unexpectedly; do not burn this output image: $IMAGE_FILE"
fi
info "boot area check passed: bytes before partition 2 are unchanged"
trap - EXIT HUP INT TERM
echo
echo "NanoKVM APP has been merged into:"
echo "$IMAGE_FILE"