diff --git a/doc/tutorials/ospp-kernelci/device-type/Lpi4A.jinja2 b/doc/tutorials/ospp-kernelci/device-type/Lpi4A.jinja2
new file mode 100755
index 0000000000000000000000000000000000000000..de2db002b1fdc3d541fd8447a91d79aa58e9fe8f
--- /dev/null
+++ b/doc/tutorials/ospp-kernelci/device-type/Lpi4A.jinja2
@@ -0,0 +1,26 @@
+{% extends 'base-uboot.jinja2' %}
+
+{% set uboot_mkimage_arch = 'riscv' %}
+{% set console_device = console_device|default('ttyS0') %}
+{% set baud_rate = baud_rate|default(115200) %}
+
+{% set booti_kernel_addr = '0x00200000' %}
+{% set booti_dtb_addr = '0x03800000' %}
+{% set booti_ramdisk_addr = '0x06000000' %}
+
+{% set uboot_initrd_high = '0xffffffffffffffff' %}
+{% set uboot_fdt_high = '0xffffffffffffffff' %}
+
+{% set boot_character_delay = 100 %}
+
+{% set shutdown_message = 'The system will reboot now!' %}
+{% set bootloader_prompt = bootloader_prompt|default('Light LPI4A#') %}
+
+{% set uboot_tftp_commands=[
+ "tftp 0x0 mine/final/dtb/fw_dynamic.bin",
+ "bootslave",
+ "tftp {KERNEL_ADDR} {KERNEL}",
+ "setenv initrd_size ${filesize}",
+ "tftp {DTB_ADDR} {DTB}"]
+-%}
+
diff --git "a/doc/tutorials/ospp-kernelci/doc/LAVA-LAB\347\232\204\346\220\255\345\273\272.md" "b/doc/tutorials/ospp-kernelci/doc/LAVA-LAB\347\232\204\346\220\255\345\273\272.md"
new file mode 100644
index 0000000000000000000000000000000000000000..4c65826d958b75aafc5d86db71e0519ff5181be3
--- /dev/null
+++ "b/doc/tutorials/ospp-kernelci/doc/LAVA-LAB\347\232\204\346\220\255\345\273\272.md"
@@ -0,0 +1,294 @@
+# 部署 LAVA LAB
+
+## 直接部署 (本文档不推荐)
+
+### 1. 系统要求
+
+确保你的 Ubuntu 系统满足以下要求:
+
+- Ubuntu 20.04 或更高版本
+- Python 3.6+
+- PostgreSQL
+- RabbitMQ
+- Git
+
+### 2. 安装依赖
+
+首先,更新系统并安装必要的依赖项:
+
+```bash
+sudo apt update
+sudo apt upgrade
+sudo apt install -y python3 python3-pip python3-dev postgresql postgresql-contrib rabbitmq-server git
+```
+
+### 3. 创建 LAVA 数据库
+
+创建一个用于 LAVA 的 PostgreSQL 数据库和用户:
+
+```bash
+sudo -u postgres psql
+CREATE DATABASE lava;
+CREATE USER lava WITH PASSWORD 'your_password';
+GRANT ALL PRIVILEGES ON DATABASE lava TO lava;
+```
+
+### 4. 克隆 LAVA 源代码
+
+使用 Git 克隆 LAVA 的源码:
+
+```bash
+git clone https://github.com/lava-lab/lava.git
+cd lava
+```
+
+### 5. 安装 Python 依赖
+
+在 LAVA 目录中,使用 pip 安装所需的 Python 依赖:
+
+```bash
+pip3 install -r requirements.txt
+```
+
+### 6. 配置 LAVA
+
+复制示例配置文件并进行编辑:
+
+```bash
+cp lava/settings.py.example lava/settings.py
+```
+
+根据需要编辑`lava/settings.py`,特别是数据库连接部分,确保填写正确的数据库名称和用户信息。
+
+### 7. 迁移数据库
+
+执行数据库迁移以创建相应的表:
+
+```bash
+python3 manage.py migrate
+```
+
+### 8. 启动服务
+
+使用以下命令启动 LAVA 服务:
+
+```bash
+python3 manage.py runserver 0.0.0.0:8000
+```
+
+### 9. 访问 LAVA
+
+在浏览器中访问 `http://你的服务器IP:8000`,你应该可以看到LAVA的界面。
+
+### 10. 配置 RabbitMQ
+
+确保 RabbitMQ 正在运行,并且可以通过以下命令查看状态:
+
+```bash
+sudo systemctl status rabbitmq-server
+```
+
+你可以使用 RabbitMQ 管理界面进行进一步配置,默认情况下,管理界面可以通过`http://localhost:15672`访问。
+
+
+
+**可以看到比较繁琐,所以lava提供了也可以通过 docker compose 来快速的构建开发环境,接下来我们着重于这方面**
+
+
+
+## 使用 docker 部署
+
+### 1.安装 docker 环境
+
+由于使用 docker compose 部署 LAVA ,所以需要安装 docker 和 docker compose , 安装方法可以参照 [Ubuntu | Docker Docs](https://docs.docker.com/engine/install/ubuntu/)
+
+由于我使用的是 WSL 2 这里我本人遇到的问题有
+
+```shell
+sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc
+```
+
+无法正常获取资源,所以我使用windows获取资源再传到我的 WSL2 对应位置中
+
+如果在安装过程中出现了无法获取docker镜像的情况,可以考虑为机器上代理
+
+如果无法正常拉取镜像,有可能是我们连接官网的速度太慢,建议可以为 docker 也配置镜像源(或者说可能存在 daemon.json 不存在的问题 https://www.converts.cn/article/7097541.html)
+
+方法为
+
+```shell
+vim /etc/docker/daemon.json
+```
+
+```shell
+{
+ "registry-mirrors": [
+ "https://dockerhub.icu", //疑似不行了
+ "https://docker.chenby.cn",
+ "https://docker.1panel.live",
+ "https://docker.aWSL9527.cn",
+ "https://docker.anyhub.us.kg",
+ "https://dhub.kubesre.xyz"
+ ]
+}
+```
+
+这里的几个源 本人用着没什么问题,不过也存在有些镜像源会对拉取次数少的镜像有限制的情况,如果是自己配置过镜像源的同学可以留意下这一点。
+
+还有记得换源后重启 docker
+
+```shell
+sudo systemctl restart docker
+```
+
+-----
+
+**将当前用户添加到docker组内(可选)**
+
+为了方便不用 sudo 执行 docker 命令,可以将当前用户添加到docker组内
+
+```
+sudo groupadd docker //添加docker用户组
+sudo usermod -a -G docker $(whoami) //将当前用户添加到docker组内
+sudo systemctl restart docker //重启docker service
+```
+
+执行完以上命令,退出当前终端操作界面再次进入,就可以不用 sudo 执行 docker 命令了
+
+-----
+
+### 2.获取 LAVA 源码
+
+用 docker compose 部署LAVA, 从 https://github.com/kernelci/lava-docker 获取源码
+
+建议 fork 下来因为还要对源码进行一些更改
+
+```shell
+git clone https://github.com/kernelci/lava-docker.git
+cd lava-docker
+```
+
+如果是第一次使用 lava-docker 的同学,我还是想要更完备的讲解下项目大概的内容,如果有需要的话可以查看 [lava-docker细节解释](./lava-docker细节解释.md)
+
+直接进入主题
+
+### 3.修改配置
+
+#### 修改 lavalab-gen.py
+
+- 修改 master 对应149行内容
+
+ ```python
+ dockcomp = {}
+ dockcomp["version"] = "2.4"
+ dockcomp["services"] = {}
+ dockcomposeymlpath = "output/%s/docker-compose.yml" % host
+ dockcomp["services"][name] = {}
+ dockcomp["services"][name]["hostname"] = name
+ dockcomp["services"][name]["ports"] = [ listen_address + ":" + str(webinterface_port) + ":80"]
+ dockcomp["services"][name]["volumes"] = [ "/home/feifei/ospp/2024ospp-large-files/ubuntu/boot:/boot", "/home/feifei/ospp/2024ospp-large-files/ubuntu/modules:/lib/modules" ,"/home/feifei/ospp/2024ospp/device-type/LicheePi4A_4.jinja2:/usr/share/lava-server/device-types/LicheePi4A_4.jinja2" ] #映射一些组件和 lichepi4a 的 device-type
+ dockcomp["services"][name]["build"] = {}
+ dockcomp["services"][name]["build"]["context"] = name
+ if "build_args" in master:
+ dockcomp["services"][name]["build"]["args"] = master['build_args']
+ dockcomp["services"][name]["restart"] = "always" #添加开机自动运行参数
+ ```
+
+- 修改 slave 对应458行内容
+
+ ```python
+ dockcomp["services"][name] = {}
+ dockcomp["services"][name]["hostname"] = name
+ dockcomp["services"][name]["dns_search"] = ""
+ dockcomp["services"][name]["ports"] = []
+ dockcomp["services"][name]["volumes"] = [ "/home/feifei/ospp/2024ospp-large-files/ubuntu/boot:/boot", "/home/feifei/ospp/2024ospp-large-files/ubuntu/modules:/lib/modules",
+ "/home/feifei/ospp/2024ospp-large-files:/home/2024ospp-large-files" ] #映射一些组件 这里包括启动需要的rooft 等文件,如果后续 job 中没有使用inline的资源便不用映射
+ dockcomp["services"][name]["environment"] = {}
+ dockcomp["services"][name]["build"] = {}
+ dockcomp["services"][name]["build"]["context"] = name
+ if "build_args" in slave:
+ dockcomp["services"][name]["build"]["args"] = slave['build_args']
+ dockcomp["services"][name]["restart"] = "always" #tip
+ ```
+
+#### 创建 board.yaml
+
+```yaml
+---
+masters:
+ - name: master
+ host: local
+ webinterface_port: 8000
+ allowed_hosts: ['*']
+ users:
+ - name: admin
+ token: adminlavatoken
+ password: v
+ superuser: true
+ staff: true
+ tokens:
+ - username: admin
+ token: dfjdfkfkdjfkdsjfslforci
+ description: no description
+slaves:
+ - name: lab-slave-1
+ host: local
+ remote_master: master
+ remote_user: admin
+ dispatcher_ip: 192.168.0.158 #这里不能用本地环回地址 因为与后续 bootloader 相关
+ use_tftp: True
+ use_nfs: True
+ host_healthcheck: false
+
+boards:
+ - name: qemu-test
+ type: qemu
+ slave: lab-slave-1
+ - name: Lpi4A
+ type: LicheePi4A_4
+ slave: lab-slave-1
+ connection_command: telnet 192.168.137.1 20000 //20000是ser2net配置的串口/dev/ttyUSB1对应的端口 也就是对应的 licheepi4a
+ #pdu_generic: ////远程控制电源的命令 这里是只用串口的
+ #(echo "OFF"; sleep 1; echo "ON") | telnet 192.168.1.100 20001
+ #(echo "ON") | telnet 192.168.1.100 20001
+ #(echo "OFF") | telnet 192.168.1.100 20001
+ uart:
+ idvendor: 0x0403
+ idproduct: 0x6010
+ devpath: "1"
+```
+
+配置完毕
+
+### 4.创建 docker 容器
+
+```shell
+./lavalab-gen.py //生成部署需要的文件, 存放在 output/local/目录下
+cd output/local
+docker compose build //生成 lava master 和 slave 的 docker image
+docker compose up -d //运行 lava master 和 slave docker 容器
+```
+
+### 5.使用 lava web
+
+可以使用 firefox edge chrome 等浏览器
+
+如果你想我一样是 WSL 2 又不想做 端口映射的话 可以简单粗暴的在 WSL 2 里下载 firefox 使用,不过我这里会有一些细小的bug,不太影响使用,比如 lava 以及 Jenkins 提供的一些 预选项 无法用鼠标点击 需要使用就键盘选择。
+
+在命令行执行以下命令进入浏览器
+```shell
+firefox &
+```
+
+在浏览器中输入 http://127.0.0.1:8000 进入 lava web 界面,8000是 boards.yaml 中设置的 webinterface_port
+
+点击右上角的 **Sign in** 进行 admin 的登陆,在 **board.yaml** 否则无法提交 job
+
+至此 LAVA LAB 的基本环境已经搭建完毕
+
+### 6.安装qemu
+
+```shell
+sudo apt install qemu-system-misc
+```
+
diff --git a/doc/tutorials/ospp-kernelci/doc/README.md b/doc/tutorials/ospp-kernelci/doc/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..1151fb1ba033ffb09cd5d570b124968d96a73ba4
--- /dev/null
+++ b/doc/tutorials/ospp-kernelci/doc/README.md
@@ -0,0 +1,84 @@
+# 板块
+
+## 需要准备的东西 - 所有板块
+
+1. 服务器设备:一台主机,系统为 linux x86 (发行版为 debian 或 ubuntu ,似乎也可以使用 centos。 LAVA官方推荐使用debian),由于我的条件有限 这里使用的是 windows 11 下的 WSL2-Ubuntu-22.04 测试后也可以正常进行 LAVA 的搭建,不过需要额外注意一些东西,后文会详细说明
+2. 被测试的设备:一块开发板 ,这里由于 ospp 的要求,我使用的是 Licheepi 4a 8g-32g , 当然也可以使用其他开发板。
+3. 电源控制设备:esp8266 或是其他带有 wifi 模块的开发板 ,不通过网络也可以完成,只不过要挨个管理串口设备,后文会提到
+4. 硬件设备:若干杜邦线 ,电源 ,继电器。
+
+# 章节
+
+1. [搭建基础的开发环境](./搭建基础的开发环境.md)
+ - 直接使用 ubuntu
+ - windows 使用 WSL 2 或 VMware
+2. [LAVA-LAB的搭建](./LAVA-LAB的搭建.md)
+ - 直接搭建
+ - **通过 lava - docker来构建**
+3. [已提供的设备类型-qemu](./已提供的设备类型-qemu.md)
+ - [lava-docker细节解释 ](./lava-docker细节解释.md)
+4. [未提供的设备类型-自定义设备类型-Licheepi 4a](./未提供的设备类型-自定义设备类型-Lip4a.md)
+5. [电源控制](./电源控制.md)
+ - **使用mqtt + esp8266**
+ - 使用其他开发板 + 串口
+6. [配置jenkins.md](./配置jenkins.md)
+7. [编写job和testcase](./编写job和testcase.md)
+
+### 可能对你有些帮助
+
+在处理 lava 时可能会需要重复的构建 docker 镜像,手动很麻烦,这里我给出几个简单的清理环境的脚本
+
+导出所有容器
+
+```shell
+#!/bin/bash
+
+# 创建一个目录来保存导出的容器
+mkdir -p ~/docker_backups
+
+# 获取所有容器的 ID
+container_ids=$(docker ps -aq)
+
+# 导出每个容器
+for id in $container_ids; do
+ container_name=$(docker inspect --format='{{.Name}}' $id | cut -c2-) # 去掉前面的斜杠
+ docker export $id -o ~/docker_backups/$container_name.tar
+ echo "导出容器 $container_name ($id) 到 ~/docker_backups/$container_name.tar"
+done
+```
+
+导出所有镜像
+
+```shell
+#!/bin/bash
+
+# 创建一个目录来保存导出的镜像
+mkdir -p ~/docker_image_backups
+
+# 获取所有镜像的名称
+image_names=$(docker images -q)
+
+# 导出每个镜像
+for image in $image_names; do
+ image_name=$(docker inspect --format='{{.RepoTags}}' $image | tr -d '[],')
+ docker save $image -o ~/docker_image_backups/$image_name.tar
+ echo "导出镜像 $image_name 到 ~/docker_image_backups/$image_name.tar"
+done
+
+```
+
+删除所有 docker 镜像和容器,你可以修改下 改成只删除 lava 相关的,我这里是**全部删除**
+
+```shell
+#!/bin/bash
+
+# 停止并删除所有容器
+docker stop $(docker ps -aq)
+docker rm $(docker ps -aq)
+
+# 删除所有镜像
+docker rmi $(docker images -q)
+
+echo "所有容器和镜像已删除。"
+
+```
diff --git a/doc/tutorials/ospp-kernelci/doc/img/jenkins/jenkins1.png b/doc/tutorials/ospp-kernelci/doc/img/jenkins/jenkins1.png
new file mode 100644
index 0000000000000000000000000000000000000000..78ed2204ed7906ab038736d803d5c8e0da5f54af
Binary files /dev/null and b/doc/tutorials/ospp-kernelci/doc/img/jenkins/jenkins1.png differ
diff --git a/doc/tutorials/ospp-kernelci/doc/img/jenkins/jenkins10.png b/doc/tutorials/ospp-kernelci/doc/img/jenkins/jenkins10.png
new file mode 100644
index 0000000000000000000000000000000000000000..2cd4268df709e1def93919c9de8c221e83378e9e
Binary files /dev/null and b/doc/tutorials/ospp-kernelci/doc/img/jenkins/jenkins10.png differ
diff --git a/doc/tutorials/ospp-kernelci/doc/img/jenkins/jenkins11.png b/doc/tutorials/ospp-kernelci/doc/img/jenkins/jenkins11.png
new file mode 100644
index 0000000000000000000000000000000000000000..2a78f7c5ae1aa4a77e844c716db1171ff14dadaf
Binary files /dev/null and b/doc/tutorials/ospp-kernelci/doc/img/jenkins/jenkins11.png differ
diff --git a/doc/tutorials/ospp-kernelci/doc/img/jenkins/jenkins12.png b/doc/tutorials/ospp-kernelci/doc/img/jenkins/jenkins12.png
new file mode 100644
index 0000000000000000000000000000000000000000..e148a5380afa8601eb115f6573b8ae408a441df0
Binary files /dev/null and b/doc/tutorials/ospp-kernelci/doc/img/jenkins/jenkins12.png differ
diff --git a/doc/tutorials/ospp-kernelci/doc/img/jenkins/jenkins13.png b/doc/tutorials/ospp-kernelci/doc/img/jenkins/jenkins13.png
new file mode 100644
index 0000000000000000000000000000000000000000..d24eac32d1e3f4d676bb47a273565e4cc4e4dbb0
Binary files /dev/null and b/doc/tutorials/ospp-kernelci/doc/img/jenkins/jenkins13.png differ
diff --git a/doc/tutorials/ospp-kernelci/doc/img/jenkins/jenkins14.png b/doc/tutorials/ospp-kernelci/doc/img/jenkins/jenkins14.png
new file mode 100644
index 0000000000000000000000000000000000000000..d16182fba114de22eb514164cf0b10072885706e
Binary files /dev/null and b/doc/tutorials/ospp-kernelci/doc/img/jenkins/jenkins14.png differ
diff --git a/doc/tutorials/ospp-kernelci/doc/img/jenkins/jenkins15.png b/doc/tutorials/ospp-kernelci/doc/img/jenkins/jenkins15.png
new file mode 100644
index 0000000000000000000000000000000000000000..6c364b17b0b74f966aa652cf6ff9ca9803d3103f
Binary files /dev/null and b/doc/tutorials/ospp-kernelci/doc/img/jenkins/jenkins15.png differ
diff --git a/doc/tutorials/ospp-kernelci/doc/img/jenkins/jenkins16.png b/doc/tutorials/ospp-kernelci/doc/img/jenkins/jenkins16.png
new file mode 100644
index 0000000000000000000000000000000000000000..fa45d70d80944aa98fb36cef3628fa68eb85d051
Binary files /dev/null and b/doc/tutorials/ospp-kernelci/doc/img/jenkins/jenkins16.png differ
diff --git a/doc/tutorials/ospp-kernelci/doc/img/jenkins/jenkins17.png b/doc/tutorials/ospp-kernelci/doc/img/jenkins/jenkins17.png
new file mode 100644
index 0000000000000000000000000000000000000000..e302f2149f8541d265a42c3367561ba842b99e7c
Binary files /dev/null and b/doc/tutorials/ospp-kernelci/doc/img/jenkins/jenkins17.png differ
diff --git a/doc/tutorials/ospp-kernelci/doc/img/jenkins/jenkins18.png b/doc/tutorials/ospp-kernelci/doc/img/jenkins/jenkins18.png
new file mode 100644
index 0000000000000000000000000000000000000000..960011f01df34ea2283db377c3ae56eaa5805ff5
Binary files /dev/null and b/doc/tutorials/ospp-kernelci/doc/img/jenkins/jenkins18.png differ
diff --git a/doc/tutorials/ospp-kernelci/doc/img/jenkins/jenkins19.png b/doc/tutorials/ospp-kernelci/doc/img/jenkins/jenkins19.png
new file mode 100644
index 0000000000000000000000000000000000000000..0c491e0cc7d801c886f438fa7bab09453d4860fd
Binary files /dev/null and b/doc/tutorials/ospp-kernelci/doc/img/jenkins/jenkins19.png differ
diff --git a/doc/tutorials/ospp-kernelci/doc/img/jenkins/jenkins2.png b/doc/tutorials/ospp-kernelci/doc/img/jenkins/jenkins2.png
new file mode 100644
index 0000000000000000000000000000000000000000..cc467dead94bff2fced468603863673855a2ec10
Binary files /dev/null and b/doc/tutorials/ospp-kernelci/doc/img/jenkins/jenkins2.png differ
diff --git a/doc/tutorials/ospp-kernelci/doc/img/jenkins/jenkins20.png b/doc/tutorials/ospp-kernelci/doc/img/jenkins/jenkins20.png
new file mode 100644
index 0000000000000000000000000000000000000000..2a8084ef324e32e2a3f39d566e1797bae0ba86fb
Binary files /dev/null and b/doc/tutorials/ospp-kernelci/doc/img/jenkins/jenkins20.png differ
diff --git a/doc/tutorials/ospp-kernelci/doc/img/jenkins/jenkins3.png b/doc/tutorials/ospp-kernelci/doc/img/jenkins/jenkins3.png
new file mode 100644
index 0000000000000000000000000000000000000000..1a78bc8565cec1bce4340f8c0582b049924f439f
Binary files /dev/null and b/doc/tutorials/ospp-kernelci/doc/img/jenkins/jenkins3.png differ
diff --git a/doc/tutorials/ospp-kernelci/doc/img/jenkins/jenkins4.png b/doc/tutorials/ospp-kernelci/doc/img/jenkins/jenkins4.png
new file mode 100644
index 0000000000000000000000000000000000000000..c886855392bfde9ce6bade38ff7afc2080a633c9
Binary files /dev/null and b/doc/tutorials/ospp-kernelci/doc/img/jenkins/jenkins4.png differ
diff --git a/doc/tutorials/ospp-kernelci/doc/img/jenkins/jenkins5.png b/doc/tutorials/ospp-kernelci/doc/img/jenkins/jenkins5.png
new file mode 100644
index 0000000000000000000000000000000000000000..455d48a06a852311daf88fa456eb9485bfa365db
Binary files /dev/null and b/doc/tutorials/ospp-kernelci/doc/img/jenkins/jenkins5.png differ
diff --git a/doc/tutorials/ospp-kernelci/doc/img/jenkins/jenkins6.png b/doc/tutorials/ospp-kernelci/doc/img/jenkins/jenkins6.png
new file mode 100644
index 0000000000000000000000000000000000000000..b67635667b3827a39410e9f7cb0fa3a403cc180d
Binary files /dev/null and b/doc/tutorials/ospp-kernelci/doc/img/jenkins/jenkins6.png differ
diff --git a/doc/tutorials/ospp-kernelci/doc/img/jenkins/jenkins7.png b/doc/tutorials/ospp-kernelci/doc/img/jenkins/jenkins7.png
new file mode 100644
index 0000000000000000000000000000000000000000..f4a24b8caae49319225f2c80b6ad20e5a069c49a
Binary files /dev/null and b/doc/tutorials/ospp-kernelci/doc/img/jenkins/jenkins7.png differ
diff --git a/doc/tutorials/ospp-kernelci/doc/img/jenkins/jenkins8.png b/doc/tutorials/ospp-kernelci/doc/img/jenkins/jenkins8.png
new file mode 100644
index 0000000000000000000000000000000000000000..f55f1f85f7c20a11204592e375f0694da2f1abd5
Binary files /dev/null and b/doc/tutorials/ospp-kernelci/doc/img/jenkins/jenkins8.png differ
diff --git a/doc/tutorials/ospp-kernelci/doc/img/jenkins/jenkins9.png b/doc/tutorials/ospp-kernelci/doc/img/jenkins/jenkins9.png
new file mode 100644
index 0000000000000000000000000000000000000000..035b968412f2d8422fe819a6464e9f8804131f88
Binary files /dev/null and b/doc/tutorials/ospp-kernelci/doc/img/jenkins/jenkins9.png differ
diff --git a/doc/tutorials/ospp-kernelci/doc/img/jenkins/jenkinsnew1.png b/doc/tutorials/ospp-kernelci/doc/img/jenkins/jenkinsnew1.png
new file mode 100644
index 0000000000000000000000000000000000000000..6e44b16d1731c249a5f1ebfc42082f23e44b44c1
Binary files /dev/null and b/doc/tutorials/ospp-kernelci/doc/img/jenkins/jenkinsnew1.png differ
diff --git a/doc/tutorials/ospp-kernelci/doc/img/jenkins/jenkinsnew10.png b/doc/tutorials/ospp-kernelci/doc/img/jenkins/jenkinsnew10.png
new file mode 100644
index 0000000000000000000000000000000000000000..6a08422f89238f9333ba6b80c483b06c8c8ce8c9
Binary files /dev/null and b/doc/tutorials/ospp-kernelci/doc/img/jenkins/jenkinsnew10.png differ
diff --git a/doc/tutorials/ospp-kernelci/doc/img/jenkins/jenkinsnew11.png b/doc/tutorials/ospp-kernelci/doc/img/jenkins/jenkinsnew11.png
new file mode 100644
index 0000000000000000000000000000000000000000..a4c6204fc6fbf3ff6fcf67fd1ca246bcaa887301
Binary files /dev/null and b/doc/tutorials/ospp-kernelci/doc/img/jenkins/jenkinsnew11.png differ
diff --git a/doc/tutorials/ospp-kernelci/doc/img/jenkins/jenkinsnew12.png b/doc/tutorials/ospp-kernelci/doc/img/jenkins/jenkinsnew12.png
new file mode 100644
index 0000000000000000000000000000000000000000..e9fb02c473fe2c59b6258bb1762e38f0dd32b24e
Binary files /dev/null and b/doc/tutorials/ospp-kernelci/doc/img/jenkins/jenkinsnew12.png differ
diff --git a/doc/tutorials/ospp-kernelci/doc/img/jenkins/jenkinsnew13.png b/doc/tutorials/ospp-kernelci/doc/img/jenkins/jenkinsnew13.png
new file mode 100644
index 0000000000000000000000000000000000000000..f18917a76ffc6723662d855ade36bfd0a9dbc885
Binary files /dev/null and b/doc/tutorials/ospp-kernelci/doc/img/jenkins/jenkinsnew13.png differ
diff --git a/doc/tutorials/ospp-kernelci/doc/img/jenkins/jenkinsnew14.png b/doc/tutorials/ospp-kernelci/doc/img/jenkins/jenkinsnew14.png
new file mode 100644
index 0000000000000000000000000000000000000000..be407aeff6800387cb229900305d3e3d5702294d
Binary files /dev/null and b/doc/tutorials/ospp-kernelci/doc/img/jenkins/jenkinsnew14.png differ
diff --git a/doc/tutorials/ospp-kernelci/doc/img/jenkins/jenkinsnew15.png b/doc/tutorials/ospp-kernelci/doc/img/jenkins/jenkinsnew15.png
new file mode 100644
index 0000000000000000000000000000000000000000..cd99a70870f2f025f8c5de60b222e1693f92443e
Binary files /dev/null and b/doc/tutorials/ospp-kernelci/doc/img/jenkins/jenkinsnew15.png differ
diff --git a/doc/tutorials/ospp-kernelci/doc/img/jenkins/jenkinsnew2.png b/doc/tutorials/ospp-kernelci/doc/img/jenkins/jenkinsnew2.png
new file mode 100644
index 0000000000000000000000000000000000000000..60e138c06bcaa56bb27ce7245b5d7c78aa651094
Binary files /dev/null and b/doc/tutorials/ospp-kernelci/doc/img/jenkins/jenkinsnew2.png differ
diff --git a/doc/tutorials/ospp-kernelci/doc/img/jenkins/jenkinsnew3.png b/doc/tutorials/ospp-kernelci/doc/img/jenkins/jenkinsnew3.png
new file mode 100644
index 0000000000000000000000000000000000000000..832301af808c2dfe81bf5fa4836f3439bdfa8ea1
Binary files /dev/null and b/doc/tutorials/ospp-kernelci/doc/img/jenkins/jenkinsnew3.png differ
diff --git a/doc/tutorials/ospp-kernelci/doc/img/jenkins/jenkinsnew4.png b/doc/tutorials/ospp-kernelci/doc/img/jenkins/jenkinsnew4.png
new file mode 100644
index 0000000000000000000000000000000000000000..05bfaf1b6e8ba09d9ca59c5619487964be1a99c1
Binary files /dev/null and b/doc/tutorials/ospp-kernelci/doc/img/jenkins/jenkinsnew4.png differ
diff --git a/doc/tutorials/ospp-kernelci/doc/img/jenkins/jenkinsnew5.png b/doc/tutorials/ospp-kernelci/doc/img/jenkins/jenkinsnew5.png
new file mode 100644
index 0000000000000000000000000000000000000000..5a697f2aa279394b6fb9d6db2397d214e9df0c5b
Binary files /dev/null and b/doc/tutorials/ospp-kernelci/doc/img/jenkins/jenkinsnew5.png differ
diff --git a/doc/tutorials/ospp-kernelci/doc/img/jenkins/jenkinsnew6.png b/doc/tutorials/ospp-kernelci/doc/img/jenkins/jenkinsnew6.png
new file mode 100644
index 0000000000000000000000000000000000000000..4c43bb0e8f2609eb733660a352e712d26d865d7e
Binary files /dev/null and b/doc/tutorials/ospp-kernelci/doc/img/jenkins/jenkinsnew6.png differ
diff --git a/doc/tutorials/ospp-kernelci/doc/img/jenkins/jenkinsnew7.png b/doc/tutorials/ospp-kernelci/doc/img/jenkins/jenkinsnew7.png
new file mode 100644
index 0000000000000000000000000000000000000000..6b54c2be6269783fdd85907d4bc3d3883d68c99a
Binary files /dev/null and b/doc/tutorials/ospp-kernelci/doc/img/jenkins/jenkinsnew7.png differ
diff --git a/doc/tutorials/ospp-kernelci/doc/img/jenkins/jenkinsnew8.png b/doc/tutorials/ospp-kernelci/doc/img/jenkins/jenkinsnew8.png
new file mode 100644
index 0000000000000000000000000000000000000000..d835b5e57d93b7c4f20e93682591778db61535bc
Binary files /dev/null and b/doc/tutorials/ospp-kernelci/doc/img/jenkins/jenkinsnew8.png differ
diff --git a/doc/tutorials/ospp-kernelci/doc/img/jenkins/jenkinsnew9.png b/doc/tutorials/ospp-kernelci/doc/img/jenkins/jenkinsnew9.png
new file mode 100644
index 0000000000000000000000000000000000000000..45ba16312fa4356858529d141cbb778205915919
Binary files /dev/null and b/doc/tutorials/ospp-kernelci/doc/img/jenkins/jenkinsnew9.png differ
diff --git "a/doc/tutorials/ospp-kernelci/doc/img/job\345\222\214testcase/job\345\222\214testcase1.png" "b/doc/tutorials/ospp-kernelci/doc/img/job\345\222\214testcase/job\345\222\214testcase1.png"
new file mode 100644
index 0000000000000000000000000000000000000000..c62df1b98f52930e198bcc5770b6220d8017d49a
Binary files /dev/null and "b/doc/tutorials/ospp-kernelci/doc/img/job\345\222\214testcase/job\345\222\214testcase1.png" differ
diff --git "a/doc/tutorials/ospp-kernelci/doc/img/lava\345\244\247\346\246\202/lava-1.png" "b/doc/tutorials/ospp-kernelci/doc/img/lava\345\244\247\346\246\202/lava-1.png"
new file mode 100644
index 0000000000000000000000000000000000000000..7b99474368439aec453f9035ee6fdc642b3a35a2
Binary files /dev/null and "b/doc/tutorials/ospp-kernelci/doc/img/lava\345\244\247\346\246\202/lava-1.png" differ
diff --git "a/doc/tutorials/ospp-kernelci/doc/img/lava\345\244\247\346\246\202/lava-2.png" "b/doc/tutorials/ospp-kernelci/doc/img/lava\345\244\247\346\246\202/lava-2.png"
new file mode 100644
index 0000000000000000000000000000000000000000..de8c4acd294acfd00c6d4ca66acab78e3860ebc7
Binary files /dev/null and "b/doc/tutorials/ospp-kernelci/doc/img/lava\345\244\247\346\246\202/lava-2.png" differ
diff --git "a/doc/tutorials/ospp-kernelci/doc/img/lava\345\244\247\346\246\202/lava-3.png" "b/doc/tutorials/ospp-kernelci/doc/img/lava\345\244\247\346\246\202/lava-3.png"
new file mode 100644
index 0000000000000000000000000000000000000000..5c65eef1ab1130c47867f13d123c5ed437b0e809
Binary files /dev/null and "b/doc/tutorials/ospp-kernelci/doc/img/lava\345\244\247\346\246\202/lava-3.png" differ
diff --git "a/doc/tutorials/ospp-kernelci/doc/img/lava\345\244\247\346\246\202/lava-4.png" "b/doc/tutorials/ospp-kernelci/doc/img/lava\345\244\247\346\246\202/lava-4.png"
new file mode 100644
index 0000000000000000000000000000000000000000..eb72a0e807abdcbda328b39583a4bfb232ec27d3
Binary files /dev/null and "b/doc/tutorials/ospp-kernelci/doc/img/lava\345\244\247\346\246\202/lava-4.png" differ
diff --git "a/doc/tutorials/ospp-kernelci/doc/img/lava\345\244\247\346\246\202/lava-5.png" "b/doc/tutorials/ospp-kernelci/doc/img/lava\345\244\247\346\246\202/lava-5.png"
new file mode 100644
index 0000000000000000000000000000000000000000..2b02c315faadcafe66e7dc15097ef438338d5f3e
Binary files /dev/null and "b/doc/tutorials/ospp-kernelci/doc/img/lava\345\244\247\346\246\202/lava-5.png" differ
diff --git "a/doc/tutorials/ospp-kernelci/doc/img/lava\345\244\247\346\246\202/lava-6.png" "b/doc/tutorials/ospp-kernelci/doc/img/lava\345\244\247\346\246\202/lava-6.png"
new file mode 100644
index 0000000000000000000000000000000000000000..d6b1b6b6a012155b58a305270e74659c02dd39a3
Binary files /dev/null and "b/doc/tutorials/ospp-kernelci/doc/img/lava\345\244\247\346\246\202/lava-6.png" differ
diff --git "a/doc/tutorials/ospp-kernelci/doc/img/lava\350\257\246\347\273\206/1.png" "b/doc/tutorials/ospp-kernelci/doc/img/lava\350\257\246\347\273\206/1.png"
new file mode 100644
index 0000000000000000000000000000000000000000..bccd2511e77f11bda38986605cab71fdc9e7b5e8
Binary files /dev/null and "b/doc/tutorials/ospp-kernelci/doc/img/lava\350\257\246\347\273\206/1.png" differ
diff --git "a/doc/tutorials/ospp-kernelci/doc/img/lava\350\257\246\347\273\206/2.png" "b/doc/tutorials/ospp-kernelci/doc/img/lava\350\257\246\347\273\206/2.png"
new file mode 100644
index 0000000000000000000000000000000000000000..9cd569f55f88420b7371d9e4311c6829736abee8
Binary files /dev/null and "b/doc/tutorials/ospp-kernelci/doc/img/lava\350\257\246\347\273\206/2.png" differ
diff --git "a/doc/tutorials/ospp-kernelci/doc/img/lava\350\257\246\347\273\206/3.png" "b/doc/tutorials/ospp-kernelci/doc/img/lava\350\257\246\347\273\206/3.png"
new file mode 100644
index 0000000000000000000000000000000000000000..0f4b158a0ea9f923ba07a3f90eb036742804ae95
Binary files /dev/null and "b/doc/tutorials/ospp-kernelci/doc/img/lava\350\257\246\347\273\206/3.png" differ
diff --git "a/doc/tutorials/ospp-kernelci/doc/img/lava\350\257\246\347\273\206/4.png" "b/doc/tutorials/ospp-kernelci/doc/img/lava\350\257\246\347\273\206/4.png"
new file mode 100644
index 0000000000000000000000000000000000000000..d1d4fe11205e863ba1a492c933665347ffcaa85d
Binary files /dev/null and "b/doc/tutorials/ospp-kernelci/doc/img/lava\350\257\246\347\273\206/4.png" differ
diff --git "a/doc/tutorials/ospp-kernelci/doc/img/lava\350\257\246\347\273\206/5.png" "b/doc/tutorials/ospp-kernelci/doc/img/lava\350\257\246\347\273\206/5.png"
new file mode 100644
index 0000000000000000000000000000000000000000..cd0ef0b623322146a0f1ae18eb3e5910a37a3738
Binary files /dev/null and "b/doc/tutorials/ospp-kernelci/doc/img/lava\350\257\246\347\273\206/5.png" differ
diff --git "a/doc/tutorials/ospp-kernelci/doc/img/lava\350\257\246\347\273\206/lava_docker_1.drawio.png" "b/doc/tutorials/ospp-kernelci/doc/img/lava\350\257\246\347\273\206/lava_docker_1.drawio.png"
new file mode 100644
index 0000000000000000000000000000000000000000..b16fef2d0ffe94afd594406e829d391cc3405301
Binary files /dev/null and "b/doc/tutorials/ospp-kernelci/doc/img/lava\350\257\246\347\273\206/lava_docker_1.drawio.png" differ
diff --git "a/doc/tutorials/ospp-kernelci/doc/img/lava\350\257\246\347\273\206/lava_docker_2.drawio.png" "b/doc/tutorials/ospp-kernelci/doc/img/lava\350\257\246\347\273\206/lava_docker_2.drawio.png"
new file mode 100644
index 0000000000000000000000000000000000000000..45961f64f5cb54d7d4a0b01e78f0258cb35ed740
Binary files /dev/null and "b/doc/tutorials/ospp-kernelci/doc/img/lava\350\257\246\347\273\206/lava_docker_2.drawio.png" differ
diff --git "a/doc/tutorials/ospp-kernelci/doc/img/lava\350\257\246\347\273\206/lava_status.png" "b/doc/tutorials/ospp-kernelci/doc/img/lava\350\257\246\347\273\206/lava_status.png"
new file mode 100644
index 0000000000000000000000000000000000000000..8f6dd842d7509035d1c70a74e3624e98f790dd9c
Binary files /dev/null and "b/doc/tutorials/ospp-kernelci/doc/img/lava\350\257\246\347\273\206/lava_status.png" differ
diff --git "a/doc/tutorials/ospp-kernelci/doc/img/lava\350\257\246\347\273\206/lava_work.png" "b/doc/tutorials/ospp-kernelci/doc/img/lava\350\257\246\347\273\206/lava_work.png"
new file mode 100644
index 0000000000000000000000000000000000000000..d160f0df608f38204e98e488fd6876e26e539c54
Binary files /dev/null and "b/doc/tutorials/ospp-kernelci/doc/img/lava\350\257\246\347\273\206/lava_work.png" differ
diff --git "a/doc/tutorials/ospp-kernelci/doc/img/lava\350\257\246\347\273\206/onlyqemu.png" "b/doc/tutorials/ospp-kernelci/doc/img/lava\350\257\246\347\273\206/onlyqemu.png"
new file mode 100644
index 0000000000000000000000000000000000000000..16074ad4bf376142e6e6f8f8d31d7f2dad2c79d3
Binary files /dev/null and "b/doc/tutorials/ospp-kernelci/doc/img/lava\350\257\246\347\273\206/onlyqemu.png" differ
diff --git "a/doc/tutorials/ospp-kernelci/doc/img/\346\210\220\346\236\234/lpi4a/all.png" "b/doc/tutorials/ospp-kernelci/doc/img/\346\210\220\346\236\234/lpi4a/all.png"
new file mode 100644
index 0000000000000000000000000000000000000000..5b169e615e3fe94b029b36162ac59d10d9a9c066
Binary files /dev/null and "b/doc/tutorials/ospp-kernelci/doc/img/\346\210\220\346\236\234/lpi4a/all.png" differ
diff --git "a/doc/tutorials/ospp-kernelci/doc/img/\346\210\220\346\236\234/lpi4a/kselftest.png" "b/doc/tutorials/ospp-kernelci/doc/img/\346\210\220\346\236\234/lpi4a/kselftest.png"
new file mode 100644
index 0000000000000000000000000000000000000000..57eecfae9c05a334855a09854df4dc542ee3d8fc
Binary files /dev/null and "b/doc/tutorials/ospp-kernelci/doc/img/\346\210\220\346\236\234/lpi4a/kselftest.png" differ
diff --git "a/doc/tutorials/ospp-kernelci/doc/img/\346\210\220\346\236\234/lpi4a/kselftest2.png" "b/doc/tutorials/ospp-kernelci/doc/img/\346\210\220\346\236\234/lpi4a/kselftest2.png"
new file mode 100644
index 0000000000000000000000000000000000000000..659bd2f21976e0be2e74118c43cf0baae807cdb0
Binary files /dev/null and "b/doc/tutorials/ospp-kernelci/doc/img/\346\210\220\346\236\234/lpi4a/kselftest2.png" differ
diff --git "a/doc/tutorials/ospp-kernelci/doc/img/\346\210\220\346\236\234/lpi4a/ltptest.png" "b/doc/tutorials/ospp-kernelci/doc/img/\346\210\220\346\236\234/lpi4a/ltptest.png"
new file mode 100644
index 0000000000000000000000000000000000000000..f39cd73242c68a1642e5c8bd1d088a6c060d0241
Binary files /dev/null and "b/doc/tutorials/ospp-kernelci/doc/img/\346\210\220\346\236\234/lpi4a/ltptest.png" differ
diff --git "a/doc/tutorials/ospp-kernelci/doc/img/\346\210\220\346\236\234/lpi4a/ltptest2.png" "b/doc/tutorials/ospp-kernelci/doc/img/\346\210\220\346\236\234/lpi4a/ltptest2.png"
new file mode 100644
index 0000000000000000000000000000000000000000..401d4bedd58178acf7ebd229f940e577bba6b134
Binary files /dev/null and "b/doc/tutorials/ospp-kernelci/doc/img/\346\210\220\346\236\234/lpi4a/ltptest2.png" differ
diff --git "a/doc/tutorials/ospp-kernelci/doc/img/\346\210\220\346\236\234/lpi4a/ltptest3.png" "b/doc/tutorials/ospp-kernelci/doc/img/\346\210\220\346\236\234/lpi4a/ltptest3.png"
new file mode 100644
index 0000000000000000000000000000000000000000..35668d4fdc01db72b5f0a941d2adf3ad98addfa1
Binary files /dev/null and "b/doc/tutorials/ospp-kernelci/doc/img/\346\210\220\346\236\234/lpi4a/ltptest3.png" differ
diff --git "a/doc/tutorials/ospp-kernelci/doc/img/\346\210\220\346\236\234/qemu/all.png" "b/doc/tutorials/ospp-kernelci/doc/img/\346\210\220\346\236\234/qemu/all.png"
new file mode 100644
index 0000000000000000000000000000000000000000..cd28528948d06a74cd260ae938f07b9206225cb4
Binary files /dev/null and "b/doc/tutorials/ospp-kernelci/doc/img/\346\210\220\346\236\234/qemu/all.png" differ
diff --git "a/doc/tutorials/ospp-kernelci/doc/img/\346\210\220\346\236\234/qemu/kselftest.png" "b/doc/tutorials/ospp-kernelci/doc/img/\346\210\220\346\236\234/qemu/kselftest.png"
new file mode 100644
index 0000000000000000000000000000000000000000..154795cbea1db5e7b2f49cf295d9b67abd2e06cf
Binary files /dev/null and "b/doc/tutorials/ospp-kernelci/doc/img/\346\210\220\346\236\234/qemu/kselftest.png" differ
diff --git "a/doc/tutorials/ospp-kernelci/doc/img/\346\210\220\346\236\234/qemu/kselftest2.png" "b/doc/tutorials/ospp-kernelci/doc/img/\346\210\220\346\236\234/qemu/kselftest2.png"
new file mode 100644
index 0000000000000000000000000000000000000000..9bc6c7fe55ce4487efebd321c568a7bc3d4ccfaa
Binary files /dev/null and "b/doc/tutorials/ospp-kernelci/doc/img/\346\210\220\346\236\234/qemu/kselftest2.png" differ
diff --git "a/doc/tutorials/ospp-kernelci/doc/img/\346\210\220\346\236\234/qemu/ltp2.png" "b/doc/tutorials/ospp-kernelci/doc/img/\346\210\220\346\236\234/qemu/ltp2.png"
new file mode 100644
index 0000000000000000000000000000000000000000..e0e4dc3af71ea142ea135d434e7d75e704116996
Binary files /dev/null and "b/doc/tutorials/ospp-kernelci/doc/img/\346\210\220\346\236\234/qemu/ltp2.png" differ
diff --git "a/doc/tutorials/ospp-kernelci/doc/img/\346\210\220\346\236\234/qemu/ltptest.png" "b/doc/tutorials/ospp-kernelci/doc/img/\346\210\220\346\236\234/qemu/ltptest.png"
new file mode 100644
index 0000000000000000000000000000000000000000..71caf7920c716c4b522b7bb4a9e33739e5f5bed8
Binary files /dev/null and "b/doc/tutorials/ospp-kernelci/doc/img/\346\210\220\346\236\234/qemu/ltptest.png" differ
diff --git "a/doc/tutorials/ospp-kernelci/doc/img/\347\241\254\344\273\266/licheepi1.png" "b/doc/tutorials/ospp-kernelci/doc/img/\347\241\254\344\273\266/licheepi1.png"
new file mode 100644
index 0000000000000000000000000000000000000000..b6e3fca62e3fb14635d65bfb10cf0e6c3e252e27
Binary files /dev/null and "b/doc/tutorials/ospp-kernelci/doc/img/\347\241\254\344\273\266/licheepi1.png" differ
diff --git "a/doc/tutorials/ospp-kernelci/doc/img/\347\241\254\344\273\266/licheepi2.png" "b/doc/tutorials/ospp-kernelci/doc/img/\347\241\254\344\273\266/licheepi2.png"
new file mode 100644
index 0000000000000000000000000000000000000000..5cf5d3630ffd78b971429f652a877341bf4ae645
Binary files /dev/null and "b/doc/tutorials/ospp-kernelci/doc/img/\347\241\254\344\273\266/licheepi2.png" differ
diff --git "a/doc/tutorials/ospp-kernelci/doc/img/\351\205\215\347\275\256\345\237\272\346\234\254\347\216\257\345\242\203/\351\205\215\347\275\256\345\237\272\346\234\254\347\216\257\345\242\2031.png" "b/doc/tutorials/ospp-kernelci/doc/img/\351\205\215\347\275\256\345\237\272\346\234\254\347\216\257\345\242\203/\351\205\215\347\275\256\345\237\272\346\234\254\347\216\257\345\242\2031.png"
new file mode 100644
index 0000000000000000000000000000000000000000..fbdb98ff0c09735a52431125ad26507ad09aea44
Binary files /dev/null and "b/doc/tutorials/ospp-kernelci/doc/img/\351\205\215\347\275\256\345\237\272\346\234\254\347\216\257\345\242\203/\351\205\215\347\275\256\345\237\272\346\234\254\347\216\257\345\242\2031.png" differ
diff --git "a/doc/tutorials/ospp-kernelci/doc/lava-docker\347\273\206\350\212\202\350\247\243\351\207\212.md" "b/doc/tutorials/ospp-kernelci/doc/lava-docker\347\273\206\350\212\202\350\247\243\351\207\212.md"
new file mode 100644
index 0000000000000000000000000000000000000000..90055bb780a26549482e9222b316cd217f2896bb
--- /dev/null
+++ "b/doc/tutorials/ospp-kernelci/doc/lava-docker\347\273\206\350\212\202\350\247\243\351\207\212.md"
@@ -0,0 +1,414 @@
+## 总体介绍
+
+首先可以参考官方文档 [LAVA 简介 — LAVA 2024.05 文档 (lavasoftware.org)](https://docs.lavasoftware.org/lava/index.html#)
+
+可能会有点难以理解
+
+
+
+可以参考官方文档的这张图
+
+通俗点说就是 LAVA 是一种测试框架,用来管理被测试设备,使用者需要根据这个测试框架的规则来开发测试套和测试用例,测试用例需要使用者根据自己的需求更改。
+
+由 **master** 提供 web 界面 以及各种交互的接口,存储测试定义,测试结果等,**slave** 与被测试的设备直接连接,来控制被测试的机器。
+
+大家可以在 [Index — LAVA 2024.05 documentation (lavasoftware.org)](https://docs.lavasoftware.org/lava/genindex.html) 找到很多信息,但是资料有些过多,并且有些已经很久没更新了,再加上其中提供的一些 url 已经失效了,可能会产生一些障碍
+
+回到项目本身,由于我们使用 lava-docker ,本质上是在当前的机器上创建了 docker 容器,如何创建详见下文。
+
+## lava-docker 基础介绍
+
+### 解释源码以及运作方式
+
+源码链接 https://github.com/kernelci/lava-docker.git
+
+
+
+使用 lavalab-gen.py 生成 master 以及 slave 的基础镜像
+
+**源码由以下部分组成**
+
+1. boards.yaml
+
+ - 根据自己的需要 编写 boards.yaml (原项目下存在一些 example)
+
+ - 根据需要修改 lavalab-gen.py
+2. healthcheck
+
+ - 存储的是 healthcheck 的定义 由于 healthcheck 需要拉取 github 上的源码,由于国内的网络问题,可能需要为生成的 docker 像配置代理等 比较麻烦,可以在这里提前将 healthcheck 拉取的源码 替换为本地路径 /或是本地地址你 fork 到 gitee 上的克隆镜像仓库地址
+3. lava-master 和 lava-slave
+ - lava-master 和 lava-slave 分别用来创建 lava-master 和 lava-slave 容器镜像
+ - 里面除了包含 Dockerfile 还有一些文件夹,用来存储一些基于自己需求的配置,应该是为了使项目不杂乱,比如把需要的一些组件放在这里,在修改 lavalab-gen.py 时指向这里,比较方便资源的管理。
+4. others
+
+ - 并非不重要,只是在当前项目中没修改的部分 ,可以自行阅读源码
+ - dhcpd:用来为网络中的设备分配 IP
+ - boards.yaml.example 或 board-ci.yaml 作为 boards.yaml 的例子
+
+将一切修改完毕 就可以运行 lavalab-gen.py 此时会出现 **local/output** 文件夹
+
+**output 文件夹由以下部分组成**
+
+1. master 文件夹 (由 boards.yaml 中的设置的内容决定文件夹名称 )
+
+ - 直接 copy 根目录中 lava-master 里面的内容
+ - 根据 boards.yaml 中的内容生成的一些 user 或 token 信息
+2. lab-slave-1 文件夹 (由 boards.yaml 中的设置的内容决定文件夹名称 )
+
+ - 直接 copy 根目录中 lava-master 里面的内容
+ - 根据 boards.yaml 中的内容生成的 一或多个 slave 容器
+3. deploy.sh
+
+ - 用于管理和配置系统 Udev 规则以及启动 Docker 容器的 Shell 脚本
+4. docker-compose.yml
+
+ - 根据 boards.yaml 中的内容生成,配置 容器的端口等设置,将主机文件映射到 docker 容器内部
+
+### 运行
+
+配置好 board.yaml 就可以顺利的 使用 docker 搭建 lava 了
+
+```shell
+./lavalab-gen.py //生成部署需要的文件, 存放在 output/local/目录下
+cd output/local
+docker compose build //生成 lava master 和 slave 的 docker image
+docker compose up -d //运行 lava master 和 slave docker 容器
+```
+
+正常的话不做任何修改也是可以跑起来的,只需要编写好 board.yaml 这里给出一个简单例子
+
+```yaml
+---
+masters:
+ - name: master
+ host: local
+ webinterface_port: 8000 //web端口
+ allowed_hosts: ['*']
+ users:
+ - name: admin
+ token: adminlavatoken //token 与 kernel ci 或是 Jenkins 交互都要使用
+ password: v
+ superuser: true
+ staff: true
+ tokens:
+ - username: admin
+ token: dfjdfkfkdjfkdsjfslforci
+ description: no description
+slaves:
+ - name: lab-slave-1
+ host: local
+ remote_master: master
+ remote_user: admin
+ dispatcher_ip: 127.0.0.1
+ use_tftp: True
+ use_nfs: True
+ host_healthcheck: false
+boards:
+ - name: qemu-test
+ type: qemu
+ slave: lab-slave-1
+```
+
+在浏览器中输入 http://127.0.0.1:8000 进入 lava web 界面,8000是 boards.yaml 中设置的 webinterface_port
+
+lava web 端可以干很多事情(其实和使用 lava service 的子命令类似)
+
+提交 device-type ,job 更改 设备状态等
+
+
+
+( lava 界面)
+
+由于此时的 **board.yaml** 中只配置了 一个 slave 和 board
+
+```yaml
+slaves:
+ - name: lab-slave-1
+ host: local
+ remote_master: master
+ remote_user: admin
+ dispatcher_ip: 127.0.0.1
+ use_tftp: True
+ use_nfs: True
+ host_healthcheck: false
+boards:
+ - name: qemu-test
+ type: qemu
+ slave: lab-slave-1
+```
+
+
+
+查看 Status
+
+
+
+## 处理问题
+
+此时的 online devices 应该是一个,而且由于 qemu 类型会自己执行 healthcheck ,所以目前应该有一个 running test job 便是 healthcheck
+
+### healthcheck
+
+上文也提到过,由于网络问题,有可能你的 healthcheck 过不去,过不去便会一直执行,导致无法处理其他job,所以要先解决 **healthcheck** 的问题
+
+解决方案:
+
+1. 为 qemu对应的 slave 容器 配置代理等,直接解决网络问题
+2. 把 定义中的 https://github.com/BayLibre/lava-healthchecks-binary.git 替换为国内的镜像仓库
+
+和我一样使用 WSL 2 的同学解决这些问题可能还会遇到一些报错,最后定位到是因为,WSL 2 中的 Ubuntu 是 Windows 特化版本的 Ubuntu ,虽然其内核版本满足了 healthcheck 的版本要求,但是其中的 引导目录`/boot`以及 模块目录`/lib/modules` 和 lava 的适配都有问题,我这里采用了最简单的方法,便是把 ubuntu-22.04 x86 对应的目录直接 copy 到 WSL 2 中,并在构建 docker 容器时 指向对应的目录,即 **修改 lavalab-gen.py**
+
+
+
+这里便是将 提供的 boot 映射为 master 的 boot ,modules 自然也是同理 ,这里陪着的是 master ,slave 在文件462行左右,配置方法都是一样的。
+
+master 不这样更改也可以 因为 master 不需要做一些测试 ,目前使用起来没出现问题。
+
+解决这些问题后,之后 WSL2 和实体机的体感应该是一致的
+
+## 编写 job
+
+这里给出一个 qemu 的 example
+
+```yaml
+# Your first LAVA JOB definition for an riscv_64 QEMU
+device_type: qemu
+job_name: qemu-oerv-24.03-smoke-test
+timeouts:
+ job:
+ minutes: 30
+ action:
+ minutes: 20
+ connection:
+ minutes: 5
+priority: medium
+visibility: public
+# context allows specific values to be overridden or included
+context:
+ # tell the qemu template which architecture is being tested
+ # the template uses that to ensure that qemu-system-riscv64 is executed.
+ arch: riscv64
+ machine: virt
+ guestfs_interface: virtio
+ extra_options:
+ - -nographic -machine virt,pflash0=pflash0,pflash1=pflash1,acpi=off
+ - -smp 4
+ - -m 8G
+ - -object memory-backend-ram,size=4G,id=ram1
+ - -numa node,memdev=ram1
+ - -object memory-backend-ram,size=4G,id=ram2
+ - -numa node,memdev=ram2
+ - -object rng-random,filename=/dev/urandom,id=rng0
+ - -device virtio-vga
+ - -device virtio-rng-device,rng=rng0
+ - -device virtio-blk-device,drive=hd0,bootindex=1
+ - -device virtio-net-device,netdev=usernet
+ - -netdev user,id=usernet,hostfwd=tcp::12055-:22
+ - -device qemu-xhci -usb -device usb-kbd -device usb-tablet
+metadata:
+ # please change these fields when modifying this job for your own tests.
+ format: Lava-Test Test Definition 1.0
+ name: qemu-oerv-24.03-test
+ description: "test for oerv qemu image"
+ version: "1.0"
+# ACTION_BLOCK
+actions:
+# DEPLOY_BLOCK
+- deploy:
+ timeout:
+ minutes: 20
+ to: tmpfs
+ images:
+ kernel_1:
+ image_arg: -blockdev node-name=pflash0,driver=file,read-only=on,filename={kernel_1}
+ url: file:///home/2024ospp-large-files/qemu/RISCV_VIRT_CODE.fd
+ kernel_2:
+ image_arg: -blockdev node-name=pflash1,driver=file,filename={kernel_2}
+ url: file:///home/2024ospp-large-files/qemu/RISCV_VIRT_VARS.fd
+ rootfs:
+ image_arg: -drive file={rootfs},format=qcow2,id=hd0
+ url: file:///home/2024ospp-large-files/qemu/openEuler-24.03-LTS-riscv64.qcow2.zst
+ compression: zstd
+# BOOT_BLOCK
+- boot:
+ timeout:
+ minutes: 20
+ method: qemu
+ media: tmpfs
+ prompts: ["root@openeuler-riscv64"]
+ auto_login:
+ login_prompt: "localhost login:"
+ username: root
+ password_prompt: "Password:"
+ password: openEuler12#$
+# TEST_BLOCK
+- test:
+ timeout:
+ minutes: 10
+ definitions:
+ - repository: https://git.linaro.org/lava-team/lava-functional-tests.git
+ from: git
+ path: lava-test-shell/smoke-tests-basic.yaml
+ name: smoke-tests
+```
+
+这里使用的镜像是 官方仓库的镜像 [openEuler下载](https://www.openeuler.org/zh/download)
+
+值得注意的是 openEuler 不同版本 或是不同来源的 镜像 启动脚本可能不太相同,需要根据需要修改 job 的内容
+
+根据你的 device 来处理 **TEST_BLOCK** 以上的内容
+
+这里以 openEuler 24.03 做演示
+
+这里用 yaml 启动部分的内容和官方提供的 start.vm 脚本做下对比
+
+### DEPLOY_BLOCK
+
+
+
+左侧为 job ,右侧为 start_vm 脚本
+
+字体有些小 但应该能看出来 实际上就是把启动脚本需要的参数 用 lava 需要的格式做出来
+
+简单来说就是 不需要引用外部文件的 不需要动 放在 context 下`当然一些 define 如 $ssh_port 可以直接替换为 其对应的值或文本`, 需要处理的 比如 start_vm 中需要 引入 openEuler-24.03-LTS-riscv64.qcow2.zst 这个 rootfs
+
+则需要把对应语句移入 - deploy 的 image 下
+
+编写大概是这样
+
+```yaml
+images:
+ roofts: #变量名对应下一句中的内容
+ image_arg: -drive file={rootfs},format=qcow2,id=hd0 #对应上一句中的 roofts
+ url: file:///home/2024ospp-large-files/qemu/openEuler-24.03-LTS-riscv64.qcow2.zst #可以是本地资源,也可以是网络资源
+ compression: zstd #提供的是什么格式的 rootfs
+```
+
+注意注意缩进 `file={rootfs}`中间不能有空格
+
+### BOOT_BLOCK
+
+```yaml
+# BOOT_BLOCK
+- boot:
+ timeout:
+ minutes: 20
+ method: qemu
+ media: tmpfs
+ prompts: ["root@openeuler-riscv64"]
+ auto_login:
+ login_prompt: "localhost login:"
+ username: root
+ password_prompt: "Password:"
+ password: openEuler12#$
+```
+
+这里需要到实际的机器中查看其提供的信息,欧拉各版本的启动提示词并不相同
+
+比如 24.03 LTS 是 `locolhost login:` 而 23.09 则是 `openeuler-riscv64 login:`
+
+我这里尝试过 字符串匹配 常出现bug,暂时就不统一了 有的区别只有 `e` 的大小写
+
+这里是最重要的环节之一,可能会遇到非常多你意想不到的问题,之后我可能会更新
+
+最后便是处理
+
+### TEST_BLOCK
+
+```yaml
+# TEST_BLOCK
+- test:
+ timeout:
+ minutes: 10
+ definitions:
+ - repository: https://git.linaro.org/lava-team/lava-functional-tests.git
+ from: git
+ path: lava-test-shell/smoke-tests-basic.yaml
+ name: smoke-tests
+```
+
+这里便是测试的相关内容,比如这个执行一个 smoke-test 来源则是 git 当然来源也可以是本地等,此时已经进入测试机环境了,你也可以直接编写测试脚本在这里运行。
+
+## 测试的方法
+
+我说的可能不清楚 可以查看 [Submit a job - LAVA](https://lava.readthedocs.io/en/latest/user/basic-tutorials/submit/)
+### 1.首先是自己编写
+
+可以查看 [Glossary of terms — LAVA 2024.05 documentation (lavasoftware.org)](https://docs.lavasoftware.org/lava/glossary.html#term-job-definition)
+
+```yaml
+
+# TEST_BLOCK
+- test:
+ timeout:
+ minutes: 600
+ definitions:
+ - repository:
+ metadata:
+ format: Lava-Test Test Definition 1.0
+ name: kselftest-ptrace-test
+ run:
+ steps:
+ - yum install -y git make gcc flex bison clang
+ - df -h
+ - cd /root
+ - git clone https://gitee.com/feifei-fertilizer/riscv-kernel.git
+ - cd riscv-kerner.git
+ - git checkout OLK-6.6
+ - make defconfig
+ - make -C tools/testing/selftests
+ - make -C tools/testing/selftests TARGETS=clone3 run_tests
+ from: inline
+ name: kselftest-inline
+ path: inline/kselftest.yaml
+```
+
+这是一个基于内核源码的 **kselftest**
+
+可以看到
+
+### 2.基于test-definitions
+
+可以通过 clone [Linaro/test-definitions: Test definitions work with and without LAVA (github.com)](https://github.com/Linaro/test-definitions) 来直接使用其准备好的测试
+
+根据描述官方文档描述 [test-definitions/docs/index.md 在 master ·Linaro/测试定义 (github.com)](https://github.com/Linaro/test-definitions/blob/master/docs/index.md)
+
+**测试套件可以在有和没有 [LAVA](http://lavasoftware.org/) 的情况下工作。以下两个 支持自动测试集。**
+
+- **`automated/linux/`**
+- **`automated/android/`**
+
+我需要做的 ltp test 正位于 **`automated/linux/`** 中
+
+```yaml
+- test:
+ timeout:
+ minutes: 600
+ definitions:
+ - repository: https://github.com/Linaro/test-definitions.git
+ from: git
+ path: automated/linux/ltp/ltp.yaml
+ parameters:
+ TST_CMDFILES: syscalls
+ SKIPFILE: skipfile-lkft.yaml
+ BOARD: qemu
+ BRANCH: master
+ ENVIRONMENT: production
+ TIMEOUT_MULTIPLIER: '30'
+ ROOT_PASSWD: openEuler12#$
+ BUILD_FROM_TAR: true
+ LTP_VERSION: 20240524
+ LTP_TMPDIR: /scratch
+ name: ltp-syscalls-tests
+```
+
+当然只要拉取 github 上面的代码总要先解决网络问题
+
+-----
+
+ps:如果你使用串口连接硬件设备进行测试 还需要更改 docker-compose.yml 中的内容,我决定放在自定义设备那章节中
+
+
+
+到这里我便演示了如何起一个最简单的测例,当然这比起真正的测试还有很多路要走.
+
diff --git "a/doc/tutorials/ospp-kernelci/doc/\345\267\262\346\217\220\344\276\233\347\232\204\350\256\276\345\244\207\347\261\273\345\236\213-qemu.md" "b/doc/tutorials/ospp-kernelci/doc/\345\267\262\346\217\220\344\276\233\347\232\204\350\256\276\345\244\207\347\261\273\345\236\213-qemu.md"
new file mode 100644
index 0000000000000000000000000000000000000000..83082eba69a7714de23be613144ac530ce9e0163
--- /dev/null
+++ "b/doc/tutorials/ospp-kernelci/doc/\345\267\262\346\217\220\344\276\233\347\232\204\350\256\276\345\244\207\347\261\273\345\236\213-qemu.md"
@@ -0,0 +1,64 @@
+做完了前面的工作
+
+如果你需要短时间测试你的 job 以及 测试用例 ,频繁的 healthcheck 会占用你的机器
+
+## 修改 healthcheck 触发条件(可选)
+
+可以修改 healthcheck 的触发时间,可以 disable healthcheck
+
+
+
+点击 **device-type**
+
+
+
+这里可以看到设备的 healthcheck 状态 我这里已经把 qemu 的 自动触发关闭了
+
+
+
+选择 **Disable health check for devices of this type**
+
+
+
+
+
+
+
+## 提交 job 及触发
+
+
+
+回到主页直接点击 **Submit** 就会出现一个提交界面,提交你的 job 定义就好啦
+
+查看 job 结果等这里都不再赘述了
+
+在 [lava-docker细节解释 ](./lava-docker细节解释.md)中我解释了一个 基于 openEuler riscv 24.03 LTS 的 smoke 测试,可以参考下
+
+
+
+## 处理 healthcheck 的网络问题
+
+由于 healthcheck 的源码位于 github 上,在拉取时可能会遇到网络问题,这里我给出一种解决方案
+
+可以在 构建 lava 容器前修改源码中 healthcheck 的 **Dockerfile**
+
+位于源码根目录的 healthcheck 文件夹下
+
+```dockerfile
+FROM bitnami/minideb:bullseye
+
+RUN apt-get update && apt-get -y install git
+RUN git clone https://github.com/BayLibre/lava-healthchecks-binary.git #将这一行换成国内的镜像仓库即可
+
+FROM nginx:mainline-alpine
+
+COPY port.conf /etc/nginx/conf.d/
+
+COPY --from=0 /lava-healthchecks-binary/mainline /usr/share/nginx/html/mainline/
+COPY --from=0 lava-healthchecks-binary/images /usr/share/nginx/html/images/
+COPY --from=0 lava-healthchecks-binary/next /usr/share/nginx/html/next/
+COPY --from=0 lava-healthchecks-binary/stable /usr/share/nginx/html/stable/
+```
+
+也可以为你的 dokcer 容器配置代理
+
diff --git "a/doc/tutorials/ospp-kernelci/doc/\346\220\255\345\273\272\345\237\272\347\241\200\347\232\204\345\274\200\345\217\221\347\216\257\345\242\203.md" "b/doc/tutorials/ospp-kernelci/doc/\346\220\255\345\273\272\345\237\272\347\241\200\347\232\204\345\274\200\345\217\221\347\216\257\345\242\203.md"
new file mode 100644
index 0000000000000000000000000000000000000000..534219c86b75ee6f726d8f393e5ee859dfc706d5
--- /dev/null
+++ "b/doc/tutorials/ospp-kernelci/doc/\346\220\255\345\273\272\345\237\272\347\241\200\347\232\204\345\274\200\345\217\221\347\216\257\345\242\203.md"
@@ -0,0 +1,103 @@
+**注 :这里是非常基础的主机环境搭建环节,相信大部分看到这里的同学都是会的,但是为了做到完整,我会在这里写上如何进行完整的环境搭建,如果你已经完成了可以跳过.不过如果你使用的是虚拟机环境,这里可能仍有一些你需要注意的地方**
+
+# 主机环境
+
+## 实体机
+
+推荐
+
+使用 Ubuntu 22.04 ,不过众所周知 ,ubuntu官方源的软件版本较低,可能需要从源码拉下来安装。
+
+## 虚拟机
+
+不太推荐,因为涉及到设备连接等问题,虚拟机的虚拟串口都是基于软件实现的,不知道哪个环节出问题就要排查好久。
+
+但本人因为身边只有这些设备不得已使用虚拟机
+
+### WSL 2
+
+可以查看 windows 的官方文档 [安装 WSL | Microsoft Learn](https://learn.microsoft.com/zh-cn/windows/WSL/install)
+
+也可以自己网络搜索各种博客等,嫌麻烦甚至可以直接去 Microsoft Store 直接下现成的
+
+### VMware
+
+直接去 Ubuntu 官网下载 [Download Ubuntu Desktop | Ubuntu](https://ubuntu.com/download/desktop) 不过我下的时候提示资源失效,但是相信国人最擅长处理的就是资源失效以及网络问题了。
+
+
+### 解决虚拟机与外界的连接问题
+
+由于后期 uboot tftp 需要开发板可以 ping 到部署 lava-slave 的机器,在该文档的情况下即主机 ip ,所以这个 ip 至少应该是局域网可 ping 的
+
+虚拟机要注意的最大问题是,默认没有独立的外部可 ping 的 ip,可能是跟随主机 ip 或是只能由主机访问的 ip 。
+
+这里给出解决方案
+
+#### WSL 2
+WSL 这里给出的解决方案是使用 hyper-v ,家庭版的 windows 系统默认并没有这个功能,可以通过网上的一些教程来获取该功能 [Windows10/11家庭版开启Hyper-V虚拟机功能详解——保姆教程及闭坑指南](https://zhuanlan.zhihu.com/p/667571538) ,然后通过桥接获得我们期望的效果 [WSL2子系统如何设置桥接和静态ip(保姆级教程)](https://blog.csdn.net/m0_73779708/article/details/140301364)
+
+#### VMware
+
+VMware 则是在虚拟机配置中将网络适配器切换至桥接模式,当然如果你用 VMware 连接开发板也需要打开串行端口和 USB 控制器
+
+
+
+
+
+
+
+# 配置软件源
+
+参考清华镜像[ubuntu | 镜像站使用帮助 | 清华大学开源软件镜像站 | Tsinghua Open Source Mirror](https://mirrors.tuna.tsinghua.edu.cn/help/ubuntu/)
+
+或是中科大,淘宝镜像源等
+
+
+
+由于我后期重新搭建了环节搭建环境出现了软件源的问题 这里给出我的配置
+
+```list
+# See http://help.ubuntu.com/community/UpgradeNotes for how to upgrade to
+# newer versions of the distribution.
+deb http://archive.ubuntu.com/ubuntu/ jammy main restricted
+# deb-src http://archive.ubuntu.com/ubuntu/ jammy main restricted
+
+## Major bug fix updates produced after the final release of the
+## distribution.
+deb http://archive.ubuntu.com/ubuntu/ jammy-updates main restricted
+# deb-src http://archive.ubuntu.com/ubuntu/ jammy-updates main restricted
+
+## N.B. software from this repository is ENTIRELY UNSUPPORTED by the Ubuntu
+## team. Also, please note that software in universe WILL NOT receive any
+## review or updates from the Ubuntu security team.
+deb http://archive.ubuntu.com/ubuntu/ jammy universe
+# deb-src http://archive.ubuntu.com/ubuntu/ jammy universe
+deb http://archive.ubuntu.com/ubuntu/ jammy-updates universe
+# deb-src http://archive.ubuntu.com/ubuntu/ jammy-updates universe
+
+## N.B. software from this repository is ENTIRELY UNSUPPORTED by the Ubuntu
+## team, and may not be under a free licence. Please satisfy yourself as to
+## your rights to use the software. Also, please note that software in
+## multiverse WILL NOT receive any review or updates from the Ubuntu
+## security team.
+deb http://archive.ubuntu.com/ubuntu/ jammy multiverse
+# deb-src http://archive.ubuntu.com/ubuntu/ jammy multiverse
+deb http://archive.ubuntu.com/ubuntu/ jammy-updates multiverse
+# deb-src http://archive.ubuntu.com/ubuntu/ jammy-updates multiverse
+
+## N.B. software from this repository may not have been tested as
+## extensively as that contained in the main release, although it includes
+## newer versions of some applications which may provide useful features.
+## Also, please note that software in backports WILL NOT receive any review
+## or updates from the Ubuntu security team.
+deb http://archive.ubuntu.com/ubuntu/ jammy-backports main restricted universe multiverse
+# deb-src http://archive.ubuntu.com/ubuntu/ jammy-backports main restricted universe multiverse
+
+deb http://security.ubuntu.com/ubuntu/ jammy-security main restricted
+# deb-src http://security.ubuntu.com/ubuntu/ jammy-security main restricted
+deb http://security.ubuntu.com/ubuntu/ jammy-security universe
+# deb-src http://security.ubuntu.com/ubuntu/ jammy-security universe
+deb http://security.ubuntu.com/ubuntu/ jammy-security multiverse
+# deb-src http://security.ubuntu.com/ubuntu/ jammy-security multiverse
+```
+
diff --git "a/doc/tutorials/ospp-kernelci/doc/\346\234\252\346\217\220\344\276\233\347\232\204\350\256\276\345\244\207\347\261\273\345\236\213-\350\207\252\345\256\232\344\271\211\350\256\276\345\244\207\347\261\273\345\236\213-Lip4a.md" "b/doc/tutorials/ospp-kernelci/doc/\346\234\252\346\217\220\344\276\233\347\232\204\350\256\276\345\244\207\347\261\273\345\236\213-\350\207\252\345\256\232\344\271\211\350\256\276\345\244\207\347\261\273\345\236\213-Lip4a.md"
new file mode 100644
index 0000000000000000000000000000000000000000..423bc642c295c3321e75db3226cfcdc31c732d9b
--- /dev/null
+++ "b/doc/tutorials/ospp-kernelci/doc/\346\234\252\346\217\220\344\276\233\347\232\204\350\256\276\345\244\207\347\261\273\345\236\213-\350\207\252\345\256\232\344\271\211\350\256\276\345\244\207\347\261\273\345\236\213-Lip4a.md"
@@ -0,0 +1,907 @@
+可以先按照之前的做法什么都不操作,**device-type** 存储在 master 中
+
+### 确定源码中是否存在
+
+```shell
+feifei@localhost:~$ docker ps -a
+CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS
+ NAMES
+314838a8259e local-lab-slave-1 "/root/entrypoint.sh…" 7 days ago Up 37 minutes 0.0.0.0:80->80/tcp, :::80->80/tcp, 127.0.0.1:69->69/udp, 0.0.0.0:61950-62000->61950-62000/tcp, :::61950-62000->61950-62000/tcp local-lab-slave-1-1
+53eeb4fc811e local-master "/root/entrypoint.sh…" 7 days ago Up 16 hours 3079/tcp, 5500/tcp, 5555-5556/tcp, 8000-8001/tcp, 0.0.0.0:8000->80/tcp local-master-1
+```
+
+然后进入 master 也就是 CONTAINER ID 为 **53eeb4fc811e** 的机器
+
+```shell
+feifei@localhost:~$ docker exec -it 53eeb4fc811e /bin/bash
+root@master:/#
+```
+
+可以到 https://github.com/Linaro/lava/tree/master/etc/dispatcher-config/device-types 查看
+
+如果你嫌麻烦,我在这里列出
+
+```shell
+root@master:/# ls usr/share/lava-server/device-types/
+aaeon-UPN-EHLX4RE-A10-0864.jinja2
+acer-R721T-grunt.jinja2
+acer-cb317-1h-c3z6-dedede.jinja2
+acer-cbv514-1h-34uz-brya.jinja2
+acer-chromebox-cxi4-puff.jinja2
+acer-chromebox-cxi5-brask.jinja2
+acer-cp514-2h-1130g7-volteer.jinja2
+acer-cp514-2h-1160g7-volteer.jinja2
+acer-cp514-3wh-r0qs-guybrush.jinja2
+acer-n20q11-r856ltn-p1s2-nissa.jinja2
+adb-nuc.jinja2
+alpine-db.jinja2
+am335x-sancloud-bbe.jinja2
+am437x-idk-evm.jinja2
+am57xx-beagle-x15.jinja2
+am6.jinja2
+apq8016-sbc-uboot.jinja2
+ar9331-dpt-module.jinja2
+arduino-nano-33-ble.jinja2
+arduino101.jinja2
+armada-370-db.jinja2
+armada-370-rd.jinja2
+armada-3720-db.jinja2
+armada-3720-espressobin.jinja2
+armada-375-db.jinja2
+armada-385-db-ap.jinja2
+armada-388-clearfog-pro.jinja2
+armada-388-clearfog.jinja2
+armada-388-gp.jinja2
+armada-398-db.jinja2
+armada-7040-db.jinja2
+armada-8040-db.jinja2
+armada-xp-db.jinja2
+armada-xp-gp.jinja2
+armada-xp-linksys-mamba.jinja2
+armada-xp-openblocks-ax3-4.jinja2
+arndale.jinja2
+asus-C433TA-AJ0005-rammus.jinja2
+asus-C436FA-Flip-hatch.jinja2
+asus-C523NA-A20057-coral.jinja2
+asus-CM1400CXA-dalboz.jinja2
+asus-cx9400-volteer.jinja2
+at91-sama5d2_xplained.jinja2
+at91-sama5d4_xplained.jinja2
+at91rm9200ek.jinja2
+at91sam9261ek.jinja2
+at91sam9g20ek.jinja2
+at91sam9m10g45ek.jinja2
+at91sam9x25ek.jinja2
+at91sam9x35ek.jinja2
+ava.jinja2
+avenger96.jinja2
+avh.jinja2
+b-u585i-iot02a.jinja2
+b2120h410.jinja2
+b2260.jinja2
+base-barebox.jinja2
+base-depthcharge.jinja2
+base-edk2.jinja2
+base-fastboot.jinja2
+base-grub.jinja2
+base-uboot.jinja2
+base.jinja2
+bcm2711-rpi-4-b.jinja2
+bcm2835-rpi-b-rev2.jinja2
+bcm2836-rpi-2-b.jinja2
+bcm2837-rpi-3-b-32.jinja2
+bcm2837-rpi-3-b.jinja2
+beagle-xm.jinja2
+beaglebone-black-barebox.jinja2
+beaglebone-black.jinja2
+cc13x2-launchpad.jinja2
+cc3220SF.jinja2
+cubietruck.jinja2
+cy8ckit-064s0s2-4343w.jinja2
+d02.jinja2
+d03.jinja2
+d2500cc.jinja2
+da850-lcdk.jinja2
+de0-nano-soc.jinja2
+dell-latitude-3445-7520c-skyrim.jinja2
+dell-latitude-5300-8145U-arcada.jinja2
+dell-latitude-5400-4305U-sarien.jinja2
+dell-latitude-5400-8665U-sarien.jinja2
+disco-l475-iot1.jinja2
+docker.jinja2
+dove-cubox.jinja2
+dra7-evm.jinja2
+dragonboard-410c.jinja2
+dragonboard-820c.jinja2
+dragonboard-845c.jinja2
+e850-96.jinja2
+exynos4-5-common.jinja2
+exynos5420-common.jinja2
+frdm-k64f.jinja2
+frdm-kw41z.jinja2
+fsl-ls-common.jinja2
+fsl-ls1012a-rdb.jinja2
+fsl-ls1028a-rdb.jinja2
+fsl-ls1043a-rdb.jinja2
+fsl-ls1046a-frwy.jinja2
+fsl-ls1046a-rdb.jinja2
+fsl-ls1088a-rdb.jinja2
+fsl-ls2088a-rdb.jinja2
+fsl-lx2160a-rdb.jinja2
+fsl-lx2162a-qds.jinja2
+fsl-s32v234sbc.jinja2
+fvp.jinja2
+gemini-ssi1328.jinja2
+hi6220-hikey-bl.jinja2
+hi6220-hikey-r2.jinja2
+hi6220-hikey.jinja2
+hi960-hikey.jinja2
+hifive-unleashed-a00.jinja2
+hifive-unmatched-a00.jinja2
+highbank.jinja2
+hip07-d05.jinja2
+hp-11A-G6-EE-grunt.jinja2
+hp-14-db0003na-grunt.jinja2
+hp-14b-na0052xx-zork.jinja2
+hp-x360-12b-ca0010nr-n4020-octopus.jinja2
+hp-x360-12b-ca0500na-n4000-octopus.jinja2
+hp-x360-14-G1-sona.jinja2
+hp-x360-14a-cb0001xx-zork.jinja2
+hsdk.jinja2
+i945gsex-qs.jinja2
+ifc6410.jinja2
+imx23-olinuxino.jinja2
+imx27-phytec-phycard-s-rdk.jinja2
+imx28-duckbill.jinja2
+imx53-qsrb.jinja2
+imx6dl-riotboard.jinja2
+imx6dl-sabreauto.jinja2
+imx6dl-sabresd.jinja2
+imx6dl-udoo.jinja2
+imx6q-nitrogen6x.jinja2
+imx6q-sabreauto.jinja2
+imx6q-sabrelite.jinja2
+imx6q-sabresd.jinja2
+imx6q-udoo.jinja2
+imx6q-var-dt6customboard.jinja2
+imx6qdl-common.jinja2
+imx6qp-sabreauto.jinja2
+imx6qp-sabresd.jinja2
+imx6qp-wandboard-revd1.jinja2
+imx6sl-evk.jinja2
+imx6sll-evk.jinja2
+imx6sx-sdb.jinja2
+imx6ul-14x14-evk.jinja2
+imx6ul-pico-hobbit.jinja2
+imx6ull-14x14-evk.jinja2
+imx6ull-evk.jinja2
+imx6ulz-14x14-evk.jinja2
+imx6ulz-lite-evk.jinja2
+imx6us7d-common.jinja2
+imx7d-sdb.jinja2
+imx7s-warp.jinja2
+imx7u-common.jinja2
+imx7ulp-evk.jinja2
+imx8dx-mek.jinja2
+imx8dxl-ddr3l-evk.jinja2
+imx8dxl-evk.jinja2
+imx8dxl-phantom-mek.jinja2
+imx8m-common.jinja2
+imx8mm-ddr4-evk.jinja2
+imx8mm-evk.jinja2
+imx8mm-innocomm-wb15-evk.jinja2
+imx8mn-ddr3l-ab2.jinja2
+imx8mn-ddr3l-evk.jinja2
+imx8mn-ddr4-evk.jinja2
+imx8mn-evk.jinja2
+imx8mp-ab2.jinja2
+imx8mp-ddr4-evk.jinja2
+imx8mp-evk.jinja2
+imx8mp-verdin-nonwifi-dahlia.jinja2
+imx8mq-evk.jinja2
+imx8mq-wevk.jinja2
+imx8mq-zii-ultra-zest.jinja2
+imx8q-common.jinja2
+imx8qm-mek.jinja2
+imx8qxp-mek.jinja2
+imx8u-common.jinja2
+imx8ulp-9x9-evk.jinja2
+imx8ulp-evk.jinja2
+imx9-common.jinja2
+imx91-11x11-evk.jinja2
+imx91p-11x11-evk.jinja2
+imx91p-9x9-qsb.jinja2
+imx93-11x11-evk-pmic-pf0900.jinja2
+imx93-11x11-evk.jinja2
+imx93-14x14-evk.jinja2
+imx93-9x9-qsb.jinja2
+imx95-19x19-evk.jinja2
+intel-ixp42x-welltech-epbx100.jinja2
+jetson-tk1.jinja2
+jh7100-beaglev-starlight.jinja2
+jh7100-starfive-visionfive-v1.jinja2
+jh7100-visionfive.jinja2
+juno-uboot.jinja2
+juno-uefi.jinja2
+juno.jinja2
+k3-am625-sk.jinja2
+kirkwood-db-88f6282.jinja2
+kirkwood-openblocks_a7.jinja2
+kontron-bl-imx8mm.jinja2
+kontron-kbox-a-230-ls.jinja2
+kontron-kswitch-d10-mmt-6g-2gs.jinja2
+kontron-kswitch-d10-mmt-8g.jinja2
+kontron-kswitch-d10-mmt-common.jinja2
+kontron-pitx-imx8m.jinja2
+kontron-sl28-common.jinja2
+kontron-sl28-var3-ads2.jinja2
+kv260.jinja2
+kvm.jinja2
+lava-slave-docker.jinja2
+lenovo-TPad-C13-Yoga-zork.jinja2
+lenovo-hr330a-7x33cto1ww-emag.jinja2
+lpcxpresso55s69.jinja2
+ls1021a-twr.jinja2
+lxc.jinja2
+mediatek-8173.jinja2
+meson-axg-s400.jinja2
+meson-g12-common.jinja2
+meson-g12a-sei510.jinja2
+meson-g12a-u200.jinja2
+meson-g12a-x96-max.jinja2
+meson-g12b-a311d-khadas-vim3.jinja2
+meson-g12b-a311d-libretech-cc.jinja2
+meson-g12b-odroid-n2.jinja2
+meson-gx-common.jinja2
+meson-gxbb-nanopi-k2.jinja2
+meson-gxbb-p200.jinja2
+meson-gxl-s805x-libretech-ac.jinja2
+meson-gxl-s805x-p241.jinja2
+meson-gxl-s905d-p230.jinja2
+meson-gxl-s905x-khadas-vim.jinja2
+meson-gxl-s905x-libretech-cc.jinja2
+meson-gxl-s905x-p212.jinja2
+meson-gxm-khadas-vim2.jinja2
+meson-gxm-q200.jinja2
+meson-sm1-khadas-vim3l.jinja2
+meson-sm1-odroid-c4.jinja2
+meson-sm1-s905d3-libretech-cc.jinja2
+meson-sm1-sei610.jinja2
+meson8b-ec100.jinja2
+meson8b-odroidc1.jinja2
+mimxrt1050_evk.jinja2
+minnowboard-common.jinja2
+minnowboard-max-E3825.jinja2
+minnowboard-turbot-E3826.jinja2
+moonshot-m400.jinja2
+morello.jinja2
+mps.jinja2
+mt8173-elm-hana.jinja2
+mt8183-kukui-jacuzzi-juniper-sku16.jinja2
+mt8186-corsola-steelix-sku131072.jinja2
+mt8192-asurada-rev1.jinja2
+mt8192-asurada-spherion-r0.jinja2
+mt8195-cherry-tomato-r2.jinja2
+mt8195-cherry-tomato-r3.jinja2
+musca-a.jinja2
+musca-b.jinja2
+musca-s.jinja2
+musca.jinja2
+mustang-grub-efi.jinja2
+mustang-uefi.jinja2
+mustang.jinja2
+n1sdp.jinja2
+nexus10.jinja2
+nexus4.jinja2
+nexus5x.jinja2
+nexus9.jinja2
+nrf52-nitrogen.jinja2
+nucleo-l476rg.jinja2
+nxp-ls2088.jinja2
+odroid-n2.jinja2
+odroid-x2.jinja2
+odroid-xu3.jinja2
+orion5x-rd88f5182-nas.jinja2
+overdrive.jinja2
+ox820-cloudengines-pogoplug-series-3.jinja2
+panda.jinja2
+pc-k10n78.jinja2
+peach-pi.jinja2
+pixel.jinja2
+poplar.jinja2
+qcom-qdf2400.jinja2
+qcs404-evb-1k.jinja2
+qcs404-evb-4k.jinja2
+qemu-aarch64.jinja2
+qemu.jinja2
+qrb4210-rb2.jinja2
+qrb5165-rb5.jinja2
+r8a7742-iwg21d-q7.jinja2
+r8a7743-iwg20d-q7.jinja2
+r8a7744-iwg20d-q7.jinja2
+r8a7745-iwg22d-sodimm.jinja2
+r8a77470-iwg23s-sbc.jinja2
+r8a774a1-hihope-rzg2m-ex.jinja2
+r8a774b1-hihope-rzg2n-ex.jinja2
+r8a774c0-ek874.jinja2
+r8a774e1-hihope-rzg2h-ex.jinja2
+r8a7791-porter.jinja2
+r8a7795-h3ulcb-kf.jinja2
+r8a7795-salvator-x.jinja2
+r8a77950-ulcb.jinja2
+r8a7796-m3ulcb-kf.jinja2
+r8a7796-m3ulcb.jinja2
+r8a779m1-ulcb.jinja2
+rcar-gen3-common.jinja2
+rk3288-miqi.jinja2
+rk3288-rock2-square.jinja2
+rk3288-veyron-jaq.jinja2
+rk3328-rock64.jinja2
+rk3399-gru-kevin.jinja2
+rk3399-khadas-edge-v.jinja2
+rk3399-puma-haikou.jinja2
+rk3399-roc-pc.jinja2
+rk3399-rock-pi-4b.jinja2
+rk3588-rock-5b.jinja2
+rpi-common.jinja2
+rzg1-common.jinja2
+rzg2-common.jinja2
+rzn1d.jinja2
+s32v234-evb.jinja2
+sama53d.jinja2
+sama5d34ek.jinja2
+sama5d36ek.jinja2
+sc7180-trogdor-kingoftown.jinja2
+sc7180-trogdor-lazor-limozeen.jinja2
+sdm845-mtp.jinja2
+seco-b68.jinja2
+seco-c61.jinja2
+sharkl2.jinja2
+sm8150-mtp.jinja2
+sm8250-mtp.jinja2
+sm8350-hdk.jinja2
+sm8350-mtp.jinja2
+sm8550-hdk.jinja2
+snow.jinja2
+soca9.jinja2
+socfpga-cyclone5-socrates.jinja2
+ssh.jinja2
+stm32-carbon.jinja2
+stm32l562e-dk.jinja2
+stm32mp157a-dhcor-avenger96.jinja2
+stm32mp157c-dk2.jinja2
+stm32mp157c-lxa-mc1.jinja2
+stm32mp157c-lxa-tac-gen1.jinja2
+stm32mp15x-eval.jinja2
+sun4i-a10-olinuxino-lime.jinja2
+sun50i-a64-bananapi-m64.jinja2
+sun50i-a64-pine64-plus.jinja2
+sun50i-h5-libretech-all-h3-cc.jinja2
+sun50i-h5-nanopi-neo-plus2.jinja2
+sun50i-h6-orangepi-3.jinja2
+sun50i-h6-orangepi-one-plus.jinja2
+sun50i-h6-pine-h64-model-b.jinja2
+sun50i-h6-pine-h64.jinja2
+sun5i-a13-olinuxino-micro.jinja2
+sun5i-gr8-chip-pro.jinja2
+sun5i-r8-chip.jinja2
+sun6i-a31-app4-evb1.jinja2
+sun7i-a20-cubieboard2.jinja2
+sun7i-a20-olinuxino-lime2.jinja2
+sun7i-a20-olinuxino-micro.jinja2
+sun8i-a23-evb.jinja2
+sun8i-a33-olinuxino.jinja2
+sun8i-a33-sinlinx-sina33.jinja2
+sun8i-a83t-allwinner-h8homlet-v2.jinja2
+sun8i-a83t-bananapi-m3.jinja2
+sun8i-h2-plus-bananapi-m2-zero.jinja2
+sun8i-h2-plus-libretech-all-h3-cc.jinja2
+sun8i-h2-plus-orangepi-r1.jinja2
+sun8i-h2-plus-orangepi-zero.jinja2
+sun8i-h3-bananapi-m2-plus.jinja2
+sun8i-h3-libretech-all-h3-cc.jinja2
+sun8i-h3-orangepi-pc.jinja2
+sun8i-r40-bananapi-m2-ultra.jinja2
+sun9i-a80-cubieboard4.jinja2
+sunxi-common.jinja2
+synquacer-acpi.jinja2
+synquacer-dtb.jinja2
+synquacer-uboot.jinja2
+synquacer.jinja2
+tc2.jinja2
+tegra124-common.jinja2
+tegra124-nyan-big.jinja2
+thunderx.jinja2
+upsquare.jinja2
+vexpress.jinja2
+x15-bl.jinja2
+x15.jinja2
+x86-atom330.jinja2
+x86-celeron.jinja2
+x86-pentium4.jinja2
+x86-x5-z8350.jinja2
+x86.jinja2
+xilinx-zcu102.jinja2
+root@master:/#
+```
+
+如果这里也没有你想要的 device-type 别急 可以查看 [Adding new device types — LAVA 2024.05 documentation (linaro.org)](https://validation.linaro.org/static/docs/v2/device-integration.html) 里面提供了
+
+### 在其他地方获取,如 gitlab 或正在运行的 lavalab
+
+-----
+
+**Find a similar existing device type**
+
+There are a number of places to check for similar types of device which are already supported in LAVA V2.
+
+1. https://master.lavasoftware.org/scheduler/ 失效
+2. https://staging.validation.linaro.org/scheduler/
+3. https://validation.linaro.org/scheduler/
+4. https://lng.validation.linaro.org/scheduler/ 失效
+5. https://gitlab.com/lava/lava/tree/master/lava_scheduler_app/tests/device-types 可能是转移到其他目录了 我没找到
+
+Check for:
+
+- similar bootloader
+- similar deployment type
+- similar deployment or boot process
+- similar sequence of boot steps
+
+-----
+
+如果都没有的话,很遗憾可能你需要自己编写了
+
+比如我手上的 Licheepi4a
+
+进入正题吧
+
+## 从零编写 device-type
+
+**并不严谨的教学**
+
+这里给出 我编写的 Licheepi4a
+
+```jinja2
+{% extends 'base-uboot.jinja2' %}
+
+{% set uboot_mkimage_arch = 'riscv' %}
+{% set console_device = console_device|default('ttyS0') %}
+{% set baud_rate = baud_rate|default(115200) %}
+
+{% set booti_kernel_addr = '0x00200000' %}
+{% set booti_dtb_addr = '0x03800000' %}
+{% set booti_ramdisk_addr = '0x06000000' %}
+
+{% set uboot_initrd_high = '0xffffffffffffffff' %}
+{% set uboot_fdt_high = '0xffffffffffffffff' %}
+
+{% set boot_character_delay = 100 %}
+
+{% set shutdown_message = 'The system will reboot now!' %}
+{% set bootloader_prompt = bootloader_prompt|default('Light LPI4A#') %}
+
+"tftpboot {KERNEL_ADDR} {KERNEL}",
+"tftpboot {RAMDISK_ADDR} {RAMDISK}",
+"tftpboot {DTB_ADDR} {DTB}"
+```
+
+这是一个 Jinja2 模板,用于生成与 U-Boot 相关的配置文件,特别是为 RISC-V 架构设计的。以下是各部分的详细解释:
+
+### 模板结构
+
+1. **扩展基模板**:
+ ```jinja
+ {% extends 'base-uboot.jinja2' %}
+ ```
+ - 该行表示当前模板从 `base-uboot.jinja2` 继承,根据你当前的开发板以及操作系统要求定,我这里是 uboot
+
+2. **设置变量**:
+ ```jinja
+ {% set uboot_mkimage_arch = 'riscv' %}
+ {% set console_device = console_device|default('ttyS0') %}
+ {% set baud_rate = baud_rate|default(115200) %}
+ ```
+ - `uboot_mkimage_arch`:设置 U-Boot 构建的架构为 `riscv`。
+ - `console_device`:设置控制台设备,默认为 `ttyS0`,如果未传递其他值。
+ - `baud_rate`:设置波特率,默认为 `115200`。
+
+3. **设置内存地址**:
+
+ ```jinja
+ {% set booti_kernel_addr = '0x00202000' %}
+ {% set booti_dtb_addr = '0x03800000' %}
+ {% set booti_ramdisk_addr = '0x06000000' %}
+ ```
+
+ - `booti_kernel_addr`:内核的加载地址。
+ - `booti_dtb_addr`:设备树 Blob (DTB) 的加载地址。
+ - `booti_ramdisk_addr`:初始 RAM 磁盘的加载地址。
+
+ 该如何获取内核加载地址呢,一是可以阅读开发板的官方文档,很遗憾,我在 Licheepi4a 的官方文档 [Lichee Pi 4A - Sipeed Wiki](https://wiki.sipeed.com/hardware/zh/lichee/th1520/lp4a.html) 翻找了很久没找到,但不代表一定没提供
+
+ 所以我采用先将 openEuler 24.03 LTS 安装到 licheepi4a 上, 在 boot 进行过程中查看
+
+ 那么首先要做的就是将 24.03 烧录进入 icheepi4a ,可以查看 openEuler 的官方文档 [RISC-V-LicheePi4A (openeuler.org)](https://docs.openeuler.org/zh/docs/24.03_LTS/docs/Installation/RISC-V-LicheePi4A.html) 下载地址在这里 [openEuler下载 | openEuler ISO镜像 | openEuler社区官网](https://www.openeuler.org/zh/download/?version=openEuler 24.03 LTS)
+
+
+
+ ps : 1.实际上不需要网线 2.注意要区分与 licheepi4a 官方的镜像烧录方式,虽然那个是烧录 debian 的,但是和 openeuler的方式略有不同
+
+
+
+ 烧录完成就可以进行串口连接了,不知道可不可以直接用 type -c 接口进行串口连接,在网络上没检索到相关的信息,这里使用的是
+
+ 官方的 plus调试器
+
+ [Sipeed LicheePi 4A Risc-V TH1520 Linux SBC 开发板 荔枝派-淘宝网 (taobao.com)](https://item.taobao.com/item.htm?id=715508771884&sku_properties=-3%3A-3) ps:非广告
+
+
+
+ 然后将 plus调试器连接到主机上
+
+ 这里会引入一个问题就是 WSL 2 需要和 windows 共享 usb 接口,下文再说
+
+ 串口连接 我在 windows 上使用的是 **MobaXterm** ,只是使用的话可以参考 [嵌入式工程师都在用的全能终端神器—MobaXterm - 知乎 (zhihu.com)](https://zhuanlan.zhihu.com/p/452450152)
+
+ 按下 RST 重启机器 在引导阶段 在 MobaXterm 串口终端中按下任意键 我按的空格,你应该按什么都行 。
+
+ 
+
+ 此时输入 h 可以看到一些帮助
+
+ 我们这里输入 printenv
+
+ ```shell
+ Light LPI4A# printenv
+ aon_ram_addr=0xffffef8000
+ arch=riscv
+ audio_ram_addr=0x32000000
+ baudrate=115200
+ board=light-c910
+ board#=LP
+ board_name=light-c910
+ boot_conf_addr_r=0xc0000000
+ boot_conf_file=/extlinux/extlinux.conf
+ bootcmd=run bootcmd_load; bootslave; sysboot mmc ${mmcdev}:${mmcbootpart} any $boot_conf_addr_r $boot_conf_file;
+ bootcmd_load=run findpart;run load_aon;run load_c906_audio; load mmc ${mmcdev}:${mmcbootpart} $opensbi_addr fw_dynamic.bin
+ bootdelay=2
+ cpu=c9xx
+ dtb_addr=0x03800000
+ eth1addr=48:da:35:60:17:f0
+ ethaddr=48:da:35:60:17:ef
+ fdt_addr_r=0x03800000
+ fdt_high=0xffffffffffffffff
+ fdtcontroladdr=ffba7840
+ fdtfile=thead/th1520-lichee-pi-4a.dtb
+ finduuid=part uuid mmc ${mmcdev}:${mmcpart} uuid
+ fwaddr=0x10000000
+ gpt_partition=gpt write mmc ${mmcdev} $partitions
+ kdump_buf=180M
+ kernel_addr_r=0x00200000
+ load_aon=load mmc ${mmcdev}:${mmcbootpart} $fwaddr light_aon_fpga.bin;cp.b $fwaddr $aon_ram_addr $filesize
+ load_c906_audio=load mmc ${mmcdev}:${mmcbootpart} $fwaddr light_c906_audio.bin;cp.b $fwaddr $audio_ram_addr $filesize
+ mmcbootpart=2
+ mmcdev=0
+ opensbi_addr=0x0
+ partitions=name=table,size=2031KB;name=boot,size=500MiB,type=boot;name=root,size=-,type=linux,uuid=${uuid_rootfsA}
+ pxefile_addr_r=0x00600000
+ ramdisk_addr_r=0x06000000
+ scriptaddr=0x00500000
+ splashimage=0x30000000
+ splashpos=m,m
+ str_ram_addr=0xffe0000000
+ uuid_rootfsA=80a5a8e9-c744-491a-93c1-4f4194fd690a
+ vendor=thead
+
+ Environment size: 1375/131068 bytes
+ ```
+
+ 就可以获取你要的信息啦
+
+4. **设置高地址限制**:
+
+ ```jinja
+ {% set uboot_initrd_high = '0xffffffffffffffff' %}
+ {% set uboot_fdt_high = '0xffffffffffffffff' %}
+ ```
+
+ - `uboot_initrd_high` 和 `uboot_fdt_high`:设置初始 RAM 磁盘和设备树的高地址限制为最大值,表示允许使用的最高地址。
+
+5. **设置 lava 输入字符的间隔**:
+
+ ```jinja2
+ {% set boot_character_delay = 100 %}
+ ```
+
+ - `boot_character_delay`:设置 lava 输入字符的时间,主要是为了模拟人类键盘输入,电脑输入过快可能会造成字符倒置等情况
+
+6. **设置 shudown 提示词**:
+
+ ```jinja2
+ {% set shutdown_message = 'The system will reboot now!' %}
+ ```
+
+ - `shutdown_message`:设置成你的机器的提示词 默认是 ‘ The system is going down for reboot NOW’,lpi4a 不太一致,
+
+ 实际上 lpi4a reboot时 甚至都不输出类似信息。
+
+7. **设置引导提示词**:
+
+ ```jinja2
+ {% set bootloader_prompt = bootloader_prompt|default('Light LPI4A#') %}
+ ```
+
+ - `bootloader_prompt`:lpi4a 是 'Light LPI4A#‘ ,跟随你的被测试硬件
+
+**TFTP 命令**
+
+```jinja
+"tftpboot {KERNEL_ADDR} {KERNEL}",
+"tftpboot {RAMDISK_ADDR} {RAMDISK}",
+"tftpboot {DTB_ADDR} {DTB}"
+```
+- 这些行定义了使用 TFTP 协议从服务器加载内核、RAM 磁盘和设备树的命令:
+ - `tftpboot {KERNEL_ADDR} {KERNEL}`:从 TFTP 服务器下载内核到指定的加载地址。
+ - `tftpboot {RAMDISK_ADDR} {RAMDISK}`:下载初始 RAM 磁盘映像。
+ - `tftpboot {DTB_ADDR} {DTB}`:下载设备树 Blob。
+
+然后就是
+
+## 配置 **board.yaml**
+
+也就是这里
+
+```yaml
+boards:
+ - name: qemu-test
+ type: qemu
+ slave: lab-slave-1
+ - name: Lpi4A
+ type: LicheePi4A_4
+ slave: lab-slave-1
+ connection_command: telnet 192.168.137.1 20000 #这里应该修改为当前的ip
+ pdu_generic: ////远程控制电源的命令
+
+ #(echo "OFF"; sleep 1; echo "ON") | telnet 192.168.1.100 20001 使用串口
+ #(echo "ON") | telnet 192.168.1.100 20001
+ #(echo "OFF") | telnet 192.168.1.100 20001
+ mosquitto_pub -h 192.168.0.158 -t "device/power" -m "RESET"
+ mosquitto_pub -h 192.168.0.158 -t "device/power" -m "ON"
+ mosquitto_pub -h 192.168.0.158 -t "device/power" -m "OFF"
+ uart:
+ idvendor: 0x0403
+ idproduct: 0x6010
+ devpath: "1"
+```
+
+
+
+ps: 测试时 我发现我的连接不上了,排查一大圈 发现是因为 WSL 2 默认情况下 ip 会随着 机器开关机而改变 导致 telnet 设置出现了问题
+
+既然说到 telnet 那么就顺便讲下如何配置
+
+## 配置串口
+
+实际上你用什么串口工具连接设备都行 , 这里写下我的做法
+
+### 1.安装NFS server
+
+```shell
+sudo apt install nfs-kernel-server
+vim /etc/exports //配置NFS共享目录
+/var/lib/lava/dispatcher/tmp *(rw,no_root_squash,no_all_squash,async,no_subtree_check)
+sudo service nfs-kernel-server restart //配置完成后重启NFS server
+```
+
+### 2 安装ser2net
+
+安装 ser2net 为了部署主机通过 telnet 可以连接到测试设备
+
+```shell
+sudo apt install ser2net
+sudo vim /etc/ser2net.yaml //配置串口信息
+```
+
+```shell
+# Find detailed documentation in ser2net.yaml(5)
+# A fully featured configuration file is in
+# /usr/share/doc/ser2net/examples/ser2net.yaml.gz
+#
+# If you find your configuration more useful than this very simple
+# one, please submit it as a bugreport
+
+define: &banner \r\nser2net port \p device \d [\B] (Debian GNU/Linux)\r\n\r\n
+
+connection: &con0827
+ accepter: tcp,20000
+ enable: on
+ options:
+ banner: *banner
+ kickolduser: true
+ telnet-brk-on-sync: true
+ connector: serialdev,
+ /dev/ttyUSB1,
+ 115200n81,local
+connection: &con0828
+ accepter: tcp,20001
+ enable: on
+ options:
+ banner: *banner
+ kickolduser: true
+ telnet-brk-on-sync: true
+ connector: serialdev,
+ /dev/ttyUSB2,
+ 9600n81,local
+```
+
+```shell
+sudo service ser2net restart //重启ser2net service
+```
+
+此时就可以用
+
+```shell
+telnet 192.168.137.1 20000 或 telnet localhost 20000 等方式 访问/dev/ttyUSB1 即 licheepi4a
+```
+
+如果你和我一样使用的是 2 这里就需要共享 windows 的 usb 接口,我的做法是这样
+
+使用 USBIPD-WIN ,可以参考 微软的官方档案 [连接 USB 设备 | Microsoft Learn ](https://learn.microsoft.com/zh-cn/windows//connect-usb) 这里就不在赘述了
+
+既然谈到这里了就顺便解决下开发板的网络问题吧
+
+如果你有路由器当然可以直接连接到到板子上 ,如果你像我一样**寒酸**,只有一台主机和无线网络的话 可以参考 [开发板上网(保姆级教程)_开发板联网-CSDN博客](https://blog.csdn.net/weixin_56862703/article/details/132412188) ,来配置网关使用,让板子使用主机的网络。
+
+## 编写 job
+
+解决了 device-type 的问题还需要解决 job 的问题,最重要的便是如何获取适合 licheepi4a 的 roofts 文件。以及dtb文件
+
+这里给出一个 licheepi4a smoke-test 定义
+
+```yaml
+device_type: LicheePi4A_4
+job_name: licheepi-smoke-test
+context:
+ boot_character_delay: 1000
+ extra_nfsroot_args: ",nolock,nfsvers=3"
+timeouts:
+ job:
+ minutes: 301
+ action:
+ minutes: 300
+ actions:
+ power-off:
+ seconds: 30
+priority: medium
+visibility: public
+metadata:
+ # please change these fields when modifying this job for your own tests.
+# ACTION_BLOCK
+actions:
+- deploy:
+ timeout:
+ minutes: 20
+ to: tftp
+ kernel:
+ url: file:///home/2024ospp-large-files/Image
+ type: image
+ dtb:
+ url: file:///home/2024ospp-large-files/licheepi4a/thead/th1520-lichee-pi-4a.dtb
+ nfsrootfs:
+ url: file:///home/2024ospp-large-files/openeuler-rootfs.tar.gz
+ compression: gz
+- boot:
+ timeout:
+ minutes: 3
+ method: qemu
+ media: tmpfs
+ prompts: ["root@openeuler-riscv64"]
+ auto_login:
+ login_prompt: "localhost login:"
+ username: root
+ password_prompt: "Password:"
+ password: openEuler12#$
+ # TEST_BLOCK
+- test:
+ timeout:
+ minutes: 10
+ definitions:
+ - repository: https://git.linaro.org/lava-team/lava-functional-tests.git
+ from: git
+ path: lava-test-shell/smoke-tests-basic.yaml
+ name: smoke-tests
+```
+
+参考 [lava-docker细节解释 ](./lava-docker细节解释.md) 中 如何编写 ACTION_BLOCK
+
+[NJU Mirror](https://mirrors.nju.edu.cn/openeuler/openEuler-24.03-LTS/embedded_img/riscv64/lpi4a/) 是 openEuler 提供的 Licheepi4a 资源仓库 ,其他镜像仓库也类似
+
+这里的重点在于,嵌入式设备并没有 qemu 所谓的 启动脚本 也没有 image 等资源 需要我们自己构建
+
+### 获取 Image 和 dtbs
+
+构建的方法
+
+```shell
+git clone https://gitee.com/feifei-fertilizer/riscv-kernel.git
+cd riscv-kerner.git
+git checkout OLK-6.6
+```
+
+由于我们只需要 Image 和 dtbs文件
+
+```shell
+make ARCH=riscv CROSS_COMPILE=riscv64-linux-gnu- openeuler_defconfig
+make ARCH=riscv CROSS_COMPILE=riscv64-linux-gnu- -j1 Image dtbs WERROR=n
+```
+
+tips:这里不需要使用 arch/riscv/configs 下的 th1520_defconfig 根据 riscv-kernel 的提交记录 ,已经和 defconfig 合并 ,这里直接使用 openeuler_deconfig 即可,这里 使用 -j1 是为了方便排查错误。
+
+```shell
+feifei@localhost:~/oerv24.03-LTS$ ls ~/riscv-kernel/arch/riscv/configs/
+32-bit.config defconfig nommu_k210_sdcard_defconfig openeuler_defconfig sg2042_defconfig
+64-bit.config nommu_k210_defconfig nommu_virt_defconfig rv32_defconfig th1520_defconfig
+```
+
+完成之后便会在 output 中获得构建的内容
+
+这里我想提一下 可能是我自己环境的问题,构建我花了很长时间,也用了很多工具链,首先是在 ubuntu 22.03 上,直接使用官方仓库下载的 riscv64-linux-gnu-gcc 应该是 gcc 11,出现了一些问题 之后 我又安装了比较新的版本 也试过源码,无果。最后是在 manjaro 上才构建成功的 ,所以我这里提供我的信息 ,如果构建不成功 也许可以参考
+
+```shell
+riscv64-linux-gnu-gcc --version
+riscv64-linux-gnu-gcc (GCC) 14.1.0
+Copyright (C) 2024 Free Software Foundation, Inc.
+This is free software; see the source for copying conditions. There is NO
+warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+```
+
+### 获取 roofts
+
+roofts 文件,可以在 [Nginx Directory (iscas.ac.cn)](https://mirror.iscas.ac.cn/openeuler-sig-riscv/openEuler-RISC-V/testing/2403LTS-test/v1/) 获取,也可以自己手动构建
+
+由于 默认的 reboot 适配有问题 https://lists.lavasoftware.org/archives/list/lava-users@lists.lavasoftware.org/thread/CH3U475AGESVN4LYBUA4YVRFUTHOZ2LD/
+
+## 修改 docker-compose.yml
+
+你需要先了解 docker-compose 中的内容如何生成 , [lava-docker细节解释](./lava-docker细节解释.md) 里有简单的描述
+
+看下我的
+
+```yml
+services:
+ lab-slave-1:
+ build:
+ context: lab-slave-1
+ dns_search: ''
+ device:
+ - /dev/Lpi4A:/dev/Lpi4A #默认是这样的
+ environment:
+ LAVA_DISPATCHER_IP: 192.168.0.158
+ LAVA_MASTER: master
+ hostname: lab-slave-1
+ ports:
+ - 192.168.0.158:69:69/udp
+ - 61950-62000:61950-62000
+ - 80:80
+ volumes:
+ - /home/feifei/ospp/2024ospp-large-files/ubuntu/boot:/boot
+ - /home/feifei/ospp/2024ospp-large-files/ubuntu/modules:/lib/modules
+ - /home/feifei/ospp/2024ospp-large-files:/home/2024ospp-large-files
+ - /var/lib/lava/dispatcher/tmp:/var/lib/lava/dispatcher/tmp
+ master:
+ build:
+ context: master
+ hostname: master
+ ports:
+ - 0.0.0.0:8000:80
+ volumes:
+ - /home/feifei/ospp/2024ospp-large-files/ubuntu/boot:/boot
+ - /home/feifei/ospp/2024ospp-large-files/ubuntu/modules:/lib/modules
+ - /home/feifei/ospp/2024ospp/device-type/Lpi4A.jinja2:/usr/share/lava-server/device-types/Lpi4A.jinja2
+ - /home/feifei/ospp/2024ospp/device-type/LicheePi4A_4.jinja2:/usr/share/lava-server/device-types/LicheePi4A_4.jinja2
+version: '2.4'
+
+```
+
+`dev/Lpi4A:/dev/Lpi4A` 应修改为 `/dev/ttyUSB1:/dev/Lpi4A` 其中 `ttyUSB1` 指的是串口连接的设备号
diff --git "a/doc/tutorials/ospp-kernelci/doc/\347\224\265\346\272\220\346\216\247\345\210\266.md" "b/doc/tutorials/ospp-kernelci/doc/\347\224\265\346\272\220\346\216\247\345\210\266.md"
new file mode 100644
index 0000000000000000000000000000000000000000..779b41b6bedfe363d2f81c01c55742a27d356fc5
--- /dev/null
+++ "b/doc/tutorials/ospp-kernelci/doc/\347\224\265\346\272\220\346\216\247\345\210\266.md"
@@ -0,0 +1,255 @@
+电源控制并不是 **board.yaml** 的必选项,但总有需要的情形
+
+这里我给出两种控制的方案
+
+## **1.使用 mqtt + esp8266**
+
+### 配置 Mosquitto 服务
+
+安装 mqtt sever, 这里使用的是 mosquitto,安装方法可以参考 https://www.vultr.com/docs/install-mosquitto-mqtt-broker-on-ubuntu-20-04-server/
+
+这里将 Mosquitto 服务器 安装到 主机上
+
+```shell
+sudo apt update
+sudo apt install mosquitto mosquitto-clients
+sudo systemctl enable mosquitto.service
+```
+
+配置mosquitto, 创建配置文件
+
+```shell
+sudo vim /etc/mosquitto/conf.d/default.conf
+```
+
+创建 /etc/mosquitto/passwd 文件
+
+````shell
+sudo vim /etc/mosquitto/passwd
+````
+
+编辑用户名密码
+
+````shell
+: //用户名:密码
+````
+
+使用mosquitto_passwd将密码文件 /etc/mosquitto/passwd 加密
+
+````shell
+sudo mosquitto_passwd -U /etc/mosquitto/passwd
+````
+
+查看是否加密成功
+
+````shell
+sudo cat /etc/mosquitto/passwd
+````
+
+配置完成后重启mosquitto service
+
+````shell
+sudo systemctl restart mosquitto
+````
+
+### 向 esp8266 烧录控制程序
+
+安装 Arduino IDE
+
+然后可以参考 [ESP8266+继电器+MQTT+VUE 实现远程开关灯_esp8266-01s电路图-CSDN博客](https://blog.csdn.net/qq_31762741/article/details/132635616) 和[ESP8266 + MQTT :如何实现 LED 灯的远程控制_esp8266 + mqtt实现远程控制led灯-CSDN博客](https://blog.csdn.net/emqx_broker/article/details/112716509)
+
+```c
+#include
+#include
+
+// WiFi 配置
+const char* ssid = "feifei_cpe"; // 替换为你的 WiFi SSID
+const char* password = "feifei0827"; // 替换为你的 WiFi 密码
+
+// MQTT 服务器配置
+const char* mqtt_server = "192.168.0.158"; // 替换为您的 MQTT 服务器地址
+const char* mqtt_topic = "device/power"; // 控制主题
+
+// GPIO 引脚
+const int relayPin = 4; // 继电器控制引脚
+
+WiFiClient espClient;
+PubSubClient client(espClient);
+
+void setup() {
+ Serial.begin(115200);
+ pinMode(relayPin, OUTPUT);
+ digitalWrite(relayPin, LOW); // 初始状态关闭继电器
+
+ // 连接到 WiFi
+ WiFi.begin(ssid, password);
+ while (WiFi.status() != WL_CONNECTED) {
+ delay(1000);
+ Serial.println("连接中...");
+ }
+ Serial.println("WiFi 连接成功");
+
+ // 设置 MQTT 服务器
+ client.setServer(mqtt_server, 1883);
+ client.setCallback(callback);
+
+ // 连接到 MQTT
+ reconnect();
+}
+
+void loop() {
+ if (!client.connected()) {
+ reconnect();
+ }
+ client.loop();
+}
+
+// MQTT 消息回调函数
+void callback(char* topic, byte* payload, unsigned int length) {
+ String message;
+ for (int i = 0; i < length; i++) {
+ message += (char)payload[i];
+ }
+
+ if (message == "ON") {
+ digitalWrite(relayPin, HIGH); // 打开继电器
+ Serial.println("电源已打开");
+ } else if (message == "OFF") {
+ digitalWrite(relayPin, LOW); // 关闭继电器
+ Serial.println("电源已关闭");
+ } else if (message == "RESET") {
+ Serial.println("重置设备...");
+ digitalWrite(relayPin, LOW); // 关闭继电器
+ Serial.println("电源已关闭");
+ delay(500);
+ digitalWrite(relayPin, HIGH); // 打开继电器
+ Serial.println("电源已打开");
+ }
+}
+
+// 连接到 MQTT 服务器
+void reconnect() {
+ while (!client.connected()) {
+ Serial.print("连接到 MQTT...");
+ if (client.connect("ESP8266Client")) {
+ Serial.println("连接成功");
+ client.subscribe(mqtt_topic);
+ } else {
+ Serial.print("失败,状态码=");
+ Serial.print(client.state());
+ delay(2000);
+ }
+ }
+}
+```
+
+只是一个简单的电源控制函数,也只针对了一个继电器的情况,暂时也没有复用性
+
+```shell
+mosquitto_pub -h 192.168.0.158 -t "device/power" -m "RESET"
+mosquitto_pub -h 192.168.0.158 -t "device/power" -m "ON"
+mosquitto_pub -h 192.168.0.158 -t "device/power" -m "OFF"
+```
+
+可以通过这个控制 继电器
+
+将安装 mosquitto-clients 的脚本映射到 master 和 salve 机器中 ,就可以远程控制继电器了
+
+**存在的问题**
+
+我买的 esp8266 不支持 5G 频段,这让我排查了很久,当然你可以买支持 5g 频段的类似 wifi 开发板,**如果你看到这里请注意**
+
+这里需要 master 和 slave 的环境中都有 mosquitto-clients
+
+我的方法比较笨就是 在构建好的 master 和 slave 的 dockerfile 中加入
+
+```dockerfile
+RUN apt-get update && \
+ apt-get install -y mosquitto-clients && \
+ apt-get clean && \
+ rm -rf /var/lib/apt/lists/*
+
+COPY /etc/mosquitto/mosquitto.conf /etc/mosquitto/mosquitto.conf
+```
+
+还要记得要将 out/put 下的 docker compose 中的
+
+```yml
+services:
+ lab-slave-1:
+ build:
+ context: lab-slave-1
+ devices:
+ - /dev/ttyUSB1:/dev/Lpi4A-
+ dns_search: ''
+ environment:
+ LAVA_DISPATCHER_IP: 127.0.0.1
+ LAVA_MASTER: master
+ hostname: lab-slave-1
+ ports:
+ - 127.0.0.1:69:69/udp
+ - 61950-62000:61950-62000
+ - 80:80
+ volumes:
+ - /home/feifei/ospp/2024ospp-large-files/ubuntu/boot:/boot
+ - /home/feifei/ospp/2024ospp-large-files/ubuntu/modules:/lib/modules
+ - /home/feifei/ospp/2024ospp-large-files:/home/2024ospp-large-files
+ - /var/lib/lava/dispatcher/tmp:/var/lib/lava/dispatcher/tmp
+ - /usr/bin:/usr/bin/mosquitto_clients # 映射整个 bin 目录
+ master:
+ build:
+ context: master
+ hostname: master
+ ports:
+ - 0.0.0.0:8000:80
+ volumes:
+ - /home/feifei/ospp/2024ospp-large-files/ubuntu/boot:/boot
+ - /home/feifei/ospp/2024ospp-large-files/ubuntu/modules:/lib/modules
+ - /home/feifei/ospp/2024ospp/device-type/Lpi4A.jinja2:/usr/share/lava-server/device-types/Lpi4A.jinja2
+ - /usr/bin:/usr/bin/mosquitto_clients # 映射整个 bin 目录
+```
+
+
+
+## 2.使用其他开发板 + 串口
+
+1. 我使用了 Arduino uno3 ,实际上都差不多 毕竟都只是使用了最简单的 gpio ,烧录方法和 esp8266 类似,由于没用到 mqtt库反而更简单,然后直接让 slave 与 Arduino uno3 串口通信来控制继电器 ,缺点在于 master 无法直接控制 slave 连接的设备的电源,需要和 slave 通信间接控制,当连接的设备多的时候 显然不太好控制
+
+ 和 esp8266 的类似
+
+ ```c
+ // 定义继电器连接的引脚
+ const int relayPin = 4;
+
+ void setup() {
+ // 初始化继电器引脚为输出模式
+ pinMode(relayPin, OUTPUT);
+ // 初始状态为关闭继电器
+ digitalWrite(relayPin, LOW);
+ }
+
+ void loop() {
+ // 打开继电器
+ digitalWrite(relayPin, HIGH);
+ Serial.println("Relay ON");
+ delay(1000); // 延时1秒
+
+ // 关闭继电器
+ digitalWrite(relayPin, LOW);
+ Serial.println("Relay OFF");
+ delay(1000); // 延时1秒
+ }
+ ```
+
+ ```shell
+ (echo "OFF"; sleep 1; echo "ON") | telnet 192.168.0.158 20001
+ (echo "ON") | telnet 192.168.0.158 20001
+ (echo "OFF") | telnet 192.168.0.158 20001
+ ```
+
+
+
+2. 使用了 canmv-k230 v1.1,由于我想整个活,尝试使用他的针脚 ,然而首先官方没提供 针脚图与实际针脚的对应关系图,其次由于canmv-k230 的针脚有多个功能 ,所以需要编辑该针脚的功能,调用基本的 gpio 功能,但由于上面提到的**没有针脚图**,我根本不知道 我写的程序能否正常运行,更不知道对应的针脚,穷举也不行。官方文档提供的 api 也不行,倒腾了两三天最后选择投降,中间还麻烦懂硬件和嵌入式的朋友帮我找找资料,无果。
+
+到这里就做好了最基础的电源控制啦
+
diff --git "a/doc/tutorials/ospp-kernelci/doc/\347\274\226\345\206\231job\345\222\214testcase.md" "b/doc/tutorials/ospp-kernelci/doc/\347\274\226\345\206\231job\345\222\214testcase.md"
new file mode 100644
index 0000000000000000000000000000000000000000..55696ce3b3d3c526b0fec7d17707190036179495
--- /dev/null
+++ "b/doc/tutorials/ospp-kernelci/doc/\347\274\226\345\206\231job\345\222\214testcase.md"
@@ -0,0 +1,412 @@
+## job 模板
+
+这里有几点建议
+
+一,要查看官方文档,从那里可以了解到一些 job 如何编写
+
+二,查看源码,这里包括 device-type 的源码,要查看你想编写的 板子的 device-type 以及 它是由哪些扩展来的, 大部分都是 uboot ,而 uboot 又是由 base 扩展而来。可以通过了解这些来查看你的 job 可以填写那些参数
+
+三,可以直接去查看他人已有的 job ,很多启动命令是不常用,甚至连官网的文档都没提到的,比如 soft_reboot
+
+四,尝试直接运行你的 job ,lava 会给出一些提示 (不符合语法的话,是过不了 lava 的检测的 ),可以按照提示来 我认为比较重要的部分是从 提供 Image 根文件系统等资源,到 boot 启动这个部分, 在之前的章节也有过介绍。你可以观察 lava 的运作方式 ( lava 运行会输出较为完整的 log ) ,来按需修改你的 job 。最后达成你的目的
+
+-----
+
+官网建议大家从 qemu 入手,这里给出官网的最基础的 job 模板 以及一些字段的解释
+
+```yaml
+# Your first LAVA JOB definition for an x86_64 QEMU
+device_type: qemu
+#一个标签,必须与要向其提交此作业的实例上声明的设备类型匹配。每种设备类型都可以有一个或多个可用设备。在本例中为 qemu
+job_name: QEMU pipeline, first job
+#此作业的自由文本名称。此名称在服务器端表中使用允许使用任何有效的 YAML 字符串,因此逗号、大写和空格都可以
+timeouts:
+ job:
+ minutes: 15
+ action:
+ minutes: 5
+ connection:
+ minutes: 2
+# 在 LAVA 测试作业中可能会出现一系列问题,因此测试编写者需要指示作业的某些部分应该花费多长时间
+priority: medium
+#支持 [0, 100] 中的任何整数。还提供三个快捷键:high(100)、medium(50)和low(0)。调度程序在对队列进行排序时会考虑作业优先级
+visibility: public
+#支持 public、personal 和 group 的值,控制允许查看作业和作业生成的结果的人员。这包括结果是否可用于查询和图表
+
+# context allows specific values to be overridden or included
+context:
+ # tell the qemu template which architecture is being tested
+ # the template uses that to ensure that qemu-system-x86_64 is executed.
+ arch: amd64
+#并非所有测试作业都会使用作业上下文,它可以覆盖某些服务器端设备配置模板。在这种情况下,arch: amd64 将模板设置为在启动仿真时使用 qemu-system-x86_64 可执行文件
+metadata:
+ # please change these fields when modifying this job for your own tests.
+ docs-source: first-job
+ docs-filename: qemu-pipeline-first-job.yaml
+#一旦测试作业成为自动提交或 CI循环的一部分,就需要使用元数据来标识每个提交,提供有关与上次测试作业相比发生的确切变化的信息,以及有关其他用户如何修改测试作业构件以扩展或调试结果的信息
+# ACTION_BLOCK
+actions:
+# DEPLOY_BLOCK
+- deploy:
+#下载启动设备所需的文件,并准备要在测试操作中运行的文件叠加层
+ timeout:
+ minutes: 5
+ to: tmpfs
+ images:
+ rootfs:
+ image_arg: -drive format=raw,file={rootfs}
+ url: https://images.validation.linaro.org/kvm/standard/stretch-2.img.gz
+ compression: gz
+#deploy 支持本地和网络资源多种格式 也可以选择
+# BOOT_BLOCK
+- boot:
+#指定启动设备的方法和提示符,这些提示将指示设备是否被视为已正确启动
+ timeout:
+ minutes: 2
+ method: qemu
+ media: tmpfs
+ prompts: ["root@debian:"]
+ auto_login:
+ login_prompt: "login:"
+ username: root
+
+# TEST_BLOCK
+- test:
+ timeout:
+ minutes: 5
+ definitions:
+ - repository: http://git.linaro.org/lava-team/lava-functional-tests.git
+ from: git
+ path: lava-test-shell/smoke-tests-basic.yaml
+ name: smoke-tests
+ - repository: https://git.linaro.org/lava-team/lava-functional-tests.git
+ from: git
+ path: lava-test-shell/single-node/singlenode03.yaml
+ name: singlenode-advanced
+```
+
+deploy 可以用的文件有网络资源和本地资源
+
+网络资源:输入其网络资源的 url 即可
+
+本地资源,首先要将其映射到 lava slave 容器中,在 [lava-docker细节解释 ](./lava-docker细节解释.md) 中有提到过如何映射 ( 修改 lavalab-gen.py )
+
+
+
+第 462 行的内容则是 映射主机的文件到 docker 容器,这里我将主机的 `/home/feifei/ospp/2024ospp-large-files` 映射为容器的 `/home/2024ospp-large-files`
+
+所以 lava job 在编写时就要写容器内部的路径 如下面这样
+
+```yaml
+- deploy:
+ timeout:
+ minutes: 20
+ to: tmpfs
+ images:
+ kernel:
+ image_arg: -kernel {kernel}
+ url: file:///home/2024ospp-large-files/Image
+ rootfs:
+ image_arg: -drive file={rootfs},format=raw,id=hd0
+ url: file:///home/2024ospp-large-files/openeuler-rootfs.img
+```
+
+一些实际可能遇到的问题在 [lava-docker细节解释 ](./lava-docker细节解释.md) 和 [未提供的设备类型-自定义设备类型-Licheepi 4a](./未提供的设备类型-自定义设备类型-Lip4a.md) 中有涉及过一部分
+
+deploy 和 boot 的 参数很多
+
+boot 更详细内容可以查看 [Boot Action Reference — LAVA 2024.09 documentation (lavasoftware.org)](https://docs.lavasoftware.org/lava/actions-boot.html#index-13)
+
+deploy 可以查看[部署操作参考 — LAVA 2024.09 文档 --- Deploy Action Reference — LAVA 2024.09 documentation (lavasoftware.org)](https://docs.lavasoftware.org/lava/actions-deploy.html#index-3)
+
+### 可选与必选字段
+
+#### 必选字段
+
+1. **device_type**:
+2. **job_name**:
+3. **timeouts**:
+4. **actions**:
+
+5. **at least one action block**:
+
+#### 可选字段
+
+1. **priority**:
+2. **visibility**:
+3. **context**:
+4. **metadata**:
+5. **timeout** (在各个块中):
+
+ - 可以选择在每个 `deploy`、`boot` 和 `test` 块中定义超时
+6. **images** (在 `deploy` 块中):
+- 测试已经配置好的设备时
+7. **prompts** (在 `boot` 块中):
+8. **auto_login** (在 `boot` 块中):
+9. **definitions** (在 `test` 块中):
+
+## 获取测试用例的两种方式
+
+### 1.首先是自己编写
+
+可以查看 [Glossary of terms — LAVA 2024.05 documentation (lavasoftware.org)](https://docs.lavasoftware.org/lava/glossary.html#term-job-definition)
+
+```yaml
+# TEST_BLOCK
+- test:
+ timeout:
+ minutes: 600
+ definitions:
+ - repository:
+ metadata:
+ format: Lava-Test Test Definition 1.0
+ run:
+ steps:
+ - yum install -y git make gcc flex bison clang
+ - df -h
+ - cd /root
+ - git clone https://gitee.com/feifei-fertilizer/riscv-kernel.git
+ - cd riscv-kerner.git
+ - git checkout OLK-6.6
+ - make defconfig
+ - make -C tools/testing/selftests
+ - make -C tools/testing/selftests TARGETS=clone3 run_tests
+ from: inline #表示在当前主机上
+ name: kselftest-inline
+ path: inline/kselftest.yaml
+```
+
+这是一个基于内核源码的 **kselftest**
+
+from 字段写成 inline
+
+然后填入一些描述 definitions, name 等
+
+steps 字段 填入你需要的命令即可
+
+这其实与你直接在机器上 敲命令没什么区别,重要的当然就是你要确保你自己在机器上可以跑通
+
+可以注意下的是 name 与 path 字段最好相关 比如这里 name 和 path 都是 kselftest
+
+### 2.基于test-definitions
+
+可以通过 clone [Linaro/test-definitions: Test definitions work with and without LAVA (github.com)](https://github.com/Linaro/test-definitions) 来直接使用其准备好的测试
+
+根据描述官方文档描述 [test-definitions/docs/index.md 在 master ·Linaro/测试定义 (github.com)](https://github.com/Linaro/test-definitions/blob/master/docs/index.md)
+
+这里给出 ltp.yaml的内容 https://github.com/Linaro/test-definitions/blob/master/automated/linux/ltp/ltp.yaml
+
+```yaml
+metadata:
+ name: ltp
+ format: "Lava-Test Test Definition 1.0"
+ description: "Run LTP test suite on Ubuntu"
+ maintainer:
+ - milosz.wasilewski@linaro.org
+ - fathi.boudra@linaro.org
+ os:
+ - ubuntu
+ scope:
+ - functional
+ devices:
+ - all
+params:
+ TST_CMDFILES: syscalls,mm,math,timers,fcntl-locktests,ipc,fsx,fs,hugetlb,io,nptl,pty,containers,fs_bind,filecaps,admin_tools,connectors
+
+ # SKIPFILE can be a filename from dir ./automated/linux/ltp/, an http URL,
+ # or a skipgen style yaml file.
+ # Examples:
+ # SKIPFILE: "skipfile-lsk-juno" # is a known file present in
+ # # dir ./automated/linux/ltp/
+ # SKIPFILE: "http://people.linaro.org/~naresh.kamboju/skipfile"
+ # SKIPFILE: "skipfile-lkft.yaml" # yaml file that will be parsed with
+ # # skipgen. Must use "yaml" extention.
+ # NOTE: busybox wget may not work with https link so prefer to use http
+ SKIPFILE: ""
+
+ # BOARD, BRANCH, and ENVIRONMENT may be specified and may be used when
+ # generating a skipfile using a yaml skipfile and skipgen.
+ BOARD: ""
+ BRANCH: ""
+ LTP_TMPDIR: "/ltp-tmp"
+ LTP_INSTALL_PATH: "/opt/ltp"
+ ENVIRONMENT: ""
+
+ SKIP_INSTALL: false
+ # Slow machines need more timeout Default is 5min and multiply * TIMEOUT_MULTIPLIER
+ TIMEOUT_MULTIPLIER: 3
+ # root's password. Needed by ltp/su01.
+ ROOT_PASSWD: root
+
+ # New kirk runner (https://github.com/linux-test-project/kirk.git)
+ # Needs to be installed onto the rootfs.
+ # Set RUNNER to full path to kik or to kirk if its in the PATH.
+ RUNNER: ""
+
+ # If the following parameter is set, then the LTP suite is
+ # cloned and used unconditionally. In particular, the version
+ # of the suite is set to the commit pointed to by the
+ # parameter. A simple choice for the value of the parameter
+ # is, e.g., HEAD. If, instead, the parameter is
+ # not set, then the suite present in TEST_DIR is used.
+ # LTP version
+ LTP_VERSION: ""
+
+ # If next parameter is set, then the LTP suite is cloned
+ # from the URL in TEST_GIT_URL. Otherwise it is cloned from the
+ # standard repository for the suite. Note that cloning is done
+ # only if LTP_VERSION is not empty
+ TEST_GIT_URL: ""
+
+ # If next parameter is set, then the LTP suite is cloned to or
+ # looked for in TEST_DIR. Otherwise it is cloned to $(pwd)/ltp
+ TEST_DIR: ""
+
+ # BUILD_FROM_TAR, if you want to download and build LTP from
+ # a released tarball, set BUILD_FROM_TAR to 'true'. You have to
+ # specify the LTP_VERSION to a release e.g., 20180926.
+ BUILD_FROM_TAR: "false"
+
+ # Number of shards that will be done, default 1 which is the same as no sharding.
+ SHARD_NUMBER: 1
+
+ # Which bucket to run, default '1' which is the same as no sharding, run it as LTP upstream decides.
+ SHARD_INDEX: 1
+run:
+ steps:
+ - cd ./automated/linux/ltp/
+ - ./ltp.sh -T "${TST_CMDFILES}" -s "${SKIP_INSTALL}" -v "${LTP_VERSION}" -M "${TIMEOUT_MULTIPLIER}" -R "${ROOT_PASSWD}" -r "${RUNNER}" -b "${BOARD}" -d "${LTP_TMPDIR}" -g "${BRANCH}" -e "${ENVIRONMENT}" -i "${LTP_INSTALL_PATH}" -S "${SKIPFILE}" -p "${TEST_DIR}" -u "${TEST_GIT_URL}" -t "${BUILD_FROM_TAR}" -n "${SHARD_NUMBER}" -c "${SHARD_INDEX}"
+ - ../../utils/send-to-lava.sh ./output/result.txt
+```
+
+看下有哪些部分组成
+
+1. 元数据部分
+
+- metadata
+
+ : 描述测试用例的基本信息。
+
+ - **name**: 测试用例的名称,`ltp`。
+ - **format**: 指定测试定义的格式版本,这里是 "Lava-Test Test Definition 1.0"。
+ - 等
+
+2. 参数部分
+
+- params
+
+ : 定义测试用例的参数,以下是主要参数的说明:
+
+ - **TST_CMDFILES**: 指定要运行的 LTP 测试命令文件列表。
+ - **SKIPFILE**: 可选的跳过文件,可以是本地文件、HTTP URL 或 YAML 文件,用于指定应跳过的测试
+ - **等**
+
+3. 运行步骤
+
+run 字段
+
+- **steps**: 定义测试执行的步骤,包含以下内容:
+ 1. `cd ./automated/linux/ltp/`: 切换到 LTP 测试的目录。
+ 2. `./ltp.sh ...`: 运行 `ltp.sh` 脚本,传入多个参数以配置测试运行。
+ 3. `../../utils/send-to-lava.sh ./output/result.txt`: 调用一个脚本,将测试结果发送到 Lava 服务器,结果存储在 `./output/result.txt` 文件中。
+
+我们在 job 中调用 可以按照以下格式来
+
+```yaml
+- test:
+ timeout:
+ minutes: 600
+ definitions:
+ - repository: https://github.com/Linaro/test-definitions.git
+ from: git
+ path: automated/linux/ltp/ltp.yaml
+ parameters:
+ TST_CMDFILES: syscalls
+ SKIPFILE: skipfile-lkft.yaml
+ BOARD: qemu
+ BRANCH: master
+ ENVIRONMENT: production
+ TIMEOUT_MULTIPLIER: '30'
+ ROOT_PASSWD: openEuler12#$
+ BUILD_FROM_TAR: true
+ LTP_VERSION: 20240524
+ LTP_TMPDIR: /scratch
+ name: ltp-syscalls-tests
+```
+
+repository: 制定了地址
+
+from:表示来源是 git
+
+parameters 表示提供的参数 参数都有哪些,对应 automated/linux/ltp/ltp.yaml 文件中的预留的 params
+
+按需填写你的信息即可 ,脚本会自动化的把这些参数提供给 test-definitions 中对应的 sh 脚本,来替你执行 shell 命令
+
+可以对照着 inline 的测试用例查看
+
+## 测试用例
+
+通过观察 test-definitions 提供的 测试用例,
+
+大致的模板是这样的
+
+```yaml
+metadata:
+ name: <测试用例名称>
+ format: "Lava-Test Test Definition 1.0" # 或其他格式
+ description: "<测试用例描述>"
+ maintainer:
+ - <维护者邮箱>
+ os:
+ - <支持的操作系统>
+ scope:
+ - <测试范围>
+ devices:
+ - <支持的设备或设备类型>
+
+params:
+ <参数名>: <默认值或说明>
+ ...
+
+run:
+ steps:
+ - <要执行的命令或脚本>
+ - <后续步骤>
+ ...
+```
+LAVA 测试定义包括 Metadata,params,run 三个不可缺少的字段 ,其中 Metadata 中有可选字段和必选字段
+
+- 必选
+
+ format
+
+ name
+
+ description
+
+ version : "1.0" 如果文件不受版本控制(即不在 git 存储库中),则还必须在元数据中指定文件的**版本**
+
+- 可选
+
+ maintainer
+
+ os
+
+ scope
+
+ devices
+
+
+steps 可以直接 使用命令,也可以像 ltp.yaml 一样 放在 sh 脚本中
+
+对于跑起来一个测试重要的是 完善 params 字段 和 run 字段 ,但对于后期的交互和维护来说 其他的字段也是必不可少的
+
+详细可以查看 [编写 Lava-Test 测试定义 1.0 — LAVA 2024.09 文档 --- Writing a Lava-Test Test Definition 1.0 — LAVA 2024.09 documentation](https://docs.lavasoftware.org/lava/writing-tests.html#test-definition-yaml)
+
+## 一些提示
+
+lava会实时检查 device-type 和 job 的状态 ,这些不符合语法 的时候无法正常进行测试,很长一段时间我都以为更新 device-type 需要重启 lava 服务,浪费了很长时间,后来发现不需要,大家在线修改即可。
+
+我在整个项目过程中困扰我最多的并不是项目本身,而是我个人工作设备所带来的问题,真的很不推荐大家使用虚拟环境来做 lava 相关的工作。
+
+了解 uboot 相关知识可能可以给你带来一些帮助,建议在工作前可以细致的了解下 启动流程相关知识。
\ No newline at end of file
diff --git "a/doc/tutorials/ospp-kernelci/doc/\351\205\215\347\275\256jenkins.md" "b/doc/tutorials/ospp-kernelci/doc/\351\205\215\347\275\256jenkins.md"
new file mode 100644
index 0000000000000000000000000000000000000000..76d68fe96ace47ef00168b76eba84ded004446a7
--- /dev/null
+++ "b/doc/tutorials/ospp-kernelci/doc/\351\205\215\347\275\256jenkins.md"
@@ -0,0 +1,889 @@
+# 配置 jenkins
+
+首先要安装 jenkins ,查看官方文档吧
+
+安装 jenkins 有多种方式,按照你的需求来 我这边直接使用 jar 包
+
+在 Jenkins.war 同级目录下使用 ` java -jar jenkins.war --httpPort=8080` 即可
+
+## jenkins 安装插件
+
+这里演示如何安装插件 **HTTP Request Plugin**
+
+
+
+
+
+进入界面后点击**Available plugins** ,搜索 **HTTP Request Plugin** 点击安装
+
+## jenkins 配置 Credentials
+
+为了便于管理密钥,也为了安全考虑 ,这里要配置 Credentials
+
+
+
+
+
+
+
+可以看到,有很多种形式,后面我们会配置 Secret text 和 SSH Username with private key
+
+
+
+## jenkins 触发 lava job
+
+### REST API
+
+这里使用 REST API 做例子,在主机中输入
+
+```shell
+curl -d '{"username":"admin", "password":"v"}' -H "Content-Type: application/json" -X POST "http://localhost:8000/api/v0.2/token/"
+#可以得到如下结果
+{"token":"adminlavatoken"}
+```
+
+其实就是使用 curl 向 LAVA API 发送 POST 请求
+
+如果你对之前的章节还有印象会发现这个 token 正是 **boards.yaml** 中设置的
+
+此外你还可以重新提交一个 job,这里是 job 15,他便会按照 job 15 的定义 重新提交一遍
+
+```shell
+curl -X POST \
+ "http://localhost:8000/api/v0.2/jobs/15/resubmit/" \
+ -H "Authorization: Token adminlavatoken"
+```
+
+他将会返回一串报文
+
+```shell
+{"message":"job(s) successfully submitted","job_ids":[33]}
+```
+
+表明 job 的提交情况和重新提交的 job id
+
+也可以直接提交一个新的 job
+
+```shell
+curl -x "" -v -H "Authorization: Token adminlavatoken" \
+ -d '{
+ "definition": "{\"device_type\":\"qemu\",\"job_name\":\"your-testjob-name\",\"timeouts\":{\"job\":{\"minutes\":30},\"action\":{\"minutes\":20},\"connection\":{\"minutes\":5}},\"priority\":\"medium\",\"visibility\":\"public\",\"context\":{\"arch\":\"riscv64\",\"machine\":\"virt\",\"guestfs_interface\":\"virtio\",\"extra_options\":[\"-nographic\",\"-smp 4\",\"-m 8G\"]},\"metadata\":{\"format\":\"Lava-Test Test Definition 1.0\",\"name\":\"your-testjob-name\",\"description\":\"Description of the test job\",\"version\":\"1.0\"},\"actions\":[{\"deploy\":{\"timeout\":{\"minutes\":20},\"to\":\"tmpfs\",\"images\":{\"kernel_1\":{\"image_arg\":\"-blockdev node-name=pflash0,driver=file,read-only=on,filename={kernel_1}\",\"url\":\"file:///path/to/kernel1\"}}}}]}"
+ }' \
+ -H "Content-Type: application/json" \
+ -X POST "http://127.0.0.1:8000/api/v0.2/jobs/"
+```
+
+这是它返回的报文
+
+```shell
+* Trying 127.0.0.1:8000...
+* Connected to 127.0.0.1 (127.0.0.1) port 8000 (#0)
+> POST /api/v0.2/jobs/ HTTP/1.1
+> Host: 127.0.0.1:8000
+> User-Agent: curl/7.81.0
+> Accept: */*
+> Authorization: Token adminlavatoken
+> Content-Type: application/json
+> Content-Length: 784
+>
+* Mark bundle as not supporting multiuse
+< HTTP/1.1 201 Created
+< Date: Mon, 14 Oct 2024 09:50:19 GMT
+< Server: gunicorn
+< Content-Type: application/json
+< Vary: Accept,Cookie
+< Allow: GET, POST, HEAD, OPTIONS
+< X-Frame-Options: DENY
+< Content-Length: 58
+< X-Content-Type-Options: nosniff
+< X-XSS-Protection: 1; mode=block
+< Referrer-Policy: same-origin
+<
+* Connection #0 to host 127.0.0.1 left intact
+{"message":"job(s) successfully submitted","job_ids":[34]}
+```
+
+这里你就完成了通过 REST API 查看 job 和 重新提交 job 的工作,当然他做更多是 详细可以查看 https://docs.lavasoftware.org/lava/data-export.html
+
+### pipeline
+
+这里给出一个简单的 pipeline
+
+```
+pipeline {
+ agent any
+
+ stages {
+ stage('Fetch Job Status') {
+ steps {
+ script {
+ def jobId = "2" // 替换为实际的 Job ID
+ def response = httpRequest(
+ url: "http://127.0.0.1:8000/api/v0.2/jobs/${jobId}", // 获取作业状态
+ httpMode: 'GET',
+ authentication: 'lava-api-token'
+ )
+ echo "Job Status: ${response.content}"
+ }
+ }
+ }
+ }
+}
+```
+
+从描述可以看出 这是一个获取 lava job status 的 pipeline
+
+其中 `authentication: 'lava-api-token'` 是 jenkins 中的 Credentials 配置
+
+这是根据 REST API 编写的,当然你也可以选择直接在 pipeline 中执行 `sh "curl -d '{"username":"admin", "password":"v"}' -H "Content-Type: application/json" -X POST "http://localhost:8000/api/v0.2/token/" "`
+
+这是一个触发已有任务的 pipeline
+
+```
+pipeline {
+ agent any
+
+ stages {
+ stage('Resubmit Job') {
+ steps {
+ script {
+ def jobId = "4" // 替换为实际的 Job ID
+ def token = "adminlavatoken" // 替换为你的 API token
+
+ def response = httpRequest(
+ url: "http://localhost:8000/api/v0.2/jobs/${jobId}/resubmit/",
+ httpMode: 'POST',
+ customHeaders: [[name: 'Authorization', value: "Token ${token}"]]
+ )
+ echo "Response: ${response.content}"
+ }
+ }
+ }
+ }
+}
+```
+
+可以注意到这里拿 token 直接放在了 pipeline 里,显然是不安全的 后面会解决这个问题
+
+可以参考官方文档 [创建您的第一个Pipeline (jenkins.io)](https://www.jenkins.io/zh/doc/pipeline/tour/hello-world/) 来了解如何创建一个 pipeline
+
+至此,完成了 lava 与 jenkins 使用 pipeline 交互的部分
+
+## kernel 源码 与 jenkins
+
+目前有两种完成 jenkins 的思路,都是使用了 **webhook**
+
+插件上可以采用 **gitee** 或 **Generic Webhook Trigger** ,安装方式上面有提到,都是类似的。
+
+选择 item 方面也可以采用 **自由软件风格项目** 和 **pipeline 项目**两种形式
+
+所以这样子搭配 至少有了四种可实现的方法
+
+这里会简单阐述方法 先采用 **自由软件风格项目** 和 **gitee** 插件 来做演示
+
+### gitee +自由软件风格项目
+
+#### gitee 插件
+
+安装方面与上面的其他插件方法一致。
+
+可以参考 gitee 的官方文档 [Jenkins 插件 - Gitee.com](https://gitee.com/help/articles/4193) ,按着其指示配置 Webhook ,此时点击项目 WebHooks 中的 **测试**
+
+
+
+会有相应的结果,但我这里显示超时,这其实是 gitee 这边测试的 bug ,似乎已经很长时间了,正常你触发的时候是没问题的
+
+
+
+
+
+正常 push 代码时是会正常触发的,可以查看 jenkins system log
+
+(我这里单独把 gitee 的 log 拎了出来)
+
+
+
+可以看到是有正常的信息的
+
+到这里你完成了 使用 gitee 插件 捕获 webhook 传来的信息
+
+#### 自由软件风格项目
+
+**Build Steps** 这部分选择使用 Execute shell ,来让 jenkins 可以直接使用部署其服务的主机的环境。
+
+由于之前的工作 ( gitee 插件会根据你的需求,自动更新你所跟踪的 gitee 仓库的状态,我们不用手动拉取),我们已经将 远程仓库的最新状态拉取到本地,由于这种情况下 jenkins 和 lava 位于同一台机器内,可以在编译 Image 后直接使用 REST API,使用 crul 来触发实现准备好的 lava job
+
+
+
+
+
+### Generic Webhook Trigger + pipeline
+
+这里我再详细的写出 Generic Webhook Trigger + pipeline 的形式的完整流程
+
+#### Generic Webhook 插件
+
+首先安装 **Generic Webhook Trigger** 插件
+
+
+
+#### pipeline 项目
+
+创建一个 pipeline 工程
+
+
+
+在 **Build Triggers** 点击 Generic Webhook Trigger
+
+
+
+只需要设置 token 即可
+
+
+
+然后配置 对应仓库的 webhook 我这里我给我的 gitee 仓库配置
+
+
+
+可以手动触发试试 浏览器输入 `你的jenkis地址/generic-webhook-trigger/invoke?token=你的token`
+
+
+
+
+
+这里是 获取源码 构建 和 触发 lava lab 的 pipeline ,实际上,获取 webhook 这一环境也可使用 pipeline,有兴趣可以自行尝试
+
+```pipeline
+pipeline {
+ agent any
+ environment {
+ PATH = "/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin"
+ }
+ stages {
+ stage('Prepare') {
+ steps {
+ script {
+ // 检查 riscv-kernel 目录是否存在
+ if (fileExists('riscv-kernel')) {
+ echo 'riscv-kernel directory exists in OLK. Checking branch...'
+ dir('riscv-kernel') {
+ // 获取当前分支
+ def currentBranch = sh(script: 'git rev-parse --abbrev-ref HEAD', returnStdout: true).trim()
+ echo "Current branch is: ${currentBranch}"
+
+ // 检查当前分支是否为 OLK-6.6
+ if (currentBranch == 'OLK-6.6') {
+ echo 'Already on OLK-6.6 branch. Pulling latest changes...'
+ sh 'git pull'
+ } else {
+ echo "Not on OLK-6.6 branch, switching..."
+ sh "git checkout OLK-6.6"
+ sh 'git pull'
+ }
+ }
+ } else {
+ echo 'riscv-kernel directory does not exist. Cloning OLK-6.6 branch...'
+ // 直接拉取指定分支的代码
+ git url: 'https://gitee.com/feifei-fertilizer/riscv-kernel.git', branch: 'OLK-6.6'
+ }
+ }
+ }
+ }
+ stage('Build') {
+ steps {
+ sh "ls"
+ dir('riscv-kernel') {
+ sh "ls"
+ // 检查 .config 文件是否存在
+ script {
+ if (fileExists('.config')) {
+ sh "rm .config"
+ } else {
+ echo '.config file does not exist, skipping removal.'
+ }
+ }
+ sh "cp arch/riscv/configs/openeuler_defconfig .config"
+ sh "make "
+ sh "make ARCH=riscv CROSS_COMPILE=riscv64-linux-gnu- Image"
+ sh "cp arch/riscv/boot/Image ~/ospp/2024-large-files/"
+ }
+ }
+ }
+ stage('Resubmit Job') {
+ steps {
+ script {
+ def jobId = "15" // 替换为实际的 Job ID
+ def token = "adminlavatoken" // 替换为你的 API token
+
+ def response = httpRequest(
+ url: "http://localhost:8000/api/v0.2/jobs/${jobId}/resubmit/",
+ httpMode: 'POST',
+ customHeaders: [[name: 'Authorization', value: "Token ${token}"]]
+ )
+ echo "Response: ${response.content}"
+ }
+ }
+ }
+ }
+}
+```
+
+如果想像这里一样 使用 pipeline 触发则需要额外安装 **HTTP Request Plugin** 插件
+
+到这里就可以完成 gitee 源码 push , 自动触发 jenkins 构建 kernel 源码, jenkins 再触发 lavajob , 恭喜你。
+
+
+
+构建过程图
+
+
+
+
+
+## 目前存在的问题
+
+可以看到 jenkins 的构建流程,我们已经打通了最基础的 kernel ci 流程,但是仍有许多不完善的地方
+
+1. 搭建 kernel ci 会将 jenkins 和 LAVA 部署在多台机器上
+2. 不能把 token 等需要保护的信息暴露在 pipeline 里
+3. 触发 job 举的例子是触发 LAVA 中已存在的 job,但既然是 CI 要考虑初次触发job的情况
+
+# 更完善的解决方案
+
+## 解决 token 暴露的问题
+
+配置 Credentials,上面有介绍过这部分内容
+
+
+
+
+
+
+
+这里要注意的是不要配置成 Admin credentials 这是管理员的凭据 ,而要配置 **Manage Jenkins 中的 credentials**。
+
+此时你就可以把 pipeline 修改为
+
+```pipeline
+pipeline {
+ agent any
+ stages {
+ stage('Resubmit Job') {
+ steps {
+ script {
+ def jobId = "4" // 替换为实际的 Job ID
+
+ // 使用 withCredentials 确保凭据被正确加载
+ withCredentials([string(credentialsId: 'lava-api-token', variable: 'TOKEN')]) {
+ def response = httpRequest(
+ url: "http://localhost:8000/api/v0.2/jobs/${jobId}/resubmit/",
+ httpMode: 'POST',
+ customHeaders: [[name: 'Authorization', value: "Token ${TOKEN}"]]
+ )
+ echo "Response: ${response.content}"
+ }
+ }
+ }
+ }
+ }
+}
+```
+
+[string(credentialsId: 'lava-api-token', variable: 'TOKEN')] 是 Jenkins Pipeline 的一个参数列表
+
+string(...):指定凭据的类型为字符串
+
+lava-api-token 对应的是上面配置的 secret text 的 credentials id ,
+
+variable:'TOKEN':定义了在 Pipeline 中使用该凭据时的环境变量名称,凭据的值将被赋给这个变量。
+
+
+
+此时 jenkins log 中 便不会显示 token 的明文信息
+
+
+
+## 解决 image 构建问题
+
+先罗列需要做的事
+
+1. 搭建 jenkins 的机器(机器A) 得到 webhook 信息
+2. 传递该信息,使负责编译源码的机器(机器B)更新代码并完成编译
+3. 机器B 将编译好的内容传递给 lava 宿主机(机器C)
+4. 机器C 完成 lava 测试
+
+我们之前 A B C 均为同一台机器,不用考虑网络,权限等问题
+
+这里我考虑三台机器的关系如下
+
+1. A -> B -> C
+2. A <-> B and B -> C
+
+第一种适合简单的情况,第二种则适用于复杂的场景.
+
+下面给出怎么做
+
+### 安装 SSH Agent 插件
+
+然后配置 **ssh credentials**
+
+这里给出示意图
+
+
+
+在 ssh 连接的服务器上配置好你的公钥即可,下面是一个 使用 ssh credentials pipeline 的基础模板
+
+```pipeline
+pipeline {
+ agent any
+
+ stages {
+ stage('Connect to Remote Machine') {
+ steps {
+ script {
+ sshagent(['my-ssh-credentials']) { // 替换为你的凭据 ID
+ sh 'ssh username@ip "command"'
+ }
+ }
+ }
+ }
+ }
+}
+```
+
+这里给出一部分 ssh 连接后的指令,这里涉及到的是源码的更新
+
+```pipeline
+pipeline {
+ agent any
+
+ stages {
+ stage('CHECK KERNEL EXIST') {
+ steps {
+ script {
+ sshagent(['my-ssh-credentials']) { // 替换为你的凭据 ID
+ def command = '''
+ if ls ~/build | grep -q 'riscv-kernel'; then
+ echo "Found 'riscv-kernel' in ~/build."
+ else
+ echo "'riscv-kernel' not found in ~/build. Cloning repository..."
+ git clone https://gitee.com/feifei-fertilizer/riscv-kernel.git ~/build
+ fi
+
+ cd ~/build/riscv-kernel
+
+ # 检查当前分支
+ current_branch=$(git rev-parse --abbrev-ref HEAD)
+ if [ "$current_branch" = "OLK-6.6" ]; then
+ echo "Currently on branch 'OLK-6.6'."
+ # 在这里添加处理分支在该分支上的代码
+ else
+ echo "Not on branch 'OLK-6.6', currently on branch '$current_branch'. Switching to 'OLK-6.6'..."
+ git checkout OLK-6.6
+ fi
+ git pull
+ '''
+ // 使用单个 SSH 连接执行全部命令
+ sh "ssh feifei@192.168.0.149 '${command}'"
+ }
+ }
+ }
+ }
+ }
+}
+```
+
+开始构建 , 这里 ssh 连接到远程构建的机器 使用其环境开始构建,我选择把 更新源码 和 编译 kernel 分为两个 stage ,这样哪一环出了问题可以更好的定位。这里检测了 config 文件是否存在 以及使用什么工具链。
+
+```pipeline
+pipeline {
+ agent any
+
+ stages {
+ stage('COMPILE THE KERNEL') {
+ steps {
+ script {
+ sshagent(['my-ssh-credentials']) { // 替换为你的凭据 ID
+ def command = '''
+ cd ~/build/riscv-kernel
+ if [ -f ~/build/riscv-kernel/.config ]; then
+ echo ".config file exists."
+ rm ~/build/riscv-kernel/.config
+ else
+ echo ".config file does not exist."
+ fi
+ cp ~/build/riscv-kernel/arch/riscv/configs/openeuler_defconfig ~/build/riscv-kernel/.config
+ make ARCH=riscv CROSS_COMPILE=riscv64-linux-gnu- Image
+ '''
+ // 使用单个 SSH 连接执行全部命令
+ sh "ssh feifei@192.168.0.149 '${command}'"
+ }
+ }
+ }
+ }
+ }
+}
+```
+
+文件传输 ,有几种思路,我这里使用了 scp,毕竟之前我们一直在使用 ssh ,你也可以把文件传输到服务器上,或 git 仓库,总之 lava 服务器能得到就行
+
+```pipeline
+pipeline {
+ agent any
+
+ stages {
+ stage('COMPILE THE KERNEL') {
+ steps {
+ script {
+ sshagent(['my-ssh-credentials']) { // 替换为你的凭据 ID
+ def command = '''l
+ if [ -f ~/build/riscv-kernel/arch/riscv/boot/Image ]; then
+ echo "Image file exists."
+ else
+ echo ".config file does not exist."
+ fi
+ scp ~/build/riscv-kernel/arch/riscv/boot/Image feifei@192.168.0.149:~/ospp/2024ospp-large-files/new
+ '''
+ // 使用单个 SSH 连接执行全部命令
+ sh "ssh feifei@192.168.0.149 '${command}'"
+ }
+ }
+ }
+ }
+ }
+}
+```
+
+## 解决首次触发问题
+
+我们之前的 ci 方案是重新提交了已有的 job,无法解决首次触发的问题
+
+lava 官方提供了三种触发方式 分别是 XML-RPC , Web , 命令行使用 lavacli 命令 (其实还有 REST API)
+
+可以查看 [提交您的第一份工作 — LAVA 2024.09 文档 --- Submitting your first job — LAVA 2024.09 documentation (lavasoftware.org)](https://docs.lavasoftware.org/lava/first-job.html#index-2)
+
+之前我们的方案就是采用了 REST API ,上面也提过可以做到,但我们接下来的方案使用的是 lavacli 原因有一下几点
+
+1. lavacli 提供的是 yaml 文件,可以拿着 job 模板直接提交,服务端也可以比较方便管理 job
+2. 使用 REST API 提交 ,lava 会进行很严格的格式检测 ,这让我们提供的测试定义被压缩在一行,可读性极差,而且本人在提交时经常因为格式问题不成功
+
+下面的 pipeline 实现了 判断有没有 同名的 job ,有的话就重新提交该 job,没有的话就通过 lavacli 提交定义
+
+```pipeline
+pipeline {
+ agent any
+
+ stages {
+ stage('COMPILE THE KERNEL') {
+ steps {
+ script {
+ sshagent(['my-ssh-credentials']) {
+ withCredentials([string(credentialsId: 'lava-api-token', variable: 'TOKEN')]) {
+ def LAVA_URI = "http://admin:${TOKEN}@192.168.0.149:8000/RPC2/"
+ def JOB_NAME = "qemu-oerv-24.03-smoke-test"
+ def JOB_Path = "~/ospp/example/job/qemu/qemu-oerv-24.03-smoke-test.yaml"
+ def command = """
+ # 列出作业并检查
+ JOB_INFO=\$(lavacli --uri "$LAVA_URI" jobs list | grep "$JOB_NAME")
+ JOB_ID=\$(echo "\$JOB_INFO" | awk "{print \\\$2}" | cut -d':' -f1 | head -n 1)
+ if [ -n "\$JOB_ID" ]; then
+ echo "Lately Job ID: \$JOB_ID."
+ curl -X POST \
+ "http://192.168.0.149:8000/api/v0.2/jobs/\$JOB_ID/resubmit/" \
+ -H "Authorization: Token ${TOKEN}"
+ else
+ echo "Job '$JOB_NAME' does not exist."
+ lavacli --uri "$LAVA_URI" jobs submit $JOB_Path
+ fi
+
+ """
+ // 使用单个 SSH 连接执行全部命令
+ sh "ssh feifei@192.168.0.149 ${command}"
+ }
+ }
+ }
+ }
+ }
+ }
+}
+```
+
+当然 这个解决方法目前也存在一些问题
+
+这个查看的只是最近作业中有没有重名 job ,考虑到大型的 lava 项目 job id 会以万为单位计算,这显然不是特别好的解决方案, 而且当 job 名称(取决于 job 中的 job name 字段 ) 与提供的 yaml 文件名称不完全一致,也无法检测出
+
+不过好在检测不出也能提供定义,进而进行测试
+
+我认为用 lavacli 的方式来管理每一个 job 会比较好,这样每个 job 在服务器中都有一个对应的 yaml 文件.
+
+## 解决问题并压缩到一个 pipeline 中
+
+```pipeline
+pipeline {
+ agent any
+
+ stages {
+ stage('CHECK KERNEL EXIST') {
+ steps {
+ script {
+ sshagent(['my-ssh-credentials']) { // 替换为你的凭据 ID
+ def command = '''
+ if ls ~/build | grep -q 'riscv-kernel'; then
+ echo "Found 'riscv-kernel' in ~/build."
+ else
+ echo "'riscv-kernel' not found in ~/build. Cloning repository..."
+ git clone https://gitee.com/feifei-fertilizer/riscv-kernel.git ~/build
+ fi
+
+ cd ~/build/riscv-kernel
+
+ # 检查当前分支
+ current_branch=$(git rev-parse --abbrev-ref HEAD)
+ if [ "$current_branch" = "OLK-6.6" ]; then
+ echo "Currently on branch 'OLK-6.6'."
+ # 在这里添加处理分支在该分支上的代码
+ else
+ echo "Not on branch 'OLK-6.6', currently on branch '$current_branch'. Switching to 'OLK-6.6'..."
+ git checkout OLK-6.6
+ fi
+ git pull
+ '''
+ // 使用单个 SSH 连接执行全部命令
+ sh "ssh feifei@192.168.0.149 '${command}'"
+ }
+ }
+ }
+ }
+ stage('COMPILE THE KERNEL') {
+ steps {
+ script {
+ sshagent(['my-ssh-credentials']) { // 替换为你的凭据 ID
+ def command = '''
+ cd ~/build/riscv-kernel
+ if [ -f ~/build/riscv-kernel/.config ]; then
+ echo ".config file exists."
+ rm ~/build/riscv-kernel/.config
+ else
+ echo ".config file does not exist."
+ fi
+ cp ~/build/riscv-kernel/arch/riscv/configs/openeuler_defconfig ~/build/riscv-kernel/.config
+ make ARCH=riscv CROSS_COMPILE=riscv64-linux-gnu- Image
+ '''
+ // 使用单个 SSH 连接执行全部命令
+ sh "ssh feifei@192.168.0.149 '${command}'"
+ }
+ }
+ }
+ }
+ stage('TRANSFER THE KERNEL') {
+ steps {
+ script {
+ sshagent(['my-ssh-credentials']) { // 替换为你的凭据 ID
+ def command = '''
+ if [ -f ~/build/riscv-kernel/arch/riscv/boot/Image ]; then
+ echo "Image file exists."
+ else
+ echo "Image does not exist."
+ fi
+ scp ~/build/riscv-kernel/arch/riscv/boot/Image feifei@192.168.0.149:~/ospp/2024ospp-large-files/new
+ '''
+ // 使用单个 SSH 连接执行全部命令
+ sh "ssh feifei@192.168.0.149 '${command}'"
+ }
+ }
+ }
+ }
+ stage('TRIGGER LAVA JOB') {
+ steps {
+ script {
+ sshagent(['my-ssh-credentials']) {
+ withCredentials([string(credentialsId: 'lava-api-token', variable: 'TOKEN')]) {
+ def LAVA_URI = "http://admin:${TOKEN}@192.168.0.149:8000/RPC2/"
+ def JOB_NAME = "qemu-oerv-24.03-smoke-test"
+ def JOB_Path = "~/ospp/example/job/qemu/qemu-oerv-24.03-smoke-test.yaml"
+ def command = """
+ # 列出作业并检查
+ JOB_INFO=\$(lavacli --uri "$LAVA_URI" jobs list | grep "$JOB_NAME")
+ JOB_ID=\$(echo "\$JOB_INFO" | awk "{print \\\$2}" | cut -d':' -f1 | head -n 1)
+ if [ -n "\$JOB_ID" ]; then
+ echo "Lately Job ID: \$JOB_ID."
+ curl -X POST \
+ "http://192.168.0.149:8000/api/v0.2/jobs/15/resubmit/" \
+ -H "Authorization: Token ${TOKEN}"
+ else
+ echo "Job '$JOB_NAME' does not exist."
+ lavacli --uri "$LAVA_URI" jobs submit $JOB_Path
+ fi
+
+ """
+ // 使用单个 SSH 连接执行全部命令
+ sh "ssh feifei@192.168.0.149 ${command}"
+ }
+ }
+ }
+ }
+ }
+ }
+}
+```
+
+**查看结果**
+
+完成 kernel 编译 并发送
+
+
+
+触发 job
+
+
+
+lava 测试结果
+
+
+
+
+
+在 jenkins 端查看结果
+
+
+
+完成
+
+## 使用 jenkins nodes
+
+经过老师的指导,了解到 jenkins 可以添加多个 node ,实在是很方便
+
+还是那几台机器 但是不用 在每个 stage 里手动连接, 只需要使用 `node('name') `即可使用配置好的机器
+
+下面展示如何配置 node
+
+
+
+按照下面的方式填写
+
+启动方式选择 Launch agents via SSH ,credentials 选择 feifei ,这个是前面提过的配置的 ssh credentials
+
+
+
+可以看到我们 nodes 列表 ,目前节点的状态
+
+注意使用 node 管理的机器需要安装有 java 17,否则会报错 ,这是之前直接使用 ssh 连接所不需要的
+
+
+
+下面是使用 node 的版本 ,可以更直观的看出都用了哪个节点
+
+```pipeline
+pipeline {
+ agent none // 不在整个 pipeline 级别上指定 agent
+ stages {
+ stage('CHECK KERNEL EXIST') {
+ steps {
+ script {
+ node('kernel') { // 指定使用标签为 'kernel' 的节点
+ sh '''
+ if ls ~/build | grep -q 'riscv-kernel'; then
+ echo "Found 'riscv-kernel' in ~/build."
+ else
+ echo "'riscv-kernel' not found in ~/build. Cloning repository..."
+ git clone https://gitee.com/feifei-fertilizer/riscv-kernel.git ~/build
+ fi
+
+ cd ~/build/riscv-kernel
+
+ # 检查当前分支
+ current_branch=$(git rev-parse --abbrev-ref HEAD)
+ if [ "$current_branch" = "OLK-6.6" ]; then
+ echo "Currently on branch 'OLK-6.6'."
+ # 在这里添加处理分支在该分支上的代码
+ else
+ echo "Not on branch 'OLK-6.6', currently on branch '$current_branch'. Switching to 'OLK-6.6'..."
+ git checkout OLK-6.6
+ fi
+ git pull
+ '''
+ }
+ }
+ }
+ }
+ stage('COMPILE THE KERNEL') {
+ steps {
+ script {
+ node('kernel') { // 使用标签为 'kernel' 的节点
+ sh '''
+ cd riscv-kernel
+ if [ -f ~.config ]; then
+ echo ".config file exists."
+ rm .config
+ else
+ echo ".config file does not exist."
+ fi
+ cp ./arch/riscv/configs/openeuler_defconfig .config
+ '''
+ }
+ }
+ }
+ }
+ stage('TRANSFER THE KERNEL') {
+ steps {
+ script {
+ node('kernel') { // 再次使用标签 'kernel'
+ sh '''
+ if [ -d ./oerv-24.03-kernel-image ]; then
+ echo "oerv-24.03-kernel-image exists."
+ else
+ echo "oerv-24.03-kernel-image does not exist."
+ git clone git@gitee.com:feifei-fertilizer/oerv-24.03-kernel-image.git
+ fi
+ cp ./riscv-kernel/arch/riscv/boot/Image ./oerv-24.03-kernel-image cd oerv-24.03-kernel-image
+ git commit -m "$(date +"%Y-%m-%d %H:%M:%S")"
+ git push
+ '''
+ }
+ }
+ }
+ }
+ stage('TRIGGER LAVA JOB') {
+ steps {
+ script {
+ node('lava') { // 使用标签 'lava'
+ withCredentials([string(credentialsId: 'lava-api-token', variable: 'TOKEN')]) {
+ def LAVA_URI = "http://admin:${TOKEN}@192.168.0.149:8000/RPC2/"
+ def JOB_NAME = "qemu-oerv-24.03-smoke-test"
+ def JOB_Path = "~/ospp/example/job/qemu/qemu-oerv-24.03-smoke-test.yaml"
+ sh """
+ # 列出作业并检查
+ if [ -d ./oerv-24.03-kernel-image ]; then
+ echo "oerv-24.03-kernel-image exists."
+ else
+ echo "oerv-24.03-kernel-image does not exist."
+ git clone git@gitee.com:feifei-fertilizer/oerv-24.03-kernel-image.git
+ fi
+ JOB_INFO=\$(lavacli --uri "$LAVA_URI" jobs list | grep "$JOB_NAME")
+ JOB_ID=\$(echo "\$JOB_INFO" | awk "{print \\\$2}" | cut -d':' -f1 | head -n 1)
+ if [ -n "\$JOB_ID" ]; then
+ echo "Lately Job ID: \$JOB_ID."
+ curl -X POST \
+ "http://192.168.0.149:8000/api/v0.2/jobs/15/resubmit/" \
+ -H "Authorization: Token ${TOKEN}"
+ else
+ echo "Job '$JOB_NAME' does not exist."
+ lavacli --uri "$LAVA_URI" jobs submit $JOB_Path
+ fi
+ """
+ }
+ }
+ }
+ }
+ }
+ }
+}
+```
+
+这次没有再用 scp 传文件,而是在编译完 Image 后上传到远程仓库中,再让 `lava` 更新远程仓库内容到本地,以此获得 Image
+
+这里套用了之前的命令行 ,看着很臃肿,你也可以用 try catch 等方式来优化一些细节
+
+结果如下
+
+
diff --git a/doc/tutorials/ospp-kernelci/jobs/Lip4a.yaml b/doc/tutorials/ospp-kernelci/jobs/Lip4a.yaml
new file mode 100755
index 0000000000000000000000000000000000000000..c43442319ed3126133f5e41ce9e827536622d65f
--- /dev/null
+++ b/doc/tutorials/ospp-kernelci/jobs/Lip4a.yaml
@@ -0,0 +1,85 @@
+device_type: Lpi4a
+job_name:
+context:
+ boot_character_delay: 1000
+ extra_nfsroot_args: ",nolock,nfsvers=3"
+timeouts:
+ job:
+ minutes: 301
+ action:
+ minutes: 300
+ actions:
+ power-off:
+ seconds: 30
+priority: medium
+visibility: public
+metadata:
+ # please change these fields when modifying this job for your own tests.
+ format:
+ name:
+ description: ""
+ version: "1.0"
+# ACTION_BLOCK
+actions:
+# DEPLOY_BLOCK
+- deploy:
+ timeout:
+ minutes: 20
+ to: tftp
+ kernel:
+ url: file:///home/2024ospp-large-files/Image
+ type: image
+ dtb:
+ url: file:///home/2024ospp-large-files/licheepi4a/thead/th1520-lichee-pi-4a.dtb
+ nfsrootfs:
+ url: file:///home/2024ospp-large-files/openeuler-rootfs.tar.gz
+ compression: gz
+# BOOT_BLOCK
+- boot:
+ timeout:
+ minutes: 20
+ method: u-boot
+ commands: nfs
+ soft_reboot:
+ - root
+ - openEuler
+ - reboot
+ - The system will reboot now!
+ prompts:
+ - '[root@openeuler-riscv64 ~]#'
+ auto_login:
+ login_prompt: "(.*)openeuler-riscv64 login:(.*)"
+ username: root
+ password_prompt: "Password:"
+ password: openEuler12#$
+# TEST_BLOCK
+- test:
+ timeout:
+ minutes: 240
+ definitions:
+ - repository:
+ metadata:
+ format: Lava-Test Test Definition 1.0
+ name: install-dependency-package
+ run:
+ steps:
+ - yum install -y gcc automake
+ - df -h
+ from: inline
+ name: install-dependency-package-inline
+ path: inline/install-dependency-package.yaml
+ - repository: https://github.com/Linaro/test-definitions.git
+ from: git
+ path: automated/linux/ltp/ltp.yaml
+ parameters:
+ TST_CMDFILES: syscalls
+ SKIPFILE: skipfile-lkft.yaml
+ BOARD: qemu
+ BRANCH: master
+ ENVIRONMENT: production
+ TIMEOUT_MULTIPLIER: '30'
+ ROOT_PASSWD: openEuler12#$
+ BUILD_FROM_TAR: true
+ LTP_VERSION: 20240524
+ TEST_DIR: /root/ltp
+ name: ltp-syscalls-tests
\ No newline at end of file
diff --git a/doc/tutorials/ospp-kernelci/jobs/qemu.yaml b/doc/tutorials/ospp-kernelci/jobs/qemu.yaml
new file mode 100755
index 0000000000000000000000000000000000000000..0db3b478c22ce068803f5f0f852b992f66421951
--- /dev/null
+++ b/doc/tutorials/ospp-kernelci/jobs/qemu.yaml
@@ -0,0 +1,91 @@
+# Your first LAVA JOB definition for an riscv_64 QEMU
+device_type: qemu
+job_name:
+timeouts:
+ job:
+ minutes: 660
+ action:
+ minutes: 650
+ connection:
+ minutes: 5
+priority: medium
+visibility: public
+# context allows specific values to be overridden or included
+context:
+ # tell the qemu template which architecture is being tested
+ # the template uses that to ensure that qemu-system-riscv64 is executed.
+ arch: riscv64
+ machine: virt
+ guestfs_interface: virtio
+ extra_options:
+ - -machine virt
+ - -nographic
+ - -smp 16
+ - -m 16G
+ - -device virtio-blk-device,drive=hd0
+ - -append "root=/dev/vda rw console=ttyS0 selinux=0"
+ - -device virtio-net-device,netdev=usernet
+ - -netdev user,id=usernet,hostfwd=tcp::10008-:22
+metadata:
+ # please change these fields when modifying this job for your own tests.
+ format:
+ name:
+ description: ""
+ version: "1.0"
+# ACTION_BLOCK
+actions:
+# DEPLOY_BLOCK
+- deploy:
+ timeout:
+ minutes: 20
+ to: tmpfs
+ images:
+ kernel:
+ image_arg: -kernel {kernel}
+ url: file:///home/2024ospp-large-files/Image
+ rootfs:
+ image_arg: -drive file={rootfs},format=raw,id=hd0
+ url: file:///home/2024ospp-large-files/openeuler-rootfs.img
+# BOOT_BLOCK
+- boot:
+ timeout:
+ minutes: 20
+ method: qemu
+ media: tmpfs
+ prompts: ["root@openeuler-riscv64"]
+ auto_login:
+ login_prompt: "openeuler-riscv64 login:"
+ username: root
+ password_prompt: "Password:"
+ password: openEuler12#$
+# TEST_BLOCK
+- test:
+ timeout:
+ minutes: 240
+ definitions:
+ - repository:
+ metadata:
+ format: Lava-Test Test Definition 1.0
+ name: install-dependency-package
+ run:
+ steps:
+ - yum install -y gcc automake
+ - df -h
+ from: inline
+ name: install-dependency-package-inline
+ path: inline/install-dependency-package.yaml
+ - repository: https://github.com/Linaro/test-definitions.git
+ from: git
+ path: automated/linux/ltp/ltp.yaml
+ parameters:
+ TST_CMDFILES: syscalls
+ SKIPFILE: skipfile-lkft.yaml
+ BOARD: qemu
+ BRANCH: master
+ ENVIRONMENT: production
+ TIMEOUT_MULTIPLIER: '30'
+ ROOT_PASSWD: openEuler12#$
+ BUILD_FROM_TAR: true
+ LTP_VERSION: 20240524
+ TEST_DIR: /root/ltp
+ name: ltp-syscalls-tests
\ No newline at end of file
diff --git a/doc/tutorials/ospp-kernelci/power-control/README.md b/doc/tutorials/ospp-kernelci/power-control/README.md
new file mode 100755
index 0000000000000000000000000000000000000000..00bb0741bca21d939f85c9b8a77cdf2f0c53fc6b
--- /dev/null
+++ b/doc/tutorials/ospp-kernelci/power-control/README.md
@@ -0,0 +1,24 @@
+电源控制有很多种方式,我这里使用的是继电器,有的开发板支持深度睡眠也可以直接通过引脚控制电源开关
+
+这里给出两种方式的 c 代码
+
+[通过 mqtt ](./mqtt-esp8266.c)
+
+在同一局域网下可以使用以下命令控制继电器 进而控制设备电源
+
+```shell
+mosquitto_pub -h 192.168.0.158 -t "device/power" -m "RESET"
+mosquitto_pub -h 192.168.0.158 -t "device/power" -m "ON"
+mosquitto_pub -h 192.168.0.158 -t "device/power" -m "OFF"
+```
+
+[通过串口](./serialport-arduino-uno3.c)
+
+通过让 slave 通过串口通信访问 arduino 开发板 控制继电器 进而控制设备电源
+
+```shell
+(echo "OFF"; sleep 1; echo "ON") | telnet 192.168.0.158 20001
+(echo "ON") | telnet 192.168.0.158 20001
+(echo "OFF") | telnet 192.168.0.158 20001
+```
+
diff --git a/doc/tutorials/ospp-kernelci/power-control/mqtt-esp8266.c b/doc/tutorials/ospp-kernelci/power-control/mqtt-esp8266.c
new file mode 100755
index 0000000000000000000000000000000000000000..1e66a924b0f9618a7d26af6b586c1725c8be73a6
--- /dev/null
+++ b/doc/tutorials/ospp-kernelci/power-control/mqtt-esp8266.c
@@ -0,0 +1,82 @@
+#include
+#include
+
+// WiFi 配置
+const char* ssid = "feifei_cpe"; // 替换为你的 WiFi SSID
+const char* password = "feifei0827"; // 替换为你的 WiFi 密码
+
+// MQTT 服务器配置
+const char* mqtt_server = "192.168.0.158"; // 替换为您的 MQTT 服务器地址
+const char* mqtt_topic = "device/power"; // 控制主题
+
+// GPIO 引脚
+const int relayPin = 4; // 继电器控制引脚
+
+WiFiClient espClient;
+PubSubClient client(espClient);
+
+void setup() {
+ Serial.begin(115200);
+ pinMode(relayPin, OUTPUT);
+ digitalWrite(relayPin, LOW); // 初始状态关闭继电器
+
+ // 连接到 WiFi
+ WiFi.begin(ssid, password);
+ while (WiFi.status() != WL_CONNECTED) {
+ delay(1000);
+ Serial.println("连接中...");
+ }
+ Serial.println("WiFi 连接成功");
+
+ // 设置 MQTT 服务器
+ client.setServer(mqtt_server, 1883);
+ client.setCallback(callback);
+
+ // 连接到 MQTT
+ reconnect();
+}
+
+void loop() {
+ if (!client.connected()) {
+ reconnect();
+ }
+ client.loop();
+}
+
+// MQTT 消息回调函数
+void callback(char* topic, byte* payload, unsigned int length) {
+ String message;
+ for (int i = 0; i < length; i++) {
+ message += (char)payload[i];
+ }
+
+ if (message == "ON") {
+ digitalWrite(relayPin, HIGH); // 打开继电器
+ Serial.println("电源已打开");
+ } else if (message == "OFF") {
+ digitalWrite(relayPin, LOW); // 关闭继电器
+ Serial.println("电源已关闭");
+ } else if (message == "RESET") {
+ Serial.println("重置设备...");
+ digitalWrite(relayPin, LOW); // 关闭继电器
+ Serial.println("电源已关闭");
+ delay(500);
+ digitalWrite(relayPin, HIGH); // 打开继电器
+ Serial.println("电源已打开");
+ }
+}
+
+// 连接到 MQTT 服务器
+void reconnect() {
+ while (!client.connected()) {
+ Serial.print("连接到 MQTT...");
+ if (client.connect("ESP8266Client")) {
+ Serial.println("连接成功");
+ client.subscribe(mqtt_topic);
+ } else {
+ Serial.print("失败,状态码=");
+ Serial.print(client.state());
+ delay(2000);
+ }
+ }
+}
\ No newline at end of file
diff --git a/doc/tutorials/ospp-kernelci/power-control/serialport-arduino-uno3.c b/doc/tutorials/ospp-kernelci/power-control/serialport-arduino-uno3.c
new file mode 100755
index 0000000000000000000000000000000000000000..d56a2ed40da3317beea99cd1063182b2b839bfeb
--- /dev/null
+++ b/doc/tutorials/ospp-kernelci/power-control/serialport-arduino-uno3.c
@@ -0,0 +1,21 @@
+// 定义继电器连接的引脚
+const int relayPin = 4;
+
+void setup() {
+ // 初始化继电器引脚为输出模式
+ pinMode(relayPin, OUTPUT);
+ // 初始状态为关闭继电器
+ digitalWrite(relayPin, LOW);
+}
+
+void loop() {
+ // 打开继电器
+ digitalWrite(relayPin, HIGH);
+ Serial.println("Relay ON");
+ delay(1000); // 延时1秒
+
+ // 关闭继电器
+ digitalWrite(relayPin, LOW);
+ Serial.println("Relay OFF");
+ delay(1000); // 延时1秒
+}
\ No newline at end of file
diff --git a/doc/tutorials/ospp-kernelci/test-definitions/kselftest/keselftest.yaml b/doc/tutorials/ospp-kernelci/test-definitions/kselftest/keselftest.yaml
new file mode 100755
index 0000000000000000000000000000000000000000..8249616ac752f47de9545ab393e9c817694105ac
--- /dev/null
+++ b/doc/tutorials/ospp-kernelci/test-definitions/kselftest/keselftest.yaml
@@ -0,0 +1,21 @@
+metadata:
+ name: kselftest
+ format: "Lava-Test Test Definition 1.0"
+ description: "Run kselftest test suite on openEuler"
+ os:
+ - openEuler
+ scope:
+ - functional
+ devices:
+ - all
+run:
+ steps:
+ - yum install -y git make gcc flex bison clang
+ - df -h
+ - cd /root
+ - git clone https://gitee.com/feifei-fertilizer/riscv-kernel.git
+ - cd riscv-kerner.git
+ - git checkout OLK-6.6
+ - make defconfig
+ - make -C tools/testing/selftests
+ - make -C tools/testing/selftests run_tests
\ No newline at end of file
diff --git a/doc/tutorials/ospp-kernelci/test-definitions/ltp/ltp.yaml b/doc/tutorials/ospp-kernelci/test-definitions/ltp/ltp.yaml
new file mode 100755
index 0000000000000000000000000000000000000000..4f70958ba84fb8f7867f85b4c610201879aaafe9
--- /dev/null
+++ b/doc/tutorials/ospp-kernelci/test-definitions/ltp/ltp.yaml
@@ -0,0 +1,26 @@
+metadata:
+ name: ltp
+ format: "Lava-Test Test Definition 1.0"
+ description: "Run ltp test suite on openEuler"
+ os:
+ - openEuler
+ scope:
+ - functional
+ devices:
+ - all
+run:
+ steps:
+ - yum install -y gcc automake
+ - df -h
+ - wget -P /root https://github.com/linux-test-project/ltp/releases/download/20240524/ltp-full-20240524.tar.xz
+ - cd /root
+ - tar -xJf ltp-full-20240524.tar.xz
+ - df -h
+ - cd ltp-full-20240524
+ - make autotools
+ - ./configure
+ - make -j $(nproc)
+ - df -h
+ - make install
+ - cd /opt/ltp
+ - ./runltp
\ No newline at end of file