diff --git a/image/conf/bblayers.conf b/image/conf/bblayers.conf index 5cff68b..2f10d69 100644 --- a/image/conf/bblayers.conf +++ b/image/conf/bblayers.conf @@ -12,6 +12,7 @@ BBLAYERS ?= " \ /workspace/yocto/meta-openembedded/meta-oe \ /workspace/yocto/meta-openembedded/meta-python \ /workspace/yocto/meta-openembedded/meta-multimedia \ + /workspace/yocto/meta-openembedded/meta-networking \ /workspace/yocto/meta-rust-bin \ /workspace/meta-layers/meta-fcb-looper \ " diff --git a/image/conf/local.conf b/image/conf/local.conf index a14bc3c..07f706f 100644 --- a/image/conf/local.conf +++ b/image/conf/local.conf @@ -35,4 +35,12 @@ VIRTUAL-RUNTIME_initscripts = "" CORE_IMAGE_EXTRA_INSTALL += "gui-app weston liberation-fonts" # Needed to enable terminal on tty2 -EXTRA_IMAGE_FEATURES += "debug-tweaks" \ No newline at end of file +EXTRA_IMAGE_FEATURES += "debug-tweaks" + +# WiFi support - Intel Centrino Advanced-N 6235 specific +DISTRO_FEATURES += "wifi opengl" +IMAGE_INSTALL:append = " wpa-supplicant iw linux-firmware packagegroup-base-wifi pciutils usbutils" +IMAGE_INSTALL:append = " linux-firmware-iwlwifi-6000g2b-6" + +# Enable iwlwifi driver in kernel +KERNEL_FEATURES:append = " features/iwlwifi/iwlwifi.scc" \ No newline at end of file diff --git a/image/implementation_plan.md b/image/implementation_plan.md index 9450b44..6ce39f5 100644 --- a/image/implementation_plan.md +++ b/image/implementation_plan.md @@ -6,7 +6,7 @@ Build a minimal, real-time Linux system for an audio looper pedal using Yocto Pr **Key Requirements:** - x64 hardware (NUC-class) -- Static IP: 192.168.0.50 +- Static IP: 192.168.0.25 - SSH access with public key authentication - USB live installer that can dd copy to disk - A/B partition scheme for reliable updates @@ -67,843 +67,4 @@ The run script wraps docker compose run and adds some environment variables. **Installation Testing:** Boot USB installer in QEMU, SSH in, run installation script on virtual disk, then boot installed system to verify complete workflow. -The implementation should focus on creating minimal, working recipes that can be tested incrementally in QEMU before hardware deployment. Each component (kernel, network, SSH, audio, updates) should be testable independently. - -## Core Architecture and Directory Structure - -The system integrates **Yocto Project 5.0 Scarthgap LTS** with Docker containerization, organizing all components within a Rust workspace directory structure. This approach minimizes host dependencies while providing a robust embedded Linux development environment with reliable over-the-air updates. - -### Project Organization Within Rust Workspace - -``` -image/ -├── Dockerfile -├── docker-compose.yml -├── run -│ -├── yocto/ -│ ├── poky/ -│ ├── meta-openembedded/ -│ ├── meta-rust-bin/ # Pre-built Rust toolchain -│ └── meta-swupdate/ # SWUpdate integration -├── meta-layers/ -│ ├── meta-custom/ # Custom project layer -│ │ ├── conf/ -│ │ │ ├── distro/ -│ │ │ ├── machine/ -│ │ │ └── layer.conf -│ │ ├── recipes-apps/ -│ │ │ └── egui-kiosk/ -│ │ ├── recipes-core/ -│ │ │ └── images/ -│ │ └── recipes-support/ -│ │ └── swupdate/ -│ └── meta-custom-bsp/ # BSP-specific configurations -├── scripts/ -│ ├── setup-environment.sh -│ ├── build-images.sh -│ ├── deploy-qemu.sh -│ └── create-update.sh -└── conf/ - ├── local.conf - └── bblayers.conf -``` - -The **Rust workspace configuration** unifies all application components: - -```toml -# rust-workspace/Cargo.toml -[workspace] -resolver = "2" -members = [ - "apps/*", - "libs/*" -] - -[workspace.package] -version = "1.0.0" -edition = "2021" -rust-version = "1.70" - -[workspace.dependencies] -egui = "0.24" -eframe = { version = "0.24", features = ["wgpu"] } -serde = { version = "1.0", features = ["derive"] } -tokio = { version = "1.0", features = ["rt-multi-thread"] } -``` - -## Yocto Layer Creation and Rust Integration - -The custom layer provides comprehensive Rust application support with modern toolchain integration using **meta-rust-bin** for faster builds and easier maintenance. - -### Custom Layer Configuration - -```bash -# meta-layers/meta-custom/conf/layer.conf -BBPATH .= ":${LAYERDIR}" -BBFILES += "${LAYERDIR}/recipes-*/*/*.bb ${LAYERDIR}/recipes-*/*/*.bbappend" - -BBFILE_COLLECTIONS += "custom-layer" -BBFILE_PATTERN_custom-layer = "^${LAYERDIR}/" -BBFILE_PRIORITY_custom-layer = "10" - -LAYERVERSION_custom-layer = "1" -LAYERSERIES_COMPAT_custom-layer = "scarthgap" - -LAYERDEPENDS_custom-layer = "core openembedded-layer meta-rust-bin" -``` - -### Rust egui Application Recipe - -The recipe integrates seamlessly with the Rust workspace, handling cross-compilation and dependencies automatically: - -```bash -# meta-layers/meta-custom/recipes-apps/egui-kiosk/egui-kiosk_1.0.bb -SUMMARY = "Rust egui Fullscreen Kiosk Application" -DESCRIPTION = "Cross-platform GUI kiosk application built with egui framework" -LICENSE = "MIT" -LIC_FILES_CHKSUM = "file://LICENSE;md5=935a9b2a57ae70704d8125b9c0e39059" - -inherit cargo_bin systemd - -# Enable network access for cargo dependencies -do_compile[network] = "1" - -SRC_URI = "\ - git://localhost/rust-workspace.git;protocol=file;branch=main \ - file://egui-kiosk.service \ - file://egui-kiosk-init.sh \ - file://weston.ini \ -" - -SRCREV = "${AUTOREV}" -S = "${WORKDIR}/git" - -# Point to specific app in workspace -CARGO_SRC_DIR = "apps/egui-kiosk" - -# Cargo features for kiosk mode -CARGO_FEATURES = "kiosk-mode fullscreen wayland" - -# Runtime dependencies for GUI applications -RDEPENDS_${PN} += "\ - wayland \ - weston \ - wayland-protocols \ - libxkbcommon \ - fontconfig \ - liberation-fonts \ - systemd \ -" - -# Build dependencies -DEPENDS += "\ - wayland-native \ - wayland-protocols-native \ - libxkbcommon \ - fontconfig \ -" - -# Install systemd service and configuration -do_install_append() { - install -d ${D}${systemd_system_unitdir} - install -m 0644 ${WORKDIR}/egui-kiosk.service ${D}${systemd_system_unitdir}/ - - install -d ${D}${bindir} - install -m 0755 ${WORKDIR}/egui-kiosk-init.sh ${D}${bindir}/ - - install -d ${D}${sysconfdir}/xdg/weston - install -m 0644 ${WORKDIR}/weston.ini ${D}${sysconfdir}/xdg/weston/ -} - -SYSTEMD_SERVICE_${PN} = "egui-kiosk.service" -SYSTEMD_AUTO_ENABLE_${PN} = "enable" - -FILES_${PN} += "\ - ${systemd_system_unitdir}/egui-kiosk.service \ - ${bindir}/egui-kiosk-init.sh \ - ${sysconfdir}/xdg/weston/weston.ini \ -" -``` - -## Rust egui Application Implementation - -The application leverages **egui 0.24** with fullscreen kiosk capabilities and system integration: - -```rust -// rust-workspace/apps/egui-kiosk/src/main.rs -use eframe::{egui, App, Frame, NativeOptions}; -use std::env; - -struct KioskApp { - counter: i32, - show_confirmation_dialog: bool, -} - -impl KioskApp { - fn new() -> Self { - Self { - counter: 0, - show_confirmation_dialog: false, - } - } -} - -impl App for KioskApp { - fn update(&mut self, ctx: &egui::Context, _frame: &mut Frame) { - egui::CentralPanel::default().show(ctx, |ui| { - ui.heading("Production Kiosk System"); - - ui.add_space(20.0); - - ui.horizontal(|ui| { - if ui.button("Increment").clicked() { - self.counter += 1; - } - ui.label(format!("Counter: {}", self.counter)); - }); - - ui.add_space(20.0); - - if ui.button("System Settings").clicked() { - self.show_confirmation_dialog = true; - } - }); - - if self.show_confirmation_dialog { - egui::Window::new("Confirm Action") - .collapsible(false) - .resizable(false) - .show(ctx, |ui| { - ui.label("Are you sure you want to access system settings?"); - ui.horizontal(|ui| { - if ui.button("Yes").clicked() { - // Handle system settings access - self.show_confirmation_dialog = false; - } - if ui.button("No").clicked() { - self.show_confirmation_dialog = false; - } - }); - }); - } - } -} - -fn main() -> Result<(), eframe::Error> { - let options = NativeOptions { - fullscreen: true, - decorated: false, - resizable: false, - always_on_top: true, - ..Default::default() - }; - - eframe::run_native( - "Kiosk Application", - options, - Box::new(|_cc| Box::new(KioskApp::new())), - ) -} -``` - -## Systemd Service Configuration for Auto-Start - -The systemd service ensures reliable application startup with proper dependencies and restart capabilities: - -```ini -# files/egui-kiosk.service -[Unit] -Description=Rust egui Kiosk Application -Documentation=https://github.com/company/egui-kiosk -After=graphical.target weston.service -Wants=weston.service -Requires=graphical.target -StartLimitIntervalSec=30 -StartLimitBurst=3 - -[Service] -Type=simple -User=kiosk -Group=kiosk -Environment="DISPLAY=:0" -Environment="WAYLAND_DISPLAY=wayland-0" -Environment="XDG_RUNTIME_DIR=/run/user/1000" -Environment="RUST_LOG=info" - -ExecStartPre=/bin/sleep 3 -ExecStart=/usr/bin/egui-kiosk -ExecReload=/bin/kill -HUP $MAINPID - -Restart=always -RestartSec=5 -WatchdogSec=30 - -# Resource limits -MemoryMax=256M -CPUQuota=80% - -# Security settings -NoNewPrivileges=true -PrivateTmp=true -ProtectSystem=strict -ProtectHome=true -ReadWritePaths=/tmp /run/user/1000 - -[Install] -WantedBy=graphical.target -``` - -## initramfs Integration Strategy - -The initramfs approach embeds the Rust application directly in the boot image for fastest startup times and minimal attack surface. - -### initramfs Image Recipe - -```bash -# meta-layers/meta-custom/recipes-core/images/initramfs-egui-image.bb -DESCRIPTION = "Minimal initramfs image with Rust GUI application" - -PACKAGE_INSTALL = "\ - initramfs-framework-base \ - busybox \ - base-files \ - egui-kiosk \ - weston \ - liberation-fonts \ - ${VIRTUAL-RUNTIME_base-utils} \ -" - -# Minimize image size -IMAGE_LINGUAS = "" -LICENSE = "MIT" - -inherit core-image - -# Optimize for minimal size -IMAGE_ROOTFS_SIZE ?= "32768" -IMAGE_ROOTFS_EXTRA_SPACE = "0" -IMAGE_OVERHEAD_FACTOR = "1.0" - -# Bundle with kernel -INITRAMFS_IMAGE_BUNDLE = "1" -``` - -### initramfs Boot Module - -```bash -# meta-layers/meta-custom/recipes-core/initramfs-egui-boot/files/egui-boot -#!/bin/sh - -egui_boot_enabled() { - return 0 -} - -egui_boot_run() { - msg "Starting GUI boot sequence..." - - # Mount essential filesystems - mount -t proc proc /proc - mount -t sysfs sysfs /sys - mount -t devtmpfs devtmpfs /dev - - # Setup runtime directories - mkdir -p /run/user/1000 - chown 1000:1000 /run/user/1000 - - # Start Wayland compositor - export XDG_RUNTIME_DIR="/run/user/1000" - export WAYLAND_DISPLAY="wayland-0" - - weston --backend=drm-backend.so --idle-time=0 & - sleep 2 - - # Start Rust GUI application - egui-kiosk & - - msg "GUI application started successfully" -} -``` - -## SWUpdate A/B Partitioning System - -The A/B update system provides **atomic updates with automatic rollback**, ensuring system reliability even during power failures or failed updates. - -### Partition Layout Configuration - -```bash -# Recommended eMMC/SSD partition layout -/dev/sda -├── sda1 # Boot partition (EFI/BIOS, 64MB) -├── sda2 # RootFS A (ext4, 2GB) -├── sda3 # RootFS B (ext4, 2GB) -├── sda4 # Data partition (ext4, remaining) -└── sda5 # U-Boot environment (1MB) -``` - -### WIC Image Configuration for A/B Layout - -```bash -# meta-layers/meta-custom/wic/dual-rootfs.wks -# Boot partition with bootloader -part /boot --source bootimg-partition --sourceparams="loader=u-boot" \ - --ondisk sda --fstype=vfat --label boot --size 64M --align 1024 - -# Root filesystem A (active partition) -part / --source rootfs --rootfs-dir=${IMAGE_ROOTFS} \ - --ondisk sda --fstype=ext4 --label rootfs_a --size 2G - -# Root filesystem B (update target, initially empty) -part --ondisk sda --fstype=ext4 --label rootfs_b --size 2G - -# Persistent data partition -part /data --ondisk sda --fstype=ext4 --label data --size 1G \ - --fsoptions="defaults" - -# U-Boot environment for A/B switching -part --ondisk sda --size 1M --label uboot_env - -bootloader u-boot -``` - -### SWUpdate Configuration - -```libconfig -# files/sw-description -software = -{ - version = "1.0.0"; - description = "Dual-copy Rust GUI system update"; - - hardware-compatibility: [ "1.0", "2.0" ]; - - stable = { - copy1 = { - images: ( - { - filename = "core-image-egui-minimal.ext4.gz"; - type = "raw"; - compressed = true; - device = "/dev/sda2"; - sha256 = "$swupdate_get_sha256(core-image-egui-minimal.ext4.gz)"; - } - ); - - scripts: ( - { - filename = "post-update.sh"; - type = "shellscript"; - } - ); - - bootenv: ( - { - name = "rootfs_part"; - value = "2"; - }, - { - name = "upgrade_available"; - value = "1"; - } - ); - }; - - copy2 = { - images: ( - { - filename = "core-image-egui-minimal.ext4.gz"; - type = "raw"; - compressed = true; - device = "/dev/sda3"; - sha256 = "$swupdate_get_sha256(core-image-egui-minimal.ext4.gz)"; - } - ); - - scripts: ( - { - filename = "post-update.sh"; - type = "shellscript"; - } - ); - - bootenv: ( - { - name = "rootfs_part"; - value = "3"; - }, - { - name = "upgrade_available"; - value = "1"; - } - ); - }; - }; - - scripts: ( - { - filename = "partition-select.lua"; - type = "lua"; - } - ); -} -``` - -### Automatic Partition Selection Logic - -```lua --- files/partition-select.lua -function preinst() - -- Determine current root partition - local f = io.open("/proc/cmdline", "r") - local cmdline = f:read("*all") - f:close() - - local current_part = cmdline:match("root=/dev/sda(%d)") - - if current_part == "2" then - -- Currently on partition 2, update partition 3 - swupdate.notify(RECOVERY, "Updating partition 3 (copy2)") - return 0, "copy2" - else - -- Currently on partition 3 or default, update partition 2 - swupdate.notify(RECOVERY, "Updating partition 2 (copy1)") - return 0, "copy1" - end -end - -function postinst() - swupdate.notify(RECOVERY, "Update installation completed") - return 0 -end -``` - -## QEMU Testing Configuration - -QEMU provides comprehensive testing capabilities with **KVM acceleration** and proper graphics support for egui application validation. - -### QEMU Launch Configuration - -```bash -#!/bin/bash -# scripts/deploy-qemu.sh - -set -e - -IMAGE_PATH="yocto/build/tmp/deploy/images/qemux86-64" -KERNEL="${IMAGE_PATH}/bzImage" -ROOTFS="${IMAGE_PATH}/core-image-egui-minimal-qemux86-64.ext4" - -# Launch QEMU with graphics support -qemu-system-x86_64 \ - -enable-kvm \ - -m 2048 \ - -smp 4 \ - -cpu host \ - -kernel "${KERNEL}" \ - -drive file="${ROOTFS}",if=virtio,format=raw \ - -append "root=/dev/vda rw console=ttyS0 console=tty0 quiet" \ - -netdev user,id=net0,hostfwd=tcp::8080-:8080,hostfwd=tcp::2222-:22 \ - -device virtio-net-pci,netdev=net0 \ - -device virtio-vga-gl \ - -display gtk,gl=on \ - -audiodev pulse,id=audio0 \ - -device intel-hda \ - -device hda-duplex,audiodev=audio0 \ - -serial stdio \ - -show-cursor -``` - -### Automated Testing Framework - -```bash -#!/bin/bash -# scripts/test-system.sh - -test_boot_time() { - echo "Testing boot time..." - start_time=$(date +%s.%N) - - timeout 60 qemu-system-x86_64 \ - -enable-kvm -m 1024 -nographic \ - -kernel "${KERNEL}" \ - -drive file="${ROOTFS}",if=virtio,format=raw \ - -append "root=/dev/vda rw console=ttyS0 init=/bin/sh" & - - QEMU_PID=$! - wait $QEMU_PID - - end_time=$(date +%s.%N) - boot_time=$(echo "$end_time - $start_time" | bc) - - echo "Boot time: ${boot_time} seconds" - if (( $(echo "$boot_time < 15" | bc -l) )); then - echo "PASS: Boot time acceptable" - else - echo "FAIL: Boot time too slow" - exit 1 - fi -} - -test_application_startup() { - echo "Testing application startup..." - # Launch system and verify egui application starts - timeout 120 expect -c ' - spawn qemu-system-x86_64 -enable-kvm -m 1024 -nographic \ - -kernel '"${KERNEL}"' \ - -drive file='"${ROOTFS}"',if=virtio,format=raw \ - -append "root=/dev/vda rw console=ttyS0" - - expect "login:" { send "root\r" } - expect "# " { send "systemctl status egui-kiosk\r" } - expect "active (running)" { - puts "SUCCESS: egui application running" - exit 0 - } - timeout { - puts "FAIL: Application not started in time" - exit 1 - } - ' -} - -test_boot_time -test_application_startup -echo "All tests passed!" -``` - -## Minimal Linux System Configuration - -The system optimizes for **minimal resource usage** while maintaining essential functionality for the Rust GUI application. - -### Minimal Image Recipe - -```bash -# meta-layers/meta-custom/recipes-core/images/core-image-egui-minimal.bb -SUMMARY = "Minimal Linux system with Rust egui application" - -IMAGE_INSTALL = "\ - packagegroup-core-boot \ - egui-kiosk \ - weston \ - liberation-fonts \ - systemd \ - networkmanager \ - swupdate \ - ${CORE_IMAGE_EXTRA_INSTALL} \ -" - -# Remove unnecessary features -DISTRO_FEATURES_remove = "alsa bluetooth wifi nfs zeroconf pci 3g nfc x11" -IMAGE_FEATURES = "read-only-rootfs" - -# Package optimization -PACKAGE_CLASSES = "package_ipk" -IMAGE_FSTYPES = "ext4 ext4.gz wic" - -# Size constraints -IMAGE_ROOTFS_SIZE ?= "512000" # 512MB -IMAGE_OVERHEAD_FACTOR = "1.1" - -LICENSE = "MIT" - -inherit core-image - -# Remove debug packages -PACKAGE_EXCLUDE = "\ - gdb \ - gdbserver \ - strace \ - ${@bb.utils.contains('DISTRO_FEATURES', 'x11', 'x11-common', '', d)} \ -" - -# Optimize systemd -IMAGE_INSTALL_append = " systemd-analyze" -SYSTEMD_DEFAULT_TARGET = "graphical.target" -``` - -### System Optimization Configuration - -```bash -# meta-layers/meta-custom/recipes-core/systemd/systemd/system.conf -[Manager] -LogLevel=warning -LogTarget=kmsg -SystemMaxUse=50M -RuntimeMaxUse=50M -DefaultTimeoutStartSec=10s -DefaultTimeoutStopSec=5s -DefaultRestartSec=5s -``` - -## Build and Deployment Workflows - -The complete workflow integrates Docker containerization with automated builds, testing, and deployment. - -### Environment Setup Script - -```bash -#!/bin/bash -# scripts/setup-environment.sh - -set -e - -echo "Setting up Yocto development environment..." - -# Export user ID for Docker -export USER_ID=$(id -u) -export GROUP_ID=$(id -g) - -# Initialize Git repositories if not present -if [ ! -d "yocto/sources/poky" ]; then - echo "Cloning Yocto repositories..." - mkdir -p yocto/sources - cd yocto/sources - - git clone git://git.yoctoproject.org/poky -b scarthgap - git clone git://git.openembedded.org/meta-openembedded -b scarthgap - git clone https://github.com/rust-embedded/meta-rust-bin.git -b master - git clone https://github.com/sbabic/meta-swupdate.git -b scarthgap - - cd ../.. -fi - -# Start Docker environment -echo "Starting containerized build environment..." -docker-compose up -d yocto-builder - -# Wait for container to be ready -sleep 5 - -# Initialize build environment inside container -docker-compose exec yocto-builder bash -c " - cd /workspace/yocto && - source sources/poky/oe-init-build-env build && - - # Configure layers - bitbake-layers add-layer ../sources/meta-openembedded/meta-oe - bitbake-layers add-layer ../sources/meta-openembedded/meta-python - bitbake-layers add-layer ../sources/meta-openembedded/meta-networking - bitbake-layers add-layer ../sources/meta-rust-bin - bitbake-layers add-layer ../sources/meta-swupdate - bitbake-layers add-layer ../../meta-layers/meta-custom - - # Configure build - cat >> conf/local.conf << 'EOF' -MACHINE = \"qemux86-64\" -DISTRO = \"poky\" - -# Rust support -ENABLE_RUST = \"1\" - -# Performance optimizations -BB_NUMBER_THREADS = \"8\" -PARALLEL_MAKE = \"-j8\" - -# Package management -PACKAGE_CLASSES = \"package_ipk\" - -# SWUpdate integration -PREFERRED_PROVIDER_u-boot-fw-utils = \"libubootenv\" -IMAGE_FSTYPES += \"ext4.gz wic\" - -# Add applications to rootfs -CORE_IMAGE_EXTRA_INSTALL += \"egui-kiosk swupdate swupdate-www\" - -# Enable systemd -DISTRO_FEATURES_append = \" systemd\" -VIRTUAL-RUNTIME_init_manager = \"systemd\" -DISTRO_FEATURES_BACKFILL_CONSIDERED = \"sysvinit\" -VIRTUAL-RUNTIME_initscripts = \"\" -EOF -" - -echo "Environment setup complete!" -echo "To enter the build environment, run: docker-compose exec yocto-builder bash" -``` - -### Complete Build Script - -```bash -#!/bin/bash -# scripts/build-images.sh - -set -e - -echo "Building Yocto images..." - -# Build in container -docker-compose exec yocto-builder bash -c " - cd /workspace/yocto && - source sources/poky/oe-init-build-env build && - - # Build core system - echo 'Building minimal egui system...' - bitbake core-image-egui-minimal - - # Build update image - echo 'Building SWUpdate package...' - bitbake update-image - - # Build SDK for development - echo 'Building extensible SDK...' - bitbake core-image-egui-minimal -c populate_sdk_ext - - echo 'Build completed successfully!' - echo 'Images available in: build/tmp/deploy/images/qemux86-64/' -" - -# Test the built image -echo "Testing built image..." -./scripts/test-system.sh - -echo "Build and test completed successfully!" -``` - -### Update Package Creation - -```bash -#!/bin/bash -# scripts/create-update.sh - -set -e - -VERSION=${1:-$(date +%Y%m%d-%H%M%S)} -OUTPUT_DIR="updates" - -echo "Creating SWUpdate package version: $VERSION" - -mkdir -p $OUTPUT_DIR - -# Build update in container -docker-compose exec yocto-builder bash -c " - cd /workspace/yocto && - source sources/poky/oe-init-build-env build && - - # Update version in sw-description - sed -i 's/version = \".*\"/version = \"$VERSION\"/' \ - /workspace/meta-layers/meta-custom/recipes-support/update-image/files/sw-description - - # Build update package - bitbake update-image - - # Copy to output directory - cp tmp/deploy/images/qemux86-64/update-image-qemux86-64.swu \ - /workspace/$OUTPUT_DIR/system-update-$VERSION.swu -" - -echo "Update package created: $OUTPUT_DIR/system-update-$VERSION.swu" -echo "Deploy with: swupdate -i $OUTPUT_DIR/system-update-$VERSION.swu" -``` - -## Production Deployment and Validation - -This comprehensive system provides a **production-ready embedded Linux platform** with automatic updates, security hardening, and reliable operation. The containerized build approach ensures consistent results across development teams, while the A/B update system provides robust field update capabilities with automatic rollback protection. - -**Key advantages of this architecture:** -- **Minimal host dependencies** through complete Docker containerization -- **Fast development cycles** with shared state caching and incremental builds -- **Reliable updates** with atomic A/B partition switching and automatic rollback -- **Optimized performance** with minimal Linux configuration and Rust applications -- **Comprehensive testing** with QEMU emulation and automated validation - -The system scales from single-developer projects to large embedded teams, providing a solid foundation for Rust-based embedded GUI applications with modern DevOps practices and reliable over-the-air update capabilities. \ No newline at end of file +The implementation should focus on creating minimal, working recipes that can be tested incrementally in QEMU before hardware deployment. Each component (kernel, network, SSH, audio, updates) should be testable independently. \ No newline at end of file diff --git a/image/meta-layers/meta-fcb-looper/recipes-connectivity/wifi-config/files/25-wireless.network b/image/meta-layers/meta-fcb-looper/recipes-connectivity/wifi-config/files/25-wireless.network new file mode 100644 index 0000000..81a8c8a --- /dev/null +++ b/image/meta-layers/meta-fcb-looper/recipes-connectivity/wifi-config/files/25-wireless.network @@ -0,0 +1,12 @@ +[Match] +Name=wlp2s0 + +[Network] +DHCP=no +Address=192.168.0.25/24 +Gateway=192.168.0.1 +DNS=192.168.0.1 +FallbackDNS=8.8.8.8 1.1.1.1 + +[DHCP] +UseDNS=yes \ No newline at end of file diff --git a/image/meta-layers/meta-fcb-looper/recipes-connectivity/wifi-config/wifi-config_1.0.bb b/image/meta-layers/meta-fcb-looper/recipes-connectivity/wifi-config/wifi-config_1.0.bb new file mode 100644 index 0000000..29a13a6 --- /dev/null +++ b/image/meta-layers/meta-fcb-looper/recipes-connectivity/wifi-config/wifi-config_1.0.bb @@ -0,0 +1,29 @@ +SUMMARY = "WiFi Auto-Connect Configuration" +DESCRIPTION = "systemd-networkd and wpa_supplicant configuration for automatic WiFi connection" +LICENSE = "MIT" +LIC_FILES_CHKSUM = "file://${COMMON_LICENSE_DIR}/MIT;md5=0835ade698e0bcf8506ecda2f7b4f302" + +SRC_URI = "file://25-wireless.network \ + file://wpa_supplicant-wlp2s0.conf" + +S = "${WORKDIR}" + +do_install() { + # Install systemd-networkd configuration + install -d ${D}${sysconfdir}/systemd/network + install -m 0644 ${WORKDIR}/25-wireless.network ${D}${sysconfdir}/systemd/network/ + + # Install wpa_supplicant configuration + install -d ${D}${sysconfdir}/wpa_supplicant + install -m 0600 ${WORKDIR}/wpa_supplicant-wlp2s0.conf ${D}${sysconfdir}/wpa_supplicant/ + + # Create systemd service symlinks for auto-start + install -d ${D}${sysconfdir}/systemd/system/multi-user.target.wants + ln -sf ${systemd_system_unitdir}/wpa_supplicant@.service ${D}${sysconfdir}/systemd/system/multi-user.target.wants/wpa_supplicant@wlp2s0.service +} + +FILES:${PN} = "${sysconfdir}/systemd/network/* \ + ${sysconfdir}/wpa_supplicant/* \ + ${sysconfdir}/systemd/system/multi-user.target.wants/*" + +RDEPENDS:${PN} = "systemd wpa-supplicant" \ No newline at end of file diff --git a/image/meta-layers/meta-fcb-looper/recipes-core/images/fcb-looper-image.bb b/image/meta-layers/meta-fcb-looper/recipes-core/images/fcb-looper-image.bb index 100f496..143e78f 100644 --- a/image/meta-layers/meta-fcb-looper/recipes-core/images/fcb-looper-image.bb +++ b/image/meta-layers/meta-fcb-looper/recipes-core/images/fcb-looper-image.bb @@ -12,6 +12,7 @@ IMAGE_INSTALL += "\ systemd \ openssh \ ssh-keys \ + wifi-config \ ${CORE_IMAGE_EXTRA_INSTALL} \ "