diff --git a/vm_build_risc_v/Dockerfile b/vm_build_risc_v/Dockerfile new file mode 100644 index 0000000..1cb8510 --- /dev/null +++ b/vm_build_risc_v/Dockerfile @@ -0,0 +1,54 @@ +FROM ubuntu:24.04 + +ENV DEBIAN_FRONTEND=noninteractive \ + TZ=Europe/Moscow \ + LANG=en_US.UTF-8 \ + LC_ALL=en_US.UTF-8 + +RUN apt update && \ + apt install -y \ + build-essential \ + chrpath \ + cpio \ + debianutils \ + diffstat \ + file \ + gawk \ + gcc \ + git \ + iputils-ping \ + libacl1 \ + liblz4-tool \ + locales \ + python3 \ + python3-git \ + python3-jinja2 \ + python3-pexpect \ + python3-pip \ + python3-subunit \ + socat \ + texinfo \ + unzip \ + wget \ + xz-utils \ + zstd \ + sudo + +RUN locale-gen en_US.UTF-8 + +RUN useradd -m -s /bin/bash builder +RUN echo "%sudo ALL=(ALL:ALL) NOPASSWD: ALL" > /etc/sudoers +RUN usermod -aG sudo builder + +WORKDIR /home/builder + +COPY scripts/build/build.sh /home/builder/scripts/build.sh +COPY scripts/build/run.sh /home/builder/scripts/run.sh +COPY meta-cluster /home/builder/meta-cluster +COPY meta-licheepi4a /home/builder/meta-licheepi4a +RUN chmod +x /home/builder/scripts/build.sh +RUN chmod +x /home/builder/scripts/run.sh + +USER builder + +CMD [ "/bin/bash" ] diff --git a/vm_build_risc_v/LICENSE b/vm_build_risc_v/LICENSE new file mode 100644 index 0000000..6690518 --- /dev/null +++ b/vm_build_risc_v/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2025 MOEVM LETI + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/vm_build_risc_v/Makefile b/vm_build_risc_v/Makefile new file mode 100644 index 0000000..a7da32d --- /dev/null +++ b/vm_build_risc_v/Makefile @@ -0,0 +1,36 @@ +IMAGE_NAME = yocto-riscv-build +VOLUME_NAME = yocto +DEPLOY_DIR = $(VOLUME_NAME)/poky/build/tmp/deploy/images/licheepi4a +.DEFAULT_GOAL = help + +build: + docker buildx build -t $(IMAGE_NAME) . + +.PHONY: yocto +yocto: + docker run --rm -it \ + --memory=12g \ + --cpus=8 \ + -v $(PWD)/$(VOLUME_NAME)/:/home/builder/$(VOLUME_NAME)/:Z \ + $(IMAGE_NAME) /home/builder/scripts/build.sh + +.PHONY: run +run: + docker run --rm -it -v $(PWD)/$(VOLUME_NAME)/:/home/builder/$(VOLUME_NAME)/:Z $(IMAGE_NAME) /home/builder/scripts/run.sh + +test: + docker run --rm -it -v $(PWD)/$(VOLUME_NAME)/:/home/builder/$(VOLUME_NAME)/:Z $(IMAGE_NAME) /bin/bash + +clean: + docker rmi $(IMAGE_NAME) + rm -rf $(VOLUME_NAME) + +help: + @echo "Makefile for building Yocto image for Lichee Pi 4A" + @echo "" + @echo "build - build the Docker container image" + @echo "yocto - build the Lichee Pi 4A DPDK image using Yocto" + @echo "run - run QEMU" + @echo "test - open interactive shell in container" + @echo "clean - delete Docker image and build directory, please? run with \"sudo\"" + @echo "help - print help information" \ No newline at end of file diff --git a/vm_build_risc_v/README.md b/vm_build_risc_v/README.md new file mode 100644 index 0000000..c17ac51 --- /dev/null +++ b/vm_build_risc_v/README.md @@ -0,0 +1,9 @@ +# vm_build_risc_v + +# Installation image licheepi4a-dpdk-image + +```sh +make build +make yocto +./scripts/flash.sh +``` \ No newline at end of file diff --git a/vm_build_risc_v/meta-cluster/COPYING.MIT b/vm_build_risc_v/meta-cluster/COPYING.MIT new file mode 100644 index 0000000..fb950dc --- /dev/null +++ b/vm_build_risc_v/meta-cluster/COPYING.MIT @@ -0,0 +1,17 @@ +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/vm_build_risc_v/meta-cluster/README b/vm_build_risc_v/meta-cluster/README new file mode 100644 index 0000000..3869db1 --- /dev/null +++ b/vm_build_risc_v/meta-cluster/README @@ -0,0 +1,12 @@ +This README file contains information on the contents of the meta-cluster layer. + +Please see the corresponding sections below for details. + +Dependencies +============ + + URI: + branch: + + URI: + branch: diff --git a/vm_build_risc_v/meta-cluster/conf/layer.conf b/vm_build_risc_v/meta-cluster/conf/layer.conf new file mode 100644 index 0000000..ecb449b --- /dev/null +++ b/vm_build_risc_v/meta-cluster/conf/layer.conf @@ -0,0 +1,13 @@ +# We have a conf and classes directory, add to BBPATH +BBPATH .= ":${LAYERDIR}" + +# We have recipes-* directories, add to BBFILES +BBFILES += "${LAYERDIR}/recipes-*/*/*.bb \ + ${LAYERDIR}/recipes-*/*/*.bbappend" + +BBFILE_COLLECTIONS += "meta-cluster" +BBFILE_PATTERN_meta-cluster = "^${LAYERDIR}/" +BBFILE_PRIORITY_meta-cluster = "6" + +LAYERDEPENDS_meta-cluster = "core" +LAYERSERIES_COMPAT_meta-cluster = "kirkstone walnascar whinlatter scarthgap" \ No newline at end of file diff --git a/vm_build_risc_v/meta-cluster/recipes-cluster/controller-bin/controller-bin.bb b/vm_build_risc_v/meta-cluster/recipes-cluster/controller-bin/controller-bin.bb new file mode 100644 index 0000000..ed972ef --- /dev/null +++ b/vm_build_risc_v/meta-cluster/recipes-cluster/controller-bin/controller-bin.bb @@ -0,0 +1,39 @@ +SUMMARY = "Controller" +DESCRIPTION = "Controller program for cluster" +LICENSE = "MIT" +LIC_FILES_CHKSUM = "file://${COMMON_LICENSE_DIR}/MIT;md5=0835ade698e0bcf8506ecda2f7b4f302" + +SRC_URI = "git://github.com/moevm/grpc_server;branch=main;protocol=https;destsuffix=git" +SRCREV = "${AUTOREV}" + +DEPENDS = "go-native protobuf-native protoc-gen-go-native protoc-gen-go-grpc-native" + +S = "${WORKDIR}/git" + +GOARCH = "${@ "amd64" if d.getVar('TARGET_ARCH') == "x86_64" else "riscv64"}" + +do_configure[noexec] = "1" +do_compile[network] = "1" + +do_compile() { + cd ${S}/controller + + protoc \ + --go_out=. \ + --go_opt=paths=source_relative \ + --go-grpc_out=. \ + --go-grpc_opt=paths=source_relative \ + pkg/proto/communication/communication.proto + + cd cmd/manager + GOOS=${TARGET_GOOS} GOARCH=${GOARCH} go build -trimpath -o manager test.go +} + +do_install() { + install -d ${D}${bindir} + install -m 0755 ${S}/controller/cmd/manager/manager ${D}${bindir}/manager +} + +INSANE_SKIP:${PN} += "ldflags" + +FILES:${PN} = "${bindir}" diff --git a/vm_build_risc_v/meta-cluster/recipes-cluster/controller/cluster-controller.bb b/vm_build_risc_v/meta-cluster/recipes-cluster/controller/cluster-controller.bb new file mode 100644 index 0000000..240d113 --- /dev/null +++ b/vm_build_risc_v/meta-cluster/recipes-cluster/controller/cluster-controller.bb @@ -0,0 +1,13 @@ +SUMMARY = "Cluster Controller" +DESCRIPTION = "A stub package for the cluster controller node" +LICENSE = "MIT" +LIC_FILES_CHKSUM = "file://${COMMON_LICENSE_DIR}/MIT;md5=0835ade698e0bcf8506ecda2f7b4f302" + +SRC_URI = "file://controller-init.sh" + +do_install() { + install -d ${D}${bindir} + install -m 0755 ${WORKDIR}/controller-init.sh ${D}${bindir}/controller-init.sh +} + +FILES_${PN} = "${bindir}/controller-init.sh" diff --git a/vm_build_risc_v/meta-cluster/recipes-cluster/controller/files/controller-init.sh b/vm_build_risc_v/meta-cluster/recipes-cluster/controller/files/controller-init.sh new file mode 100755 index 0000000..f0a3616 --- /dev/null +++ b/vm_build_risc_v/meta-cluster/recipes-cluster/controller/files/controller-init.sh @@ -0,0 +1,2 @@ +#!/bin/sh +echo "Controller node initialized!" diff --git a/vm_build_risc_v/meta-cluster/recipes-cluster/prometheus-cpp/prometheus-cpp.bb b/vm_build_risc_v/meta-cluster/recipes-cluster/prometheus-cpp/prometheus-cpp.bb new file mode 100644 index 0000000..9fd36ae --- /dev/null +++ b/vm_build_risc_v/meta-cluster/recipes-cluster/prometheus-cpp/prometheus-cpp.bb @@ -0,0 +1,33 @@ +SUMMARY = "Prometheus Client Library for Modern C++" +HOMEPAGE = "https://github.com/jupp0r/prometheus-cpp" +LICENSE = "MIT" +LIC_FILES_CHKSUM = "file://${COMMON_LICENSE_DIR}/MIT;md5=0835ade698e0bcf8506ecda2f7b4f302" + +SRC_URI = "git://github.com/jupp0r/prometheus-cpp.git;protocol=https;branch=master;destsuffix=git" +SRCREV = "v1.3.0" + +S = "${WORKDIR}/git" + +DEPENDS = "zlib openssl curl" + +inherit cmake + +EXTRA_OECMAKE = " \ + -DBUILD_SHARED_LIBS=ON \ + -DENABLE_PUSH=ON \ + -DENABLE_TESTING=OFF \ + -DUSE_THIRDPARTY_LIBRARIES=OFF \ + -DENABLE_COMPRESSION=OFF \ + -DOVERRIDE_CATCH=OFF \ + -DGENERATE_PKGCONFIG=ON \ + -DENABLE_PULL=OFF \ +" + +OECMAKE_SOURCEPATH = "${S}" + +do_configure:prepend() { + bbnote "=== DEBUG: Content of ${S} ===" + ls -la ${S} + bbnote "=== Looking for CMakeLists.txt ===" + find ${S} -name "CMakeLists.txt" -type f +} \ No newline at end of file diff --git a/vm_build_risc_v/meta-cluster/recipes-cluster/protoc-gen-go-grpc/protoc-gen-go-grpc.bb b/vm_build_risc_v/meta-cluster/recipes-cluster/protoc-gen-go-grpc/protoc-gen-go-grpc.bb new file mode 100644 index 0000000..a5302f5 --- /dev/null +++ b/vm_build_risc_v/meta-cluster/recipes-cluster/protoc-gen-go-grpc/protoc-gen-go-grpc.bb @@ -0,0 +1,32 @@ +SUMMARY = "Go gRPC protocol buffers compiler plugin" +HOMEPAGE = "https://github.com/grpc/grpc-go" +LICENSE = "Apache-2.0" +LIC_FILES_CHKSUM = "file://LICENSE;md5=3b83ef96387f14655fc854ddc3c6bd57" + +SRC_URI = "git://github.com/grpc/grpc-go.git;branch=master;protocol=https;destsuffix=git" +SRCREV = "${AUTOREV}" + +S = "${WORKDIR}/git" + +DEPENDS = "go-native" + +GOARCH = "${@ "amd64" if d.getVar('TARGET_ARCH') == "x86_64" else "riscv64"}" + +do_configure[noexec] = "1" +do_compile[network] = "1" + +do_compile() { + cd ${S}/cmd/protoc-gen-go-grpc + GOOS=${TARGET_GOOS} GOARCH=${GOARCH} go build -trimpath -o protoc-gen-go-grpc +} + +do_install() { + install -d ${D}${bindir} + install -m 0755 ${S}/cmd/protoc-gen-go-grpc/protoc-gen-go-grpc ${D}${bindir}/protoc-gen-go-grpc +} + +INSANE_SKIP:${PN} += "ldflags" + +FILES:${PN} = "${bindir}" + +BBCLASSEXTEND = "native" diff --git a/vm_build_risc_v/meta-cluster/recipes-cluster/protoc-gen-go/protoc-gen-go.bb b/vm_build_risc_v/meta-cluster/recipes-cluster/protoc-gen-go/protoc-gen-go.bb new file mode 100644 index 0000000..337d1d1 --- /dev/null +++ b/vm_build_risc_v/meta-cluster/recipes-cluster/protoc-gen-go/protoc-gen-go.bb @@ -0,0 +1,45 @@ +SUMMARY = "Go protocol buffers compiler plugin" +HOMEPAGE = "https://github.com/golang/protobuf" +LICENSE = "BSD-3-Clause" +LIC_FILES_CHKSUM = "file://LICENSE;md5=939cce1ec101726fa754e698ac871622" + +SRC_URI = "git://github.com/golang/protobuf;branch=master;protocol=https;destsuffix=git" +SRCREV = "${AUTOREV}" + +S = "${WORKDIR}/git" + +DEPENDS = "go-native" + +GOARCH = "${@ "amd64" if d.getVar('TARGET_ARCH') == "x86_64" else "riscv64"}" + +do_configure[noexec] = "1" +do_compile[network] = "1" + +do_compile() { + cd ${S} + if [ -d "cmd/protoc-gen-go" ]; then + cd cmd/protoc-gen-go + elif [ -d "protoc-gen-go" ]; then + cd protoc-gen-go + else + bbfatal "Cannot find protoc-gen-go directory" + fi + GOOS=${TARGET_GOOS} GOARCH=${GOARCH} go build -trimpath -o protoc-gen-go +} + +do_install() { + install -d ${D}${bindir} + if [ -f ${S}/cmd/protoc-gen-go/protoc-gen-go ]; then + install -m 0755 ${S}/cmd/protoc-gen-go/protoc-gen-go ${D}${bindir}/protoc-gen-go + elif [ -f ${S}/protoc-gen-go/protoc-gen-go ]; then + install -m 0755 ${S}/protoc-gen-go/protoc-gen-go ${D}${bindir}/protoc-gen-go + else + bbfatal "protoc-gen-go binary not found" + fi +} + +INSANE_SKIP:${PN} += "ldflags" + +FILES:${PN} = "${bindir}" + +BBCLASSEXTEND = "native" diff --git a/vm_build_risc_v/meta-cluster/recipes-cluster/unit/cluster-unit.bb b/vm_build_risc_v/meta-cluster/recipes-cluster/unit/cluster-unit.bb new file mode 100644 index 0000000..cc53abd --- /dev/null +++ b/vm_build_risc_v/meta-cluster/recipes-cluster/unit/cluster-unit.bb @@ -0,0 +1,13 @@ +SUMMARY = "Cluster Unit" +DESCRIPTION = "A stub package for the cluster unit node" +LICENSE = "MIT" +LIC_FILES_CHKSUM = "file://${COMMON_LICENSE_DIR}/MIT;md5=0835ade698e0bcf8506ecda2f7b4f302" + +SRC_URI = "file://unit-init.sh" + +do_install() { + install -d ${D}${bindir} + install -m 0755 ${WORKDIR}/unit-init.sh ${D}${bindir}/unit-init.sh +} + +FILES_${PN} = "${bindir}/unit-init.sh" diff --git a/vm_build_risc_v/meta-cluster/recipes-cluster/unit/files/unit-init.sh b/vm_build_risc_v/meta-cluster/recipes-cluster/unit/files/unit-init.sh new file mode 100755 index 0000000..0c43cf5 --- /dev/null +++ b/vm_build_risc_v/meta-cluster/recipes-cluster/unit/files/unit-init.sh @@ -0,0 +1,2 @@ +#!/bin/sh +echo "Unit node initialized!" diff --git a/vm_build_risc_v/meta-cluster/recipes-cluster/worker-bin/worker-bin.bb b/vm_build_risc_v/meta-cluster/recipes-cluster/worker-bin/worker-bin.bb new file mode 100644 index 0000000..256c44d --- /dev/null +++ b/vm_build_risc_v/meta-cluster/recipes-cluster/worker-bin/worker-bin.bb @@ -0,0 +1,27 @@ +SUMMARY = "Worker" +DESCRIPTION = "Worker program for cluster" +LICENSE = "MIT" +LIC_FILES_CHKSUM = "file://${COMMON_LICENSE_DIR}/MIT;md5=0835ade698e0bcf8506ecda2f7b4f302" + +SRC_URI = "git://github.com/moevm/grpc_server;branch=main;protocol=https;destsuffix=git" +SRCREV = "3bf8b7841cde8c3c4c684f0ae18ff80f950e7d8b" + +S = "${WORKDIR}/git" + +DEPENDS = "openssl curl prometheus-cpp" + +do_compile() { + cd ${S}/worker/src + ${CXX} ${CXXFLAGS} ${LDFLAGS} -o worker \ + main.cpp md_calculator.cpp file.cpp metrics_collector.cpp worker.cpp \ + -lssl -lcrypto -lprometheus-cpp-push \ + -lprometheus-cpp-core -lcurl +} + +do_install() { + install -d ${D}${bindir} + install -m 0755 ${S}/worker/src/worker ${D}${bindir}/worker +} + +FILES_${PN} = "${bindir}/worker" + \ No newline at end of file diff --git a/vm_build_risc_v/meta-cluster/recipes-extended/dpdk/dpdk/0001-config-meson-get-cpu_instruction_set-from-meson-opti.patch b/vm_build_risc_v/meta-cluster/recipes-extended/dpdk/dpdk/0001-config-meson-get-cpu_instruction_set-from-meson-opti.patch new file mode 100644 index 0000000..92e3523 --- /dev/null +++ b/vm_build_risc_v/meta-cluster/recipes-extended/dpdk/dpdk/0001-config-meson-get-cpu_instruction_set-from-meson-opti.patch @@ -0,0 +1,32 @@ +From 121e5d019f0bb6dec0ace2b361611edd10fc8ff8 Mon Sep 17 00:00:00 2001 +From: Lee Chee Yang +Date: Wed, 6 Dec 2023 16:58:10 +0800 +Subject: [PATCH] config/meson: get cpu_instruction_set from meson option + +Workaround error: +| ../git/config/meson.build:178:8: ERROR: Problem encountered: Compiler +does not support "x86_64" arch flag. + +Upstream-Status: Inappropriate [ yocto specific to set cpu_instruction_set ] + +Signed-off-by: Lee Chee Yang +--- + config/meson.build | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/config/meson.build b/config/meson.build +index a9ccd56deb..f310c7adf6 100644 +--- a/config/meson.build ++++ b/config/meson.build +@@ -105,7 +105,7 @@ platform = get_option('platform') + + # set the cpu_instruction_set and cflags for it + if meson.is_cross_build() +- cpu_instruction_set = host_machine.cpu() ++ cpu_instruction_set = get_option('cpu_instruction_set') + else + cpu_instruction_set = get_option('cpu_instruction_set') + machine = get_option('machine') +-- +2.37.3 + diff --git a/vm_build_risc_v/meta-cluster/recipes-extended/dpdk/dpdk_23.11.5.bb b/vm_build_risc_v/meta-cluster/recipes-extended/dpdk/dpdk_23.11.5.bb new file mode 100644 index 0000000..c0bfc0c --- /dev/null +++ b/vm_build_risc_v/meta-cluster/recipes-extended/dpdk/dpdk_23.11.5.bb @@ -0,0 +1,67 @@ +SUMMARY = "Data Plane Development Kit - helloworld example for RISC-V" +HOMEPAGE = "http://dpdk.org" +LICENSE = "BSD-3-Clause & LGPL-2.1-only & GPL-2.0-only" +LIC_FILES_CHKSUM = "file://license/gpl-2.0.txt;md5=b234ee4d69f5fce4486a80fdaf4a4263 \ + file://license/lgpl-2.1.txt;md5=4b54a1fd55a448865a0b32d41598759d \ + file://license/bsd-3-clause.txt;md5=0f00d99239d922ffd13cabef83b33444" + +SRC_URI = "git://dpdk.org/git/dpdk-stable;protocol=https;branch=23.11 \ + file://0001-config-meson-get-cpu_instruction_set-from-meson-opti.patch \ + " +SRCREV = "62f583c49bf67dd4d6733ece14e55fe6839e66d1" + +S = "${WORKDIR}/git" + +DEPENDS = "numactl python3-pyelftools-native" + +inherit meson pkgconfig + +EXTRA_OEMESON = " \ + -Dplatform=generic \ + -Dcpu_instruction_set=rv64gc \ + -Dexamples=helloworld \ + -Denable_docs=false \ + -Dtests=false \ + -Ddisable_drivers=* \ + -Dmax_lcores=128 \ + -Dmax_numa_nodes=1 \ +" + +EXTRA_OEMESON:append:riscv64 = " \ + --cross-file ${WORKDIR}/riscv-dpdk-cross.ini \ +" + +do_configure:prepend() { + cat > ${WORKDIR}/riscv-dpdk-cross.ini << 'EOF' +[properties] +vendor_id = 'generic' +arch_id = 'generic' +numa = false +EOF +} + +do_install:append() { + if [ -f ${B}/examples/dpdk-helloworld ]; then + install -d ${D}${bindir} + install -m 0755 ${B}/examples/dpdk-helloworld ${D}${bindir}/dpdk-helloworld + fi + + rm -rf ${D}${datadir}/dpdk/examples || true + rm -rf ${D}${prefix}/share/dpdk/examples || true +} + +PACKAGES =+ "${PN}-examples" + +FILES:${PN} += " \ + ${libdir}/*.so* \ + ${libdir}/dpdk/ \ +" +FILES:${PN}-examples = "${bindir}/dpdk-helloworld" +FILES:${PN}-dev = "${includedir} ${libdir}/pkgconfig" + +RDEPENDS:${PN} += "numactl" +RDEPENDS:${PN}-examples += "${PN}" + +INSANE_SKIP:${PN} += "dev-so" + +COMPATIBLE_MACHINE = "(qemuriscv64|licheepi4a)" diff --git a/vm_build_risc_v/meta-licheepi4a/conf/layer.conf b/vm_build_risc_v/meta-licheepi4a/conf/layer.conf new file mode 100644 index 0000000..1d5bde2 --- /dev/null +++ b/vm_build_risc_v/meta-licheepi4a/conf/layer.conf @@ -0,0 +1,13 @@ +BBPATH .= ":${LAYERDIR}" + +BBFILES += " \ + ${LAYERDIR}/recipes-*/*/*.bb \ + ${LAYERDIR}/recipes-*/*/*.bbappend \ +" + +BBFILE_COLLECTIONS += "meta-licheepi4a" +BBFILE_PATTERN_meta-licheepi4a = "^${LAYERDIR}/" +BBFILE_PRIORITY_meta-licheepi4a = "10" + +LAYERDEPENDS_meta-licheepi4a = "core openembedded-layer" +LAYERSERIES_COMPAT_meta-licheepi4a = "kirkstone scarthgap" diff --git a/vm_build_risc_v/meta-licheepi4a/conf/machine/licheepi4a.conf b/vm_build_risc_v/meta-licheepi4a/conf/machine/licheepi4a.conf new file mode 100644 index 0000000..596affd --- /dev/null +++ b/vm_build_risc_v/meta-licheepi4a/conf/machine/licheepi4a.conf @@ -0,0 +1,46 @@ +#@TYPE: Machine +#@NAME: Lichee Pi 4A +#@DESCRIPTION: Machine configuration for Lichee Pi 4A (T-Head TH1520 SoC) + +require conf/machine/include/riscv/tune-riscv.inc + +DEFAULTTUNE = "riscv64" +TUNE_FEATURES:tune-riscv64 = "riscv64" + +MACHINE_FEATURES = "screen keyboard usbhost usbgadget wifi bluetooth ext2 ext3 serial ethernet" + +PREFERRED_PROVIDER_virtual/kernel = "linux-revyos-th1520" +KERNEL_IMAGETYPE = "Image" +KERNEL_DEVICETREE = "thead/th1520-lichee-pi-4a.dtb" + +PREFERRED_PROVIDER_virtual/bootloader = "u-boot-thead" +UBOOT_MACHINE = "light_lpi4a_defconfig" + +RISCV_SBI_PLAT = "generic" +RISCV_SBI_FDT = "thead/th1520-lichee-pi-4a.dtb" + +EXTRA_IMAGEDEPENDS += "opensbi-thead firmware-th1520 u-boot-thead" + +SERIAL_CONSOLES = "115200;ttyS0" + +MACHINE_ESSENTIAL_EXTRA_RRECOMMENDS += " \ + kernel-modules \ +" + +IMAGE_FSTYPES = "ext4 wic.gz" +IMAGE_BOOT_FILES = " \ + fw_dynamic.bin \ + ${KERNEL_IMAGETYPE} \ + th1520-lichee-pi-4a.dtb \ + light_aon_fpga.bin \ +" + +WKS_FILE ?= "licheepi4a-sdcard.wks" +WIC_CREATE_EXTRA_ARGS ?= "--no-fstab-update" +WKS_FILE_DEPENDS ?= " \ + opensbi-thead \ + e2fsprogs-native \ + bmaptool-native \ +" + +MACHINEOVERRIDES =. "licheepi4a:" \ No newline at end of file diff --git a/vm_build_risc_v/meta-licheepi4a/recipes-bsp/firmware/firmware-th1520.bb b/vm_build_risc_v/meta-licheepi4a/recipes-bsp/firmware/firmware-th1520.bb new file mode 100644 index 0000000..6cb93f5 --- /dev/null +++ b/vm_build_risc_v/meta-licheepi4a/recipes-bsp/firmware/firmware-th1520.bb @@ -0,0 +1,30 @@ +SUMMARY = "TH1520 AON firmware binary" +DESCRIPTION = "Firmware blob for the TH1520 Always-On subsystem. \ +Required by the kernel for power management and co-processor communication." +HOMEPAGE = "https://github.com/revyos/th1520-boot-firmware" +LICENSE = "CLOSED" +SRC_URI = "git://github.com/revyos/th1520-boot-firmware.git;branch=master;protocol=https" +SRCREV = "725756411ecc20f2c2dbc5ea6b8e5aacc6f83aad" + +S = "${WORKDIR}/git" + +inherit deploy + +do_install() { + install -d ${D}${nonarch_base_libdir}/firmware + if [ -f ${S}/addons/boot/light_aon_fpga.bin ]; then + install -m 0644 ${S}/addons/boot/light_aon_fpga.bin ${D}${nonarch_base_libdir}/firmware/ + fi +} + +do_deploy() { + if [ -f ${S}/addons/boot/light_aon_fpga.bin ]; then + install -m 0644 ${S}/addons/boot/light_aon_fpga.bin ${DEPLOYDIR}/ + fi +} + +addtask deploy after do_install + +FILES:${PN} = "${nonarch_base_libdir}/firmware/light_aon_fpga.bin" + +COMPATIBLE_MACHINE = "(licheepi4a)" diff --git a/vm_build_risc_v/meta-licheepi4a/recipes-bsp/opensbi/opensbi-thead.bb b/vm_build_risc_v/meta-licheepi4a/recipes-bsp/opensbi/opensbi-thead.bb new file mode 100644 index 0000000..2013d25 --- /dev/null +++ b/vm_build_risc_v/meta-licheepi4a/recipes-bsp/opensbi/opensbi-thead.bb @@ -0,0 +1,42 @@ +SUMMARY = "OpenSBI for T-Head TH1520 SoC" +DESCRIPTION = "RISC-V Open Source Supervisor Binary Interface implementation \ +from RevyOS project, with T-Head TH1520 platform support." +LICENSE = "BSD-2-Clause" +LIC_FILES_CHKSUM = "file://COPYING.BSD;md5=42dd9555eb177f35150cf9aa240b61e5" + +inherit deploy + +BRANCH = "th1520" +SRC_URI = "git://github.com/revyos/thead-opensbi.git;branch=${BRANCH};protocol=https" +SRCREV = "${AUTOREV}" + +S = "${WORKDIR}/git" + +DEPENDS += "dtc-native" + +EXTRA_OEMAKE += "PLATFORM=${RISCV_SBI_PLAT} I=${D} FW_PIC=n CLANG_TARGET=" + +do_configure[noexec] = "1" + +do_compile() { + oe_runmake +} + +do_install() { + install -d ${D}/share/opensbi + install -m 0644 ${S}/build/platform/${RISCV_SBI_PLAT}/firmware/fw_dynamic.bin ${D}/share/opensbi/ + install -m 0644 ${S}/build/platform/${RISCV_SBI_PLAT}/firmware/fw_dynamic.elf ${D}/share/opensbi/ +} + +do_deploy() { + install -m 0644 ${S}/build/platform/${RISCV_SBI_PLAT}/firmware/fw_dynamic.bin ${DEPLOYDIR}/ + install -m 0644 ${S}/build/platform/${RISCV_SBI_PLAT}/firmware/fw_dynamic.elf ${DEPLOYDIR}/ +} + +addtask deploy after do_install + +FILES:${PN} += "/share/opensbi/*" + +COMPATIBLE_MACHINE = "(licheepi4a)" +INHIBIT_PACKAGE_STRIP = "1" +SECURITY_CFLAGS = "" diff --git a/vm_build_risc_v/meta-licheepi4a/recipes-bsp/u-boot/u-boot-thead.bb b/vm_build_risc_v/meta-licheepi4a/recipes-bsp/u-boot/u-boot-thead.bb new file mode 100644 index 0000000..ae1dda9 --- /dev/null +++ b/vm_build_risc_v/meta-licheepi4a/recipes-bsp/u-boot/u-boot-thead.bb @@ -0,0 +1,61 @@ +SUMMARY = "U-Boot for T-Head TH1520 (Lichee Pi 4A)" +DESCRIPTION = "U-Boot bootloader for TH1520-based boards from RevyOS project. \ +Includes SPL, secure boot libraries, LPDDR4 init, and full LPi4A board support." + +LICENSE = "GPL-2.0-or-later" +LIC_FILES_CHKSUM = "file://Licenses/README;md5=30503fd321432fc713238f582193b78e" + +SRC_URI = " \ + git://github.com/revyos/thead-u-boot.git;protocol=https;branch=th1520 \ +" +SRCREV = "${AUTOREV}" + +S = "${WORKDIR}/git" +B = "${S}" + +DEPENDS += "dtc-native bison-native flex-native swig-native python3-native bc-native openssl-native" + +UBOOT_MACHINE = "light_lpi4a_defconfig" + +EXTRA_OEMAKE = " \ + CROSS_COMPILE='${TARGET_PREFIX}' \ + ARCH=riscv \ + HOSTCC='${BUILD_CC}' \ + HOSTCXX='${BUILD_CXX}' \ + HOSTCFLAGS='${BUILD_CFLAGS}' \ + HOSTLDFLAGS='${BUILD_LDFLAGS}' \ +" + +do_configure() { + oe_runmake ${UBOOT_MACHINE} +} + +do_compile() { + LIBGCC_DIR=$(dirname $(${CC} -print-libgcc-file-name)) + oe_runmake PLATFORM_LIBGCC="-L ${LIBGCC_DIR} -lgcc" +} + +inherit deploy + +do_install() { + : +} + +do_deploy() { + if [ -f ${B}/u-boot-with-spl.bin ]; then + install -m 644 ${B}/u-boot-with-spl.bin ${DEPLOYDIR}/ + fi + if [ -f ${B}/u-boot.bin ]; then + install -m 644 ${B}/u-boot.bin ${DEPLOYDIR}/ + fi + if [ -f ${B}/spl/u-boot-spl.bin ]; then + install -m 644 ${B}/spl/u-boot-spl.bin ${DEPLOYDIR}/ + fi +} + +addtask deploy after do_compile + +TOOLCHAIN = "gcc" +COMPATIBLE_MACHINE = "(licheepi4a)" +PACKAGE_ARCH = "${MACHINE_ARCH}" +PARALLEL_MAKE = "" \ No newline at end of file diff --git a/vm_build_risc_v/meta-licheepi4a/recipes-core/images/licheepi4a-dpdk-image.bb b/vm_build_risc_v/meta-licheepi4a/recipes-core/images/licheepi4a-dpdk-image.bb new file mode 100644 index 0000000..f0082a0 --- /dev/null +++ b/vm_build_risc_v/meta-licheepi4a/recipes-core/images/licheepi4a-dpdk-image.bb @@ -0,0 +1,74 @@ +SUMMARY = "Lichee Pi 4A image with DPDK support" +DESCRIPTION = "Custom Yocto image for Lichee Pi 4A based on RevyOS kernel 6.6 \ +with DPDK data plane development kit and networking utilities." +LICENSE = "MIT" + +inherit core-image + +# Image Features +IMAGE_FEATURES += " \ + ssh-server-openssh \ + tools-debug \ + package-management \ +" + +# DPDK packages +IMAGE_INSTALL:append = " \ + dpdk \ + dpdk-examples \ + numactl \ +" + +# Networking tools +IMAGE_INSTALL:append = " \ + ethtool \ + iperf3 \ + iproute2 \ + iptables \ + tcpdump \ + net-tools \ + openssh-sftp-server \ + nfs-utils-client \ +" + +# System utilities +IMAGE_INSTALL:append = " \ + htop \ + vim \ + nano \ + less \ + screen \ + tmux \ + bash \ + procps \ + util-linux \ + pciutils \ + usbutils \ + i2c-tools \ + lmsensors \ +" + +# Development tools +IMAGE_INSTALL:append = " \ + gcc \ + g++ \ + make \ + cmake \ + pkgconfig \ + strace \ + gdb \ + python3 \ +" + +# Kernel modules +IMAGE_INSTALL:append = " \ + kernel-modules \ +" + +# Firmware +IMAGE_INSTALL:append = " \ + firmware-th1520 \ +" + +# Extra rootfs space +IMAGE_ROOTFS_EXTRA_SPACE = "1048576" diff --git a/vm_build_risc_v/meta-licheepi4a/recipes-kernel/linux/files/dpdk.cfg b/vm_build_risc_v/meta-licheepi4a/recipes-kernel/linux/files/dpdk.cfg new file mode 100644 index 0000000..5cdabda --- /dev/null +++ b/vm_build_risc_v/meta-licheepi4a/recipes-kernel/linux/files/dpdk.cfg @@ -0,0 +1,16 @@ +# DPDK kernel requirements for TH1520 +CONFIG_HUGETLBFS=y +CONFIG_HUGETLB_PAGE=y +CONFIG_UIO=m +CONFIG_UIO_PDRV_GENIRQ=m +CONFIG_VFIO=m +CONFIG_VFIO_PCI=m +CONFIG_VFIO_NOIOMMU=y +CONFIG_PCI_MSI=y +CONFIG_PROC_PAGE_MONITOR=y +CONFIG_CMA=y +CONFIG_DMA_CMA=y +CONFIG_EVENTFD=y +CONFIG_HIGH_RES_TIMERS=y +CONFIG_MODULES=y +CONFIG_MODULE_UNLOAD=y \ No newline at end of file diff --git a/vm_build_risc_v/meta-licheepi4a/recipes-kernel/linux/files/extra.cfg b/vm_build_risc_v/meta-licheepi4a/recipes-kernel/linux/files/extra.cfg new file mode 100644 index 0000000..189d913 --- /dev/null +++ b/vm_build_risc_v/meta-licheepi4a/recipes-kernel/linux/files/extra.cfg @@ -0,0 +1,40 @@ +# Extra kernel config for TH1520 / Lichee Pi 4A + +# TH1520 SoC support +CONFIG_ARCH_XUANTIE=y + +# Networking +CONFIG_NET=y +CONFIG_INET=y +CONFIG_IPV6=y +CONFIG_NETDEVICES=y +CONFIG_ETHERNET=y +CONFIG_STMMAC_ETH=y +CONFIG_STMMAC_PLATFORM=y + +# USB +CONFIG_USB=y +CONFIG_USB_DWC3=y +CONFIG_USB_DWC3_HOST=y +CONFIG_USB_XHCI_HCD=y +CONFIG_USB_STORAGE=y + +# WiFi +CONFIG_WIRELESS=y +CONFIG_CFG80211=m +CONFIG_MAC80211=m +CONFIG_WLAN=y + +# Filesystem +CONFIG_EXT4_FS=y +CONFIG_TMPFS=y +CONFIG_PROC_FS=y +CONFIG_SYSFS=y +CONFIG_DEVTMPFS=y +CONFIG_DEVTMPFS_MOUNT=y + +# SSH / debugging +CONFIG_UNIX=y +CONFIG_PACKET=y +CONFIG_NETFILTER=y +CONFIG_CRYPTO=y \ No newline at end of file diff --git a/vm_build_risc_v/meta-licheepi4a/recipes-kernel/linux/linux-revyos-th1520.bb b/vm_build_risc_v/meta-licheepi4a/recipes-kernel/linux/linux-revyos-th1520.bb new file mode 100644 index 0000000..7a1db92 --- /dev/null +++ b/vm_build_risc_v/meta-licheepi4a/recipes-kernel/linux/linux-revyos-th1520.bb @@ -0,0 +1,36 @@ +SUMMARY = "RevyOS Linux Kernel for T-Head TH1520 (Lichee Pi 4A)" +DESCRIPTION = "Linux kernel 6.6 from RevyOS project, optimized for TH1520 SoC \ +with full hardware support including WiFi, USB, GPU, Ethernet." +SECTION = "kernel" +LICENSE = "GPL-2.0-only" +LIC_FILES_CHKSUM = "file://COPYING;md5=6bc538ed5bd9a7fc9398086aedcd7e46" + +inherit kernel + +DEPENDS += "dtc-native" + +BRANCH = "master" +SRC_URI = "git://github.com/revyos/th1520-linux-kernel.git;protocol=https;branch=${BRANCH} \ + file://dpdk.cfg \ + file://extra.cfg \ + " + +SRCREV = "${AUTOREV}" + +S = "${WORKDIR}/git" + +LINUX_VERSION ?= "6.6" +LINUX_VERSION_EXTENSION = "-th1520-revyos" +PV = "${LINUX_VERSION}+git" + +KERNEL_VERSION_SANITY_SKIP = "1" + +KBUILD_DEFCONFIG = "defconfig" + +do_configure:prepend() { + if ! grep -q "CONFIG_ARCH_XUANTIE" ${B}/.config 2>/dev/null; then + echo "CONFIG_ARCH_XUANTIE=y" >> ${WORKDIR}/extra.cfg + fi +} + +COMPATIBLE_MACHINE = "(licheepi4a)" diff --git a/vm_build_risc_v/meta-licheepi4a/wic/licheepi4a-sdcard.wks b/vm_build_risc_v/meta-licheepi4a/wic/licheepi4a-sdcard.wks new file mode 100644 index 0000000..4c40948 --- /dev/null +++ b/vm_build_risc_v/meta-licheepi4a/wic/licheepi4a-sdcard.wks @@ -0,0 +1,7 @@ +# WKS file for Lichee Pi 4A SD card / eMMC image +# Layout matches RevyOS fastboot partition scheme: +# - boot partition: fw_dynamic.bin, Image, DTB, light_aon_fpga.bin +# - root partition: ext4 rootfs + +part /boot --source bootimg-partition --ondisk mmcblk0 --fstype=ext4 --label boot --active --align 4096 --size 200M +part / --source rootfs --ondisk mmcblk0 --fstype=ext4 --label root --align 4096 diff --git a/vm_build_risc_v/scripts/build/build.sh b/vm_build_risc_v/scripts/build/build.sh new file mode 100644 index 0000000..20bcaaf --- /dev/null +++ b/vm_build_risc_v/scripts/build/build.sh @@ -0,0 +1,88 @@ +#!/bin/bash + +set -e + +YOCTO_BRANCH="scarthgap" +WORKDIR="/home/builder/yocto" + +mkdir -p "${WORKDIR}" +sudo chown -R builder:builder "${WORKDIR}" +cd "${WORKDIR}" + +if [ ! -d "poky" ]; then + git clone -b "${YOCTO_BRANCH}" --depth=1 https://git.yoctoproject.org/poky +fi + +cd poky + +if [ ! -d "meta-openembedded" ]; then + git clone -b "${YOCTO_BRANCH}" --depth=1 https://github.com/openembedded/meta-openembedded +fi + +source oe-init-build-env build + +bitbake-layers add-layer ../meta-openembedded/meta-oe 2>/dev/null || true +bitbake-layers add-layer ../meta-openembedded/meta-python 2>/dev/null || true +bitbake-layers add-layer ../meta-openembedded/meta-networking 2>/dev/null || true +bitbake-layers add-layer ../meta-openembedded/meta-filesystems 2>/dev/null || true +bitbake-layers add-layer /home/builder/meta-cluster 2>/dev/null || true +bitbake-layers add-layer /home/builder/meta-licheepi4a 2>/dev/null || true + +if ! grep -q "### LICHEEPI4A CONFIG ###" conf/local.conf 2>/dev/null; then + cat >> conf/local.conf << 'CONFEOF' +### LICHEEPI4A CONFIG ### +# Machine: Lichee Pi 4A with TH1520 SoC +MACHINE = "licheepi4a" + +# Use RevyOS kernel 6.6 for full hardware support +PREFERRED_PROVIDER_virtual/kernel = "linux-revyos-th1520" + +# Extra disk space in rootfs +IMAGE_ROOTFS_EXTRA_SPACE = "1048576" + +# Accept all licenses (needed for some firmware blobs) +LICENSE_FLAGS_ACCEPTED = "commercial" + +# Package management on target +EXTRA_IMAGE_FEATURES += "package-management" + +# Disable network connectivity check (runs inside Docker) +CONNECTIVITY_CHECK_URIS = "" +### END LICHEEPI4A CONFIG ### +CONFEOF +fi + +bitbake licheepi4a-dpdk-image + +DEPLOY="tmp/deploy/images/licheepi4a" +BOOT_DIR=$(mktemp -d) +BOOT_IMG="${DEPLOY}/boot-licheepi4a.ext4" +BOOT_SIZE_MB=200 + +cp -v "${DEPLOY}/Image" "${BOOT_DIR}/" +cp -v "${DEPLOY}/fw_dynamic.bin" "${BOOT_DIR}/" +cp -v "${DEPLOY}/light_aon_fpga.bin" "${BOOT_DIR}/" + +mkdir -p "${BOOT_DIR}/dtbs" +cp -v "${DEPLOY}/th1520-lichee-pi-4a.dtb" "${BOOT_DIR}/dtbs/" + +mkdir -p "${BOOT_DIR}/extlinux" +cat > "${BOOT_DIR}/extlinux/extlinux.conf" << 'EXTEOF' +default yocto +menu title Lichee Pi 4A Boot Menu + +label yocto + menu label Yocto DPDK Image + linux /Image + fdt /dtbs/th1520-lichee-pi-4a.dtb + append root=PARTUUID=80a5a8e9-c744-491a-93c1-4f4194fd690a console=ttyS0,115200 rootwait rw earlycon clk_ignore_unused loglevel=7 rootfstype=ext4 +EXTEOF + +cat "${BOOT_DIR}/extlinux/extlinux.conf" + +dd if=/dev/zero of="${BOOT_IMG}" bs=1M count=${BOOT_SIZE_MB} +mkfs.ext4 -d "${BOOT_DIR}" -L boot "${BOOT_IMG}" + +rm -rf "${BOOT_DIR}" +echo "Created: ${BOOT_IMG}" +echo "Output artifacts in: ${DEPLOY}/" diff --git a/vm_build_risc_v/scripts/build/run.sh b/vm_build_risc_v/scripts/build/run.sh new file mode 100644 index 0000000..4c28f38 --- /dev/null +++ b/vm_build_risc_v/scripts/build/run.sh @@ -0,0 +1,19 @@ +#!/bin/bash + +set -e + +if [ -d "/home/builder/qemu/poky" ]; then + cd /home/builder/qemu/poky +else + echo "error: /home/builder/qemu/poky/ doesn't exist" + exit 1 +fi + +source oe-init-build-env + +if [ -d "tmp/deploy/images/qemuriscv64/" ]; then + cd tmp/deploy/images + runqemu qemuriscv64 slirp nographic +else + echo "error: Image doesn't exist. Please run \"make build\" before executing this command" +fi diff --git a/vm_build_risc_v/scripts/flash.sh b/vm_build_risc_v/scripts/flash.sh new file mode 100755 index 0000000..340364a --- /dev/null +++ b/vm_build_risc_v/scripts/flash.sh @@ -0,0 +1,54 @@ +#!/bin/bash + +set -e + +usage() { + cat << EOF +Usage: $0 [options] + +Options:" + -h, --help Show this help message and exit" + -i, --image-dir Directory containing the built Yocto images" + +This script flashes the built Yocto images to Lichee Pi 4A using fastboot." +EOF +} + +for arg in "$@"; do + case $arg in + -h|--help) + usage + exit 0 + ;; + -i|--image-dir) + shift + IMAGE_DIR="$1" + if [ ! -d "$IMAGE_DIR" ]; then + echo "Error: Image directory '$IMAGE_DIR' does not exist." + exit 1 + fi + ;; + *) + echo "Unknown option: $arg" + usage + exit 1 + ;; + esac +done + +if [ -z "$IMAGE_DIR" ]; then + IMAGE_DIR="../yocto/poky/build/tmp/deploy/images/licheepi4a" +fi + +lsusb | grep "T-HEAD" || { + echo "Error: Lichee Pi 4A not detected. Please connect the device via USB-C and ensure it's in fastboot mode (hold BOOT button while connecting)." + exit 1 +} + +sudo fastboot flash ram "${IMAGE_DIR}/u-boot-with-spl.bin" +sudo fastboot reboot +sleep 1 + +sudo fastboot flash uboot "${IMAGE_DIR}/u-boot-with-spl.bin" +sudo fastboot flash boot "${IMAGE_DIR}/boot-licheepi4a.ext4" +sudo fastboot flash root "${IMAGE_DIR}/licheepi4a-dpdk-image-licheepi4a.rootfs.ext4" \ No newline at end of file diff --git a/vm_build_risc_v/scripts/run.sh b/vm_build_risc_v/scripts/run.sh new file mode 100755 index 0000000..19094c1 --- /dev/null +++ b/vm_build_risc_v/scripts/run.sh @@ -0,0 +1,157 @@ +#!/bin/bash + +die() { echo "Error: $@" 1>&2; exit 1; } + +show_help() { + cat < 1) is **only supported with --use-host-qemu**. + - For any VM count (even 1), SSH ports must be listed in 'ports.conf' (one port per line). + - With --use-host-qemu: + - Each VM will use its own copy of the root filesystem (in 'build/vm_images'). + - SSH port forwarding is enabled (hostfwd=tcp::PORT-:22). + - Without --use-host-qemu: + - Only a single VM can be launched using Yocto's 'runqemu'. + - Port forwarding and rootfs copying are not used. + - VM logs are saved as 'vm_0.log', 'vm_1.log', etc. + +Examples: + $(basename "$0") --vm-count=2 --use-host-qemu -m 1G -smp 2 + $(basename "$0") -m 256M # Launch single VM using runqemu +EOF +} + +USE_HOST_QEMU=false +VM_COUNT=1 +PORTS_FILE="ports.conf" +VM_IMAGE_DIR="build/vm_images" +EXTRA_ARGS=() + +#parse arguments +for arg in "$@"; do + case $arg in + --use-host-qemu) + USE_HOST_QEMU=true + shift + ;; + --vm-count=*) + VM_COUNT="${arg#*=}" + shift + ;; + --help) + show_help + exit 0 + ;; + *) + EXTRA_ARGS+=("$arg") + shift + ;; + esac +done + +IMAGE_PATH="tmp/deploy/images/qemuriscv64/core-image-minimal-qemuriscv64.ext4" +KERNEL_IMAGE_PATH="tmp/deploy/images/qemuriscv64/Image" + +[ -d build ] || die "The script must be started from the 'poky' directory." + +if [ "$USE_HOST_QEMU" = true ]; then + [ -f "$PORTS_FILE" ] || die "Port config file '$PORTS_FILE' not found." + + mapfile -t PORTS < "$PORTS_FILE" + [ "${#PORTS[@]}" -lt "$VM_COUNT" ] && die "Not enough ports in $PORTS_FILE for $VM_COUNT VMs." + + command -v qemu-system-riscv64 >/dev/null || die "Host QEMU not found!" + QEMU_VERSION=$( + qemu-system-riscv64 --version 2>/dev/null | grep -oP '([0-9]+)\.([0-9]+)' | head -n1 + ) + QEMU_MAJOR=$(echo "$QEMU_VERSION" | cut -d. -f1) + QEMU_MINOR=$(echo "$QEMU_VERSION" | cut -d. -f2) + [ "$QEMU_MAJOR" -lt 7 ] && die "QEMU version must be >= 7. Found: $QEMU_VERSION" + + cd build || die "Failed to enter build directory." + + [ -f "$KERNEL_IMAGE_PATH" ] || die "Kernel image not found: $KERNEL_IMAGE_PATH" + +else + [ -f oe-init-build-env ] || die "'oe-init-build-env' not found!" + source oe-init-build-env build || die "Failed to source Yocto environment." + command -v runqemu >/dev/null || die "runqemu not found." +fi + +[ -f "$IMAGE_PATH" ] || die "Rootfs image not found! Run 'bitbake core-image-minimal' first." + +#check if QEMU is already running +PIDS=$(pgrep -f qemu-system-riscv64) +if [ -n "$PIDS" ]; then + echo "Warning: QEMU is already running. The virtual machine might be active!" + echo "Terminating the existing process..." + + pkill -f qemu-system-riscv64 + + for PID in $PIDS; do + if command -v pidwait >/dev/null 2>&1; then + pidwait $PID 2>/dev/null || wait $PID 2>/dev/null + else + wait $PID 2>/dev/null + fi + done +fi + +#special case: one VM with runqemu +if [ "$USE_HOST_QEMU" = false ] && [ "$VM_COUNT" -eq 1 ]; then + echo "Launching single VM using runqemu..." + runqemu qemuriscv64 nographic "${EXTRA_ARGS[@]}" > "vm_0.log" 2>&1 & + echo "VM started in background. Log: vm_0.log" + exit 0 +fi + +#multiple VMs only supported with host QEMU +if [ "$USE_HOST_QEMU" = false ]; then + die "Multiple VM launch is only supported with host QEMU (--use-host-qemu)" +fi + +mkdir -p "$VM_IMAGE_DIR" + +#multiple VM +for ((i=0; i "$LOGFILE" 2>&1 & +done + +echo "All $VM_COUNT VMs started in background. Logs: vm_*.log" diff --git a/vm_build_risc_v/scripts/stop_vms.sh b/vm_build_risc_v/scripts/stop_vms.sh new file mode 100644 index 0000000..419cb0a --- /dev/null +++ b/vm_build_risc_v/scripts/stop_vms.sh @@ -0,0 +1,23 @@ +#!/bin/bash + +die() { echo "Error: $@" 1>&2; exit 1; } + +PIDS=$(pgrep -f qemu-system-riscv64) + +if [ -n "$PIDS" ]; then + echo "Terminating the existing process..." + + pkill -f qemu-system-riscv64 || die "Failed to terminate QEMU processes." + + for PID in $PIDS; do + if command -v pidwait >/dev/null 2>&1; then + pidwait $PID 2>/dev/null || wait $PID 2>/dev/null + else + wait $PID 2>/dev/null + fi + done + + echo "All QEMU processes terminated successfully." +else + echo "No running QEMU processes found." +fi diff --git a/vm_build_risc_v/wiki/own_layer/README.md b/vm_build_risc_v/wiki/own_layer/README.md new file mode 100644 index 0000000..5256ffb --- /dev/null +++ b/vm_build_risc_v/wiki/own_layer/README.md @@ -0,0 +1,155 @@ +# Сборка собственного слоя Yocto для кластера (meta-cluster) +## 1. Подготовка окружения +### Установка зависимостей (если не установлены) +```sh +sudo apt update && sudo apt install -y gawk wget git diffstat unzip texinfo gcc g++ \ + build-essential chrpath socat cpio python3 python3-pip python3-pexpect xz-utils \ + debianutils iputils-ping python3-git python3-jinja2 libegl1 libsdl1.2-dev pylint \ + xterm python3-subunit mesa-common-dev zstd liblz4-tool +``` + +### Клонирование Yocto и слоев +```sh +mkdir ~/yocto-riscv +cd ~/yocto-riscv +git clone -b kirkstone git://git.yoctoproject.org/poky.git +git clone -b kirkstone https://github.com/riscv/meta-riscv.git +git clone -b kirkstone https://git.openembedded.org/meta-openembedded +git clone -b kirkstone git://git.yoctoproject.org/meta-virtualization +``` + +### Инициализация окружения Yocto +```sh +cd poky +source oe-init-build-env +``` + +--- + +## 2. Создание собственного слоя `meta-cluster` +```sh +cd ~/yocto-riscv +bitbake-layers create-layer meta-cluster +``` +Добавляем слой в `bblayers.conf`: +```sh +nano ~/yocto-riscv/poky/build/conf/bblayers.conf +``` +Добавляем строку: +``` +BBLAYERS += "${TOPDIR}/../meta-cluster" +``` + +--- + +## 3. Создание заглушек для `controller` и `unit` + +### `cluster-controller` +Создаем папку и файл рецепта: +```sh +mkdir -p ~/yocto-riscv/meta-cluster/recipes-cluster/controller +nano ~/yocto-riscv/meta-cluster/recipes-cluster/controller/cluster-controller.bb +``` +Добавляем следующий код: +```bitbake +DESCRIPTION = "Cluster Controller Stub" +LICENSE = "MIT" +LIC_FILES_CHKSUM = "file://${COMMON_LICENSE_DIR}/MIT;md5=0835ade698e0bcf8506ecda2f7b4f302" + +SRC_URI = "file://controller.sh" + +do_install() { + install -d ${D}/usr/bin + install -m 0755 ${WORKDIR}/controller.sh ${D}/usr/bin/controller +} +FILES:${PN} += "/usr/bin/controller" +``` + +Создаем заглушку `controller.sh`: +```sh +mkdir -p ~/yocto-riscv/meta-cluster/recipes-cluster/controller/files +nano ~/yocto-riscv/meta-cluster/recipes-cluster/controller/files/controller.sh +``` +Добавляем: +```sh +#!/bin/sh +echo "Cluster Controller is running" +``` +Делаем файл исполняемым: +```sh +chmod +x ~/yocto-riscv/meta-cluster/recipes-cluster/controller/files/controller.sh +``` + +--- + +### `cluster-unit` +Создаем папку и файл рецепта: +```sh +mkdir -p ~/yocto-riscv/meta-cluster/recipes-cluster/unit +nano ~/yocto-riscv/meta-cluster/recipes-cluster/unit/cluster-unit.bb +``` +Добавляем код: +```bitbake +DESCRIPTION = "Cluster Unit Stub" +LICENSE = "MIT" +LIC_FILES_CHKSUM = "file://${COMMON_LICENSE_DIR}/MIT;md5=0835ade698e0bcf8506ecda2f7b4f302" + +SRC_URI = "file://unit.sh" + +do_install() { + install -d ${D}/usr/bin + install -m 0755 ${WORKDIR}/unit.sh ${D}/usr/bin/unit +} +FILES:${PN} += "/usr/bin/unit" +``` + +Создаем заглушку `unit.sh`: +```sh +mkdir -p ~/yocto-riscv/meta-cluster/recipes-cluster/unit/files +nano ~/yocto-riscv/meta-cluster/recipes-cluster/unit/files/unit.sh +``` +Добавляем: +```sh +#!/bin/sh +echo "Cluster Unit is running" +``` +Делаем файл исполняемым: +```sh +chmod +x ~/yocto-riscv/meta-cluster/recipes-cluster/unit/files/unit.sh +``` + +--- + +## 4. Добавление пакетов в сборку +Редактируем `local.conf`: +```sh +nano ~/yocto-riscv/poky/build/conf/local.conf +``` +Добавляем: +``` +IMAGE_INSTALL:append = " cluster-controller cluster-unit" +``` + +--- + +## 5. Сборка образа +```sh +bitbake core-image-minimal +``` + +--- + +## 6. Запуск в QEMU и проверка +```sh +runqemu qemuriscv64 +``` +Проверяем заглушки: +```sh +controller +unit +``` +Они должны вывести: +``` +Cluster Controller is running +Cluster Unit is running +``` \ No newline at end of file