From 09bb7ec1a0c542c00656c48f355eb554db511e69 Mon Sep 17 00:00:00 2001 From: orangepi-xunlong <258384131@qq.com> Date: Thu, 17 Aug 2023 09:39:58 +0800 Subject: [PATCH] Support Raspberry Pi OS --- external/config/boards/orangepi3b.conf | 2 +- external/config/boards/orangepicm4.conf | 2 +- .../config/cli/raspi/debootstrap/components | 1 + .../config/cli/raspi/debootstrap/packages | 1 + external/config/cli/raspi/main/packages | 81 +++++ .../config/cli/raspi/main/packages.additional | 1 + .../environments/lxde/config_base/packages | 92 +++++ .../desktop/raspi/environments/lxde/support | 1 + external/config/distributions/raspi/name | 1 + external/config/distributions/raspi/support | 1 + .../families/include/rk356x_gpu_vpu.inc | 103 +++++- external/packages/raspi/.gitignore | 1 + .../export-image/00-allow-rerun/00-run.sh | 9 + .../export-image/01-user-rename/00-packages | 1 + .../export-image/01-user-rename/01-run.sh | 9 + .../export-image/02-set-sources/01-run.sh | 9 + .../raspi/export-image/03-network/01-run.sh | 3 + .../export-image/03-network/files/resolv.conf | 1 + .../export-image/04-set-partuuid/00-run.sh | 17 + .../raspi/export-image/05-finalise/01-run.sh | 116 ++++++ .../packages/raspi/export-image/prerun.sh | 67 ++++ .../packages/raspi/orangepi/common/01-run.sh | 13 + .../raspi/orangepi/common/files/hciattach_opi | Bin 0 -> 195328 bytes .../files/orangepi-hardware-optimization | 106 ++++++ .../files/orangepi-hardware-optimize.service | 19 + external/packages/raspi/scripts/common | 105 ++++++ .../packages/raspi/scripts/dependencies_check | 53 +++ .../packages/raspi/scripts/qcow2_handling | 256 +++++++++++++ .../raspi/scripts/remove-comments.sed | 11 + .../raspi/stage0/00-configure-apt/00-run.sh | 24 ++ .../raspi/stage0/00-configure-apt/01-packages | 1 + .../stage0/00-configure-apt/files/51cache | 1 + .../files/raspberrypi.gpg.key | 30 ++ .../stage0/00-configure-apt/files/raspi.list | 7 + .../00-configure-apt/files/sources.list | 15 + .../raspi/stage0/01-locale/00-debconf | 6 + .../raspi/stage0/01-locale/00-packages | 1 + .../raspi/stage0/02-firmware/01-packages | 4 + .../raspi/stage0/files/raspberrypi.gpg | Bin 0 -> 2424 bytes external/packages/raspi/stage0/prerun.sh | 11 + .../raspi/stage1/00-boot-files/00-run.sh | 4 + .../stage1/00-boot-files/files/cmdline.txt | 1 + .../stage1/00-boot-files/files/config.txt | 83 +++++ .../packages/raspi/stage1/01-sys-tweaks/.pc | 1 + .../raspi/stage1/01-sys-tweaks/00-packages | 1 + .../01-sys-tweaks/00-patches/01-bashrc.diff | 33 ++ .../stage1/01-sys-tweaks/00-patches/series | 1 + .../raspi/stage1/01-sys-tweaks/00-run.sh | 23 ++ .../raspi/stage1/01-sys-tweaks/files/.bashrc | 113 ++++++ .../raspi/stage1/01-sys-tweaks/files/fstab | 3 + .../stage1/01-sys-tweaks/files/noclear.conf | 2 + .../raspi/stage1/02-net-tweaks/00-packages | 1 + .../raspi/stage1/02-net-tweaks/00-run.sh | 8 + .../stage1/03-install-packages/00-packages | 2 + external/packages/raspi/stage1/prerun.sh | 5 + .../raspi/stage2/01-sys-tweaks/00-debconf | 26 ++ .../raspi/stage2/01-sys-tweaks/00-packages | 35 ++ .../raspi/stage2/01-sys-tweaks/00-packages-nr | 4 + .../01-sys-tweaks/00-patches/01-useradd.diff | 22 ++ .../01-sys-tweaks/00-patches/02-swap.diff | 13 + .../01-sys-tweaks/00-patches/04-inputrc.diff | 12 + .../01-sys-tweaks/00-patches/05-path.diff | 26 ++ .../00-patches/07-resize-init.diff | 5 + .../stage2/01-sys-tweaks/00-patches/series | 5 + .../raspi/stage2/01-sys-tweaks/01-run.sh | 95 +++++ .../raspi/stage2/01-sys-tweaks/files/50raspi | 5 + .../stage2/01-sys-tweaks/files/90-qemu.rules | 3 + .../stage2/01-sys-tweaks/files/console-setup | 16 + .../stage2/01-sys-tweaks/files/login.defs | 340 ++++++++++++++++++ .../raspi/stage2/01-sys-tweaks/files/profile | 34 ++ .../raspi/stage2/01-sys-tweaks/files/rc.local | 20 ++ .../stage2/01-sys-tweaks/files/resize2fs_once | 25 ++ .../stage2/01-sys-tweaks/files/ttyoutput.conf | 2 + .../raspi/stage2/02-net-tweaks/00-packages | 5 + .../raspi/stage2/02-net-tweaks/01-run.sh | 40 +++ .../02-net-tweaks/files/wpa_supplicant.conf | 2 + .../03-accept-mathematica-eula/00-debconf | 2 + .../raspi/stage2/03-set-timezone/02-run.sh | 8 + external/packages/raspi/stage2/prerun.sh | 5 + .../stage3/00-install-packages/00-debconf | 2 + .../stage3/00-install-packages/00-packages | 17 + .../stage3/00-install-packages/00-packages-nr | 7 + .../stage3/00-install-packages/01-run.sh | 5 + .../packages/raspi/stage3/01-tweaks/00-run.sh | 5 + external/packages/raspi/stage3/prerun.sh | 5 + .../stage4/00-install-packages/00-debconf | 2 + .../stage4/00-install-packages/00-packages | 26 ++ .../stage4/00-install-packages/00-packages-nr | 2 + .../stage4/00-install-packages/01-packages | 22 ++ .../stage4/00-install-packages/02-packages | 4 + .../stage4/01-console-autologin/00-run.sh | 5 + .../packages/raspi/stage4/02-extras/00-run.sh | 7 + .../raspi/stage4/03-bookshelf/00-run.sh | 15 + .../stage4/03-bookshelf/files/.gitignore | 1 + .../raspi/stage4/04-enable-xcompmgr/00-run.sh | 5 + .../raspi/stage4/05-print-support/00-packages | 2 + .../raspi/stage4/05-print-support/01-run.sh | 5 + .../raspi/stage4/06-orangepi/00-packages | 10 + external/packages/raspi/stage4/prerun.sh | 5 + .../stage5/00-install-extras/00-packages | 13 + .../stage5/00-install-libreoffice/00-packages | 3 + external/packages/raspi/stage5/prerun.sh | 5 + scripts/configuration.sh | 7 +- scripts/debootstrap.sh | 83 ++++- scripts/distributions.sh | 319 ++++++++++++++++ scripts/general.sh | 34 +- scripts/main.sh | 4 +- 107 files changed, 2813 insertions(+), 20 deletions(-) create mode 100644 external/config/cli/raspi/debootstrap/components create mode 100644 external/config/cli/raspi/debootstrap/packages create mode 100644 external/config/cli/raspi/main/packages create mode 100644 external/config/cli/raspi/main/packages.additional create mode 100644 external/config/desktop/raspi/environments/lxde/config_base/packages create mode 100644 external/config/desktop/raspi/environments/lxde/support create mode 100644 external/config/distributions/raspi/name create mode 100644 external/config/distributions/raspi/support create mode 100644 external/packages/raspi/.gitignore create mode 100755 external/packages/raspi/export-image/00-allow-rerun/00-run.sh create mode 100644 external/packages/raspi/export-image/01-user-rename/00-packages create mode 100755 external/packages/raspi/export-image/01-user-rename/01-run.sh create mode 100755 external/packages/raspi/export-image/02-set-sources/01-run.sh create mode 100755 external/packages/raspi/export-image/03-network/01-run.sh create mode 100644 external/packages/raspi/export-image/03-network/files/resolv.conf create mode 100755 external/packages/raspi/export-image/04-set-partuuid/00-run.sh create mode 100755 external/packages/raspi/export-image/05-finalise/01-run.sh create mode 100755 external/packages/raspi/export-image/prerun.sh create mode 100755 external/packages/raspi/orangepi/common/01-run.sh create mode 100755 external/packages/raspi/orangepi/common/files/hciattach_opi create mode 100755 external/packages/raspi/orangepi/common/files/orangepi-hardware-optimization create mode 100755 external/packages/raspi/orangepi/common/files/orangepi-hardware-optimize.service create mode 100644 external/packages/raspi/scripts/common create mode 100644 external/packages/raspi/scripts/dependencies_check create mode 100644 external/packages/raspi/scripts/qcow2_handling create mode 100644 external/packages/raspi/scripts/remove-comments.sed create mode 100755 external/packages/raspi/stage0/00-configure-apt/00-run.sh create mode 100644 external/packages/raspi/stage0/00-configure-apt/01-packages create mode 100644 external/packages/raspi/stage0/00-configure-apt/files/51cache create mode 100644 external/packages/raspi/stage0/00-configure-apt/files/raspberrypi.gpg.key create mode 100644 external/packages/raspi/stage0/00-configure-apt/files/raspi.list create mode 100644 external/packages/raspi/stage0/00-configure-apt/files/sources.list create mode 100644 external/packages/raspi/stage0/01-locale/00-debconf create mode 100644 external/packages/raspi/stage0/01-locale/00-packages create mode 100644 external/packages/raspi/stage0/02-firmware/01-packages create mode 100644 external/packages/raspi/stage0/files/raspberrypi.gpg create mode 100755 external/packages/raspi/stage0/prerun.sh create mode 100755 external/packages/raspi/stage1/00-boot-files/00-run.sh create mode 100644 external/packages/raspi/stage1/00-boot-files/files/cmdline.txt create mode 100644 external/packages/raspi/stage1/00-boot-files/files/config.txt create mode 120000 external/packages/raspi/stage1/01-sys-tweaks/.pc create mode 100644 external/packages/raspi/stage1/01-sys-tweaks/00-packages create mode 100644 external/packages/raspi/stage1/01-sys-tweaks/00-patches/01-bashrc.diff create mode 100644 external/packages/raspi/stage1/01-sys-tweaks/00-patches/series create mode 100755 external/packages/raspi/stage1/01-sys-tweaks/00-run.sh create mode 100644 external/packages/raspi/stage1/01-sys-tweaks/files/.bashrc create mode 100644 external/packages/raspi/stage1/01-sys-tweaks/files/fstab create mode 100644 external/packages/raspi/stage1/01-sys-tweaks/files/noclear.conf create mode 100644 external/packages/raspi/stage1/02-net-tweaks/00-packages create mode 100755 external/packages/raspi/stage1/02-net-tweaks/00-run.sh create mode 100644 external/packages/raspi/stage1/03-install-packages/00-packages create mode 100755 external/packages/raspi/stage1/prerun.sh create mode 100644 external/packages/raspi/stage2/01-sys-tweaks/00-debconf create mode 100644 external/packages/raspi/stage2/01-sys-tweaks/00-packages create mode 100644 external/packages/raspi/stage2/01-sys-tweaks/00-packages-nr create mode 100644 external/packages/raspi/stage2/01-sys-tweaks/00-patches/01-useradd.diff create mode 100644 external/packages/raspi/stage2/01-sys-tweaks/00-patches/02-swap.diff create mode 100644 external/packages/raspi/stage2/01-sys-tweaks/00-patches/04-inputrc.diff create mode 100644 external/packages/raspi/stage2/01-sys-tweaks/00-patches/05-path.diff create mode 100644 external/packages/raspi/stage2/01-sys-tweaks/00-patches/07-resize-init.diff create mode 100644 external/packages/raspi/stage2/01-sys-tweaks/00-patches/series create mode 100755 external/packages/raspi/stage2/01-sys-tweaks/01-run.sh create mode 100644 external/packages/raspi/stage2/01-sys-tweaks/files/50raspi create mode 100644 external/packages/raspi/stage2/01-sys-tweaks/files/90-qemu.rules create mode 100644 external/packages/raspi/stage2/01-sys-tweaks/files/console-setup create mode 100644 external/packages/raspi/stage2/01-sys-tweaks/files/login.defs create mode 100644 external/packages/raspi/stage2/01-sys-tweaks/files/profile create mode 100755 external/packages/raspi/stage2/01-sys-tweaks/files/rc.local create mode 100644 external/packages/raspi/stage2/01-sys-tweaks/files/resize2fs_once create mode 100644 external/packages/raspi/stage2/01-sys-tweaks/files/ttyoutput.conf create mode 100644 external/packages/raspi/stage2/02-net-tweaks/00-packages create mode 100755 external/packages/raspi/stage2/02-net-tweaks/01-run.sh create mode 100644 external/packages/raspi/stage2/02-net-tweaks/files/wpa_supplicant.conf create mode 100644 external/packages/raspi/stage2/03-accept-mathematica-eula/00-debconf create mode 100755 external/packages/raspi/stage2/03-set-timezone/02-run.sh create mode 100755 external/packages/raspi/stage2/prerun.sh create mode 100644 external/packages/raspi/stage3/00-install-packages/00-debconf create mode 100644 external/packages/raspi/stage3/00-install-packages/00-packages create mode 100644 external/packages/raspi/stage3/00-install-packages/00-packages-nr create mode 100755 external/packages/raspi/stage3/00-install-packages/01-run.sh create mode 100755 external/packages/raspi/stage3/01-tweaks/00-run.sh create mode 100755 external/packages/raspi/stage3/prerun.sh create mode 100644 external/packages/raspi/stage4/00-install-packages/00-debconf create mode 100644 external/packages/raspi/stage4/00-install-packages/00-packages create mode 100644 external/packages/raspi/stage4/00-install-packages/00-packages-nr create mode 100644 external/packages/raspi/stage4/00-install-packages/01-packages create mode 100644 external/packages/raspi/stage4/00-install-packages/02-packages create mode 100755 external/packages/raspi/stage4/01-console-autologin/00-run.sh create mode 100755 external/packages/raspi/stage4/02-extras/00-run.sh create mode 100755 external/packages/raspi/stage4/03-bookshelf/00-run.sh create mode 100644 external/packages/raspi/stage4/03-bookshelf/files/.gitignore create mode 100755 external/packages/raspi/stage4/04-enable-xcompmgr/00-run.sh create mode 100644 external/packages/raspi/stage4/05-print-support/00-packages create mode 100755 external/packages/raspi/stage4/05-print-support/01-run.sh create mode 100644 external/packages/raspi/stage4/06-orangepi/00-packages create mode 100755 external/packages/raspi/stage4/prerun.sh create mode 100644 external/packages/raspi/stage5/00-install-extras/00-packages create mode 100644 external/packages/raspi/stage5/00-install-libreoffice/00-packages create mode 100755 external/packages/raspi/stage5/prerun.sh diff --git a/external/config/boards/orangepi3b.conf b/external/config/boards/orangepi3b.conf index 6223c69d799b..da5d29dd610b 100755 --- a/external/config/boards/orangepi3b.conf +++ b/external/config/boards/orangepi3b.conf @@ -7,7 +7,7 @@ MODULES_BLACKLIST_LEGACY="bcmdhd" KERNEL_TARGET="legacy" BOOT_LOGO="desktop" BOOT_SUPPORT_SPI="yes" -DISTRIB_TYPE_LEGACY="focal jammy bullseye" +DISTRIB_TYPE_LEGACY="focal jammy bullseye raspi" BOOTFS_TYPE="fat" IMAGE_PARTITION_TABLE="gpt" BOOT_FDT_FILE="rockchip/rk3566-orangepi-3b.dtb" diff --git a/external/config/boards/orangepicm4.conf b/external/config/boards/orangepicm4.conf index bfceccdfbb5f..65dedda82cf6 100755 --- a/external/config/boards/orangepicm4.conf +++ b/external/config/boards/orangepicm4.conf @@ -7,7 +7,7 @@ MODULES_BLACKLIST_LEGACY="bcmdhd" KERNEL_TARGET="legacy" BOOT_LOGO="desktop" BOOT_SUPPORT_SPI="yes" -DISTRIB_TYPE_LEGACY="focal jammy bullseye" +DISTRIB_TYPE_LEGACY="focal jammy bullseye raspi" BOOTFS_TYPE="fat" IMAGE_PARTITION_TABLE="gpt" BOOT_FDT_FILE="rockchip/rk3566-orangepi-cm4.dtb" diff --git a/external/config/cli/raspi/debootstrap/components b/external/config/cli/raspi/debootstrap/components new file mode 100644 index 000000000000..ba2906d0666c --- /dev/null +++ b/external/config/cli/raspi/debootstrap/components @@ -0,0 +1 @@ +main diff --git a/external/config/cli/raspi/debootstrap/packages b/external/config/cli/raspi/debootstrap/packages new file mode 100644 index 000000000000..a3068018e373 --- /dev/null +++ b/external/config/cli/raspi/debootstrap/packages @@ -0,0 +1 @@ +locales diff --git a/external/config/cli/raspi/main/packages b/external/config/cli/raspi/main/packages new file mode 100644 index 000000000000..73d577cca42a --- /dev/null +++ b/external/config/cli/raspi/main/packages @@ -0,0 +1,81 @@ +raspberrypi-archive-keyring +raspi-config +netbase +libraspberrypi-bin +libraspberrypi0 +systemd-timesyncd +ssh +less +fbset +sudo +psmisc +strace +ed +ncdu +crda +console-setup +keyboard-configuration +debconf-utils +parted +build-essential +manpages-dev +bash-completion +gdb +pkg-config +python-is-python3 +python3-rpi.gpio +v4l-utils +python3-gpiozero +avahi-daemon +lua5.1 +luajit +hardlink +ca-certificates +curl +fake-hwclock +nfs-common +usbutils +libraspberrypi-dev +libraspberrypi-doc +libfreetype6-dev +dosfstools +dphys-swapfile +raspberrypi-sys-mods +pi-bluetooth +apt-listchanges +usb-modeswitch +libpam-chksshpwd +rpi-update +libmtp-runtime +rsync +htop +man-db +policykit-1 +ssh-import-id +rng-tools +ethtool +ntfs-3g +pciutils +rpi-eeprom +raspinfo +udisks2 +unzip +zip +p7zip-full +file +kms++-utils +cifs-utils +libcamera-apps-lite +mkvtoolnix +python3-picamera2 +wpasupplicant +wireless-tools +firmware-atheros +firmware-brcm80211 +firmware-libertas +firmware-misc-nonfree +firmware-realtek +raspberrypi-net-mods +dhcpcd5 +network-manager +net-tools diff --git a/external/config/cli/raspi/main/packages.additional b/external/config/cli/raspi/main/packages.additional new file mode 100644 index 000000000000..7171e3296633 --- /dev/null +++ b/external/config/cli/raspi/main/packages.additional @@ -0,0 +1 @@ +u-boot-tools diff --git a/external/config/desktop/raspi/environments/lxde/config_base/packages b/external/config/desktop/raspi/environments/lxde/config_base/packages new file mode 100644 index 000000000000..8779d0f42e5d --- /dev/null +++ b/external/config/desktop/raspi/environments/lxde/config_base/packages @@ -0,0 +1,92 @@ +gstreamer1.0-x +gstreamer1.0-plugins-base +gstreamer1.0-plugins-good +gstreamer1.0-plugins-bad +gstreamer1.0-alsa +gstreamer1.0-libav +qpdfview +gtk2-engines +alsa-utils +desktop-base +git +policykit-1 +gvfs +rfkill +chromium-browser +rpi-chromium-mods +libwidevinecdm0 +gldriver-test +fonts-droid-fallback +fonts-liberation2 +obconf +arandr +libcamera-tools +libcamera-apps +python3-pyqt5 +python3-opengl +python3-pygame +python3-tk thonny +python3-pgzero +python3-serial +debian-reference-en +dillo +raspberrypi-net-mods +raspberrypi-ui-mods +python3-pip +python3-numpy +pypy +alacarte +rc-gui +sense-hat +tree +libgl1-mesa-dri +libgles1 +libgles2-mesa +xcompmgr +geany +piclone +pigpio +python3-pigpio +raspi-gpio +python3-rpi.gpio +python3-spidev +python3-twython +python3-smbus +python3-flask +pprompt +piwiz +rp-prefapps +ffmpeg +vlc +rpi-imager +rpi-wayland +pi-package +realvnc-vnc-server +python3-automationhat +python3-blinkt +python3-cap1xxx +python3-drumhat +python3-envirophat +python3-explorerhat +python3-fourletterphat +python3-microdotphat +python3-mote +python3-motephat +python3-phatbeat +python3-pianohat +python3-piglow +python3-rainbowhat +python3-scrollphat +python3-scrollphathd +python3-sn3218 +python3-skywriter +python3-touchphat +python3-buttonshim +python3-unicornhathd +python3-pantilthat +hunspell-en-gb +hyphen-en-gb +wamerican +wbritish +cups +system-config-printer diff --git a/external/config/desktop/raspi/environments/lxde/support b/external/config/desktop/raspi/environments/lxde/support new file mode 100644 index 000000000000..a23e5fb945c1 --- /dev/null +++ b/external/config/desktop/raspi/environments/lxde/support @@ -0,0 +1 @@ +supported diff --git a/external/config/distributions/raspi/name b/external/config/distributions/raspi/name new file mode 100644 index 000000000000..bd14f59d20c4 --- /dev/null +++ b/external/config/distributions/raspi/name @@ -0,0 +1 @@ +Raspberry Pi OS diff --git a/external/config/distributions/raspi/support b/external/config/distributions/raspi/support new file mode 100644 index 000000000000..a23e5fb945c1 --- /dev/null +++ b/external/config/distributions/raspi/support @@ -0,0 +1 @@ +supported diff --git a/external/config/sources/families/include/rk356x_gpu_vpu.inc b/external/config/sources/families/include/rk356x_gpu_vpu.inc index fa19f0e866b3..e4873f035b92 100755 --- a/external/config/sources/families/include/rk356x_gpu_vpu.inc +++ b/external/config/sources/families/include/rk356x_gpu_vpu.inc @@ -226,7 +226,7 @@ rk356x_gpu_vpu_tweaks() if [[ ${BOARD} =~ orangepicm4|orangepi3b && ${SELECTED_CONFIGURATION} == desktop && ${DESKTOP_ENVIRONMENT} == xfce && ${RELEASE} == bullseye ]]; then - rk356x_deb+=("rk356x_packages/common/libmali/libmali-bifrost-g52-g13p0-x11-gbm_1.9-1_arm64.deb") ## + rk356x_deb+=("rk356x_packages/common/libmali/libmali-bifrost-g52-g13p0-x11-gbm_1.9-1_arm64.deb") rk356x_deb+=("rk356x_packages/common/rga2/librga2_2.2.0-1_arm64.deb") rk356x_deb+=("rk356x_packages/common/rga2/librga-dev_2.2.0-1_arm64.deb") rk356x_deb+=("rk356x_packages/common/rkaiq/camera_engine_rkaiq_rk3568_arm64.deb") @@ -346,3 +346,104 @@ rk356x_gpu_vpu_tweaks() fi } + +rk356x_gpu_vpu_tweaks_for_raspios() +{ + if [[ ${BOARD} =~ orangepicm4|orangepi3b && ${SELECTED_CONFIGURATION} == desktop && ${RELEASE} == raspi ]]; then + + rk356x_deb+=("rk356x_packages/common/libmali/libmali-bifrost-g52-g13p0-x11-gbm_1.9-1_arm64.deb") + rk356x_deb+=("rk356x_packages/common/rga2/librga2_2.2.0-1_arm64.deb") + rk356x_deb+=("rk356x_packages/common/rga2/librga-dev_2.2.0-1_arm64.deb") + rk356x_deb+=("rk356x_packages/common/rkaiq/camera_engine_rkaiq_rk3568_arm64.deb") + rk356x_deb+=("rk356x_packages/common/rktoolkit/rktoolkit_1.0.0-1_arm64.deb") + rk356x_deb+=("rk356x_packages/bullseye/mpp/librockchip-mpp1_1.5.0-2_arm64.deb") + rk356x_deb+=("rk356x_packages/bullseye/mpp/librockchip-mpp-dev_1.5.0-2_arm64.deb") + rk356x_deb+=("rk356x_packages/bullseye/mpp/librockchip-vpu0_1.5.0-2_arm64.deb") + rk356x_deb+=("rk356x_packages/bullseye/mpp/rockchip-mpp-demos_1.5.0-2_arm64.deb") + rk356x_deb+=("rk356x_packages/bullseye/xserver-raspios/xserver-common_1.20.11-1+rpt3+deb11u6_all.deb") + rk356x_deb+=("rk356x_packages/bullseye/xserver-raspios/xserver-xorg-dev_1.20.11-1+rpt3+deb11u6_arm64.deb") + rk356x_deb+=("rk356x_packages/bullseye/xserver-raspios/xserver-xorg-core_1.20.11-1+rpt3+deb11u6_arm64.deb") + rk356x_deb+=("rk356x_packages/bullseye/xserver-raspios/xserver-xorg-legacy_1.20.11-1+rpt3+deb11u6_arm64.deb") + rk356x_deb+=("rk356x_packages/bullseye/xserver-raspios/xwayland_1.20.11-1+rpt3+deb11u6_arm64.deb") + rk356x_deb+=("rk356x_packages/bullseye/gst-rkmpp/gstreamer1.0-rockchip1_1.14-4_arm64.deb") + rk356x_deb+=("rk356x_packages/bullseye/gstreamer/gir1.2-gstreamer-1.0_1.18.5-1_arm64.deb") + rk356x_deb+=("rk356x_packages/bullseye/gstreamer/gstreamer1.0-tools_1.18.5-1_arm64.deb") + rk356x_deb+=("rk356x_packages/bullseye/gstreamer/libgstreamer1.0-0_1.18.5-1_arm64.deb") + rk356x_deb+=("rk356x_packages/bullseye/gstreamer/libgstreamer1.0-dev_1.18.5-1_arm64.deb") + rk356x_deb+=("rk356x_packages/bullseye/gst-plugins-base1.0/gir1.2-gst-plugins-base-1.0_1.18.5-1_arm64.deb") + rk356x_deb+=("rk356x_packages/bullseye/gst-plugins-base1.0/gstreamer1.0-alsa_1.18.5-1_arm64.deb") + rk356x_deb+=("rk356x_packages/bullseye/gst-plugins-base1.0/gstreamer1.0-gl_1.18.5-1_arm64.deb") + rk356x_deb+=("rk356x_packages/bullseye/gst-plugins-base1.0/gstreamer1.0-plugins-base_1.18.5-1_arm64.deb") + rk356x_deb+=("rk356x_packages/bullseye/gst-plugins-base1.0/gstreamer1.0-plugins-base-apps_1.18.5-1_arm64.deb") + rk356x_deb+=("rk356x_packages/bullseye/gst-plugins-base1.0/gstreamer1.0-x_1.18.5-1_arm64.deb") + rk356x_deb+=("rk356x_packages/bullseye/gst-plugins-base1.0/libgstreamer-gl1.0-0_1.18.5-1_arm64.deb") + rk356x_deb+=("rk356x_packages/bullseye/gst-plugins-base1.0/libgstreamer-plugins-base1.0-0_1.18.5-1_arm64.deb") + rk356x_deb+=("rk356x_packages/bullseye/gst-plugins-base1.0/libgstreamer-plugins-base1.0-dev_1.18.5-1_arm64.deb") + rk356x_deb+=("rk356x_packages/bullseye/gst-plugins-bad1.0/libgstreamer-plugins-bad1.0-0_1.18.5-1_arm64.deb") + rk356x_deb+=("rk356x_packages/bullseye/gst-plugins-bad1.0/gir1.2-gst-plugins-bad-1.0_1.18.5-1_arm64.deb") + rk356x_deb+=("rk356x_packages/bullseye/gst-plugins-bad1.0/libgstreamer-opencv1.0-0_1.18.5-1_arm64.deb") + rk356x_deb+=("rk356x_packages/bullseye/gst-plugins-bad1.0/gstreamer1.0-opencv_1.18.5-1_arm64.deb") + rk356x_deb+=("rk356x_packages/bullseye/gst-plugins-bad1.0/gstreamer1.0-plugins-bad_1.18.5-1_arm64.deb") + rk356x_deb+=("rk356x_packages/bullseye/gst-plugins-bad1.0/gstreamer1.0-plugins-bad-apps_1.18.5-1_arm64.deb") + rk356x_deb+=("rk356x_packages/bullseye/gst-plugins-bad1.0/gstreamer1.0-wpe_1.18.5-1_arm64.deb") + rk356x_deb+=("rk356x_packages/bullseye/gst-plugins-bad1.0/libgstreamer-plugins-bad1.0-dev_1.18.5-1_arm64.deb") + rk356x_deb+=("rk356x_packages/bullseye/gst-plugins-good1.0/gstreamer1.0-gtk3_1.18.5-1_arm64.deb") + rk356x_deb+=("rk356x_packages/bullseye/gst-plugins-good1.0/gstreamer1.0-plugins-good_1.18.5-1_arm64.deb") + rk356x_deb+=("rk356x_packages/bullseye/gst-plugins-good1.0/gstreamer1.0-pulseaudio_1.18.5-1_arm64.deb") + rk356x_deb+=("rk356x_packages/bullseye/gst-plugins-ugly1.0/gstreamer1.0-plugins-ugly_1.18.5-1_arm64.deb") + rk356x_deb+=("rk356x_packages/bullseye/gst-libav1.0/gstreamer1.0-plugins-ugly_1.18.5-1_arm64.deb") + rk356x_deb+=("rk356x_packages/bullseye/libv4l/libdvbv5-0_1.20.0-2_arm64.deb") + rk356x_deb+=("rk356x_packages/bullseye/libv4l/dvb-tools_1.20.0-2_arm64.deb") + rk356x_deb+=("rk356x_packages/bullseye/libv4l/ir-keytable_1.20.0-2_arm64.deb") + rk356x_deb+=("rk356x_packages/bullseye/libv4l/libdvbv5-dev_1.20.0-2_arm64.deb") + rk356x_deb+=("rk356x_packages/bullseye/libv4l/libdvbv5-doc_1.20.0-2_all.deb") + rk356x_deb+=("rk356x_packages/bullseye/libv4l/libv4l-0_1.20.0-2_arm64.deb") + rk356x_deb+=("rk356x_packages/bullseye/libv4l/libv4l2rds0_1.20.0-2_arm64.deb") + rk356x_deb+=("rk356x_packages/bullseye/libv4l/libv4lconvert0_1.20.0-2_arm64.deb") + rk356x_deb+=("rk356x_packages/bullseye/libv4l/libv4l-dev_1.20.0-2_arm64.deb") + rk356x_deb+=("rk356x_packages/bullseye/libv4l/libv4l-rkmpp_1.5.1-1.1_arm64.deb") + rk356x_deb+=("rk356x_packages/bullseye/libv4l/v4l-utils_1.20.0-2_arm64.deb") + rk356x_deb+=("rk356x_packages/bullseye/chromium/chromium-x11_91.0.4472.164_arm64.deb") + rk356x_deb+=("rk356x_packages/bullseye/libdrm-cursor/libdrm-cursor_1.4.1-1_arm64.deb") + rk356x_deb+=("rk356x_packages/bullseye/libdrm-cursor/libdrm-cursor-dev_1.4.1-1_arm64.deb") + rk356x_deb+=("rk356x_packages/bullseye/glmark2/glmark2-data_2022.06~git.3f1104d-1_all.deb") + rk356x_deb+=("rk356x_packages/bullseye/glmark2/glmark2-es2-drm_2022.06~git.3f1104d-1_arm64.deb") + rk356x_deb+=("rk356x_packages/bullseye/glmark2/glmark2-es2-x11_2022.06~git.3f1104d-1_arm64.deb") + rk356x_deb+=("rk356x_packages/bullseye/ffmpeg/libavutil56_4.3.5-0+deb11u1_arm64.deb") + rk356x_deb+=("rk356x_packages/bullseye/ffmpeg/libavutil-dev_4.3.5-0+deb11u1_arm64.deb") + rk356x_deb+=("rk356x_packages/bullseye/ffmpeg/libpostproc55_4.3.5-0+deb11u1_arm64.deb") + rk356x_deb+=("rk356x_packages/bullseye/ffmpeg/libpostproc-dev_4.3.5-0+deb11u1_arm64.deb") + rk356x_deb+=("rk356x_packages/bullseye/ffmpeg/libswresample3_4.3.5-0+deb11u1_arm64.deb") + rk356x_deb+=("rk356x_packages/bullseye/ffmpeg/libswresample-dev_4.3.5-0+deb11u1_arm64.deb") + rk356x_deb+=("rk356x_packages/bullseye/ffmpeg/libswscale5_4.3.5-0+deb11u1_arm64.deb") + rk356x_deb+=("rk356x_packages/bullseye/ffmpeg/libswscale-dev_4.3.5-0+deb11u1_arm64.deb") + rk356x_deb+=("rk356x_packages/bullseye/ffmpeg/libavcodec58_4.3.5-0+deb11u1_arm64.deb") + rk356x_deb+=("rk356x_packages/bullseye/ffmpeg/libavcodec-dev_4.3.5-0+deb11u1_arm64.deb") + rk356x_deb+=("rk356x_packages/bullseye/ffmpeg/libavformat58_4.3.5-0+deb11u1_arm64.deb") + rk356x_deb+=("rk356x_packages/bullseye/ffmpeg/libavformat-dev_4.3.5-0+deb11u1_arm64.deb") + rk356x_deb+=("rk356x_packages/bullseye/ffmpeg/libavresample4_4.3.5-0+deb11u1_arm64.deb") + rk356x_deb+=("rk356x_packages/bullseye/ffmpeg/libavresample-dev_4.3.5-0+deb11u1_arm64.deb") + rk356x_deb+=("rk356x_packages/bullseye/ffmpeg/libavfilter7_4.3.5-0+deb11u1_arm64.deb") + rk356x_deb+=("rk356x_packages/bullseye/ffmpeg/libavfilter-dev_4.3.5-0+deb11u1_arm64.deb") + rk356x_deb+=("rk356x_packages/bullseye/ffmpeg/libavdevice58_4.3.5-0+deb11u1_arm64.deb") + rk356x_deb+=("rk356x_packages/bullseye/ffmpeg/libavdevice-dev_4.3.5-0+deb11u1_arm64.deb") + rk356x_deb+=("rk356x_packages/bullseye/ffmpeg/ffmpeg_4.3.5-0+deb11u1_arm64.deb") + rk356x_deb+=("rk356x_packages/bullseye/mpv/libmpv1_0.32.0-3_arm64.deb") + rk356x_deb+=("rk356x_packages/bullseye/mpv/libmpv-dev_0.32.0-3_arm64.deb") + rk356x_deb+=("rk356x_packages/bullseye/mpv/mpv_0.32.0-3_arm64.deb") + + for deb in ${rk356x_deb[@]} + do + dpkg_install_deb_chroot "$EXTER/cache/sources/${deb}" + done + + chroot $SDCARD /bin/bash -c "sed -i '5aexport LD_PRELOAD=libdrm-cursor.so.1' /usr/bin/X" + + # The chromium using fixed pathes for libv4l2.so + chroot $SDCARD /bin/bash -c "ln -rsf /usr/lib/*/libv4l2.so /usr/lib/" + chroot $SDCARD /bin/bash -c "[ -e /usr/lib/aarch64-linux-gnu/ ] && ln -Tsf lib /usr/lib64" + + chroot $SDCARD /bin/bash -c "cd /usr/lib/aarch64-linux-gnu/dri/;cp kms_swrast_dri.so swrast_dri.so rockchip_dri.so /" + chroot $SDCARD /bin/bash -c "rm /usr/lib/aarch64-linux-gnu/dri/*.so;mv /*.so /usr/lib/aarch64-linux-gnu/dri/" + fi +} diff --git a/external/packages/raspi/.gitignore b/external/packages/raspi/.gitignore new file mode 100644 index 000000000000..bd5dbb3335a4 --- /dev/null +++ b/external/packages/raspi/.gitignore @@ -0,0 +1 @@ +*/SKIP diff --git a/external/packages/raspi/export-image/00-allow-rerun/00-run.sh b/external/packages/raspi/export-image/00-allow-rerun/00-run.sh new file mode 100755 index 000000000000..dd67f4cbe443 --- /dev/null +++ b/external/packages/raspi/export-image/00-allow-rerun/00-run.sh @@ -0,0 +1,9 @@ +#!/bin/bash -e + +if [ ! -x "${ROOTFS_DIR}/usr/bin/qemu-arm-static" ]; then + cp /usr/bin/qemu-arm-static "${ROOTFS_DIR}/usr/bin/" +fi + +if [ -e "${ROOTFS_DIR}/etc/ld.so.preload" ]; then + mv "${ROOTFS_DIR}/etc/ld.so.preload" "${ROOTFS_DIR}/etc/ld.so.preload.disabled" +fi diff --git a/external/packages/raspi/export-image/01-user-rename/00-packages b/external/packages/raspi/export-image/01-user-rename/00-packages new file mode 100644 index 000000000000..e8b69fc4e2ad --- /dev/null +++ b/external/packages/raspi/export-image/01-user-rename/00-packages @@ -0,0 +1 @@ +userconf-pi diff --git a/external/packages/raspi/export-image/01-user-rename/01-run.sh b/external/packages/raspi/export-image/01-user-rename/01-run.sh new file mode 100755 index 000000000000..aa5dd941024a --- /dev/null +++ b/external/packages/raspi/export-image/01-user-rename/01-run.sh @@ -0,0 +1,9 @@ +#!/bin/bash -e + +if [[ "${DISABLE_FIRST_BOOT_USER_RENAME}" == "0" ]]; then + on_chroot <<- EOF + SUDO_USER="${FIRST_USER_NAME}" rename-user -f -s + EOF +else + rm -f "${ROOTFS_DIR}/etc/xdg/autostart/piwiz.desktop" +fi diff --git a/external/packages/raspi/export-image/02-set-sources/01-run.sh b/external/packages/raspi/export-image/02-set-sources/01-run.sh new file mode 100755 index 000000000000..5f512099b3fd --- /dev/null +++ b/external/packages/raspi/export-image/02-set-sources/01-run.sh @@ -0,0 +1,9 @@ +#!/bin/bash -e + +rm -f "${ROOTFS_DIR}/etc/apt/apt.conf.d/51cache" +find "${ROOTFS_DIR}/var/lib/apt/lists/" -type f -delete +on_chroot << EOF +apt-get update +apt-get -y dist-upgrade +apt-get clean +EOF diff --git a/external/packages/raspi/export-image/03-network/01-run.sh b/external/packages/raspi/export-image/03-network/01-run.sh new file mode 100755 index 000000000000..4150732ca8ec --- /dev/null +++ b/external/packages/raspi/export-image/03-network/01-run.sh @@ -0,0 +1,3 @@ +#!/bin/bash -e + +install -m 644 files/resolv.conf "${ROOTFS_DIR}/etc/" diff --git a/external/packages/raspi/export-image/03-network/files/resolv.conf b/external/packages/raspi/export-image/03-network/files/resolv.conf new file mode 100644 index 000000000000..cae093a833db --- /dev/null +++ b/external/packages/raspi/export-image/03-network/files/resolv.conf @@ -0,0 +1 @@ +nameserver 8.8.8.8 diff --git a/external/packages/raspi/export-image/04-set-partuuid/00-run.sh b/external/packages/raspi/export-image/04-set-partuuid/00-run.sh new file mode 100755 index 000000000000..a025c85a5be3 --- /dev/null +++ b/external/packages/raspi/export-image/04-set-partuuid/00-run.sh @@ -0,0 +1,17 @@ +#!/bin/bash -e + +#if [ "${NO_PRERUN_QCOW2}" = "0" ]; then +# +# IMG_FILE="${STAGE_WORK_DIR}/${IMG_FILENAME}${IMG_SUFFIX}.img" +# +# IMGID="$(dd if="${IMG_FILE}" skip=440 bs=1 count=4 2>/dev/null | xxd -e | cut -f 2 -d' ')" +# +# BOOT_PARTUUID="${IMGID}-01" +# ROOT_PARTUUID="${IMGID}-02" +# +# sed -i "s/BOOTDEV/PARTUUID=${BOOT_PARTUUID}/" "${ROOTFS_DIR}/etc/fstab" +# sed -i "s/ROOTDEV/PARTUUID=${ROOT_PARTUUID}/" "${ROOTFS_DIR}/etc/fstab" +# +# sed -i "s/ROOTDEV/PARTUUID=${ROOT_PARTUUID}/" "${ROOTFS_DIR}/boot/cmdline.txt" +# +#fi diff --git a/external/packages/raspi/export-image/05-finalise/01-run.sh b/external/packages/raspi/export-image/05-finalise/01-run.sh new file mode 100755 index 000000000000..294259ea4c8f --- /dev/null +++ b/external/packages/raspi/export-image/05-finalise/01-run.sh @@ -0,0 +1,116 @@ +#!/bin/bash -e + +#IMG_FILE="${STAGE_WORK_DIR}/${IMG_FILENAME}${IMG_SUFFIX}.img" +#INFO_FILE="${STAGE_WORK_DIR}/${IMG_FILENAME}${IMG_SUFFIX}.info" + +on_chroot << EOF +if [ -x /etc/init.d/fake-hwclock ]; then + /etc/init.d/fake-hwclock stop +fi +if hash hardlink 2>/dev/null; then + hardlink -t /usr/share/doc +fi +EOF + +if [ -d "${ROOTFS_DIR}/home/${FIRST_USER_NAME}/.config" ]; then + chmod 700 "${ROOTFS_DIR}/home/${FIRST_USER_NAME}/.config" +fi + +rm -f "${ROOTFS_DIR}/usr/bin/qemu-arm-static" + +if [ "${USE_QEMU}" != "1" ]; then + if [ -e "${ROOTFS_DIR}/etc/ld.so.preload.disabled" ]; then + mv "${ROOTFS_DIR}/etc/ld.so.preload.disabled" "${ROOTFS_DIR}/etc/ld.so.preload" + fi +fi + +rm -f "${ROOTFS_DIR}/etc/network/interfaces.dpkg-old" + +rm -f "${ROOTFS_DIR}/etc/apt/sources.list~" +rm -f "${ROOTFS_DIR}/etc/apt/trusted.gpg~" + +rm -f "${ROOTFS_DIR}/etc/passwd-" +rm -f "${ROOTFS_DIR}/etc/group-" +rm -f "${ROOTFS_DIR}/etc/shadow-" +rm -f "${ROOTFS_DIR}/etc/gshadow-" +rm -f "${ROOTFS_DIR}/etc/subuid-" +rm -f "${ROOTFS_DIR}/etc/subgid-" + +rm -f "${ROOTFS_DIR}"/var/cache/debconf/*-old +rm -f "${ROOTFS_DIR}"/var/lib/dpkg/*-old + +rm -f "${ROOTFS_DIR}"/usr/share/icons/*/icon-theme.cache + +rm -f "${ROOTFS_DIR}/var/lib/dbus/machine-id" + +true > "${ROOTFS_DIR}/etc/machine-id" + +ln -nsf /proc/mounts "${ROOTFS_DIR}/etc/mtab" + +find "${ROOTFS_DIR}/var/log/" -type f -exec cp /dev/null {} \; + +rm -f "${ROOTFS_DIR}/root/.vnc/private.key" +rm -f "${ROOTFS_DIR}/etc/vnc/updateid" + +#update_issue "$(basename "${EXPORT_DIR}")" +#install -m 644 "${ROOTFS_DIR}/etc/rpi-issue" "${ROOTFS_DIR}/boot/issue.txt" +# +#cp "$ROOTFS_DIR/etc/rpi-issue" "$INFO_FILE" + + +#{ +# if [ -f "$ROOTFS_DIR/usr/share/doc/raspberrypi-kernel/changelog.Debian.gz" ]; then +# firmware=$(zgrep "firmware as of" \ +# "$ROOTFS_DIR/usr/share/doc/raspberrypi-kernel/changelog.Debian.gz" | \ +# head -n1 | sed -n 's|.* \([^ ]*\)$|\1|p') +# printf "\nFirmware: https://github.com/raspberrypi/firmware/tree/%s\n" "$firmware" +# +# kernel="$(curl -s -L "https://github.com/raspberrypi/firmware/raw/$firmware/extra/git_hash")" +# printf "Kernel: https://github.com/raspberrypi/linux/tree/%s\n" "$kernel" +# +# uname="$(curl -s -L "https://github.com/raspberrypi/firmware/raw/$firmware/extra/uname_string7")" +# printf "Uname string: %s\n" "$uname" +# fi +# +# printf "\nPackages:\n" +# dpkg -l --root "$ROOTFS_DIR" +#} >> "$INFO_FILE" + +#mkdir -p "${DEPLOY_DIR}" +# +#rm -f "${DEPLOY_DIR}/${ARCHIVE_FILENAME}${IMG_SUFFIX}.*" +#rm -f "${DEPLOY_DIR}/${IMG_FILENAME}${IMG_SUFFIX}.img" +# +#mv "$INFO_FILE" "$DEPLOY_DIR/" +# +#if [ "${USE_QCOW2}" = "0" ] && [ "${NO_PRERUN_QCOW2}" = "0" ]; then +# ROOT_DEV="$(mount | grep "${ROOTFS_DIR} " | cut -f1 -d' ')" +# +# unmount "${ROOTFS_DIR}" +# zerofree "${ROOT_DEV}" +# +# unmount_image "${IMG_FILE}" +#else +# unload_qimage +# make_bootable_image "${STAGE_WORK_DIR}/${IMG_FILENAME}${IMG_SUFFIX}.qcow2" "$IMG_FILE" +#fi +# +#case "${DEPLOY_COMPRESSION}" in +#zip) +# pushd "${STAGE_WORK_DIR}" > /dev/null +# zip -"${COMPRESSION_LEVEL}" \ +# "${DEPLOY_DIR}/${ARCHIVE_FILENAME}${IMG_SUFFIX}.zip" "$(basename "${IMG_FILE}")" +# popd > /dev/null +# ;; +#gz) +# pigz --force -"${COMPRESSION_LEVEL}" "$IMG_FILE" --stdout > \ +# "${DEPLOY_DIR}/${ARCHIVE_FILENAME}${IMG_SUFFIX}.img.gz" +# ;; +#xz) +# xz --compress --force --threads 0 --memlimit-compress=50% -"${COMPRESSION_LEVEL}" \ +# --stdout "$IMG_FILE" > "${DEPLOY_DIR}/${ARCHIVE_FILENAME}${IMG_SUFFIX}.img.xz" +# ;; +#none | *) +# cp "$IMG_FILE" "$DEPLOY_DIR/" +#;; +#esac diff --git a/external/packages/raspi/export-image/prerun.sh b/external/packages/raspi/export-image/prerun.sh new file mode 100755 index 000000000000..0bdd49ad099d --- /dev/null +++ b/external/packages/raspi/export-image/prerun.sh @@ -0,0 +1,67 @@ +#!/bin/bash -e + +#if [ "${NO_PRERUN_QCOW2}" = "0" ]; then +# IMG_FILE="${STAGE_WORK_DIR}/${IMG_FILENAME}${IMG_SUFFIX}.img" +# +# unmount_image "${IMG_FILE}" +# +# rm -f "${IMG_FILE}" +# +# rm -rf "${ROOTFS_DIR}" +# mkdir -p "${ROOTFS_DIR}" +# +# BOOT_SIZE="$((256 * 1024 * 1024))" +# ROOT_SIZE=$(du --apparent-size -s "${EXPORT_ROOTFS_DIR}" --exclude var/cache/apt/archives --exclude boot --block-size=1 | cut -f 1) +# +# # All partition sizes and starts will be aligned to this size +# ALIGN="$((4 * 1024 * 1024))" +# # Add this much space to the calculated file size. This allows for +# # some overhead (since actual space usage is usually rounded up to the +# # filesystem block size) and gives some free space on the resulting +# # image. +# ROOT_MARGIN="$(echo "($ROOT_SIZE * 0.2 + 200 * 1024 * 1024) / 1" | bc)" +# +# BOOT_PART_START=$((ALIGN)) +# BOOT_PART_SIZE=$(((BOOT_SIZE + ALIGN - 1) / ALIGN * ALIGN)) +# ROOT_PART_START=$((BOOT_PART_START + BOOT_PART_SIZE)) +# ROOT_PART_SIZE=$(((ROOT_SIZE + ROOT_MARGIN + ALIGN - 1) / ALIGN * ALIGN)) +# IMG_SIZE=$((BOOT_PART_START + BOOT_PART_SIZE + ROOT_PART_SIZE)) +# +# truncate -s "${IMG_SIZE}" "${IMG_FILE}" +# +# parted --script "${IMG_FILE}" mklabel msdos +# parted --script "${IMG_FILE}" unit B mkpart primary fat32 "${BOOT_PART_START}" "$((BOOT_PART_START + BOOT_PART_SIZE - 1))" +# parted --script "${IMG_FILE}" unit B mkpart primary ext4 "${ROOT_PART_START}" "$((ROOT_PART_START + ROOT_PART_SIZE - 1))" +# +# echo "Creating loop device..." +# cnt=0 +# until LOOP_DEV="$(losetup --show --find --partscan "$IMG_FILE")"; do +# if [ $cnt -lt 5 ]; then +# cnt=$((cnt + 1)) +# echo "Error in losetup. Retrying..." +# sleep 5 +# else +# echo "ERROR: losetup failed; exiting" +# exit 1 +# fi +# done +# +# BOOT_DEV="${LOOP_DEV}p1" +# ROOT_DEV="${LOOP_DEV}p2" +# +# ROOT_FEATURES="^huge_file" +# for FEATURE in 64bit; do +# if grep -q "$FEATURE" /etc/mke2fs.conf; then +# ROOT_FEATURES="^$FEATURE,$ROOT_FEATURES" +# fi +# done +# mkdosfs -n bootfs -F 32 -s 4 -v "$BOOT_DEV" > /dev/null +# mkfs.ext4 -L rootfs -O "$ROOT_FEATURES" "$ROOT_DEV" > /dev/null +# +# mount -v "$ROOT_DEV" "${ROOTFS_DIR}" -t ext4 +# mkdir -p "${ROOTFS_DIR}/boot" +# mount -v "$BOOT_DEV" "${ROOTFS_DIR}/boot" -t vfat +# +# rsync -aHAXx --exclude /var/cache/apt/archives --exclude /boot "${EXPORT_ROOTFS_DIR}/" "${ROOTFS_DIR}/" +# rsync -rtx "${EXPORT_ROOTFS_DIR}/boot/" "${ROOTFS_DIR}/boot/" +#fi diff --git a/external/packages/raspi/orangepi/common/01-run.sh b/external/packages/raspi/orangepi/common/01-run.sh new file mode 100755 index 000000000000..18203d7eec6e --- /dev/null +++ b/external/packages/raspi/orangepi/common/01-run.sh @@ -0,0 +1,13 @@ +#!/bin/bash -e + +#sed "s/# SKEL=.*/SKEL=\/etc\/skel/" -i "${ROOTFS_DIR}/etc/default/useradd" +# +#install -d "${ROOTFS_DIR}/etc/systemd/system/rc-local.service.d" +#install -m 644 files/ttyoutput.conf "${ROOTFS_DIR}/etc/systemd/system/rc-local.service.d/" +# +#on_chroot << EOF +#systemctl enable regenerate_ssh_host_keys +#EOF + +install -m 644 files/hciattach_opi "${ROOTFS_DIR}/usr/bin/" + diff --git a/external/packages/raspi/orangepi/common/files/hciattach_opi b/external/packages/raspi/orangepi/common/files/hciattach_opi new file mode 100755 index 0000000000000000000000000000000000000000..6766016fb8b495ecf077a8b22f4df1e669a13091 GIT binary patch literal 195328 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%0DB9RNnBc0 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�WQ?9I=S9e9BI7lMJNOC7 zYog&?m`u@QMRIX!wQMXI^~jPJX^(o@MahV1p=9x7x+CW`r!wu~9D9RDMx&{P$wVp~ zEx4u!ub`aqiE5d0&7(vr63)fEbT}7j^(C|3Mv1t9RIetLjwMBj>LU>|R_-m##3?Nm z%cL`~Q9-Vd&80J`G*zf*X{nG2_k19)qHhxH#=duS%*p$n9%`tj*FKjCt9v{>pD^!YXBoj~POmjTbzA#LW%eK5E zxk5#i%?Ji2Sdd$kj**|*0@!p`y<(y;@#|t#JN}2DPD#%Z@i;-GHO`e+5NC32TrZQn zNG9TSq{%;GhB%MiAkm)o7Q`}HauhEYZ;z!qa(Nl~SWrMFa@I%lJ)EuPY~vTYHs_po zB{X_#Ro-e7c^&G&&v6Kdx0q~OlShupcC(3i+M}-LH7%k7vw$LS3SGd4#y~am6H%v# zrZQ9m;bcq9%cf&7^8Bibcs3KJ8WG!xgks8r{ElK2`Cc2VquU!WcprxFca6K$2XPRd8H38tlX;p{|e;mj1p zfmC8vGTcP{tA*P@o6q+99JhMwLNC(X;zgQF3ww#jZYE*Did!yEwfB;$W!9DA2sU%+ z>RKRbS47oGre$_K8BWaOTBm3l@p85(+G{))?I znOU8=Skn67JPBGp83(ou6+Uak&%|oMyE`-F+#QJWHlpMaheM-L&+DMU$gq#I<6B>E zj#5zW$XbVGHFBG%)4@A4UM9RyA{9sLj%391$d~dT$J^8r6uHu+f7x(MDXGpEP+URr ze0`D!bt*RtZCDcbCufsEp80&-UXYFS>MhimDe}&kZF0YcX%A;;qBN0WdRuG}J2~g! z*HFJwMG70LrJaR>Lwh*lg`-h=xU4@hJ^bt|E}2FdX0b+fWRp_h zZjOa>YVQzo8lA!kdq@jR2n9RBTG!4@Y= zgNmiC+ht=cOa(USWkwiF~^*TD@H0APJw}$h1 zF;eFfwWQZXv#wairlJXPhDH(;#iDeyBX5xA1-XO9ht0R(1n0c|xf_Nl0lbhVc63t_IR#1_eM_v}rO|Ifk6eBL5e(@}C z)+IHb2cF2l6gO(TnyW9Fe({`{K?zx*Q0;jaUUG#us}_c8Yc4n5g>{$Cm|o{yI(zoK zS@mB1^ci)tJkuU)r+!&|Vcnb=Gd=qAbm!Wp=Ej{kfg6uMai8$0M>Ivqr8{T_l8ooI zNJdj5>Ps;;)t*`qb8XQQAR9BeNOPhi+v*oKg>y6=_4zK%ClcX^IGgo7nX`z4C6hF| z+4y1mk_0^JLHUl%y)>8VNcgiLDiKTi84g`yfWt?&Bh9T5n8C3ICfBxCrf3ElTcD9E zmrAsoW}0PX{Z_M!vWZknfT3PN<0`i_tv{$^a#VS-w6l*8rF9+6DYCQ(qxqeU znKaDhGcN=QS|-a%*z=mGH(R$NXUx}MHqMJTnxe*SY~;Xeg~ZwVUD(R&6B|ZtOv)#u zn3v49(_$^1T1as@K{Mq9xmTySzyIm@2@q6xD3z|Bw<8{qN;TO4BkO6~MQky|CwatU zzu~1^Q#={NLm(cuzhNosf#ktaxu{m7@aOtd6Y=_2`uj&x))w0QO6G`mR9AgJZC zJ;` z8LEbKJmA$foV0m?n&J7n-=1wv8nU^8q<-41i@G`z1>?zUJK`CdC-&BFo5FSuK(?IT z#d%PN;ci=q1iYoe+XJNT&x>oB{ZoQZIz{6blCvjfX*UY3VT9OlN4_F0qrM z0C^1WSlCTs4!X7naUkGFvZeI54&|Z_!F6nvcvz=_D%0lWN5MkZ%3DECw~btAfnvjG zp_}W#YPSJ-CZaB!pp6>a(1nsxU!@{v)3nHlc{$o-@eQ#};bw#pHPF-lIVjSE#c2gv z>m|dq`O4|Uv8bkb2}KKfOWInUY%5jv#;xbGI(KWG2IX=I?xGQzwLAVy56in#{^q37 z*)FYUMn~f$O%q(P9eS<528uwYXmFD!l-ZZ8Yh)4@wp+OR92^7;t)C_O*+jOyvf8uF z%c`giJIv=>Q=_77aeAs~N1%stIy?8l$YBQncYct|^qA1ma4CD4{<_F#3Kt^h0@`&r2}TN*}{rLhEz_=1xz;EmqB)N zmY@}^f3)GXO)zlgTb^r@UeQp)Wn;mHBL@wpk&Sfg(KOnnI^r5Ec`an=eETd&aqpp6 zMx$X1sfi0Wxz6izD(omTW2gE&8{~x|myDJg{@P+4?Mmv?)}6^Q!+}AOHQAASj&U65 z@_m!Tb$+pte+CJ5x;uhSk&I<%>jXX@=v~}PJaj95*M^ZxUb)#4)9lG^J=3t9^aUU; zTp@yS=khDj zuI^3kCNn%947463vt&4#$|hn#k15m~uPC|T@!TQ~E4Fh7Vsr6%6mJ~)i^oRun@O~F z)=IB3dz82%-z90k$*yx;6a47Zh3phlA0^Oy>PXy*yh8OY_N*Q|C2a)g1fM!bYhY@r zu11|ih9aIj*p%#mP7TN|7uM6{eQ_Shdo@>Zj9i4Pp@|+Ouv+P*GUVM13lOlav)TF& zchF8`GRG4VUXmtd1%RnnVH+|3j<(RPMJEvKxoP;}XqiqU4WoR&uy4NHHVB%qvst?` zN>h)rp38F$U$LdPFkuIfLZs?tpT=s~fr<6);DtR0n*3QG;xJ+-`Zf!9HO<>{%{;LP zb`COhm}z=&+K{F#*g%}3p64!CB&O&*j-0HSwjroblUH;5_E^gC!xWasw8d%Ph1x}- zeX8JG3vaCQdl~%PwDjQcW^0?YX<|)Vlk&0xqHvVzJr}2WlDq?;EE2R+;BUPJ@*I9D z(%c?yqhPquPuhy+n89yj8Q5;;PR+T!IZIip&|)gk;mH%|Kfl$EUL#F3IJ5Mv;rJDe zytbnX#+oDBW6iNZgRnm<>!N}A0k;5GAdj!ov6ayw2&)UbI_CHu*x#_L_;`<1yywvl zmF{ZBTgVA04}U?Z3X;9JxhxDh7RlhxWzh|aAj=!syil_nV;a!|+hVqDxRG!QfK1t5 z6sIXOS0K$%F!jhc7Hdl{=4HAD1D$7^1(;X+A0+Pus$J;!G`wUo$rMit?E1(}CONqq zJ^aYFf6LqTy!|Fx#_~I#Jb`F$m!fvd$!>Z0*H~O*ylso!U7IwPjARz2>6JDIM|=Ln zEmky6uU`tAu;l9E$$GRQKdq1%0gdj-*uwlspk5PR5RTI-z&=beAE>Fp_%#;qqvfBY z*Q!Rt^ZNyBM9pFt;}MKi*mL z<3@X%GqrE#2P1vD@ znye7~?Ss(X2JJ!GY8FQe&RIDhyRxDOFs35AsGX)#bf;m&-dpt(&x$i?Q$af+u?jj; zR?*ZEPejL3X@r_SW6s!IxW!mmYdG6#Dx!;$WKZtYCRU;q?FSyo=&fs*6W~*t&P`QV z538U>4SlxnASyB`yJuMuYsFEZR_Y0PBq`)fkfhMhoQks`1GYHf_IQNKlOn_PzY3e1 zSf>3xL+|X`+xf)MKY!6Ndc!CCaNIKgyFU8&bXe}c

0mp<|DRzZ#+wPFdVWz; zl;{WCC)3@ZUVkS@?;%IuOSw;+O8@-n_4k{@t_EE98k>eZ_j;PHE_?xB2w?ch<`O z!SuT*Etg-rnf{(t2rcODvf*|~znVL(?{d@g*Q~hwl|CK*sOisic-H01f0vwu*Z=QA{&TB^89_JxioNEq p@q@#&mR&UE|K;1o>g-SX*+Ra`^4ErYOP_pC(wAyMk-&lGe*+(NrMv(D literal 0 HcmV?d00001 diff --git a/external/packages/raspi/orangepi/common/files/orangepi-hardware-optimization b/external/packages/raspi/orangepi/common/files/orangepi-hardware-optimization new file mode 100755 index 000000000000..a7b81932841f --- /dev/null +++ b/external/packages/raspi/orangepi/common/files/orangepi-hardware-optimization @@ -0,0 +1,106 @@ +#!/bin/bash + +source /etc/orangepi-release + +prepare_board() { + + case ${BOARD} in + + orangepi5|orangepi5b|orangepi5plus|orangepitab|orangepi900) + + [[ $BOARD =~ orangepi5|orangepi5b ]] && echo host > /sys/kernel/debug/usb/fc000000.usb/mode + if [[ -c /dev/mpp_service ]]; then + chmod 0666 /dev/mpp_service + + { + echo "type=dec" + echo "codecs=VP8:VP9:H.264:H.265:AV1" + echo "max-width=7680" + echo "max-height=4320" + } > /dev/video-dec0 + + # Create dummy video node for chromium V4L2 VDA/VEA with rkmpp plugin + echo enc > /dev/video-enc0 + chmod 0660 /dev/video-* + chown root:video /dev/video-* + fi + bt_status=$(cat /proc/device-tree/wireless-bluetooth/status) + wifi_chip=$(cat /proc/device-tree/wireless-wlan/wifi_chip_type) + if [[ ${wifi_chip} == "ap6275p" && ${bt_status} == "okay" ]]; then + rfkill unblock all + brcm_patchram_plus --bd_addr_rand --enable_hci --no2bytes --use_baudrate_for_download --tosleep 200000 \ + --baudrate 1500000 --patchram /lib/firmware/ap6275p/BCM4362A2.hcd /dev/ttyS9 & + fi + ;; + orangepicm4|orangepi3b) + if [[ -c /dev/mpp_service ]]; then + chmod 666 /dev/mpp_service + + # Create dummy video node for chromium V4L2 VDA/VEA with rkmpp plugin + echo dec > /dev/video-dec0 + echo enc > /dev/video-enc0 + chmod 660 /dev/video-* + chown root.video /dev/video-* + fi + + for p in $(modetest|grep "^Planes:" -A 9999|grep -o "^[0-9]*"); + do + modetest -M rockchip -aw $p:ASYNC_COMMIT:1 &>/dev/null + done + + amixer -c 0 cset name='Playback Path' HP > /dev/null 2>&1 + amixer -c 0 cset name='Capture MIC Path' 'Main Mic' > /dev/null 2>&1 + + rfkill unblock all + /usr/bin/hciattach_opi -n -s 1500000 /dev/ttyBT0 sprd & + #rfkill unblock all + #brcm_patchram_plus --bd_addr_rand --enable_hci --no2bytes --use_baudrate_for_download --tosleep 200000 \ + # --baudrate 1500000 --patchram /lib/firmware/cyw43455/BCM4345C0.hcd /dev/ttyS1 & + ;; + orangepizero2|orangepizero2-lts|orangepizero2-b|orangepizero3|orangepir1b|orangepizero2w) + kv=$(uname -r) + if [[ $BOARD == orangepir1b ]]; then + + #for 100m interface + interface_100m="eth1" + echo netdev > /sys/class/leds/100m_act/trigger + echo "${interface_100m}" > /sys/class/leds/100m_act/device_name + echo 1 > /sys/class/leds/100m_act/tx + echo 1 > /sys/class/leds/100m_act/rx + + echo netdev > /sys/class/leds/100m_link/trigger + echo ${interface_100m} > /sys/class/leds/100m_link/device_name + echo 1 > /sys/class/leds/100m_link/link + + echo netdev > /sys/class/leds/lan_led/trigger + echo ${interface_100m} > /sys/class/leds/lan_led/device_name + echo 1 > /sys/class/leds/lan_led/link + echo 1 > /sys/class/leds/lan_led/tx + echo 1 > /sys/class/leds/lan_led/rx + + #for 1000m interface + interface_1000m="eth0" + echo netdev > /sys/class/leds/wan_led/trigger + echo ${interface_1000m} > /sys/class/leds/wan_led/device_name + echo 1 > /sys/class/leds/wan_led/link + echo 1 > /sys/class/leds/wan_led/tx + echo 1 > /sys/class/leds/wan_led/rx + + fi + + if [[ ${kv} == 4.9* ]]; then + aplay /usr/share/sounds/alsa/audio.wav -D hw:2,0 > /dev/null 2>&1 + fi + + rfkill unblock all + /usr/bin/hciattach_opi -n -s 1500000 /dev/ttyBT0 sprd & + ;; + esac +} + +case $1 in + *start*) + # hardware preparation + prepare_board & + ;; +esac diff --git a/external/packages/raspi/orangepi/common/files/orangepi-hardware-optimize.service b/external/packages/raspi/orangepi/common/files/orangepi-hardware-optimize.service new file mode 100755 index 000000000000..3ea71b3e18ef --- /dev/null +++ b/external/packages/raspi/orangepi/common/files/orangepi-hardware-optimize.service @@ -0,0 +1,19 @@ +# Orange Pi hardware optimization service +# Apply optimisations +# This service may block the boot process for up to 2 minutes + +[Unit] +Description=Orange Pi hardware optimization +Before=basic.target +After=sysinit.target local-fs.target orangepi-hardware-monitor.target +DefaultDependencies=no + +[Service] +Type=oneshot +ExecStart=/usr/lib/orangepi/orangepi-hardware-optimization start +ExecStop=/usr/lib/orangepi/orangepi-hardware-optimization stop +RemainAfterExit=yes +TimeoutStartSec=2min + +[Install] +WantedBy=basic.target diff --git a/external/packages/raspi/scripts/common b/external/packages/raspi/scripts/common new file mode 100644 index 000000000000..72368962b76f --- /dev/null +++ b/external/packages/raspi/scripts/common @@ -0,0 +1,105 @@ +log (){ + date +"[%T] $*" | tee -a "${LOG_FILE}" +} +export -f log + +bootstrap(){ + local BOOTSTRAP_CMD=debootstrap + local BOOTSTRAP_ARGS=() + + export http_proxy=${APT_PROXY} + + BOOTSTRAP_ARGS+=(--arch arm64) + BOOTSTRAP_ARGS+=(--include gnupg) + BOOTSTRAP_ARGS+=(--components "main,contrib,non-free") + #BOOTSTRAP_ARGS+=(--keyring "${STAGE_DIR}/files/raspberrypi.gpg") + BOOTSTRAP_ARGS+=(--exclude=info) + BOOTSTRAP_ARGS+=(--include=ca-certificates) + BOOTSTRAP_ARGS+=("$@") + printf -v BOOTSTRAP_STR '%q ' "${BOOTSTRAP_ARGS[@]}" + + capsh $CAPSH_ARG -- -c "'${BOOTSTRAP_CMD}' $BOOTSTRAP_STR" || true + + if [ -d "$2/debootstrap" ] && ! rmdir "$2/debootstrap"; then + cp "$2/debootstrap/debootstrap.log" "${STAGE_WORK_DIR}" + log "bootstrap failed: please check ${STAGE_WORK_DIR}/debootstrap.log" + return 1 + fi +} +export -f bootstrap + +copy_previous(){ + if [ ! -d "${PREV_ROOTFS_DIR}" ]; then + echo "Previous stage rootfs not found" + false + fi + mkdir -p "${ROOTFS_DIR}" + rsync -aHAXx --exclude var/cache/apt/archives "${PREV_ROOTFS_DIR}/" "${ROOTFS_DIR}/" +} +export -f copy_previous + +unmount(){ + if [ -z "$1" ]; then + DIR=$PWD + else + DIR=$1 + fi + + while mount | grep -q "$DIR"; do + local LOCS + LOCS=$(mount | grep "$DIR" | cut -f 3 -d ' ' | sort -r) + for loc in $LOCS; do + umount "$loc" + done + done +} +export -f unmount + +unmount_image(){ + sync + sleep 1 + LOOP_DEVICE=$(losetup --list | grep "$1" | cut -f1 -d' ') + if [ -n "$LOOP_DEVICE" ]; then + for part in "$LOOP_DEVICE"p*; do + if DIR=$(findmnt -n -o target -S "$part"); then + unmount "$DIR" + fi + done + losetup -d "$LOOP_DEVICE" + fi +} +export -f unmount_image + +on_chroot() { + if ! mount | grep -q "$(realpath "${ROOTFS_DIR}"/proc)"; then + mount -t proc proc "${ROOTFS_DIR}/proc" + fi + + if ! mount | grep -q "$(realpath "${ROOTFS_DIR}"/dev)"; then + mount --bind /dev "${ROOTFS_DIR}/dev" + fi + + if ! mount | grep -q "$(realpath "${ROOTFS_DIR}"/dev/pts)"; then + mount --bind /dev/pts "${ROOTFS_DIR}/dev/pts" + fi + + if ! mount | grep -q "$(realpath "${ROOTFS_DIR}"/sys)"; then + mount --bind /sys "${ROOTFS_DIR}/sys" + fi + + if ! mount | grep -q "$(realpath "${ROOTFS_DIR}"/run)"; then + mount -t tmpfs tmpfs "${ROOTFS_DIR}/run" + fi + + if ! mount | grep -q "$(realpath "${ROOTFS_DIR}"/tmp)"; then + mount -t tmpfs tmpfs "${ROOTFS_DIR}/tmp" + fi + + capsh $CAPSH_ARG "--chroot=${ROOTFS_DIR}/" -- -e "$@" +} +export -f on_chroot + +update_issue() { + echo -e "Raspberry Pi reference ${IMG_DATE}\nGenerated using ${PI_GEN}, ${PI_GEN_REPO}, ${GIT_HASH}, ${1}" > "${ROOTFS_DIR}/etc/rpi-issue" +} +export -f update_issue diff --git a/external/packages/raspi/scripts/dependencies_check b/external/packages/raspi/scripts/dependencies_check new file mode 100644 index 000000000000..32c42eff96e5 --- /dev/null +++ b/external/packages/raspi/scripts/dependencies_check @@ -0,0 +1,53 @@ +# dependencies_check +# $@ Dependency files to check +# +# Each dependency is in the form of a tool to test for, optionally followed by +# a : and the name of a package if the package on a Debian-ish system is not +# named for the tool (i.e., qemu-user-static). +dependencies_check() +{ + local depfile deps missing + + for depfile in "$@"; do + if [[ -e "$depfile" ]]; then + deps="$(sed -f "${SCRIPT_DIR}/remove-comments.sed" < "${BASE_DIR}/depends")" + + fi + for dep in $deps; do + if ! hash "${dep%:*}" 2>/dev/null; then + missing="${missing:+$missing }${dep#*:}" + fi + done + done + + if [[ "$missing" ]]; then + echo "Required dependencies not installed" + echo + echo "This can be resolved on Debian/Raspbian systems by installing:" + echo "$missing" + false + fi + + # If we're building on a native arm platform, we don't need to check for + # binfmt_misc or require it to be loaded. + + binfmt_misc_required=1 + + case $(uname -m) in + aarch64) + binfmt_misc_required=0 + ;; + arm*) + binfmt_misc_required=0 + ;; + esac + + if [[ "${binfmt_misc_required}" == "1" ]]; then + if ! grep -q "/proc/sys/fs/binfmt_misc" /proc/mounts; then + echo "Module binfmt_misc not loaded in host" + echo "Please run:" + echo " sudo modprobe binfmt_misc" + exit 1 + fi + fi +} diff --git a/external/packages/raspi/scripts/qcow2_handling b/external/packages/raspi/scripts/qcow2_handling new file mode 100644 index 000000000000..66708e710e24 --- /dev/null +++ b/external/packages/raspi/scripts/qcow2_handling @@ -0,0 +1,256 @@ +#!/bin/bash + +# QCOW2 Routines + +export CURRENT_IMAGE +export CURRENT_MOUNTPOINT + +export NBD_DEV +export MAP_BOOT_DEV +export MAP_ROOT_DEV + +# set in build.sh +# should be fairly enough for the beginning +# overwrite here by uncommenting following lines +# BASE_QCOW2_SIZE=12G + +# find and initialize free block device nodes +init_nbd() { + modprobe nbd max_part=16 + if [ -z "${NBD_DEV}" ]; then + for x in /sys/class/block/nbd* ; do + S=`cat $x/size` + if [ "$S" == "0" ] ; then + NBD_DEV=/dev/$(basename $x) + MAP_BOOT_DEV=/dev/mapper/$(basename $x)p1 + MAP_ROOT_DEV=/dev/mapper/$(basename $x)p2 + break + fi + done + fi +} +export -f init_nbd + +# connect image to block device +connect_blkdev() { + init_nbd + qemu-nbd --discard=unmap -c $NBD_DEV "$1" + sync + kpartx -as $NBD_DEV + sync + CURRENT_IMAGE="$1" +} +export -f connect_blkdev + +# disconnect image from block device +disconnect_blkdev() { + kpartx -d $NBD_DEV + qemu-nbd -d $NBD_DEV + NBD_DEV= + MAP_BOOT_DEV= + MAP_ROOT_DEV= + CURRENT_IMAGE= +} +export -f disconnect_blkdev + +# mount qcow2 image: mount_image +mount_qimage() { + connect_blkdev "$1" + mount -v -t ext4 $MAP_ROOT_DEV "$2" + mkdir -p "${ROOTFS_DIR}/boot" + mount -v -t vfat $MAP_BOOT_DEV "$2/boot" + CURRENT_MOUNTPOINT="$2" +} +export -f mount_qimage + +# umount qcow2 image: umount_image +umount_qimage() { + sync + #umount "$1/boot" + while mount | grep -q "$1"; do + local LOCS + LOCS=$(mount | grep "$1" | cut -f 3 -d ' ' | sort -r) + for loc in $LOCS; do + echo "$loc" + while mountpoint -q "$loc" && ! umount "$loc"; do + sleep 0.1 + done + done + done + CURRENT_MOUNTPOINT= + disconnect_blkdev +} +export -f umount_qimage + +# create base image / backing image / mount image +load_qimage() { + if [ -z "${CURRENT_MOUNTPOINT}" ]; then + if [ ! -d "${ROOTFS_DIR}" ]; then + mkdir -p "${ROOTFS_DIR}"; + fi + + if [ "${CLEAN}" = "1" ] && [ -f "${WORK_DIR}/image-${STAGE}.qcow2" ]; then + rm -f "${WORK_DIR}/image-${STAGE}.qcow2"; + fi + + if [ ! -f "${WORK_DIR}/image-${STAGE}.qcow2" ]; then + pushd ${WORK_DIR} > /dev/null + init_nbd + if [ -z "${PREV_STAGE}" ]; then + echo "Creating base image: image-${STAGE}.qcow2" + # -o preallocation=falloc + qemu-img create -f qcow2 image-${STAGE}.qcow2 $BASE_QCOW2_SIZE + sync + qemu-nbd --discard=unmap -c $NBD_DEV image-${STAGE}.qcow2 + sync + sfdisk $NBD_DEV << EOF +4MiB,250MiB,c,* +254MiB,,83; +EOF + sync + kpartx -as $NBD_DEV + mkdosfs -n boot -F 32 -s 4 -v $MAP_BOOT_DEV + mkfs.ext4 -L rootfs -O "^huge_file,^64bit" $MAP_ROOT_DEV + sync + else + if [ ! -f "${WORK_DIR}/image-${PREV_STAGE}.qcow2" ]; then + exit 1; + fi + echo "Creating backing image: image-${STAGE}.qcow2 <- ${WORK_DIR}/image-${PREV_STAGE}.qcow2" + qemu-img create -f qcow2 \ + -o backing_file=${WORK_DIR}/image-${PREV_STAGE}.qcow2 \ + ${WORK_DIR}/image-${STAGE}.qcow2 + sync + qemu-nbd --discard=unmap -c $NBD_DEV image-${STAGE}.qcow2 + sync + kpartx -as $NBD_DEV + fi + + mount -v -t ext4 $MAP_ROOT_DEV "${ROOTFS_DIR}" + mkdir -p "${ROOTFS_DIR}/boot" + mount -v -t vfat $MAP_BOOT_DEV "${ROOTFS_DIR}/boot" + CURRENT_IMAGE=${WORK_DIR}/image-${STAGE}.qcow2 + CURRENT_MOUNTPOINT=${ROOTFS_DIR} + popd > /dev/null + else + mount_qimage "${WORK_DIR}/image-${STAGE}.qcow2" "${ROOTFS_DIR}" + fi + echo "Current image in use: ${CURRENT_IMAGE} (MP: ${CURRENT_MOUNTPOINT})" + fi +} +export -f load_qimage + +# umount current image and refresh mount point env var +unload_qimage() { + if [ ! -z "${CURRENT_MOUNTPOINT}" ]; then + fstrim -v "${CURRENT_MOUNTPOINT}" || true + umount_qimage "${CURRENT_MOUNTPOINT}" + fi +} +export -f unload_qimage + +# based on: https://github.com/SirLagz/RaspberryPi-ImgAutoSizer +# helper function for make_bootable_image, do not call directly +function resize_qcow2() { + if [ -z "$CALL_FROM_MBI" ]; then + echo "resize_qcow2: cannot be called directly, use make_bootable_image instead" + return 1 + fi + + # ROOT_MARGIN=$((800*1024*1024)) + ROOT_MARGIN=$((1*1024*1024)) + PARTED_OUT=`parted -s -m "$NBD_DEV" unit B print` + PART_NO=`echo "$PARTED_OUT" | grep ext4 | awk -F: ' { print $1 } '` + PART_START=`echo "$PARTED_OUT" | grep ext4 | awk -F: ' { print substr($2,1,length($2)-1) } '` + + e2fsck -y -f $MAP_ROOT_DEV || true + + DATA_SIZE=`resize2fs -P $MAP_ROOT_DEV | awk -F': ' ' { print $2 } '` + BLOCK_SIZE=$(dumpe2fs -h $MAP_ROOT_DEV | grep 'Block size' | awk -F': ' ' { print $2 }') + BLOCK_SIZE=${BLOCK_SIZE// /} + + let DATA_SIZE=$DATA_SIZE+$ROOT_MARGIN/$BLOCK_SIZE + resize2fs -p $MAP_ROOT_DEV $DATA_SIZE + sleep 1 + + let PART_NEW_SIZE=$DATA_SIZE*$BLOCK_SIZE + let PART_NEW_END=$PART_START+$PART_NEW_SIZE + ACT1=`parted -s "$NBD_DEV" rm 2` + ACT2=`parted -s "$NBD_DEV" unit B mkpart primary $PART_START $PART_NEW_END` + NEW_IMG_SIZE=`parted -s -m "$NBD_DEV" unit B print free | tail -1 | awk -F: ' { print substr($2,1,length($2)-1) } '` +} +export -f resize_qcow2 + +# create raw img from qcow2: make_bootable_image +function make_bootable_image() { + + EXPORT_QCOW2="$1" + EXPORT_IMAGE="$2" + + echo "Connect block device to source qcow2" + connect_blkdev "${EXPORT_QCOW2}" + + echo "Resize fs and partition" + CALL_FROM_MBI=1 + resize_qcow2 + sync + CALL_FROM_MBI= + + echo "Disconnect block device" + disconnect_blkdev + + if [ -z "$NEW_IMG_SIZE" ]; then + echo "NEW_IMG_SIZE could not be calculated, cannot process image. Exit." + exit 1 + fi + + echo "Shrinking qcow2 image" + qemu-img resize --shrink "${EXPORT_QCOW2}" $NEW_IMG_SIZE + sync + + echo "Convert qcow2 to raw image" + qemu-img convert -f qcow2 -O raw "${EXPORT_QCOW2}" "${EXPORT_IMAGE}" + sync + + echo "Get PARTUUIDs from image" + IMGID="$(blkid -o value -s PTUUID "${EXPORT_IMAGE}")" + + BOOT_PARTUUID="${IMGID}-01" + echo "Boot: $BOOT_PARTUUID" + ROOT_PARTUUID="${IMGID}-02" + echo "Root: $ROOT_PARTUUID" + + echo "Mount image" + MOUNTROOT=${WORK_DIR}/tmpimage + mkdir -p $MOUNTROOT + + MOUNTPT=$MOUNTROOT + PARTITION=2 + mount "${EXPORT_IMAGE}" "$MOUNTPT" -o loop,offset=$[ `/sbin/sfdisk -d "${EXPORT_IMAGE}" | grep "start=" | head -n $PARTITION | tail -n1 | sed 's/.*start=[ ]*//' | sed 's/,.*//'` * 512 ],sizelimit=$[ `/sbin/sfdisk -d "${EXPORT_IMAGE}" | grep "start=" | head -n $PARTITION | tail -n1 | sed 's/.*size=[ ]*//' | sed 's/,.*//'` * 512 ] || exit 1 + + MOUNTPT=$MOUNTROOT/boot + PARTITION=1 + mount "${EXPORT_IMAGE}" "$MOUNTPT" -o loop,offset=$[ `/sbin/sfdisk -d "${EXPORT_IMAGE}" | grep "start=" | head -n $PARTITION | tail -n1 | sed 's/.*start=[ ]*//' | sed 's/,.*//'` * 512 ],sizelimit=$[ `/sbin/sfdisk -d "${EXPORT_IMAGE}" | grep "start=" | head -n $PARTITION | tail -n1 | sed 's/.*size=[ ]*//' | sed 's/,.*//'` * 512 ] || exit 1 + + if [ ! -d "${MOUNTROOT}/root" ]; then + echo "Image damaged or not mounted. Exit." + exit 1 + fi + + echo "Setup PARTUUIDs" + if [ ! -z "$BOOT_PARTUUID" ] && [ ! -z "$ROOT_PARTUUID" ]; then + echo "Set UUIDs to make it bootable" + sed -i "s/BOOTDEV/PARTUUID=${BOOT_PARTUUID}/" "${MOUNTROOT}/etc/fstab" + sed -i "s/ROOTDEV/PARTUUID=${ROOT_PARTUUID}/" "${MOUNTROOT}/etc/fstab" + sed -i "s/ROOTDEV/PARTUUID=${ROOT_PARTUUID}/" "${MOUNTROOT}/boot/cmdline.txt" + fi + + echo "Umount image" + sync + umount "${MOUNTROOT}/boot" || exit 1 + umount "${MOUNTROOT}" || exit 1 + + echo "Remove qcow2 export image" + rm -f "${EXPORT_QCOW2}" +} +export -f make_bootable_image diff --git a/external/packages/raspi/scripts/remove-comments.sed b/external/packages/raspi/scripts/remove-comments.sed new file mode 100644 index 000000000000..2a6889fe4f6f --- /dev/null +++ b/external/packages/raspi/scripts/remove-comments.sed @@ -0,0 +1,11 @@ +# Deletes comments and collapses whitespace in ##-packages files + +# Append (N)ext line to buffer +# if (!)not ($)buffer is EOF, (b)ranch to (:)label loop +:loop +N +$ !b loop + +# Buffer is "line1\nline2\n...lineN", del comments and collapse whitespace +s/#[^\n]*//g +s/[[:space:]]\{1,\}/ /g diff --git a/external/packages/raspi/stage0/00-configure-apt/00-run.sh b/external/packages/raspi/stage0/00-configure-apt/00-run.sh new file mode 100755 index 000000000000..49238b7491cc --- /dev/null +++ b/external/packages/raspi/stage0/00-configure-apt/00-run.sh @@ -0,0 +1,24 @@ +#!/bin/bash -e + + +install -m 644 files/sources.list "${ROOTFS_DIR}/etc/apt/" +install -m 644 files/raspi.list "${ROOTFS_DIR}/etc/apt/sources.list.d/" +sed -i "s/RELEASE/bullseye/g" "${ROOTFS_DIR}/etc/apt/sources.list" +sed -i "s/RELEASE/bullseye/g" "${ROOTFS_DIR}/etc/apt/sources.list.d/raspi.list" + +if [ -n "$APT_PROXY" ]; then + install -m 644 files/51cache "${ROOTFS_DIR}/etc/apt/apt.conf.d/51cache" + sed "${ROOTFS_DIR}/etc/apt/apt.conf.d/51cache" -i -e "s|APT_PROXY|${APT_PROXY}|" +else + rm -f "${ROOTFS_DIR}/etc/apt/apt.conf.d/51cache" +fi + +cat files/raspberrypi.gpg.key | gpg --dearmor > "${ROOTFS_DIR}/raspberrypi-archive-stable.gpg" +install -m 644 "${ROOTFS_DIR}/raspberrypi-archive-stable.gpg" "${ROOTFS_DIR}/etc/apt/trusted.gpg.d/" +rm "${ROOTFS_DIR}/raspberrypi-archive-stable.gpg" + +on_chroot << EOF +dpkg --add-architecture armhf +apt-get update +apt-get dist-upgrade -y +EOF diff --git a/external/packages/raspi/stage0/00-configure-apt/01-packages b/external/packages/raspi/stage0/00-configure-apt/01-packages new file mode 100644 index 000000000000..f5e37894ed8d --- /dev/null +++ b/external/packages/raspi/stage0/00-configure-apt/01-packages @@ -0,0 +1 @@ +raspberrypi-archive-keyring diff --git a/external/packages/raspi/stage0/00-configure-apt/files/51cache b/external/packages/raspi/stage0/00-configure-apt/files/51cache new file mode 100644 index 000000000000..a8920a9a1d71 --- /dev/null +++ b/external/packages/raspi/stage0/00-configure-apt/files/51cache @@ -0,0 +1 @@ +Acquire::http { Proxy "APT_PROXY"; }; diff --git a/external/packages/raspi/stage0/00-configure-apt/files/raspberrypi.gpg.key b/external/packages/raspi/stage0/00-configure-apt/files/raspberrypi.gpg.key new file mode 100644 index 000000000000..60b5f658251e --- /dev/null +++ b/external/packages/raspi/stage0/00-configure-apt/files/raspberrypi.gpg.key @@ -0,0 +1,30 @@ +-----BEGIN PGP PUBLIC KEY BLOCK----- +Version: GnuPG v1.4.12 (GNU/Linux) + +mQENBE/d7o8BCACrwqQacGJfn3tnMzGui6mv2lLxYbsOuy/+U4rqMmGEuo3h9m92 +30E2EtypsoWczkBretzLUCFv+VUOxaA6sV9+puTqYGhhQZFuKUWcG7orf7QbZRuu +TxsEUepW5lg7MExmAu1JJzqM0kMQX8fVyWVDkjchZ/is4q3BPOUCJbUJOsE+kK/6 +8kW6nWdhwSAjfDh06bA5wvoXNjYoDdnSZyVdcYCPEJXEg5jfF/+nmiFKMZBraHwn +eQsepr7rBXxNcEvDlSOPal11fg90KXpy7Umre1UcAZYJdQeWcHu7X5uoJx/MG5J8 +ic6CwYmDaShIFa92f8qmFcna05+lppk76fsnABEBAAG0IFJhc3BiZXJyeSBQaSBB +cmNoaXZlIFNpZ25pbmcgS2V5iQE4BBMBAgAiBQJP3e6PAhsDBgsJCAcDAgYVCAIJ +CgsEFgIDAQIeAQIXgAAKCRCCsSmSf6MwPk6vB/9pePB3IukU9WC9Bammh3mpQTvL +OifbkzHkmAYxzjfK6D2I8pT0xMxy949+ThzJ7uL60p6T/32ED9DR3LHIMXZvKtuc +mQnSiNDX03E2p7lIP/htoxW2hDP2n8cdlNdt0M9IjaWBppsbO7IrDppG2B1aRLni +uD7v8bHRL2mKTtIDLX42Enl8aLAkJYgNWpZyPkDyOqamjijarIWjGEPCkaURF7g4 +d44HvYhpbLMOrz1m6N5Bzoa5+nq3lmifeiWKxioFXU+Hy5bhtAM6ljVb59hbD2ra +X4+3LXC9oox2flmQnyqwoyfZqVgSQa0B41qEQo8t1bz6Q1Ti7fbMLThmbRHiuQEN +BE/d7o8BCADNlVtBZU63fm79SjHh5AEKFs0C3kwa0mOhp9oas/haDggmhiXdzeD3 +49JWz9ZTx+vlTq0s+I+nIR1a+q+GL+hxYt4HhxoA6vlDMegVfvZKzqTX9Nr2VqQa +S4Kz3W5ULv81tw3WowK6i0L7pqDmvDqgm73mMbbxfHD0SyTt8+fk7qX6Ag2pZ4a9 +ZdJGxvASkh0McGpbYJhk1WYD+eh4fqH3IaeJi6xtNoRdc5YXuzILnp+KaJyPE5CR +qUY5JibOD3qR7zDjP0ueP93jLqmoKltCdN5+yYEExtSwz5lXniiYOJp8LWFCgv5h +m8aYXkcJS1xVV9Ltno23YvX5edw9QY4hABEBAAGJAR8EGAECAAkFAk/d7o8CGwwA +CgkQgrEpkn+jMD5Figf/dIC1qtDMTbu5IsI5uZPX63xydaExQNYf98cq5H2fWF6O +yVR7ERzA2w33hI0yZQrqO6pU9SRnHRxCFvGv6y+mXXXMRcmjZG7GiD6tQWeN/3wb +EbAn5cg6CJ/Lk/BI4iRRfBX07LbYULCohlGkwBOkRo10T+Ld4vCCnBftCh5x2OtZ +TOWRULxP36y2PLGVNF+q9pho98qx+RIxvpofQM/842ZycjPJvzgVQsW4LT91KYAE +4TVf6JjwUM6HZDoiNcX6d7zOhNfQihXTsniZZ6rky287htsWVDNkqOi5T3oTxWUo +m++/7s3K3L0zWopdhMVcgg6Nt9gcjzqN1c0gy55L/g== +=mNSj +-----END PGP PUBLIC KEY BLOCK----- diff --git a/external/packages/raspi/stage0/00-configure-apt/files/raspi.list b/external/packages/raspi/stage0/00-configure-apt/files/raspi.list new file mode 100644 index 000000000000..fd557ffedfcb --- /dev/null +++ b/external/packages/raspi/stage0/00-configure-apt/files/raspi.list @@ -0,0 +1,7 @@ +deb http://mirrors.ustc.edu.cn/archive.raspberrypi.org/debian/ RELEASE main +# Uncomment line below then 'apt-get update' to enable 'apt-get source' +#deb-src http://mirrors.ustc.edu.cn/archive.raspberrypi.org/debian/ RELEASE main + +#deb http://archive.raspberrypi.org/debian/ RELEASE main +# Uncomment line below then 'apt-get update' to enable 'apt-get source' +#deb-src http://archive.raspberrypi.org/debian/ RELEASE main diff --git a/external/packages/raspi/stage0/00-configure-apt/files/sources.list b/external/packages/raspi/stage0/00-configure-apt/files/sources.list new file mode 100644 index 000000000000..7957199d8cff --- /dev/null +++ b/external/packages/raspi/stage0/00-configure-apt/files/sources.list @@ -0,0 +1,15 @@ +deb http://mirrors.ustc.edu.cn/debian RELEASE main contrib non-free +deb http://mirrors.ustc.edu.cn/debian-security RELEASE-security main contrib non-free +deb http://mirrors.ustc.edu.cn/debian/ RELEASE-updates main contrib non-free +# Uncomment deb-src lines below then 'apt-get update' to enable 'apt-get source' +#deb-src http://mirrors.ustc.edu.cn/debian RELEASE main contrib non-free +#deb-src http://mirrors.ustc.edu.cn/debian-security RELEASE-security main contrib non-free +#deb-src http://mirrors.ustc.edu.cn/debian RELEASE-updates main contrib non-free + +#deb http://deb.debian.org/debian RELEASE main contrib non-free +#deb http://security.debian.org/debian-security RELEASE-security main contrib non-free +#deb http://deb.debian.org/debian RELEASE-updates main contrib non-free +## Uncomment deb-src lines below then 'apt-get update' to enable 'apt-get source' +##deb-src http://deb.debian.org/debian RELEASE main contrib non-free +##deb-src http://security.debian.org/debian-security RELEASE-security main contrib non-free +##deb-src http://deb.debian.org/debian RELEASE-updates main contrib non-free diff --git a/external/packages/raspi/stage0/01-locale/00-debconf b/external/packages/raspi/stage0/01-locale/00-debconf new file mode 100644 index 000000000000..b0ad3e4afb68 --- /dev/null +++ b/external/packages/raspi/stage0/01-locale/00-debconf @@ -0,0 +1,6 @@ +# Locales to be generated: +# Choices: All locales, aa_DJ ISO-8859-1, aa_DJ.UTF-8 UTF-8, aa_ER UTF-8, aa_ER@saaho UTF-8, aa_ET UTF-8, af_ZA ISO-8859-1, af_ZA.UTF-8 UTF-8, ak_GH UTF-8, am_ET UTF-8, an_ES ISO-8859-15, an_ES.UTF-8 UTF-8, anp_IN UTF-8, ar_AE ISO-8859-6, ar_AE.UTF-8 UTF-8, ar_BH ISO-8859-6, ar_BH.UTF-8 UTF-8, ar_DZ ISO-8859-6, ar_DZ.UTF-8 UTF-8, ar_EG ISO-8859-6, ar_EG.UTF-8 UTF-8, ar_IN UTF-8, ar_IQ ISO-8859-6, ar_IQ.UTF-8 UTF-8, ar_JO ISO-8859-6, ar_JO.UTF-8 UTF-8, ar_KW ISO-8859-6, ar_KW.UTF-8 UTF-8, ar_LB ISO-8859-6, ar_LB.UTF-8 UTF-8, ar_LY ISO-8859-6, ar_LY.UTF-8 UTF-8, ar_MA ISO-8859-6, ar_MA.UTF-8 UTF-8, ar_OM ISO-8859-6, ar_OM.UTF-8 UTF-8, ar_QA ISO-8859-6, ar_QA.UTF-8 UTF-8, ar_SA ISO-8859-6, ar_SA.UTF-8 UTF-8, ar_SD ISO-8859-6, ar_SD.UTF-8 UTF-8, ar_SS UTF-8, ar_SY ISO-8859-6, ar_SY.UTF-8 UTF-8, ar_TN ISO-8859-6, ar_TN.UTF-8 UTF-8, ar_YE ISO-8859-6, ar_YE.UTF-8 UTF-8, as_IN UTF-8, ast_ES ISO-8859-15, ast_ES.UTF-8 UTF-8, ayc_PE UTF-8, az_AZ UTF-8, be_BY CP1251, be_BY.UTF-8 UTF-8, be_BY@latin UTF-8, bem_ZM UTF-8, ber_DZ UTF-8, ber_MA UTF-8, bg_BG CP1251, bg_BG.UTF-8 UTF-8, bho_IN UTF-8, bn_BD UTF-8, bn_IN UTF-8, bo_CN UTF-8, bo_IN UTF-8, br_FR ISO-8859-1, br_FR.UTF-8 UTF-8, br_FR@euro ISO-8859-15, brx_IN UTF-8, bs_BA ISO-8859-2, bs_BA.UTF-8 UTF-8, byn_ER UTF-8, ca_AD ISO-8859-15, ca_AD.UTF-8 UTF-8, ca_ES ISO-8859-1, ca_ES.UTF-8 UTF-8, ca_ES.UTF-8@valencia UTF-8, ca_ES@euro ISO-8859-15, ca_ES@valencia ISO-8859-15, ca_FR ISO-8859-15, ca_FR.UTF-8 UTF-8, ca_IT ISO-8859-15, ca_IT.UTF-8 UTF-8, cmn_TW UTF-8, crh_UA UTF-8, cs_CZ ISO-8859-2, cs_CZ.UTF-8 UTF-8, csb_PL UTF-8, cv_RU UTF-8, cy_GB ISO-8859-14, cy_GB.UTF-8 UTF-8, da_DK ISO-8859-1, da_DK.UTF-8 UTF-8, de_AT ISO-8859-1, de_AT.UTF-8 UTF-8, de_AT@euro ISO-8859-15, de_BE ISO-8859-1, de_BE.UTF-8 UTF-8, de_BE@euro ISO-8859-15, de_CH ISO-8859-1, de_CH.UTF-8 UTF-8, de_DE ISO-8859-1, de_DE.UTF-8 UTF-8, de_DE@euro ISO-8859-15, de_LI.UTF-8 UTF-8, de_LU ISO-8859-1, de_LU.UTF-8 UTF-8, de_LU@euro ISO-8859-15, doi_IN UTF-8, dv_MV UTF-8, dz_BT UTF-8, el_CY ISO-8859-7, el_CY.UTF-8 UTF-8, el_GR ISO-8859-7, el_GR.UTF-8 UTF-8, en_AG UTF-8, en_AU ISO-8859-1, en_AU.UTF-8 UTF-8, en_BW ISO-8859-1, en_BW.UTF-8 UTF-8, en_CA ISO-8859-1, en_CA.UTF-8 UTF-8, en_DK ISO-8859-1, en_DK.ISO-8859-15 ISO-8859-15, en_DK.UTF-8 UTF-8, en_GB ISO-8859-1, en_GB.ISO-8859-15 ISO-8859-15, en_GB.UTF-8 UTF-8, en_HK ISO-8859-1, en_HK.UTF-8 UTF-8, en_IE ISO-8859-1, en_IE.UTF-8 UTF-8, en_IE@euro ISO-8859-15, en_IN UTF-8, en_NG UTF-8, en_NZ ISO-8859-1, en_NZ.UTF-8 UTF-8, en_PH ISO-8859-1, en_PH.UTF-8 UTF-8, en_SG ISO-8859-1, en_SG.UTF-8 UTF-8, en_US ISO-8859-1, en_US.ISO-8859-15 ISO-8859-15, en_US.UTF-8 UTF-8, en_ZA ISO-8859-1, en_ZA.UTF-8 UTF-8, en_ZM UTF-8, en_ZW ISO-8859-1, en_ZW.UTF-8 UTF-8, eo ISO-8859-3, eo.UTF-8 UTF-8, es_AR ISO-8859-1, es_AR.UTF-8 UTF-8, es_BO ISO-8859-1, es_BO.UTF-8 UTF-8, es_CL ISO-8859-1, es_CL.UTF-8 UTF-8, es_CO ISO-8859-1, es_CO.UTF-8 UTF-8, es_CR ISO-8859-1, es_CR.UTF-8 UTF-8, es_CU UTF-8, es_DO ISO-8859-1, es_DO.UTF-8 UTF-8, es_EC ISO-8859-1, es_EC.UTF-8 UTF-8, es_ES ISO-8859-1, es_ES.UTF-8 UTF-8, es_ES@euro ISO-8859-15, es_GT ISO-8859-1, es_GT.UTF-8 UTF-8, es_HN ISO-8859-1, es_HN.UTF-8 UTF-8, es_MX ISO-8859-1, es_MX.UTF-8 UTF-8, es_NI ISO-8859-1, es_NI.UTF-8 UTF-8, es_PA ISO-8859-1, es_PA.UTF-8 UTF-8, es_PE ISO-8859-1, es_PE.UTF-8 UTF-8, es_PR ISO-8859-1, es_PR.UTF-8 UTF-8, es_PY ISO-8859-1, es_PY.UTF-8 UTF-8, es_SV ISO-8859-1, es_SV.UTF-8 UTF-8, es_US ISO-8859-1, es_US.UTF-8 UTF-8, es_UY ISO-8859-1, es_UY.UTF-8 UTF-8, es_VE ISO-8859-1, es_VE.UTF-8 UTF-8, et_EE ISO-8859-1, et_EE.ISO-8859-15 ISO-8859-15, et_EE.UTF-8 UTF-8, eu_ES ISO-8859-1, eu_ES.UTF-8 UTF-8, eu_ES@euro ISO-8859-15, eu_FR ISO-8859-1, eu_FR.UTF-8 UTF-8, eu_FR@euro ISO-8859-15, fa_IR UTF-8, ff_SN UTF-8, fi_FI ISO-8859-1, fi_FI.UTF-8 UTF-8, fi_FI@euro ISO-8859-15, fil_PH UTF-8, fo_FO ISO-8859-1, fo_FO.UTF-8 UTF-8, fr_BE ISO-8859-1, fr_BE.UTF-8 UTF-8, fr_BE@euro ISO-8859-15, fr_CA ISO-8859-1, fr_CA.UTF-8 UTF-8, fr_CH ISO-8859-1, fr_CH.UTF-8 UTF-8, fr_FR ISO-8859-1, fr_FR.UTF-8 UTF-8, fr_FR@euro ISO-8859-15, fr_LU ISO-8859-1, fr_LU.UTF-8 UTF-8, fr_LU@euro ISO-8859-15, fur_IT UTF-8, fy_DE UTF-8, fy_NL UTF-8, ga_IE ISO-8859-1, ga_IE.UTF-8 UTF-8, ga_IE@euro ISO-8859-15, gd_GB ISO-8859-15, gd_GB.UTF-8 UTF-8, gez_ER UTF-8, gez_ER@abegede UTF-8, gez_ET UTF-8, gez_ET@abegede UTF-8, gl_ES ISO-8859-1, gl_ES.UTF-8 UTF-8, gl_ES@euro ISO-8859-15, gu_IN UTF-8, gv_GB ISO-8859-1, gv_GB.UTF-8 UTF-8, ha_NG UTF-8, hak_TW UTF-8, he_IL ISO-8859-8, he_IL.UTF-8 UTF-8, hi_IN UTF-8, hne_IN UTF-8, hr_HR ISO-8859-2, hr_HR.UTF-8 UTF-8, hsb_DE ISO-8859-2, hsb_DE.UTF-8 UTF-8, ht_HT UTF-8, hu_HU ISO-8859-2, hu_HU.UTF-8 UTF-8, hy_AM UTF-8, hy_AM.ARMSCII-8 ARMSCII-8, ia_FR UTF-8, id_ID ISO-8859-1, id_ID.UTF-8 UTF-8, ig_NG UTF-8, ik_CA UTF-8, is_IS ISO-8859-1, is_IS.UTF-8 UTF-8, it_CH ISO-8859-1, it_CH.UTF-8 UTF-8, it_IT ISO-8859-1, it_IT.UTF-8 UTF-8, it_IT@euro ISO-8859-15, iu_CA UTF-8, iw_IL ISO-8859-8, iw_IL.UTF-8 UTF-8, ja_JP.EUC-JP EUC-JP, ja_JP.UTF-8 UTF-8, ka_GE GEORGIAN-PS, ka_GE.UTF-8 UTF-8, kk_KZ PT154, kk_KZ RK1048, kk_KZ.UTF-8 UTF-8, kl_GL ISO-8859-1, kl_GL.UTF-8 UTF-8, km_KH UTF-8, kn_IN UTF-8, ko_KR.EUC-KR EUC-KR, ko_KR.UTF-8 UTF-8, kok_IN UTF-8, ks_IN UTF-8, ks_IN@devanagari UTF-8, ku_TR ISO-8859-9, ku_TR.UTF-8 UTF-8, kw_GB ISO-8859-1, kw_GB.UTF-8 UTF-8, ky_KG UTF-8, lb_LU UTF-8, lg_UG ISO-8859-10, lg_UG.UTF-8 UTF-8, li_BE UTF-8, li_NL UTF-8, lij_IT UTF-8, lo_LA UTF-8, lt_LT ISO-8859-13, lt_LT.UTF-8 UTF-8, lv_LV ISO-8859-13, lv_LV.UTF-8 UTF-8, lzh_TW UTF-8, mag_IN UTF-8, mai_IN UTF-8, mg_MG ISO-8859-15, mg_MG.UTF-8 UTF-8, mhr_RU UTF-8, mi_NZ ISO-8859-13, mi_NZ.UTF-8 UTF-8, mk_MK ISO-8859-5, mk_MK.UTF-8 UTF-8, ml_IN UTF-8, mn_MN UTF-8, mni_IN UTF-8, mr_IN UTF-8, ms_MY ISO-8859-1, ms_MY.UTF-8 UTF-8, mt_MT ISO-8859-3, mt_MT.UTF-8 UTF-8, my_MM UTF-8, nan_TW UTF-8, nan_TW@latin UTF-8, nb_NO ISO-8859-1, nb_NO.UTF-8 UTF-8, nds_DE UTF-8, nds_NL UTF-8, ne_NP UTF-8, nhn_MX UTF-8, niu_NU UTF-8, niu_NZ UTF-8, nl_AW UTF-8, nl_BE ISO-8859-1, nl_BE.UTF-8 UTF-8, nl_BE@euro ISO-8859-15, nl_NL ISO-8859-1, nl_NL.UTF-8 UTF-8, nl_NL@euro ISO-8859-15, nn_NO ISO-8859-1, nn_NO.UTF-8 UTF-8, nr_ZA UTF-8, nso_ZA UTF-8, oc_FR ISO-8859-1, oc_FR.UTF-8 UTF-8, om_ET UTF-8, om_KE ISO-8859-1, om_KE.UTF-8 UTF-8, or_IN UTF-8, os_RU UTF-8, pa_IN UTF-8, pa_PK UTF-8, pap_AN UTF-8, pap_AW UTF-8, pap_CW UTF-8, pl_PL ISO-8859-2, pl_PL.UTF-8 UTF-8, ps_AF UTF-8, pt_BR ISO-8859-1, pt_BR.UTF-8 UTF-8, pt_PT ISO-8859-1, pt_PT.UTF-8 UTF-8, pt_PT@euro ISO-8859-15, quz_PE UTF-8, ro_RO ISO-8859-2, ro_RO.UTF-8 UTF-8, ru_RU ISO-8859-5, ru_RU.CP1251 CP1251, ru_RU.KOI8-R KOI8-R, ru_RU.UTF-8 UTF-8, ru_UA KOI8-U, ru_UA.UTF-8 UTF-8, rw_RW UTF-8, sa_IN UTF-8, sat_IN UTF-8, sc_IT UTF-8, sd_IN UTF-8, sd_IN@devanagari UTF-8, se_NO UTF-8, shs_CA UTF-8, si_LK UTF-8, sid_ET UTF-8, sk_SK ISO-8859-2, sk_SK.UTF-8 UTF-8, sl_SI ISO-8859-2, sl_SI.UTF-8 UTF-8, so_DJ ISO-8859-1, so_DJ.UTF-8 UTF-8, so_ET UTF-8, so_KE ISO-8859-1, so_KE.UTF-8 UTF-8, so_SO ISO-8859-1, so_SO.UTF-8 UTF-8, sq_AL ISO-8859-1, sq_AL.UTF-8 UTF-8, sq_MK UTF-8, sr_ME UTF-8, sr_RS UTF-8, sr_RS@latin UTF-8, ss_ZA UTF-8, st_ZA ISO-8859-1, st_ZA.UTF-8 UTF-8, sv_FI ISO-8859-1, sv_FI.UTF-8 UTF-8, sv_FI@euro ISO-8859-15, sv_SE ISO-8859-1, sv_SE.ISO-8859-15 ISO-8859-15, sv_SE.UTF-8 UTF-8, sw_KE UTF-8, sw_TZ UTF-8, szl_PL UTF-8, ta_IN UTF-8, ta_LK UTF-8, te_IN UTF-8, tg_TJ KOI8-T, tg_TJ.UTF-8 UTF-8, th_TH TIS-620, th_TH.UTF-8 UTF-8, the_NP UTF-8, ti_ER UTF-8, ti_ET UTF-8, tig_ER UTF-8, tk_TM UTF-8, tl_PH ISO-8859-1, tl_PH.UTF-8 UTF-8, tn_ZA UTF-8, tr_CY ISO-8859-9, tr_CY.UTF-8 UTF-8, tr_TR ISO-8859-9, tr_TR.UTF-8 UTF-8, ts_ZA UTF-8, tt_RU UTF-8, tt_RU@iqtelif UTF-8, ug_CN UTF-8, uk_UA KOI8-U, uk_UA.UTF-8 UTF-8, unm_US UTF-8, ur_IN UTF-8, ur_PK UTF-8, uz_UZ ISO-8859-1, uz_UZ.UTF-8 UTF-8, uz_UZ@cyrillic UTF-8, ve_ZA UTF-8, vi_VN UTF-8, wa_BE ISO-8859-1, wa_BE.UTF-8 UTF-8, wa_BE@euro ISO-8859-15, wae_CH UTF-8, wal_ET UTF-8, wo_SN UTF-8, xh_ZA ISO-8859-1, xh_ZA.UTF-8 UTF-8, yi_US CP1255, yi_US.UTF-8 UTF-8, yo_NG UTF-8, yue_HK UTF-8, zh_CN GB2312, zh_CN.GB18030 GB18030, zh_CN.GBK GBK, zh_CN.UTF-8 UTF-8, zh_HK BIG5-HKSCS, zh_HK.UTF-8 UTF-8, zh_SG GB2312, zh_SG.GBK GBK, zh_SG.UTF-8 UTF-8, zh_TW BIG5, zh_TW.EUC-TW EUC-TW, zh_TW.UTF-8 UTF-8, zu_ZA ISO-8859-1, zu_ZA.UTF-8 UTF-8 +locales locales/locales_to_be_generated multiselect ${LOCALE_DEFAULT} UTF-8 +# Default locale for the system environment: +# Choices: None, C.UTF-8, en_GB.UTF-8 +locales locales/default_environment_locale select ${LOCALE_DEFAULT} diff --git a/external/packages/raspi/stage0/01-locale/00-packages b/external/packages/raspi/stage0/01-locale/00-packages new file mode 100644 index 000000000000..a3068018e373 --- /dev/null +++ b/external/packages/raspi/stage0/01-locale/00-packages @@ -0,0 +1 @@ +locales diff --git a/external/packages/raspi/stage0/02-firmware/01-packages b/external/packages/raspi/stage0/02-firmware/01-packages new file mode 100644 index 000000000000..2d8e014a48de --- /dev/null +++ b/external/packages/raspi/stage0/02-firmware/01-packages @@ -0,0 +1,4 @@ +raspberrypi-bootloader +raspberrypi-kernel +u-boot-tools +initramfs-tools diff --git a/external/packages/raspi/stage0/files/raspberrypi.gpg b/external/packages/raspi/stage0/files/raspberrypi.gpg new file mode 100644 index 0000000000000000000000000000000000000000..fe1d207eb1ec50f159e3b99415dd00b363262fb4 GIT binary patch literal 2424 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 literal 0 HcmV?d00001 diff --git a/external/packages/raspi/stage0/prerun.sh b/external/packages/raspi/stage0/prerun.sh new file mode 100755 index 000000000000..f4f4b93cfccc --- /dev/null +++ b/external/packages/raspi/stage0/prerun.sh @@ -0,0 +1,11 @@ +#!/bin/bash -e + +if [ "$RELEASE" != "raspi" ]; then + echo "WARNING: RELEASE does not match the intended option for this branch." + echo " Please check the relevant README.md section." +fi + +#if [ ! -d "${ROOTFS_DIR}" ] || [ "${USE_QCOW2}" = "1" ]; then +# bootstrap ${RELEASE} "${ROOTFS_DIR}" https://mirrors.ustc.edu.cn/debian/ +# #bootstrap ${RELEASE} "${ROOTFS_DIR}" http://deb.debian.org/debian/ +#fi diff --git a/external/packages/raspi/stage1/00-boot-files/00-run.sh b/external/packages/raspi/stage1/00-boot-files/00-run.sh new file mode 100755 index 000000000000..b3d6622b3706 --- /dev/null +++ b/external/packages/raspi/stage1/00-boot-files/00-run.sh @@ -0,0 +1,4 @@ +#!/bin/bash -e + +#install -m 644 files/cmdline.txt "${ROOTFS_DIR}/boot/" +#install -m 644 files/config.txt "${ROOTFS_DIR}/boot/" diff --git a/external/packages/raspi/stage1/00-boot-files/files/cmdline.txt b/external/packages/raspi/stage1/00-boot-files/files/cmdline.txt new file mode 100644 index 000000000000..03cde688e643 --- /dev/null +++ b/external/packages/raspi/stage1/00-boot-files/files/cmdline.txt @@ -0,0 +1 @@ +console=serial0,115200 console=tty1 root=ROOTDEV rootfstype=ext4 fsck.repair=yes rootwait diff --git a/external/packages/raspi/stage1/00-boot-files/files/config.txt b/external/packages/raspi/stage1/00-boot-files/files/config.txt new file mode 100644 index 000000000000..ffdd603eb8d3 --- /dev/null +++ b/external/packages/raspi/stage1/00-boot-files/files/config.txt @@ -0,0 +1,83 @@ +# For more options and information see +# http://rpf.io/configtxt +# Some settings may impact device functionality. See link above for details + +# uncomment if you get no picture on HDMI for a default "safe" mode +#hdmi_safe=1 + +# uncomment the following to adjust overscan. Use positive numbers if console +# goes off screen, and negative if there is too much border +#overscan_left=16 +#overscan_right=16 +#overscan_top=16 +#overscan_bottom=16 + +# uncomment to force a console size. By default it will be display's size minus +# overscan. +#framebuffer_width=1280 +#framebuffer_height=720 + +# uncomment if hdmi display is not detected and composite is being output +#hdmi_force_hotplug=1 + +# uncomment to force a specific HDMI mode (this will force VGA) +#hdmi_group=1 +#hdmi_mode=1 + +# uncomment to force a HDMI mode rather than DVI. This can make audio work in +# DMT (computer monitor) modes +#hdmi_drive=2 + +# uncomment to increase signal to HDMI, if you have interference, blanking, or +# no display +#config_hdmi_boost=4 + +# uncomment for composite PAL +#sdtv_mode=2 + +#uncomment to overclock the arm. 700 MHz is the default. +#arm_freq=800 + +# Uncomment some or all of these to enable the optional hardware interfaces +#dtparam=i2c_arm=on +#dtparam=i2s=on +#dtparam=spi=on + +# Uncomment this to enable infrared communication. +#dtoverlay=gpio-ir,gpio_pin=17 +#dtoverlay=gpio-ir-tx,gpio_pin=18 + +# Additional overlays and parameters are documented /boot/overlays/README + +# Enable audio (loads snd_bcm2835) +dtparam=audio=on + +# Automatically load overlays for detected cameras +camera_auto_detect=1 + +# Automatically load overlays for detected DSI displays +display_auto_detect=1 + +# Enable DRM VC4 V3D driver +dtoverlay=vc4-kms-v3d +max_framebuffers=2 + +# Run in 64-bit mode +arm_64bit=1 + +# Disable compensation for displays with overscan +disable_overscan=1 + +[cm4] +# Enable host mode on the 2711 built-in XHCI USB controller. +# This line should be removed if the legacy DWC2 controller is required +# (e.g. for USB device mode) or if USB support is not required. +otg_mode=1 + +[all] + +[pi4] +# Run as fast as firmware / board allows +arm_boost=1 + +[all] diff --git a/external/packages/raspi/stage1/01-sys-tweaks/.pc b/external/packages/raspi/stage1/01-sys-tweaks/.pc new file mode 120000 index 000000000000..c82abeeeca4b --- /dev/null +++ b/external/packages/raspi/stage1/01-sys-tweaks/.pc @@ -0,0 +1 @@ +/home/test/orangepi-build/output/raspi/01-sys-tweaks-pc \ No newline at end of file diff --git a/external/packages/raspi/stage1/01-sys-tweaks/00-packages b/external/packages/raspi/stage1/01-sys-tweaks/00-packages new file mode 100644 index 000000000000..9e91ea1ae327 --- /dev/null +++ b/external/packages/raspi/stage1/01-sys-tweaks/00-packages @@ -0,0 +1 @@ +raspi-config diff --git a/external/packages/raspi/stage1/01-sys-tweaks/00-patches/01-bashrc.diff b/external/packages/raspi/stage1/01-sys-tweaks/00-patches/01-bashrc.diff new file mode 100644 index 000000000000..efa2104d5ade --- /dev/null +++ b/external/packages/raspi/stage1/01-sys-tweaks/00-patches/01-bashrc.diff @@ -0,0 +1,33 @@ +--- a/rootfs/etc/skel/.bashrc ++++ b/rootfs/etc/skel/.bashrc +@@ -43,7 +43,7 @@ + # uncomment for a colored prompt, if the terminal has the capability; turned + # off by default to not distract the user: the focus in a terminal window + # should be on the output of commands, not on the prompt +-#force_color_prompt=yes ++force_color_prompt=yes + + if [ -n "$force_color_prompt" ]; then + if [ -x /usr/bin/tput ] && tput setaf 1 >&/dev/null; then +@@ -57,7 +57,7 @@ + fi + + if [ "$color_prompt" = yes ]; then +- PS1='${debian_chroot:+($debian_chroot)}\[\033[01;32m\]\u@\h\[\033[00m\]:\[\033[01;34m\]\w\[\033[00m\]\$ ' ++ PS1='${debian_chroot:+($debian_chroot)}\[\033[01;32m\]\u@\h\[\033[00m\]:\[\033[01;34m\]\w \$\[\033[00m\] ' + else + PS1='${debian_chroot:+($debian_chroot)}\u@\h:\w\$ ' + fi +@@ -79,9 +79,9 @@ + #alias dir='dir --color=auto' + #alias vdir='vdir --color=auto' + +- #alias grep='grep --color=auto' +- #alias fgrep='fgrep --color=auto' +- #alias egrep='egrep --color=auto' ++ alias grep='grep --color=auto' ++ alias fgrep='fgrep --color=auto' ++ alias egrep='egrep --color=auto' + fi + + # colored GCC warnings and errors diff --git a/external/packages/raspi/stage1/01-sys-tweaks/00-patches/series b/external/packages/raspi/stage1/01-sys-tweaks/00-patches/series new file mode 100644 index 000000000000..6287f0be2bfe --- /dev/null +++ b/external/packages/raspi/stage1/01-sys-tweaks/00-patches/series @@ -0,0 +1 @@ +01-bashrc.diff diff --git a/external/packages/raspi/stage1/01-sys-tweaks/00-run.sh b/external/packages/raspi/stage1/01-sys-tweaks/00-run.sh new file mode 100755 index 000000000000..710100463b35 --- /dev/null +++ b/external/packages/raspi/stage1/01-sys-tweaks/00-run.sh @@ -0,0 +1,23 @@ +#!/bin/bash -e + +# 00-patches + +## 01-bashrc.diff +install -v -m 644 files/.bashrc "${ROOTFS_DIR}/etc/skel/" + +# 00-patches + +install -d "${ROOTFS_DIR}/etc/systemd/system/getty@tty1.service.d" +install -m 644 files/noclear.conf "${ROOTFS_DIR}/etc/systemd/system/getty@tty1.service.d/noclear.conf" +install -v -m 644 files/fstab "${ROOTFS_DIR}/etc/fstab" + +on_chroot << EOF +if ! id -u ${FIRST_USER_NAME} >/dev/null 2>&1; then + adduser --disabled-password --gecos "" ${FIRST_USER_NAME} +fi + +if [ -n "${FIRST_USER_PASS}" ]; then + echo "${FIRST_USER_NAME}:${FIRST_USER_PASS}" | chpasswd +fi +echo "root:root" | chpasswd +EOF diff --git a/external/packages/raspi/stage1/01-sys-tweaks/files/.bashrc b/external/packages/raspi/stage1/01-sys-tweaks/files/.bashrc new file mode 100644 index 000000000000..d7159926f8dc --- /dev/null +++ b/external/packages/raspi/stage1/01-sys-tweaks/files/.bashrc @@ -0,0 +1,113 @@ +# ~/.bashrc: executed by bash(1) for non-login shells. +# see /usr/share/doc/bash/examples/startup-files (in the package bash-doc) +# for examples + +# If not running interactively, don't do anything +case $- in + *i*) ;; + *) return;; +esac + +# don't put duplicate lines or lines starting with space in the history. +# See bash(1) for more options +HISTCONTROL=ignoreboth + +# append to the history file, don't overwrite it +shopt -s histappend + +# for setting history length see HISTSIZE and HISTFILESIZE in bash(1) +HISTSIZE=1000 +HISTFILESIZE=2000 + +# check the window size after each command and, if necessary, +# update the values of LINES and COLUMNS. +shopt -s checkwinsize + +# If set, the pattern "**" used in a pathname expansion context will +# match all files and zero or more directories and subdirectories. +#shopt -s globstar + +# make less more friendly for non-text input files, see lesspipe(1) +#[ -x /usr/bin/lesspipe ] && eval "$(SHELL=/bin/sh lesspipe)" + +# set variable identifying the chroot you work in (used in the prompt below) +if [ -z "${debian_chroot:-}" ] && [ -r /etc/debian_chroot ]; then + debian_chroot=$(cat /etc/debian_chroot) +fi + +# set a fancy prompt (non-color, unless we know we "want" color) +case "$TERM" in + xterm-color|*-256color) color_prompt=yes;; +esac + +# uncomment for a colored prompt, if the terminal has the capability; turned +# off by default to not distract the user: the focus in a terminal window +# should be on the output of commands, not on the prompt +force_color_prompt=yes + +if [ -n "$force_color_prompt" ]; then + if [ -x /usr/bin/tput ] && tput setaf 1 >&/dev/null; then + # We have color support; assume it's compliant with Ecma-48 + # (ISO/IEC-6429). (Lack of such support is extremely rare, and such + # a case would tend to support setf rather than setaf.) + color_prompt=yes + else + color_prompt= + fi +fi + +if [ "$color_prompt" = yes ]; then + PS1='${debian_chroot:+($debian_chroot)}\[\033[01;32m\]\u@\h\[\033[00m\]:\[\033[01;34m\]\w \$\[\033[00m\] ' +else + PS1='${debian_chroot:+($debian_chroot)}\u@\h:\w\$ ' +fi +unset color_prompt force_color_prompt + +# If this is an xterm set the title to user@host:dir +case "$TERM" in +xterm*|rxvt*) + PS1="\[\e]0;${debian_chroot:+($debian_chroot)}\u@\h: \w\a\]$PS1" + ;; +*) + ;; +esac + +# enable color support of ls and also add handy aliases +if [ -x /usr/bin/dircolors ]; then + test -r ~/.dircolors && eval "$(dircolors -b ~/.dircolors)" || eval "$(dircolors -b)" + alias ls='ls --color=auto' + #alias dir='dir --color=auto' + #alias vdir='vdir --color=auto' + + alias grep='grep --color=auto' + alias fgrep='fgrep --color=auto' + alias egrep='egrep --color=auto' +fi + +# colored GCC warnings and errors +#export GCC_COLORS='error=01;31:warning=01;35:note=01;36:caret=01;32:locus=01:quote=01' + +# some more ls aliases +#alias ll='ls -l' +#alias la='ls -A' +#alias l='ls -CF' + +# Alias definitions. +# You may want to put all your additions into a separate file like +# ~/.bash_aliases, instead of adding them here directly. +# See /usr/share/doc/bash-doc/examples in the bash-doc package. + +if [ -f ~/.bash_aliases ]; then + . ~/.bash_aliases +fi + +# enable programmable completion features (you don't need to enable +# this, if it's already enabled in /etc/bash.bashrc and /etc/profile +# sources /etc/bash.bashrc). +if ! shopt -oq posix; then + if [ -f /usr/share/bash-completion/bash_completion ]; then + . /usr/share/bash-completion/bash_completion + elif [ -f /etc/bash_completion ]; then + . /etc/bash_completion + fi +fi diff --git a/external/packages/raspi/stage1/01-sys-tweaks/files/fstab b/external/packages/raspi/stage1/01-sys-tweaks/files/fstab new file mode 100644 index 000000000000..f16e3fb8aaa6 --- /dev/null +++ b/external/packages/raspi/stage1/01-sys-tweaks/files/fstab @@ -0,0 +1,3 @@ +proc /proc proc defaults 0 0 +BOOTDEV /boot vfat defaults 0 2 +ROOTDEV / ext4 defaults,noatime 0 1 diff --git a/external/packages/raspi/stage1/01-sys-tweaks/files/noclear.conf b/external/packages/raspi/stage1/01-sys-tweaks/files/noclear.conf new file mode 100644 index 000000000000..52671c758d83 --- /dev/null +++ b/external/packages/raspi/stage1/01-sys-tweaks/files/noclear.conf @@ -0,0 +1,2 @@ +[Service] +TTYVTDisallocate=no diff --git a/external/packages/raspi/stage1/02-net-tweaks/00-packages b/external/packages/raspi/stage1/02-net-tweaks/00-packages new file mode 100644 index 000000000000..3e09fe92ede4 --- /dev/null +++ b/external/packages/raspi/stage1/02-net-tweaks/00-packages @@ -0,0 +1 @@ +netbase diff --git a/external/packages/raspi/stage1/02-net-tweaks/00-run.sh b/external/packages/raspi/stage1/02-net-tweaks/00-run.sh new file mode 100755 index 000000000000..95dfbdc5b7d6 --- /dev/null +++ b/external/packages/raspi/stage1/02-net-tweaks/00-run.sh @@ -0,0 +1,8 @@ +#!/bin/bash -e + +echo "${TARGET_HOSTNAME}" > "${ROOTFS_DIR}/etc/hostname" +echo "127.0.1.1 ${TARGET_HOSTNAME}" >> "${ROOTFS_DIR}/etc/hosts" + +on_chroot << EOF + SUDO_USER="${FIRST_USER_NAME}" raspi-config nonint do_net_names 1 +EOF diff --git a/external/packages/raspi/stage1/03-install-packages/00-packages b/external/packages/raspi/stage1/03-install-packages/00-packages new file mode 100644 index 000000000000..a3d2fb66fd74 --- /dev/null +++ b/external/packages/raspi/stage1/03-install-packages/00-packages @@ -0,0 +1,2 @@ +libraspberrypi-bin libraspberrypi0 +systemd-timesyncd diff --git a/external/packages/raspi/stage1/prerun.sh b/external/packages/raspi/stage1/prerun.sh new file mode 100755 index 000000000000..398be92fcdfb --- /dev/null +++ b/external/packages/raspi/stage1/prerun.sh @@ -0,0 +1,5 @@ +#!/bin/bash -e + +#if [ ! -d "${ROOTFS_DIR}" ]; then +# copy_previous +#fi diff --git a/external/packages/raspi/stage2/01-sys-tweaks/00-debconf b/external/packages/raspi/stage2/01-sys-tweaks/00-debconf new file mode 100644 index 000000000000..c13e3b194942 --- /dev/null +++ b/external/packages/raspi/stage2/01-sys-tweaks/00-debconf @@ -0,0 +1,26 @@ +# Encoding to use on the console: +# Choices: ARMSCII-8, CP1251, CP1255, CP1256, GEORGIAN-ACADEMY, GEORGIAN-PS, IBM1133, ISIRI-3342, ISO-8859-1, ISO-8859-10, ISO-8859-11, ISO-8859-13, ISO-8859-14, ISO-8859-15, ISO-8859-16, ISO-8859-2, ISO-8859-3, ISO-8859-4, ISO-8859-5, ISO-8859-6, ISO-8859-7, ISO-8859-8, ISO-8859-9, KOI8-R, KOI8-U, TIS-620, UTF-8, VISCII +console-setup console-setup/charmap47 select UTF-8 +# Character set to support: +# Choices: . Arabic, # Armenian, # Cyrillic - KOI8-R and KOI8-U, # Cyrillic - non-Slavic languages, # Cyrillic - Slavic languages (also Bosnian and Serbian Latin), . Ethiopic, # Georgian, # Greek, # Hebrew, # Lao, # Latin1 and Latin5 - western Europe and Turkic languages, # Latin2 - central Europe and Romanian, # Latin3 and Latin8 - Chichewa; Esperanto; Irish; Maltese and Welsh, # Latin7 - Lithuanian; Latvian; Maori and Marshallese, . Latin - Vietnamese, # Thai, . Combined - Latin; Slavic Cyrillic; Hebrew; basic Arabic, . Combined - Latin; Slavic Cyrillic; Greek, . Combined - Latin; Slavic and non-Slavic Cyrillic, Guess optimal character set +console-setup console-setup/codeset47 select Guess optimal character set +# Font for the console: +# Choices: Fixed, Goha, GohaClassic, Terminus, TerminusBold, TerminusBoldVGA, VGA, Do not change the boot/kernel font, Let the system select a suitable font +console-setup console-setup/fontface47 select Do not change the boot/kernel font +# Key to function as AltGr: +# Choices: The default for the keyboard layout, No AltGr key, Right Alt (AltGr), Right Control, Right Logo key, Menu key, Left Alt, Left Logo key, Keypad Enter key, Both Logo keys, Both Alt keys +keyboard-configuration keyboard-configuration/altgr select The default for the keyboard layout +# Keyboard model: +# Choices: A4Tech KB-21, A4Tech KBS-8, A4Tech Wireless Desktop RFKB-23, Acer AirKey V, Acer C300, Acer Ferrari 4000, Acer Laptop, Advance Scorpius KI, Amiga, Apple, Apple Aluminium Keyboard (ANSI), Apple Aluminium Keyboard (ISO), Apple Aluminium Keyboard (JIS), Apple Laptop, Asus Laptop, Atari TT, Azona RF2300 wireless Internet Keyboard, BTC 5090, BTC 5113RF Multimedia, BTC 5126T, BTC 6301URF, BTC 9000, BTC 9000A, BTC 9001AH, BTC 9019U, BTC 9116U Mini Wireless Internet and Gaming, BenQ X-Touch, BenQ X-Touch 730, BenQ X-Touch 800, Brother Internet Keyboard, Cherry B.UNLIMITED, Cherry Blue Line CyBo@rd, Cherry Blue Line CyBo@rd (alternate option), Cherry CyBo@rd USB-Hub, Cherry CyMotion Expert, Cherry CyMotion Master Linux, Cherry CyMotion Master XPress, Chicony Internet Keyboard, Chicony KB-9885, Chicony KU-0108, Chicony KU-0420, Classmate PC, Compaq Easy Access Keyboard, Compaq Internet Keyboard (13 keys), Compaq Internet Keyboard (18 keys), Compaq Internet Keyboard (7 keys), Compaq iPaq Keyboard, Creative Desktop Wireless 7000, DTK2000, Dell, Dell 101-key PC, Dell Laptop/notebook Inspiron 6xxx/8xxx, Dell Laptop/notebook Precision M series, Dell Latitude series laptop, Dell Precision M65, Dell SK-8125, Dell SK-8135, Dell USB Multimedia Keyboard, Dexxa Wireless Desktop Keyboard, Diamond 9801 / 9802 series, Ennyah DKB-1008, Everex STEPnote, FL90, Fujitsu-Siemens Computers AMILO laptop, Generic 101-key PC, Generic 102-key (Intl) PC, Generic 104-key PC, Generic 105-key (Intl) PC, Genius Comfy KB-12e, Genius Comfy KB-16M / Genius MM Keyboard KWD-910, Genius Comfy KB-21e-Scroll, Genius KB-19e NB, Genius KKB-2050HS, Gyration, HTC Dream, Happy Hacking Keyboard, Happy Hacking Keyboard for Mac, Hewlett-Packard Internet Keyboard, Hewlett-Packard Mini 110 Notebook, Hewlett-Packard Omnibook 500 FA, Hewlett-Packard Omnibook 5xx, Hewlett-Packard Omnibook 6000/6100, Hewlett-Packard Omnibook XE3 GC, Hewlett-Packard Omnibook XE3 GF, Hewlett-Packard Omnibook XT1000, Hewlett-Packard Pavilion ZT11xx, Hewlett-Packard Pavilion dv5, Hewlett-Packard SK-250x Multimedia Keyboard, Hewlett-Packard nx9020, Honeywell Euroboard, Htc Dream phone, IBM Rapid Access, IBM Rapid Access II, IBM Space Saver, IBM ThinkPad 560Z/600/600E/A22E, IBM ThinkPad R60/T60/R61/T61, IBM ThinkPad Z60m/Z60t/Z61m/Z61t, Keytronic FlexPro, Kinesis, Laptop/notebook Compaq (eg. Armada) Laptop Keyboard, Laptop/notebook Compaq (eg. Presario) Internet Keyboard, Laptop/notebook eMachines m68xx, Logitech Access Keyboard, Logitech Cordless Desktop, Logitech Cordless Desktop (alternate option), Logitech Cordless Desktop EX110, Logitech Cordless Desktop LX-300, Logitech Cordless Desktop Navigator, Logitech Cordless Desktop Optical, Logitech Cordless Desktop Pro (alternate option 2), Logitech Cordless Desktop iTouch, Logitech Cordless Freedom/Desktop Navigator, Logitech G15 extra keys via G15daemon, Logitech Generic Keyboard, Logitech Internet 350 Keyboard, Logitech Internet Keyboard, Logitech Internet Navigator Keyboard, Logitech Media Elite Keyboard, Logitech Ultra-X Cordless Media Desktop Keyboard, Logitech Ultra-X Keyboard, Logitech diNovo Edge Keyboard, Logitech diNovo Keyboard, Logitech iTouch, Logitech iTouch Cordless Keyboard (model Y-RB6), Logitech iTouch Internet Navigator Keyboard SE, Logitech iTouch Internet Navigator Keyboard SE (USB), MacBook/MacBook Pro, MacBook/MacBook Pro (Intl), Macintosh, Macintosh Old, Memorex MX1998, Memorex MX2500 EZ-Access Keyboard, Memorex MX2750, Microsoft Comfort Curve Keyboard 2000, Microsoft Internet Keyboard, Microsoft Internet Keyboard Pro\, Swedish, Microsoft Natural, Microsoft Natural Keyboard Elite, Microsoft Natural Keyboard Pro / Microsoft Internet Keyboard Pro, Microsoft Natural Keyboard Pro OEM, Microsoft Natural Keyboard Pro USB / Microsoft Internet Keyboard Pro, Microsoft Natural Wireless Ergonomic Keyboard 4000, Microsoft Natural Wireless Ergonomic Keyboard 7000, Microsoft Office Keyboard, Microsoft Wireless Multimedia Keyboard 1.0A, Northgate OmniKey 101, OLPC, Ortek MCK-800 MM/Internet keyboard, PC-98xx Series, Propeller Voyager (KTEZ-1000), QTronix Scorpius 98N+, SILVERCREST Multimedia Wireless Keyboard, SK-1300, SK-2500, SK-6200, SK-7100, SVEN Ergonomic 2500, SVEN Slim 303, Samsung SDM 4500P, Samsung SDM 4510P, Sanwa Supply SKB-KG3, Sun Type 4, Sun Type 5, Sun Type 6 (Japanese layout), Sun Type 6 USB (Japanese layout), Sun Type 6 USB (Unix layout), Sun Type 6/7 USB, Sun Type 6/7 USB (European layout), Sun Type 7 USB, Sun Type 7 USB (European layout), Sun Type 7 USB (Japanese layout) / Japanese 106-key, Sun Type 7 USB (Unix layout), Super Power Multimedia Keyboard, Symplon PaceBook (tablet PC), Targa Visionary 811, Toshiba Satellite S3000, Trust Direct Access Keyboard, Trust Slimline, Trust Wireless Keyboard Classic, TypeMatrix EZ-Reach 2020, TypeMatrix EZ-Reach 2030 PS2, TypeMatrix EZ-Reach 2030 USB, TypeMatrix EZ-Reach 2030 USB (102/105:EU mode), TypeMatrix EZ-Reach 2030 USB (106:JP mode), Unitek KB-1925, ViewSonic KU-306 Internet Keyboard, Winbook Model XP5, Yahoo! Internet Keyboard +keyboard-configuration keyboard-configuration/model select Generic 105-key (Intl) PC +# Keymap to use: +# Choices: American English, Albanian, Arabic, Asturian, Bangladesh, Belarusian, Bengali, Belgian, Bosnian, Brazilian, British English, Bulgarian, Bulgarian (phonetic layout), Burmese, Canadian French, Canadian Multilingual, Catalan, Chinese, Croatian, Czech, Danish, Dutch, Dvorak, Dzongkha, Esperanto, Estonian, Ethiopian, Finnish, French, Georgian, German, Greek, Gujarati, Gurmukhi, Hebrew, Hindi, Hungarian, Icelandic, Irish, Italian, Japanese, Kannada, Kazakh, Khmer, Kirghiz, Korean, Kurdish (F layout), Kurdish (Q layout), Lao, Latin American, Latvian, Lithuanian, Macedonian, Malayalam, Nepali, Northern Sami, Norwegian, Persian, Philippines, Polish, Portuguese, Punjabi, Romanian, Russian, Serbian (Cyrillic), Sindhi, Sinhala, Slovak, Slovenian, Spanish, Swedish, Swiss French, Swiss German, Tajik, Tamil, Telugu, Thai, Tibetan, Turkish (F layout), Turkish (Q layout), Ukrainian, Uyghur, Vietnamese +keyboard-configuration keyboard-configuration/xkb-keymap select ${KEYBOARD_KEYMAP} +# Compose key: +# Choices: No compose key, Right Alt (AltGr), Right Control, Right Logo key, Menu key, Left Logo key, Caps Lock +keyboard-configuration keyboard-configuration/compose select No compose key +# Use Control+Alt+Backspace to terminate the X server? +keyboard-configuration keyboard-configuration/ctrl_alt_bksp boolean true +# Keyboard layout: +# Choices: English (UK), English (UK) - English (UK\, Colemak), English (UK) - English (UK\, Dvorak with UK punctuation), English (UK) - English (UK\, Dvorak), English (UK) - English (UK\, Macintosh international), English (UK) - English (UK\, Macintosh), English (UK) - English (UK\, extended WinKeys), English (UK) - English (UK\, international with dead keys), Other +keyboard-configuration keyboard-configuration/variant select ${KEYBOARD_LAYOUT} diff --git a/external/packages/raspi/stage2/01-sys-tweaks/00-packages b/external/packages/raspi/stage2/01-sys-tweaks/00-packages new file mode 100644 index 000000000000..df535920469a --- /dev/null +++ b/external/packages/raspi/stage2/01-sys-tweaks/00-packages @@ -0,0 +1,35 @@ +ssh less fbset sudo psmisc strace ed ncdu crda +console-setup keyboard-configuration debconf-utils parted +build-essential manpages-dev bash-completion gdb pkg-config +python-is-python3 +python3-rpi.gpio v4l-utils +python3-gpiozero +avahi-daemon +lua5.1 +luajit +hardlink ca-certificates curl +fake-hwclock nfs-common usbutils +libraspberrypi-dev libraspberrypi-doc libfreetype6-dev +dosfstools +dphys-swapfile +raspberrypi-sys-mods +pi-bluetooth +apt-listchanges +usb-modeswitch +libpam-chksshpwd +rpi-update +libmtp-runtime +rsync +htop +man-db +policykit-1 +ssh-import-id +rng-tools +ethtool +ntfs-3g +pciutils +raspinfo +udisks2 +unzip zip p7zip-full +file +kms++-utils diff --git a/external/packages/raspi/stage2/01-sys-tweaks/00-packages-nr b/external/packages/raspi/stage2/01-sys-tweaks/00-packages-nr new file mode 100644 index 000000000000..453ada8be209 --- /dev/null +++ b/external/packages/raspi/stage2/01-sys-tweaks/00-packages-nr @@ -0,0 +1,4 @@ +cifs-utils +libcamera-apps-lite +mkvtoolnix +python3-picamera2 diff --git a/external/packages/raspi/stage2/01-sys-tweaks/00-patches/01-useradd.diff b/external/packages/raspi/stage2/01-sys-tweaks/00-patches/01-useradd.diff new file mode 100644 index 000000000000..e81ad5a1aa12 --- /dev/null +++ b/external/packages/raspi/stage2/01-sys-tweaks/00-patches/01-useradd.diff @@ -0,0 +1,22 @@ +Index: jessie-stage2/rootfs/etc/default/useradd +=================================================================== +--- jessie-stage2.orig/rootfs/etc/default/useradd ++++ jessie-stage2/rootfs/etc/default/useradd +@@ -5,7 +5,7 @@ + # Similar to DHSELL in adduser. However, we use "sh" here because + # useradd is a low level utility and should be as general + # as possible +-SHELL=/bin/sh ++SHELL=/bin/bash + # + # The default group for users + # 100=users on Debian systems +@@ -29,7 +29,7 @@ SHELL=/bin/sh + # The SKEL variable specifies the directory containing "skeletal" user + # files; in other words, files such as a sample .profile that will be + # copied to the new user's home directory when it is created. +-# SKEL=/etc/skel ++SKEL=/etc/skel + # + # Defines whether the mail spool should be created while + # creating the account diff --git a/external/packages/raspi/stage2/01-sys-tweaks/00-patches/02-swap.diff b/external/packages/raspi/stage2/01-sys-tweaks/00-patches/02-swap.diff new file mode 100644 index 000000000000..745a344e4993 --- /dev/null +++ b/external/packages/raspi/stage2/01-sys-tweaks/00-patches/02-swap.diff @@ -0,0 +1,13 @@ +Index: jessie-stage2/rootfs/etc/dphys-swapfile +=================================================================== +--- jessie-stage2.orig/rootfs/etc/dphys-swapfile ++++ jessie-stage2/rootfs/etc/dphys-swapfile +@@ -13,7 +13,7 @@ + + # set size to absolute value, leaving empty (default) then uses computed value + # you most likely don't want this, unless you have an special disk situation +-#CONF_SWAPSIZE= ++CONF_SWAPSIZE=100 + + # set size to computed value, this times RAM size, dynamically adapts, + # guarantees that there is enough swap without wasting disk space on excess diff --git a/external/packages/raspi/stage2/01-sys-tweaks/00-patches/04-inputrc.diff b/external/packages/raspi/stage2/01-sys-tweaks/00-patches/04-inputrc.diff new file mode 100644 index 000000000000..c81fa62d8cf6 --- /dev/null +++ b/external/packages/raspi/stage2/01-sys-tweaks/00-patches/04-inputrc.diff @@ -0,0 +1,12 @@ +Index: jessie-stage2/rootfs/etc/inputrc +=================================================================== +--- jessie-stage2.orig/rootfs/etc/inputrc ++++ jessie-stage2/rootfs/etc/inputrc +@@ -65,3 +65,7 @@ $endif + # "\e[F": end-of-line + + $endif ++ ++# mappings for up and down arrows search history ++# "\e[B": history-search-forward ++# "\e[A": history-search-backward diff --git a/external/packages/raspi/stage2/01-sys-tweaks/00-patches/05-path.diff b/external/packages/raspi/stage2/01-sys-tweaks/00-patches/05-path.diff new file mode 100644 index 000000000000..25b80a197a95 --- /dev/null +++ b/external/packages/raspi/stage2/01-sys-tweaks/00-patches/05-path.diff @@ -0,0 +1,26 @@ +Index: jessie-stage2/rootfs/etc/login.defs +=================================================================== +--- jessie-stage2.orig/rootfs/etc/login.defs ++++ jessie-stage2/rootfs/etc/login.defs +@@ -100,7 +100,7 @@ HUSHLOGIN_FILE .hushlogin + # + # (they are minimal, add the rest in the shell startup files) + ENV_SUPATH PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin +-ENV_PATH PATH=/usr/local/bin:/usr/bin:/bin:/usr/local/games:/usr/games ++ENV_PATH PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/local/games:/usr/games + + # + # Terminal permissions +Index: jessie-stage2/rootfs/etc/profile +=================================================================== +--- jessie-stage2.orig/rootfs/etc/profile ++++ jessie-stage2/rootfs/etc/profile +@@ -4,7 +4,7 @@ + if [ "`id -u`" -eq 0 ]; then + PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" + else +- PATH="/usr/local/bin:/usr/bin:/bin:/usr/local/games:/usr/games" ++ PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/local/games:/usr/games" + fi + export PATH + diff --git a/external/packages/raspi/stage2/01-sys-tweaks/00-patches/07-resize-init.diff b/external/packages/raspi/stage2/01-sys-tweaks/00-patches/07-resize-init.diff new file mode 100644 index 000000000000..dfc01d495032 --- /dev/null +++ b/external/packages/raspi/stage2/01-sys-tweaks/00-patches/07-resize-init.diff @@ -0,0 +1,5 @@ +--- stage2.orig/rootfs/boot/cmdline.txt ++++ stage2/rootfs/boot/cmdline.txt +@@ -1 +1 @@ +-console=serial0,115200 console=tty1 root=ROOTDEV rootfstype=ext4 fsck.repair=yes rootwait ++console=serial0,115200 console=tty1 root=ROOTDEV rootfstype=ext4 fsck.repair=yes rootwait quiet init=/usr/lib/raspberrypi-sys-mods/firstboot diff --git a/external/packages/raspi/stage2/01-sys-tweaks/00-patches/series b/external/packages/raspi/stage2/01-sys-tweaks/00-patches/series new file mode 100644 index 000000000000..5acb04ef307e --- /dev/null +++ b/external/packages/raspi/stage2/01-sys-tweaks/00-patches/series @@ -0,0 +1,5 @@ +#01-useradd.diff +#02-swap.diff +#04-inputrc.diff +#05-path.diff +#07-resize-init.diff diff --git a/external/packages/raspi/stage2/01-sys-tweaks/01-run.sh b/external/packages/raspi/stage2/01-sys-tweaks/01-run.sh new file mode 100755 index 000000000000..e351603155be --- /dev/null +++ b/external/packages/raspi/stage2/01-sys-tweaks/01-run.sh @@ -0,0 +1,95 @@ +#!/bin/bash -e + +# 00-patches + +## 01-useradd.diff +sed "s/^SHELL=.*/SHELL=\/bin\/bash/" -i "${ROOTFS_DIR}/etc/default/useradd" +sed "s/# SKEL=.*/SKEL=\/etc\/skel/" -i "${ROOTFS_DIR}/etc/default/useradd" + +## 02-swap.diff +sed "s/#CONF_SWAPSIZE=.*/CONF_SWAPSIZE=100/" -i "${ROOTFS_DIR}/etc/dphys-swapfile" + +## 04-inputrc.diff +echo ' ' >> "${ROOTFS_DIR}/etc/inputrc" +echo '# mappings for up and down arrows search history' >> "${ROOTFS_DIR}/etc/inputrc" +echo '# "\e[B": history-search-forward' >> "${ROOTFS_DIR}/etc/inputrc" +echo '# "\e[A": history-search-backward' >> "${ROOTFS_DIR}/etc/inputrc" + +## 05-path.diff +install -m 644 files/login.defs "${ROOTFS_DIR}/etc/" +install -m 644 files/profile "${ROOTFS_DIR}/etc/" + +## 07-resize-init.diff + +# 00-patches + +install -m 755 files/resize2fs_once "${ROOTFS_DIR}/etc/init.d/" + +install -d "${ROOTFS_DIR}/etc/systemd/system/rc-local.service.d" +install -m 644 files/ttyoutput.conf "${ROOTFS_DIR}/etc/systemd/system/rc-local.service.d/" + +install -m 644 files/50raspi "${ROOTFS_DIR}/etc/apt/apt.conf.d/" + +install -m 644 files/console-setup "${ROOTFS_DIR}/etc/default/" + +install -m 755 files/rc.local "${ROOTFS_DIR}/etc/" + +if [ -n "${PUBKEY_SSH_FIRST_USER}" ]; then + install -v -m 0700 -o 1000 -g 1000 -d "${ROOTFS_DIR}"/home/"${FIRST_USER_NAME}"/.ssh + echo "${PUBKEY_SSH_FIRST_USER}" >"${ROOTFS_DIR}"/home/"${FIRST_USER_NAME}"/.ssh/authorized_keys + chown 1000:1000 "${ROOTFS_DIR}"/home/"${FIRST_USER_NAME}"/.ssh/authorized_keys + chmod 0600 "${ROOTFS_DIR}"/home/"${FIRST_USER_NAME}"/.ssh/authorized_keys +fi + +if [ "${PUBKEY_ONLY_SSH}" = "1" ]; then + sed -i -Ee 's/^#?[[:blank:]]*PubkeyAuthentication[[:blank:]]*no[[:blank:]]*$/PubkeyAuthentication yes/ +s/^#?[[:blank:]]*PasswordAuthentication[[:blank:]]*yes[[:blank:]]*$/PasswordAuthentication no/' "${ROOTFS_DIR}"/etc/ssh/sshd_config +fi + +on_chroot << EOF +systemctl disable hwclock.sh +systemctl disable nfs-common +systemctl disable rpcbind +if [ "${ENABLE_SSH}" == "1" ]; then + systemctl enable ssh +else + systemctl disable ssh +fi +systemctl enable regenerate_ssh_host_keys +EOF + +if [ "${USE_QEMU}" = "1" ]; then + echo "enter QEMU mode" + install -m 644 files/90-qemu.rules "${ROOTFS_DIR}/etc/udev/rules.d/" + on_chroot << EOF +systemctl disable resize2fs_once +EOF + echo "leaving QEMU mode" +else + on_chroot << EOF +systemctl enable resize2fs_once +EOF +fi + +on_chroot < MAX, the highest value will be used. +# +# SHA_CRYPT_MIN_ROUNDS 5000 +# SHA_CRYPT_MAX_ROUNDS 5000 + +################# OBSOLETED BY PAM ############## +# # +# These options are now handled by PAM. Please # +# edit the appropriate file in /etc/pam.d/ to # +# enable the equivelants of them. +# +############### + +#MOTD_FILE +#DIALUPS_CHECK_ENAB +#LASTLOG_ENAB +#MAIL_CHECK_ENAB +#OBSCURE_CHECKS_ENAB +#PORTTIME_CHECKS_ENAB +#SU_WHEEL_ONLY +#CRACKLIB_DICTPATH +#PASS_CHANGE_TRIES +#PASS_ALWAYS_WARN +#ENVIRON_FILE +#NOLOGINS_FILE +#ISSUE_FILE +#PASS_MIN_LEN +#PASS_MAX_LEN +#ULIMIT +#ENV_HZ +#CHFN_AUTH +#CHSH_AUTH +#FAIL_DELAY + +################# OBSOLETED ####################### +# # +# These options are no more handled by shadow. # +# # +# Shadow utilities will display a warning if they # +# still appear. # +# # +################################################### + +# CLOSE_SESSIONS +# LOGIN_STRING +# NO_PASSWORD_CONSOLE +# QMAIL_DIR + + + diff --git a/external/packages/raspi/stage2/01-sys-tweaks/files/profile b/external/packages/raspi/stage2/01-sys-tweaks/files/profile new file mode 100644 index 000000000000..4ee0896ee923 --- /dev/null +++ b/external/packages/raspi/stage2/01-sys-tweaks/files/profile @@ -0,0 +1,34 @@ +# /etc/profile: system-wide .profile file for the Bourne shell (sh(1)) +# and Bourne compatible shells (bash(1), ksh(1), ash(1), ...). + +if [ "$(id -u)" -eq 0 ]; then + PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" +else + PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/local/games:/usr/games" +fi +export PATH + +if [ "${PS1-}" ]; then + if [ "${BASH-}" ] && [ "$BASH" != "/bin/sh" ]; then + # The file bash.bashrc already sets the default PS1. + # PS1='\h:\w\$ ' + if [ -f /etc/bash.bashrc ]; then + . /etc/bash.bashrc + fi + else + if [ "$(id -u)" -eq 0 ]; then + PS1='# ' + else + PS1='$ ' + fi + fi +fi + +if [ -d /etc/profile.d ]; then + for i in /etc/profile.d/*.sh; do + if [ -r $i ]; then + . $i + fi + done + unset i +fi diff --git a/external/packages/raspi/stage2/01-sys-tweaks/files/rc.local b/external/packages/raspi/stage2/01-sys-tweaks/files/rc.local new file mode 100755 index 000000000000..7d39ed7cf0cb --- /dev/null +++ b/external/packages/raspi/stage2/01-sys-tweaks/files/rc.local @@ -0,0 +1,20 @@ +#!/bin/sh -e +# +# rc.local +# +# This script is executed at the end of each multiuser runlevel. +# Make sure that the script will "exit 0" on success or any other +# value on error. +# +# In order to enable or disable this script just change the execution +# bits. +# +# By default this script does nothing. + +# Print the IP address +_IP=$(hostname -I) || true +if [ "$_IP" ]; then + printf "My IP address is %s\n" "$_IP" +fi + +exit 0 diff --git a/external/packages/raspi/stage2/01-sys-tweaks/files/resize2fs_once b/external/packages/raspi/stage2/01-sys-tweaks/files/resize2fs_once new file mode 100644 index 000000000000..38a4d47ab5d8 --- /dev/null +++ b/external/packages/raspi/stage2/01-sys-tweaks/files/resize2fs_once @@ -0,0 +1,25 @@ +#!/bin/sh +### BEGIN INIT INFO +# Provides: resize2fs_once +# Required-Start: +# Required-Stop: +# Default-Start: 3 +# Default-Stop: +# Short-Description: Resize the root filesystem to fill partition +# Description: +### END INIT INFO +. /lib/lsb/init-functions +case "$1" in + start) + log_daemon_msg "Starting resize2fs_once" + ROOT_DEV=$(findmnt / -o source -n) && + resize2fs $ROOT_DEV && + update-rc.d resize2fs_once remove && + rm /etc/init.d/resize2fs_once && + log_end_msg $? + ;; + *) + echo "Usage: $0 start" >&2 + exit 3 + ;; +esac diff --git a/external/packages/raspi/stage2/01-sys-tweaks/files/ttyoutput.conf b/external/packages/raspi/stage2/01-sys-tweaks/files/ttyoutput.conf new file mode 100644 index 000000000000..6a396a48e07d --- /dev/null +++ b/external/packages/raspi/stage2/01-sys-tweaks/files/ttyoutput.conf @@ -0,0 +1,2 @@ +[Service] +StandardOutput=tty diff --git a/external/packages/raspi/stage2/02-net-tweaks/00-packages b/external/packages/raspi/stage2/02-net-tweaks/00-packages new file mode 100644 index 000000000000..f0125f6a6d09 --- /dev/null +++ b/external/packages/raspi/stage2/02-net-tweaks/00-packages @@ -0,0 +1,5 @@ +wpasupplicant wireless-tools firmware-atheros firmware-brcm80211 firmware-libertas firmware-misc-nonfree firmware-realtek +raspberrypi-net-mods +dhcpcd5 +network-manager +net-tools diff --git a/external/packages/raspi/stage2/02-net-tweaks/01-run.sh b/external/packages/raspi/stage2/02-net-tweaks/01-run.sh new file mode 100755 index 000000000000..3b06c0577e95 --- /dev/null +++ b/external/packages/raspi/stage2/02-net-tweaks/01-run.sh @@ -0,0 +1,40 @@ +#!/bin/bash -e + +install -v -d "${ROOTFS_DIR}/etc/wpa_supplicant" +install -v -m 600 files/wpa_supplicant.conf "${ROOTFS_DIR}/etc/wpa_supplicant/" + +on_chroot << EOF + SUDO_USER="${FIRST_USER_NAME}" raspi-config nonint do_boot_wait 0 + SUDO_USER="${FIRST_USER_NAME}" raspi-config nonint do_netconf 1 +EOF + +if [ -v WPA_COUNTRY ]; then + on_chroot <<- EOF + SUDO_USER="${FIRST_USER_NAME}" raspi-config nonint do_wifi_country "${WPA_COUNTRY}" + EOF +fi + +if [ -v WPA_ESSID ] && [ -v WPA_PASSWORD ]; then +on_chroot <> "${ROOTFS_DIR}/etc/wpa_supplicant/wpa_supplicant.conf" << EOL + +network={ + ssid="${WPA_ESSID}" + key_mgmt=NONE +} +EOL +fi + +# Disable wifi on 5GHz models if WPA_COUNTRY is not set +mkdir -p "${ROOTFS_DIR}/var/lib/systemd/rfkill/" +if [ -n "$WPA_COUNTRY" ]; then + echo 0 > "${ROOTFS_DIR}/var/lib/systemd/rfkill/platform-3f300000.mmcnr:wlan" + echo 0 > "${ROOTFS_DIR}/var/lib/systemd/rfkill/platform-fe300000.mmcnr:wlan" +else + echo 1 > "${ROOTFS_DIR}/var/lib/systemd/rfkill/platform-3f300000.mmcnr:wlan" + echo 1 > "${ROOTFS_DIR}/var/lib/systemd/rfkill/platform-fe300000.mmcnr:wlan" +fi diff --git a/external/packages/raspi/stage2/02-net-tweaks/files/wpa_supplicant.conf b/external/packages/raspi/stage2/02-net-tweaks/files/wpa_supplicant.conf new file mode 100644 index 000000000000..0fc335ebb969 --- /dev/null +++ b/external/packages/raspi/stage2/02-net-tweaks/files/wpa_supplicant.conf @@ -0,0 +1,2 @@ +ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev +update_config=1 diff --git a/external/packages/raspi/stage2/03-accept-mathematica-eula/00-debconf b/external/packages/raspi/stage2/03-accept-mathematica-eula/00-debconf new file mode 100644 index 000000000000..d9743fe9a0d1 --- /dev/null +++ b/external/packages/raspi/stage2/03-accept-mathematica-eula/00-debconf @@ -0,0 +1,2 @@ +# Do you accept the Wolfram - Raspberry PiĀ® Bundle License Agreement? +wolfram-engine shared/accepted-wolfram-eula boolean true diff --git a/external/packages/raspi/stage2/03-set-timezone/02-run.sh b/external/packages/raspi/stage2/03-set-timezone/02-run.sh new file mode 100755 index 000000000000..96b22c7f4ef9 --- /dev/null +++ b/external/packages/raspi/stage2/03-set-timezone/02-run.sh @@ -0,0 +1,8 @@ +#!/bin/bash -e + +echo "${TIMEZONE_DEFAULT}" > "${ROOTFS_DIR}/etc/timezone" +rm "${ROOTFS_DIR}/etc/localtime" + +on_chroot << EOF +dpkg-reconfigure -f noninteractive tzdata +EOF diff --git a/external/packages/raspi/stage2/prerun.sh b/external/packages/raspi/stage2/prerun.sh new file mode 100755 index 000000000000..398be92fcdfb --- /dev/null +++ b/external/packages/raspi/stage2/prerun.sh @@ -0,0 +1,5 @@ +#!/bin/bash -e + +#if [ ! -d "${ROOTFS_DIR}" ]; then +# copy_previous +#fi diff --git a/external/packages/raspi/stage3/00-install-packages/00-debconf b/external/packages/raspi/stage3/00-install-packages/00-debconf new file mode 100644 index 000000000000..7dbd12eb2815 --- /dev/null +++ b/external/packages/raspi/stage3/00-install-packages/00-debconf @@ -0,0 +1,2 @@ +# Adobe Flash Player. Copyright 1996-2015. Adobe Systems Incorporated. All Rights Reserved. +rpi-chromium-mods rpi-chromium-mods/adobe note diff --git a/external/packages/raspi/stage3/00-install-packages/00-packages b/external/packages/raspi/stage3/00-install-packages/00-packages new file mode 100644 index 000000000000..9b01ad5515f8 --- /dev/null +++ b/external/packages/raspi/stage3/00-install-packages/00-packages @@ -0,0 +1,17 @@ +gstreamer1.0-x gstreamer1.0-plugins-base gstreamer1.0-plugins-good gstreamer1.0-plugins-bad gstreamer1.0-alsa gstreamer1.0-libav +qpdfview gtk2-engines alsa-utils +desktop-base +git +policykit-1 +gvfs +rfkill +#chromium-browser rpi-chromium-mods libwidevinecdm0 +gldriver-test +fonts-droid-fallback +fonts-liberation2 +obconf +arandr +libcamera-tools +libcamera-apps +python3-pyqt5 +python3-opengl diff --git a/external/packages/raspi/stage3/00-install-packages/00-packages-nr b/external/packages/raspi/stage3/00-install-packages/00-packages-nr new file mode 100644 index 000000000000..8c16b4016f14 --- /dev/null +++ b/external/packages/raspi/stage3/00-install-packages/00-packages-nr @@ -0,0 +1,7 @@ +xserver-xorg xinit +mousepad +lxde lxtask menu-xdg +zenity xdg-utils +gvfs-backends gvfs-fuse +lightdm gnome-themes-standard gnome-icon-theme +gnome-keyring diff --git a/external/packages/raspi/stage3/00-install-packages/01-run.sh b/external/packages/raspi/stage3/00-install-packages/01-run.sh new file mode 100755 index 000000000000..f4c67276f0bd --- /dev/null +++ b/external/packages/raspi/stage3/00-install-packages/01-run.sh @@ -0,0 +1,5 @@ +#!/bin/bash -e + +on_chroot << EOF + apt-mark auto python3-pyqt5 python3-opengl +EOF diff --git a/external/packages/raspi/stage3/01-tweaks/00-run.sh b/external/packages/raspi/stage3/01-tweaks/00-run.sh new file mode 100755 index 000000000000..79b749e3974c --- /dev/null +++ b/external/packages/raspi/stage3/01-tweaks/00-run.sh @@ -0,0 +1,5 @@ +#!/bin/bash -e + +on_chroot << EOF + SUDO_USER="${FIRST_USER_NAME}" raspi-config nonint do_boot_wait 1 +EOF diff --git a/external/packages/raspi/stage3/prerun.sh b/external/packages/raspi/stage3/prerun.sh new file mode 100755 index 000000000000..398be92fcdfb --- /dev/null +++ b/external/packages/raspi/stage3/prerun.sh @@ -0,0 +1,5 @@ +#!/bin/bash -e + +#if [ ! -d "${ROOTFS_DIR}" ]; then +# copy_previous +#fi diff --git a/external/packages/raspi/stage4/00-install-packages/00-debconf b/external/packages/raspi/stage4/00-install-packages/00-debconf new file mode 100644 index 000000000000..87932e208088 --- /dev/null +++ b/external/packages/raspi/stage4/00-install-packages/00-debconf @@ -0,0 +1,2 @@ +# Enable realtime process priority? +jackd2 jackd/tweak_rt_limits boolean true diff --git a/external/packages/raspi/stage4/00-install-packages/00-packages b/external/packages/raspi/stage4/00-install-packages/00-packages new file mode 100644 index 000000000000..ec44495749ae --- /dev/null +++ b/external/packages/raspi/stage4/00-install-packages/00-packages @@ -0,0 +1,26 @@ +python3-pygame +python3-tk thonny +python3-pgzero +python3-serial +debian-reference-en dillo +raspberrypi-net-mods raspberrypi-ui-mods +python3-pip +python3-numpy +pypy +alacarte rc-gui sense-hat +tree +libgl1-mesa-dri libgles1 libgles2-mesa xcompmgr +geany +piclone +pigpio python3-pigpio raspi-gpio python3-rpi.gpio +python3-spidev +python3-twython +python3-smbus +python3-flask +pprompt +piwiz +rp-prefapps +ffmpeg +vlc +rpi-imager +#rpi-wayland diff --git a/external/packages/raspi/stage4/00-install-packages/00-packages-nr b/external/packages/raspi/stage4/00-install-packages/00-packages-nr new file mode 100644 index 000000000000..b904b8081fa5 --- /dev/null +++ b/external/packages/raspi/stage4/00-install-packages/00-packages-nr @@ -0,0 +1,2 @@ +pi-package +realvnc-vnc-server diff --git a/external/packages/raspi/stage4/00-install-packages/01-packages b/external/packages/raspi/stage4/00-install-packages/01-packages new file mode 100644 index 000000000000..5441d9dd167e --- /dev/null +++ b/external/packages/raspi/stage4/00-install-packages/01-packages @@ -0,0 +1,22 @@ +python3-automationhat +python3-blinkt +python3-cap1xxx +python3-drumhat +python3-envirophat +python3-explorerhat +python3-fourletterphat +python3-microdotphat +python3-mote +python3-motephat +python3-phatbeat +python3-pianohat +python3-piglow +python3-rainbowhat +python3-scrollphat +python3-scrollphathd +python3-sn3218 +python3-skywriter +python3-touchphat +python3-buttonshim +python3-unicornhathd +python3-pantilthat diff --git a/external/packages/raspi/stage4/00-install-packages/02-packages b/external/packages/raspi/stage4/00-install-packages/02-packages new file mode 100644 index 000000000000..fc43d173136c --- /dev/null +++ b/external/packages/raspi/stage4/00-install-packages/02-packages @@ -0,0 +1,4 @@ +hunspell-en-gb +hyphen-en-gb +wamerican +wbritish diff --git a/external/packages/raspi/stage4/01-console-autologin/00-run.sh b/external/packages/raspi/stage4/01-console-autologin/00-run.sh new file mode 100755 index 000000000000..665dcdb7a15d --- /dev/null +++ b/external/packages/raspi/stage4/01-console-autologin/00-run.sh @@ -0,0 +1,5 @@ +#!/bin/bash -e + +on_chroot << EOF + SUDO_USER="${FIRST_USER_NAME}" raspi-config nonint do_boot_behaviour B4 +EOF diff --git a/external/packages/raspi/stage4/02-extras/00-run.sh b/external/packages/raspi/stage4/02-extras/00-run.sh new file mode 100755 index 000000000000..6a24f8254fb9 --- /dev/null +++ b/external/packages/raspi/stage4/02-extras/00-run.sh @@ -0,0 +1,7 @@ +#!/bin/bash -e + +#Alacarte fixes +install -v -o 1000 -g 1000 -d "${ROOTFS_DIR}/home/${FIRST_USER_NAME}/.local" +install -v -o 1000 -g 1000 -d "${ROOTFS_DIR}/home/${FIRST_USER_NAME}/.local/share" +install -v -o 1000 -g 1000 -d "${ROOTFS_DIR}/home/${FIRST_USER_NAME}/.local/share/applications" +install -v -o 1000 -g 1000 -d "${ROOTFS_DIR}/home/${FIRST_USER_NAME}/.local/share/desktop-directories" diff --git a/external/packages/raspi/stage4/03-bookshelf/00-run.sh b/external/packages/raspi/stage4/03-bookshelf/00-run.sh new file mode 100755 index 000000000000..8244568bd6d7 --- /dev/null +++ b/external/packages/raspi/stage4/03-bookshelf/00-run.sh @@ -0,0 +1,15 @@ +#!/bin/sh -e + +BOOKSHELF_URL="https://magpi.raspberrypi.org/bookshelf.xml" +GUIDE_URL="$(curl -s "$BOOKSHELF_URL" | awk -F '[<>]' "/Raspberry Pi Beginner's Guide 4th Edition<\/TITLE>/ {f=1; next} f==1 && /PDF/ {print \$3; exit}")" +OUTPUT="$(basename "$GUIDE_URL" | cut -f1 -d'?')" + +if [ ! -f "files/$OUTPUT" ]; then + rm files/*.pdf -f + curl -s "$GUIDE_URL" -o "files/$OUTPUT" +fi + +file "files/$OUTPUT" | grep -q "PDF document" + +install -v -o 1000 -g 1000 -d "${ROOTFS_DIR}/home/${FIRST_USER_NAME}/Bookshelf" +install -v -o 1000 -g 1000 -m 644 "files/$OUTPUT" "${ROOTFS_DIR}/home/${FIRST_USER_NAME}/Bookshelf/" diff --git a/external/packages/raspi/stage4/03-bookshelf/files/.gitignore b/external/packages/raspi/stage4/03-bookshelf/files/.gitignore new file mode 100644 index 000000000000..a1363379944a --- /dev/null +++ b/external/packages/raspi/stage4/03-bookshelf/files/.gitignore @@ -0,0 +1 @@ +*.pdf diff --git a/external/packages/raspi/stage4/04-enable-xcompmgr/00-run.sh b/external/packages/raspi/stage4/04-enable-xcompmgr/00-run.sh new file mode 100755 index 000000000000..ad6298df7b7e --- /dev/null +++ b/external/packages/raspi/stage4/04-enable-xcompmgr/00-run.sh @@ -0,0 +1,5 @@ +#!/bin/bash -e + +on_chroot << EOF + raspi-config nonint do_xcompmgr 0 +EOF diff --git a/external/packages/raspi/stage4/05-print-support/00-packages b/external/packages/raspi/stage4/05-print-support/00-packages new file mode 100644 index 000000000000..e9c36bda29aa --- /dev/null +++ b/external/packages/raspi/stage4/05-print-support/00-packages @@ -0,0 +1,2 @@ +cups +system-config-printer diff --git a/external/packages/raspi/stage4/05-print-support/01-run.sh b/external/packages/raspi/stage4/05-print-support/01-run.sh new file mode 100755 index 000000000000..dc9e2b2c3c5c --- /dev/null +++ b/external/packages/raspi/stage4/05-print-support/01-run.sh @@ -0,0 +1,5 @@ +#!/bin/bash -e + +on_chroot <<EOF +adduser "$FIRST_USER_NAME" lpadmin +EOF diff --git a/external/packages/raspi/stage4/06-orangepi/00-packages b/external/packages/raspi/stage4/06-orangepi/00-packages new file mode 100644 index 000000000000..0bfe6fbaa1d8 --- /dev/null +++ b/external/packages/raspi/stage4/06-orangepi/00-packages @@ -0,0 +1,10 @@ +xserver-xorg-dev +libgstreamer1.0-dev +libgstreamer-plugins-base1.0-dev +libgstreamer-opencv1.0-0 +gstreamer1.0-opencv +gstreamer1.0-wpe +libgstreamer-plugins-bad1.0-dev +gstreamer1.0-plugins-ugly +libre2-9 +libmpv1 diff --git a/external/packages/raspi/stage4/prerun.sh b/external/packages/raspi/stage4/prerun.sh new file mode 100755 index 000000000000..398be92fcdfb --- /dev/null +++ b/external/packages/raspi/stage4/prerun.sh @@ -0,0 +1,5 @@ +#!/bin/bash -e + +#if [ ! -d "${ROOTFS_DIR}" ]; then +# copy_previous +#fi diff --git a/external/packages/raspi/stage5/00-install-extras/00-packages b/external/packages/raspi/stage5/00-install-extras/00-packages new file mode 100644 index 000000000000..6350ab31f219 --- /dev/null +++ b/external/packages/raspi/stage5/00-install-extras/00-packages @@ -0,0 +1,13 @@ +mu-editor +#sonic-pi +#scratch nuscratch scratch3 +smartsim + +python3-sense-emu sense-emu-tools python-sense-emu-doc + +wolfram-engine +claws-mail +greenfoot-unbundled bluej-unbundled +realvnc-vnc-viewer + +code-the-classics diff --git a/external/packages/raspi/stage5/00-install-libreoffice/00-packages b/external/packages/raspi/stage5/00-install-libreoffice/00-packages new file mode 100644 index 000000000000..dc1b8d770b04 --- /dev/null +++ b/external/packages/raspi/stage5/00-install-libreoffice/00-packages @@ -0,0 +1,3 @@ +libreoffice-pi openjdk-11-jre- +libreoffice-help-en-gb +libreoffice-l10n-en-gb diff --git a/external/packages/raspi/stage5/prerun.sh b/external/packages/raspi/stage5/prerun.sh new file mode 100755 index 000000000000..398be92fcdfb --- /dev/null +++ b/external/packages/raspi/stage5/prerun.sh @@ -0,0 +1,5 @@ +#!/bin/bash -e + +#if [ ! -d "${ROOTFS_DIR}" ]; then +# copy_previous +#fi diff --git a/scripts/configuration.sh b/scripts/configuration.sh index 4cc56e6d4cc2..a34b07ccfcd5 100755 --- a/scripts/configuration.sh +++ b/scripts/configuration.sh @@ -347,7 +347,7 @@ fi # "-z ${VAR+x}" allows to check for unset variable # Technically, someone might want to build a desktop with no additional # appgroups. -if [[ $BUILD_DESKTOP == "yes" && -z ${DESKTOP_APPGROUPS_SELECTED+x} ]]; then +if [[ $BUILD_DESKTOP == "yes" && -z ${DESKTOP_APPGROUPS_SELECTED+x} && ${RELEASE} != "raspi" ]]; then options=() for appgroup_path in "${DESKTOP_APPGROUPS_DIR}/"*; do @@ -418,6 +418,8 @@ BOOTCONFIG_VAR_NAME=BOOTCONFIG_${BRANCH^^} if [[ "$RELEASE" =~ ^(xenial|bionic|focal|hirsute|impish|jammy)$ ]]; then DISTRIBUTION="Ubuntu" +elif [[ "$RELEASE" == raspi ]]; then + DISTRIBUTION="Bullseye" else DISTRIBUTION="Debian" fi @@ -575,6 +577,7 @@ unset LOG_OUTPUT_FILE DEBIAN_MIRROR='deb.debian.org/debian' DEBIAN_SECURTY='security.debian.org/' UBUNTU_MIRROR='ports.ubuntu.com/' +RASPI_MIRROR='archive.raspberrypi.org/debian/' if [[ $DOWNLOAD_MIRROR == "china" ]] ; then @@ -590,6 +593,8 @@ if [[ $DOWNLOAD_MIRROR == "china" ]] ; then UBUNTU_MIRROR='repo.huaweicloud.com/ubuntu-ports/' fi + RASPI_MIRROR='mirrors.ustc.edu.cn/archive.raspberrypi.org/debian/' + fi if [[ $DOWNLOAD_MIRROR == "bfsu" ]] ; then diff --git a/scripts/debootstrap.sh b/scripts/debootstrap.sh index d160c384d386..ce1f3b916f7f 100755 --- a/scripts/debootstrap.sh +++ b/scripts/debootstrap.sh @@ -57,24 +57,29 @@ PRE_INSTALL_DISTRIBUTION_SPECIFIC # stage: install kernel and u-boot packages # install distribution and board specific applications - install_distribution_specific - install_common + if [[ ${RELEASE} == "raspi" ]]; then + install_opi_specific + else + install_distribution_specific + install_common - # install locally built packages or install pre-built packages from orangepi - [[ $EXTERNAL_NEW == compile || $EXTERNAL_NEW == prebuilt ]] && chroot_installpackages_local + # install locally built packages or install pre-built packages from orangepi + [[ $EXTERNAL_NEW == compile || $EXTERNAL_NEW == prebuilt ]] && chroot_installpackages_local - #[[ $EXTERNAL_NEW == prebuilt ]] && chroot_installpackages "yes" + #[[ $EXTERNAL_NEW == prebuilt ]] && chroot_installpackages "yes" - # stage: user customization script - # NOTE: installing too many packages may fill tmpfs mount - customize_image + # stage: user customization script + # NOTE: installing too many packages may fill tmpfs mount + customize_image - # remove packages that are no longer needed. Since we have intrudoced uninstall feature, we might want to clean things that are no longer needed - display_alert "No longer needed packages" "purge" "info" - chroot $SDCARD /bin/bash -c "apt-get autoremove -y" >/dev/null 2>&1 + # remove packages that are no longer needed. Since we have intrudoced uninstall feature, we might want to clean things that are no longer needed + display_alert "No longer needed packages" "purge" "info" + chroot $SDCARD /bin/bash -c "apt-get autoremove -y" >/dev/null 2>&1 - # create list of installed packages for debug purposes - chroot $SDCARD /bin/bash -c "dpkg --get-selections" | grep -v deinstall | awk '{print $1}' | cut -f1 -d':' > $DEST/${LOG_SUBPATH}/installed-packages-${RELEASE}$([[ ${BUILD_MINIMAL} == yes ]] && echo "-minimal")$([[ ${BUILD_DESKTOP} == yes ]] && echo "-desktop").list 2>&1 + # create list of installed packages for debug purposes + chroot $SDCARD /bin/bash -c "dpkg --get-selections" | grep -v deinstall | awk '{print $1}' | cut -f1 -d':' > $DEST/${LOG_SUBPATH}/installed-packages-${RELEASE}$([[ ${BUILD_MINIMAL} == yes ]] && echo "-minimal")$([[ ${BUILD_DESKTOP} == yes ]] && echo "-desktop").list 2>&1 + + fi # clean up / prepare for making the image umount_chroot "$SDCARD" @@ -104,6 +109,26 @@ PRE_INSTALL_DISTRIBUTION_SPECIFIC trap - INT TERM EXIT } ############################################################################# +bootstrap(){ + local BOOTSTRAP_CMD=debootstrap + local BOOTSTRAP_ARGS=() + + export CAPSH_ARG="--drop=cap_setfcap" + export http_proxy=${APT_PROXY} + + BOOTSTRAP_ARGS+=(--arch arm64) + BOOTSTRAP_ARGS+=(--include gnupg) + #BOOTSTRAP_ARGS+=(--components "main,contrib,non-free") + BOOTSTRAP_ARGS+=(--components "main") + BOOTSTRAP_ARGS+=(--exclude=info) + BOOTSTRAP_ARGS+=(--include=ca-certificates) + BOOTSTRAP_ARGS+=("$@") + printf -v BOOTSTRAP_STR '%q ' "${BOOTSTRAP_ARGS[@]}" + + ${BOOTSTRAP_CMD} $BOOTSTRAP_STR || true +} +export -f bootstrap + # create_rootfs_cache # # unpacks cached rootfs for $RELEASE or creates one @@ -128,6 +153,32 @@ create_rootfs_cache() rm $SDCARD/etc/resolv.conf echo "nameserver $NAMESERVER" >> $SDCARD/etc/resolv.conf create_sources_list "$RELEASE" "$SDCARD/" + elif [[ $RELEASE == "raspi" ]]; then + display_alert "local not found" "Creating new rootfs cache for $RELEASE" "info" + + cd $SDCARD # this will prevent error sh: 0: getcwd() failed + + bootstrap bullseye "$SDCARD" "https://mirrors.ustc.edu.cn/debian/" + + mount_chroot "$SDCARD" + + display_alert "Diverting" "initctl/start-stop-daemon" "info" + # policy-rc.d script prevents starting or reloading services during image creation + printf '#!/bin/sh\nexit 101' > $SDCARD/usr/sbin/policy-rc.d + LC_ALL=C LANG=C chroot $SDCARD /bin/bash -c "dpkg-divert --quiet --local --rename --add /sbin/initctl" &> /dev/null + LC_ALL=C LANG=C chroot $SDCARD /bin/bash -c "dpkg-divert --quiet --local --rename --add /sbin/start-stop-daemon" &> /dev/null + printf '#!/bin/sh\necho "Warning: Fake start-stop-daemon called, doing nothing"' > $SDCARD/sbin/start-stop-daemon + printf '#!/bin/sh\necho "Warning: Fake initctl called, doing nothing"' > $SDCARD/sbin/initctl + chmod 755 $SDCARD/usr/sbin/policy-rc.d + chmod 755 $SDCARD/sbin/initctl + chmod 755 $SDCARD/sbin/start-stop-daemon + + install_raspi_specific + + umount_chroot "$SDCARD" + + tar cp --xattrs --directory=$SDCARD/ --exclude='./dev/*' --exclude='./proc/*' --exclude='./run/*' --exclude='./tmp/*' \ + --exclude='./sys/*' . | pv -p -b -r -s $(du -sb $SDCARD/ | cut -f1) -N "$display_name" | lz4 -5 -c > $cache_fname else display_alert "local not found" "Creating new rootfs cache for $RELEASE" "info" @@ -153,6 +204,7 @@ create_rootfs_cache() display_alert "Installing base system" "Stage 1/2" "info" cd $SDCARD # this will prevent error sh: 0: getcwd() failed + eval 'debootstrap --variant=minbase --include=${DEBOOTSTRAP_LIST// /,} ${PACKAGE_LIST_EXCLUDE:+ --exclude=${PACKAGE_LIST_EXCLUDE// /,}} \ --arch=$ARCH --components=${DEBOOTSTRAP_COMPONENTS} $DEBOOTSTRAP_OPTION --foreign $RELEASE $SDCARD/ $apt_mirror' \ ${PROGRESS_LOG_TO_FILE:+' | tee -a $DEST/${LOG_SUBPATH}/debootstrap.log'} \ @@ -753,6 +805,11 @@ create_image() else local version="${BOARD^}_${REVISION}_${DISTRIBUTION,}_${RELEASE}_${IMAGE_TYPE}"${DESKTOP_ENVIRONMENT:+_$DESKTOP_ENVIRONMENT}"_linux$(grab_version "$LINUXSOURCEDIR")" fi + + if [[ ${RELEASE} == "raspi" ]]; then + local version="${BOARD^}_${REVISION}_raspios_bullseye_${IMAGE_TYPE}"${DESKTOP_ENVIRONMENT:+_$DESKTOP_ENVIRONMENT}"_linux$(grab_version "$LINUXSOURCEDIR")" + fi + [[ $ROOTFS_TYPE == nfs ]] && version=${version}_nfsboot destimg=$DEST/images/${version} diff --git a/scripts/distributions.sh b/scripts/distributions.sh index 33f4fda6e005..cf8ee51cde4f 100755 --- a/scripts/distributions.sh +++ b/scripts/distributions.sh @@ -820,3 +820,322 @@ It is too late to run any chrooted commands, since the supporting filesystems ar POST_POST_DEBOOTSTRAP_TWEAKS } + +on_chroot() +{ + if [ "$SETFCAP" != "1" ]; then + export CAPSH_ARG="--drop=cap_setfcap" + fi + + capsh $CAPSH_ARG "--chroot=${ROOTFS_DIR}/" -- -e "$@" +} +export -f on_chroot + +# shellcheck disable=SC2119 +run_sub_stage() +{ + log "Begin ${SUB_STAGE_DIR}" + #pushd "${SUB_STAGE_DIR}" > /dev/null + cd ${SUB_STAGE_DIR} + + for i in {00..99}; do + if [ -f "${SUB_STAGE_DIR}/${i}-debconf" ]; then + display_alert "Begin ${SUB_STAGE_DIR}/${i}-debconf" "" "info" + on_chroot << EOF +debconf-set-selections <<SELEOF +$(cat "${i}-debconf") +SELEOF +EOF + display_alert "End ${SUB_STAGE_DIR}/${i}-debconf" "" "info" + fi + if [ -f "${SUB_STAGE_DIR}/${i}-packages-nr" ]; then + display_alert "Begin ${SUB_STAGE_DIR}/${i}-packages-nr" "" "info" + PACKAGES="$(sed -f "${EXTER}/packages/raspi/scripts/remove-comments.sed" < "${SUB_STAGE_DIR}/${i}-packages-nr")" + if [ -n "$PACKAGES" ]; then + on_chroot << EOF +apt-get -o Acquire::Retries=3 install --no-install-recommends -y $PACKAGES +EOF + fi + display_alert "End ${SUB_STAGE_DIR}/${i}-packages-nr" "" "info" + fi + if [ -f "${SUB_STAGE_DIR}/${i}-packages" ]; then + display_alert "Begin ${SUB_STAGE_DIR}/${i}-packages" "" "info" + PACKAGES="$(sed -f "${EXTER}/packages/raspi/scripts/remove-comments.sed" < "${SUB_STAGE_DIR}/${i}-packages")" + if [ -n "$PACKAGES" ]; then + on_chroot << EOF +apt-get -o Acquire::Retries=3 install -y $PACKAGES +EOF + fi + display_alert "End ${SUB_STAGE_DIR}/${i}-packages" "" "info" + fi +# if [ -d "${SUB_STAGE_DIR}/${i}-patches" ]; then +# log "Begin ${SUB_STAGE_DIR}/${i}-patches" +# pushd "${STAGE_WORK_DIR}" > /dev/null +# #cd ${STAGE_WORK_DIR} +# +# QUILT_PATCHES="${SUB_STAGE_DIR}/${i}-patches" +# SUB_STAGE_QUILT_PATCH_DIR="$(basename "$SUB_STAGE_DIR")-pc" +# mkdir -p "$STAGE_WORK_DIR/$SUB_STAGE_QUILT_PATCH_DIR" +# ln -snf "$STAGE_WORK_DIR/$SUB_STAGE_QUILT_PATCH_DIR" .pc +# ln -snfv "${ROOTFS_DIR}" ${STAGE_WORK_DIR}/rootfs +# quilt upgrade +# if [ -e "${SUB_STAGE_DIR}/${i}-patches/EDIT" ]; then +# echo "Dropping into bash to edit patches..." +# bash +# fi +# RC=0 +# quilt push -a || RC=$? +# case "$RC" in +# 0|2) +# ;; +# *) +# false +# ;; +# esac +# #popd > /dev/null +# cd - +# log "End ${SUB_STAGE_DIR}/${i}-patches" +# fi + if [ -x ${i}-run.sh ]; then + display_alert "Begin ${SUB_STAGE_DIR}/${i}-run.sh" "" "info" + ./${i}-run.sh + display_alert "End ${SUB_STAGE_DIR}/${i}-run.sh" "" "info" + fi + if [ -f ${i}-run-chroot.sh ]; then + display_alert "Begin ${SUB_STAGE_DIR}/${i}-run-chroot.sh" "" "info" + on_chroot < ${i}-run-chroot.sh + display_alert "End ${SUB_STAGE_DIR}/${i}-run-chroot.sh" "" "info" + fi + done + #popd > /dev/null + log "End ${SUB_STAGE_DIR}" +} + +run_stage(){ + rm -rf "${SRC}"/output/raspi + [[ ! -d "${SRC}"/output/raspi ]] && mkdir -p "${SRC}"/output/raspi + + STAGE_WORK_DIR="${SRC}/output/raspi" + + if [ ! -f ${STAGE_DIR}/SKIP ]; then + if [ -x ${STAGE_DIR}/prerun.sh ]; then + display_alert "Begin ${STAGE_DIR}/prerun.sh" "" "info" + source ${STAGE_DIR}/prerun.sh + display_alert "End ${STAGE_DIR}/prerun.sh" "" "info" + fi + + for SUB_STAGE_DIR in "${STAGE_DIR}"/*; do + if [ -d "${SUB_STAGE_DIR}" ] && [ ! -f "${SUB_STAGE_DIR}/SKIP" ]; then + run_sub_stage + fi + done + fi +} + +log () +{ + date +"[%T] $*" +} + +install_opi_specific() +{ + cd $SRC + + # install u-boot + UBOOT_VER=$(dpkg --info "${DEB_STORAGE}/u-boot/${CHOSEN_UBOOT}_${REVISION}_${ARCH}.deb" | grep Descr | awk '{print $(NF)}') + install_deb_chroot "${DEB_STORAGE}/u-boot/${CHOSEN_UBOOT}_${REVISION}_${ARCH}.deb" + + # install kernel + VER=$(dpkg --info "${DEB_STORAGE}/${CHOSEN_KERNEL}_${REVISION}_${ARCH}.deb" | awk -F"-" '/Source:/{print $2}') + install_deb_chroot "${DEB_STORAGE}/${CHOSEN_KERNEL}_${REVISION}_${ARCH}.deb" + if [[ -f ${DEB_STORAGE}/${CHOSEN_KERNEL/image/dtb}_${REVISION}_${ARCH}.deb ]]; then + install_deb_chroot "${DEB_STORAGE}/${CHOSEN_KERNEL/image/dtb}_${REVISION}_${ARCH}.deb" + fi + if [[ $INSTALL_HEADERS == yes ]]; then + install_deb_chroot "${DEB_STORAGE}/${CHOSEN_KERNEL/image/headers}_${REVISION}_${ARCH}.deb" + else + cp "${DEB_STORAGE}/${CHOSEN_KERNEL/image/headers}_${REVISION}_${ARCH}.deb" "${SDCARD}"/opt/ + fi + + rk356x_gpu_vpu_tweaks_for_raspios + + [[ ! -d "${SDCARD}/lib/firmware" ]] && mkdir -p "${SDCARD}/lib/firmware" + cp -rfa ${EXTER}/cache/sources/orangepi-firmware-git/* ${SDCARD}/lib/firmware/ + + # NOTE: this needs to be executed before family_tweaks + local bootscript_src=${BOOTSCRIPT%%:*} + local bootscript_dst=${BOOTSCRIPT##*:} + + if [[ "${BOOTCONFIG}" != "none" ]]; then + if [ -f "${USERPATCHES_PATH}/bootscripts/${bootscript_src}" ]; then + cp "${USERPATCHES_PATH}/bootscripts/${bootscript_src}" "${SDCARD}/boot/${bootscript_dst}" + else + cp "${EXTER}/config/bootscripts/${bootscript_src}" "${SDCARD}/boot/${bootscript_dst}" + fi + fi + + if [[ -n $BOOTENV_FILE ]]; then + if [[ -f $USERPATCHES_PATH/bootenv/$BOOTENV_FILE ]]; then + cp "$USERPATCHES_PATH/bootenv/${BOOTENV_FILE}" "${SDCARD}"/boot/orangepiEnv.txt + elif [[ -f $EXTER/config/bootenv/$BOOTENV_FILE ]]; then + cp "${EXTER}/config/bootenv/${BOOTENV_FILE}" "${SDCARD}"/boot/orangepiEnv.txt + fi + fi + + [[ -n $OVERLAY_PREFIX && -f "${SDCARD}"/boot/orangepiEnv.txt && ($BRANCH =~ current|next || $BOARDFAMILY =~ "rockchip-rk3588"|"rockchip-rk356x") ]] && \ + echo "overlay_prefix=$OVERLAY_PREFIX" >> "${SDCARD}"/boot/orangepiEnv.txt + + [[ -n $DEFAULT_OVERLAYS && -f "${SDCARD}"/boot/orangepiEnv.txt && ($BRANCH =~ current|next || $BOARDFAMILY =~ "rockchip-rk3588"|"rockchip-rk356x") ]] && \ + echo "overlays=${DEFAULT_OVERLAYS//,/ }" >> "${SDCARD}"/boot/orangepiEnv.txt + + [[ -n $BOOT_FDT_FILE && -f "${SDCARD}"/boot/orangepiEnv.txt ]] && \ + echo "fdtfile=${BOOT_FDT_FILE}" >> "${SDCARD}/boot/orangepiEnv.txt" + + # create modules file + local modules=MODULES_${BRANCH^^} + if [[ -n "${!modules}" ]]; then + tr ' ' '\n' <<< "${!modules}" > "${SDCARD}"/etc/modules + elif [[ -n "${MODULES}" ]]; then + tr ' ' '\n' <<< "${MODULES}" > "${SDCARD}"/etc/modules + fi + + # create blacklist files + local blacklist=MODULES_BLACKLIST_${BRANCH^^} + if [[ -n "${!blacklist}" ]]; then + tr ' ' '\n' <<< "${!blacklist}" | sed -e 's/^/blacklist /' > "${SDCARD}/etc/modprobe.d/blacklist-${BOARD}.conf" + elif [[ -n "${MODULES_BLACKLIST}" ]]; then + tr ' ' '\n' <<< "${MODULES_BLACKLIST}" | sed -e 's/^/blacklist /' > "${SDCARD}/etc/modprobe.d/blacklist-${BOARD}.conf" + fi + + cat <<-EOF > "${SDCARD}"/etc/orangepi-release + # PLEASE DO NOT EDIT THIS FILE + BOARD=${BOARD} + BOARD_NAME="$BOARD_NAME" + BOARDFAMILY=${BOARDFAMILY} + BUILD_REPOSITORY_URL=${BUILD_REPOSITORY_URL} + BUILD_REPOSITORY_COMMIT=${BUILD_REPOSITORY_COMMIT} + DISTRIBUTION_CODENAME=${RELEASE} + DISTRIBUTION_STATUS=${DISTRIBUTION_STATUS} + VERSION=${REVISION} + LINUXFAMILY=${LINUXFAMILY} + ARCH=${ARCHITECTURE} + IMAGE_TYPE=$IMAGE_TYPE + BOARD_TYPE=$BOARD_TYPE + INITRD_ARCH=${INITRD_ARCH} + KERNEL_IMAGE_TYPE=${KERNEL_IMAGE_TYPE} + BRANCH=${BRANCH} + EOF + + install -d "${SDCARD}/etc/initramfs/post-update.d/" + install -m 755 "${EXTER}/packages/bsp/common/etc/initramfs/post-update.d/99-uboot" "${SDCARD}/etc/initramfs/post-update.d/" + + install -m 755 "${EXTER}/packages/raspi/orangepi/common/files/hciattach_opi" "${SDCARD}/usr/bin/" + + install -d "${SDCARD}/usr/lib/orangepi/" + install -m 755 "${EXTER}/packages/raspi/orangepi/common/files/orangepi-hardware-optimization" "${SDCARD}/usr/lib/orangepi/" + install -m 755 "${EXTER}/packages/raspi/orangepi/common/files/orangepi-hardware-optimize.service" "${SDCARD}/usr/lib/systemd/system/" + chroot "${SDCARD}" /bin/bash -c "systemctl --no-reload enable orangepi-hardware-optimize.service >/dev/null 2>&1" + + install_wiringop + + rm $SDCARD/root/*.deb >/dev/null 2>&1 +} + +install_raspi_specific() +{ + export TARGET_HOSTNAME=${TARGET_HOSTNAME:-raspberrypi} + export FIRST_USER_NAME=${FIRST_USER_NAME:-pi} + export FIRST_USER_PASS + export DISABLE_FIRST_BOOT_USER_RENAME=${DISABLE_FIRST_BOOT_USER_RENAME:-0} + export WPA_ESSID + export WPA_PASSWORD + export WPA_COUNTRY + export ENABLE_SSH="${ENABLE_SSH:-0}" + export PUBKEY_ONLY_SSH="${PUBKEY_ONLY_SSH:-0}" + + export LOCALE_DEFAULT="${LOCALE_DEFAULT:-en_GB.UTF-8}" + + export KEYBOARD_KEYMAP="${KEYBOARD_KEYMAP:-gb}" + export KEYBOARD_LAYOUT="${KEYBOARD_LAYOUT:-English (UK)}" + + export TIMEZONE_DEFAULT="${TIMEZONE_DEFAULT:-Europe/London}" + + export PUBKEY_SSH_FIRST_USER + + export APT_PROXY + + export STAGE + export STAGE_DIR + export STAGE_WORK_DIR + export PREV_STAGE + export PREV_STAGE_DIR + export ROOTFS_DIR=${SDCARD} + export PREV_ROOTFS_DIR + export IMG_SUFFIX + export NOOBS_NAME + export NOOBS_DESCRIPTION + export EXPORT_DIR + export EXPORT_ROOTFS_DIR + + export QUILT_PATCHES + export QUILT_NO_DIFF_INDEX=1 + export QUILT_NO_DIFF_TIMESTAMPS=1 + export QUILT_REFRESH_ARGS="-p ab" + + #check username is valid + if [[ ! "$FIRST_USER_NAME" =~ ^[a-z][-a-z0-9_]*$ ]]; then + echo "Invalid FIRST_USER_NAME: $FIRST_USER_NAME" + exit 1 + fi + + if [[ "$DISABLE_FIRST_BOOT_USER_RENAME" == "1" ]] && [ -z "${FIRST_USER_PASS}" ]; then + echo "To disable user rename on first boot, FIRST_USER_PASS needs to be set" + echo "Not setting FIRST_USER_PASS makes your system vulnerable and open to cyberattacks" + exit 1 + fi + + if [[ "$DISABLE_FIRST_BOOT_USER_RENAME" == "1" ]]; then + echo "User rename on the first boot is disabled" + echo "Be advised of the security risks linked to shipping a device with default username/password set." + fi + + if [[ -n "${APT_PROXY}" ]] && ! curl --silent "${APT_PROXY}" >/dev/null ; then + echo "Could not reach APT_PROXY server: ${APT_PROXY}" + exit 1 + fi + + if [[ -n "${WPA_PASSWORD}" && ${#WPA_PASSWORD} -lt 8 || ${#WPA_PASSWORD} -gt 63 ]] ; then + echo "WPA_PASSWORD" must be between 8 and 63 characters + exit 1 + fi + + if [[ "${PUBKEY_ONLY_SSH}" = "1" && -z "${PUBKEY_SSH_FIRST_USER}" ]]; then + echo "Must set 'PUBKEY_SSH_FIRST_USER' to a valid SSH public key if using PUBKEY_ONLY_SSH" + exit 1 + fi + + RASPI_DIR="${EXTER}/packages/raspi" + + if [[ ${BUILD_DESKTOP} == "yes" ]]; then + rm -r ${RASPI_DIR}/stage3/SKIP ${RASPI_DIR}/stage4/SKIP ${RASPI_DIR}/stage5/SKIP 2>/dev/null + touch ${RASPI_DIR}/stage5/SKIP + else + rm -r ${RASPI_DIR}/stage1/SKIP ${RASPI_DIR}/stage2/SKIP 2>/dev/null + touch ${RASPI_DIR}/stage3/SKIP ${RASPI_DIR}/stage4/SKIP ${RASPI_DIR}/stage5/SKIP + export FIRST_USER_PASS="pi" + fi + + STAGE_LIST=${RASPI_DIR}/stage* + + for STAGE_DIR in $STAGE_LIST; do + STAGE_DIR=$(realpath "${STAGE_DIR}") + run_stage + done + + STAGE_DIR=${RASPI_DIR}/export-image + run_stage + + rm -rf ${SDCARD}/boot/* + rm -rf ${SDCARD}/lib/firmware + rm -rf ${SDCARD}/lib/modules/* +} diff --git a/scripts/general.sh b/scripts/general.sh index b8a5d06cc7bd..02f98bc3e593 100755 --- a/scripts/general.sh +++ b/scripts/general.sh @@ -184,7 +184,7 @@ create_sources_list() EOF ;; - bullseye|trixie) + bullseye) cat <<-EOF > "${basedir}"/etc/apt/sources.list deb https://${DEBIAN_MIRROR} $release main contrib non-free #deb-src https://${DEBIAN_MIRROR} $release main contrib non-free @@ -241,6 +241,38 @@ create_sources_list() #deb-src http://${UBUNTU_MIRROR} ${release}-backports main restricted universe multiverse EOF ;; + + raspi) + cat <<-EOF > "${basedir}"/etc/apt/sources.list + deb http://${DEBIAN_MIRROR} bullseye main contrib non-free + #deb-src http://${DEBIAN_MIRROR} bullseye main contrib non-free + + deb http://${DEBIAN_MIRROR} bullseye-updates main contrib non-free + #deb-src http://${DEBIAN_MIRROR} bullseye-updates main contrib non-free + + deb http://${DEBIAN_MIRROR} bullseye-backports main contrib non-free + #deb-src http://${DEBIAN_MIRROR} bullseye-backports main contrib non-free + + deb http://${DEBIAN_SECURTY} bullseye-security main contrib non-free + #deb-src http://${DEBIAN_SECURTY} bullseye-security main contrib non-free + EOF + + cat <<-EOF > "${basedir}"/etc/apt/sources.list.d/raspi.list + deb http://${RASPI_MIRROR} bullseye main + # Uncomment line below then 'apt-get update' to enable 'apt-get source' + #deb-src http://archive.raspberrypi.org/debian/ bullseye main + EOF + + if [ -n "$APT_PROXY" ]; then + install -m 644 files/51cache "${APT_PROXY}/etc/apt/apt.conf.d/51cache" + sed "${basedir}/etc/apt/apt.conf.d/51cache" -i -e "s|APT_PROXY|${APT_PROXY}|" + else + rm -f "${basedir}/etc/apt/apt.conf.d/51cache" + fi + + cat ${EXTER}/packages/raspi/stage0/00-configure-apt/files/raspberrypi.gpg.key | gpg --dearmor > "${basedir}/raspberrypi-archive-stable.gpg" + install -m 644 "${basedir}/raspberrypi-archive-stable.gpg" "${basedir}/etc/apt/trusted.gpg.d/" + ;; esac # stage: add armbian repository and install key diff --git a/scripts/main.sh b/scripts/main.sh index a9147084db8b..af8389b5adbc 100755 --- a/scripts/main.sh +++ b/scripts/main.sh @@ -464,13 +464,13 @@ if [[ ${IGNORE_UPDATES} != yes ]]; then fi - if [[ ${BOARDFAMILY} == "rockchip-rk3588" && $RELEASE =~ bullseye|bookworm|focal|jammy ]]; then + if [[ ${BOARDFAMILY} == "rockchip-rk3588" && $RELEASE =~ bullseye|bookworm|focal|jammy|raspi ]]; then [[ ${BUILD_OPT} == image ]] && fetch_from_repo "https://github.com/orangepi-xunlong/rk-rootfs-build.git" "${EXTER}/cache/sources/rk3588_packages_${RELEASE}" "branch:rk3588_packages_${RELEASE}" fi - if [[ ${BOARDFAMILY} == "rockchip-rk356x" && $RELEASE =~ bullseye|focal|jammy ]]; then + if [[ ${BOARDFAMILY} == "rockchip-rk356x" && $RELEASE =~ bullseye|focal|jammy|raspi ]]; then [[ ${BUILD_OPT} == image ]] && fetch_from_repo "https://github.com/orangepi-xunlong/rk-rootfs-build.git" "${EXTER}/cache/sources/rk356x_packages" "branch:rk356x_packages"