# # SPDX-License-Identifier: GPL-2.0 # # Copyright (c) 2013-2023 Igor Pecovnik, igor@armbian.com # # This file is a part of the Armbian Build Framework # https://github.com/armbian/build/ # declare -g LINUXFAMILY=bcm2711 declare -g OVERLAY_DIR="/boot/dtb/broadcom/overlay" declare -g ARCH=arm64 declare -g UEFI_FS_LABEL="RPICFG" # Windows/Mac users will see this if they mount the SD card. Configurable, but should be uppercase always declare -g CPUMIN=500000 declare -g CPUMAX=2900000 declare -g GOVERNOR=ondemand declare -g INSTALL_ARMBIAN_FIRMWARE=no declare -g UEFISIZE=512 # in MiB. Not really UEFI, but partition layout is the same. declare -g BOOTSIZE=0 # No separate /boot; instead we have /boot/firmware fat32 partition declare -g BOOTCONFIG=none # We are currently not using U-boot for Raspberry Pi boards declare -g UEFI_MOUNT_POINT="/boot/firmware" # mount uefi partition at /boot/firmware declare -g LINUXCONFIG="linux-${LINUXFAMILY}-${BRANCH}" case "${BRANCH}" in legacy) declare -g KERNELSOURCE='https://github.com/raspberrypi/linux' declare -g KERNEL_MAJOR_MINOR="6.12" # Major and minor versions of this kernel. For mainline caching. declare -g KERNELBRANCH="branch:rpi-6.12.y" ;; current) declare -g KERNELSOURCE='https://github.com/raspberrypi/linux' declare -g KERNEL_MAJOR_MINOR="6.18" # Major and minor versions of this kernel. For mainline caching. declare -g KERNELBRANCH="branch:rpi-6.18.y" ;; edge) declare -g KERNELSOURCE='https://github.com/raspberrypi/linux' declare -g KERNEL_MAJOR_MINOR="6.19" # Major and minor versions of this kernel. For mainline caching. declare -g KERNELBRANCH="branch:rpi-6.19.y" ;; esac function post_family_config__mark_bsp_as_firmware_containing() { if [[ "${SKIP_ARMBIAN_REPO}" != "yes" ]]; then declare -g -r RASPI_FIRMWARE_DIR="/usr/lib/linux-firmware-raspi" display_alert "SKIP_ARMBIAN_REPO is set to" "${SKIP_ARMBIAN_REPO} - not adding rpi firmware to bsp" "info" return 0 fi display_alert "Marking BSP name as firmware-containing" "bcm2711" "info" declare -g EXTRA_BSP_NAME="${EXTRA_BSP_NAME}-raspifw" # Unique bsp name. declare -g -r RASPI_FIRMWARE_DIR="/usr/lib/armbian-firmware-raspi" } function post_family_config__add_rpi_packages() { display_alert "Preparing bcm2711" "${RELEASE}" "info" unset BOOTSOURCE # To try and convince lib/ to not build or install u-boot. declare -g SERIALCON="${RASPI_SERIALCON:-tty1}" # HDMI etc, not serial. most people don't have UART on rpi # those older releases are not working as we don't provide binaries for libraspberrypi-bin local not_usable_releases="bullseye|buster|focal" # if RELEASE is set, make sure it is one of the ones we support. if [[ -n "${RELEASE}" ]]; then if [[ "$RELEASE" =~ ^(${not_usable_releases})$ ]]; then exit_with_target_not_supported_error "Can't use release '${RELEASE}' for ${BOARD}. Invalid releases: '${not_usable_releases}'" "'${RELEASE}' not supported" fi fi } # Make sure we don't try to install or remove /boot/dtb-$kvers directory function post_family_tweaks_bsp__add_hooks_to_move_kernel_initrd_and_dtb() { run_host_command_logged mkdir -p "${destination}"/etc/kernel/post{inst,rm}.d # Copy new files to /boot/firmware; RASPI_FIRMWARE_DIR determines where they come from (at build time only!) # By default, kernel post-install scripts use filenames starting with "z50-". # However, Debian's 'raspi-firmware' package already uses this naming, which can cause conflicts. # To avoid this, we rename our script to /etc/kernel/postinst.d/z51-raspi-firmware # and include a runtime check for the distribution name. # This prevents issues on Debian where the conflict exists, while Ubuntu is unaffected. display_alert "Setting up z51-raspi-firmware" "bcm2711 - from ${RASPI_FIRMWARE_DIR}" "info" run_host_command_logged cat <<- z51-raspi-firmware > "${destination}"/etc/kernel/postinst.d/z51-raspi-firmware #!/bin/bash -e # We are using same name as the debian's raspi-firmware script, but we # only need to run this script on ubuntu. Debian's package has a postinst # section capable of copying files, but Ubuntu relies on flash-kernel [[ -d ${RASPI_FIRMWARE_DIR} ]] || exit 0 if grep -q '^ID=debian' /etc/os-release; then exit 0 fi # Play nice when run under debconf. exec &2 # Ensure the target directory exists. mkdir -p /boot/firmware for file in ${RASPI_FIRMWARE_DIR}/* do file=\$( basename "\$file" ) cp "${RASPI_FIRMWARE_DIR}/\$file" "/boot/firmware/\$file" sync -f "/boot/firmware/\$file" || true done exit 0 z51-raspi-firmware # Copy new files to /boot/firmware run_host_command_logged cat <<- 'zzz-copy-new-files' > "${destination}"/etc/kernel/postinst.d/zzz-copy-new-files #!/bin/bash -e # Play nice when run under debconf. exec &2 abi=$1 target=/boot/firmware dtb_dir=/usr/lib/linux-image-$abi/ # The kernel image can be named either "Image" (standardized for ARM platforms) # or "vmlinuz-${abi}" (default naming convention for Linux kernels). We need # too support both conventions. if [[ -f /boot/Image ]]; then cp /boot/Image ${target}/vmlinuz elif [[ -f /boot/vmlinuz-${abi} ]]; then cp /boot/vmlinuz-${abi} ${target}/vmlinuz else echo "Error: No kernel file (Image or vmlinuz-${abi}) found in /boot!" exit 1 fi cp ${dtb_dir}/broadcom/*.dtb ${target}/ cp -r ${dtb_dir}/overlays ${target}/ sync -f ${target}/vmlinuz || true exit 0 zzz-copy-new-files # Remove old files from /boot/firmware run_host_command_logged cat <<- 'zzz-remove-old-files' > "${destination}"/etc/kernel/postrm.d/zzz-remove-old-files #!/bin/bash -e # Play nice when run under debconf. exec &2 abi=$1 target=/boot/firmware rm ${target}/vmlinuz rm ${target}/*.dtb rm -r ${target}/overlays exit 0 zzz-remove-old-files run_host_command_logged chmod a+rx "${destination}"/etc/kernel/postinst.d/z51-raspi-firmware run_host_command_logged chmod a+rx "${destination}"/etc/kernel/postinst.d/zzz-copy-new-files run_host_command_logged chmod a+rx "${destination}"/etc/kernel/postrm.d/zzz-remove-old-files run_host_command_logged rm "${destination}"/etc/initramfs/post-update.d/99-uboot # copy new initramfs file run_host_command_logged cat <<- 'zzz-update-initramfs' > "${destination}"/etc/initramfs/post-update.d/zzz-update-initramfs #!/bin/bash -e # Play nice when run under debconf. exec &2 abi=$1 initrd_file=$2 target=/boot/firmware cp ${initrd_file} ${target}/initrd.img sync -f ${target}/initrd.img || true exit 0 zzz-update-initramfs run_host_command_logged chmod a+x "${destination}"/etc/initramfs/post-update.d/zzz-update-initramfs } function post_family_tweaks_bsp__add_x11_config() { display_alert "rpi5b" "Adding X11 configuration" "info" run_host_command_logged mkdir -p "${destination}"/etc/X11/xorg.conf.d/ run_host_command_logged cat <<- '99-vc4.conf' > "${destination}"/etc/X11/xorg.conf.d/99-vc4.conf Section "OutputClass" Identifier "vc4" MatchDriver "vc4" Driver "modesetting" Option "PrimaryGPU" "true" EndSection 99-vc4.conf } function post_family_tweaks__populate_boot_firmware_directory() { # We install kernel before we install bsp package. This means hooks present in bsp are not executed. # Running the hooks from bsp to populate /boot/firmware directory. display_alert "Populating /boot/firmware directory" "bcm2711" "info" modules_dir="$(find "${SDCARD}/lib/modules"/ -maxdepth 1 -type d -name "*${IMAGE_INSTALLED_KERNEL_VERSION}*")" kern_ver="$(basename "$modules_dir")" run_host_command_logged mkdir -p "${SDCARD}"/boot/firmware chroot_sdcard /etc/kernel/postinst.d/z51-raspi-firmware "${kern_ver}" chroot_sdcard /etc/kernel/postinst.d/zzz-copy-new-files "${kern_ver}" display_alert "Populating /boot/firmware directory" "bcm2711 - done" "info" } function post_family_tweaks_bsp__rpi_firmware_in_bsp() { if [[ "${SKIP_ARMBIAN_REPO}" != "yes" ]]; then display_alert "SKIP_ARMBIAN_REPO is set to" "${SKIP_ARMBIAN_REPO} - not adding rpi firmware to bsp" "info" return 0 fi display_alert "Using in-BSP firmware files for" "bcm2711::${BOARD}" "info" declare firmware_commit_sha1="9cafcd85f8aed1ec0c0f609b98af591fae367ba2" # Keep this inside this file, so hashing detect changes and bumps the version of the bsp package declare destdir="${destination}/usr/lib/armbian-firmware-raspi" run_host_command_logged mkdir -p "${destdir}" # Get the firmware files from the Debian git repo fetch_from_repo "https://salsa.debian.org/debian/raspi-firmware.git" "debian-raspi-firmware" "commit:${firmware_commit_sha1}" "yes" declare srcdir="${SRC}/cache/sources/debian-raspi-firmware/${firmware_commit_sha1}" # Copy the files from the git repo boot dir to the destdir run_host_command_logged cp -prv "${srcdir}/boot/"* "${destdir}"/ } function pre_install_distribution_specific__add_rpi_packages() { # If we're skipping the Armbian repo, and on Debian, we'll install Debian version of Wifi/BT-related firmware. if [[ "${SKIP_ARMBIAN_REPO}" == "yes" ]]; then display_alert "SKIP_ARMBIAN_REPO is set to" "${SKIP_ARMBIAN_REPO} - no Armbian repo packages will be installed" "info" if [[ "${DISTRIBUTION}" == "Debian" ]]; then display_alert "Installing Debian-sourced Wifi/BT firmware packages" "Debian::bcm2711::${BOARD}" "info" do_with_retries 3 chroot_sdcard_apt_get_update chroot_sdcard_apt_get_install firmware-brcm80211 firmware-misc-nonfree bluez-firmware bluetooth fi if [[ "${DISTRIBUTION}" == "Ubuntu" ]]; then display_alert "Installing Ubuntu-sourced Wifi/BT firmware packages plus raspi-config and raspi-eeprom" "Ubuntu::bcm2711::${BOARD}" "info" do_with_retries 3 chroot_sdcard_apt_get_update chroot_sdcard_apt_get_install rpi-eeprom pi-bluetooth busybox raspi-config bluetooth fi else # we store Rpi firmware packages in our repository # https://github.com/armbian/os/wiki/Import-3rd-party-packages display_alert "Enable Armbian repository to fetch Rpi packages" "" "info" mv "${SDCARD}"/etc/apt/sources.list.d/armbian.sources.disabled "${SDCARD}"/etc/apt/sources.list.d/armbian.sources do_with_retries 3 chroot_sdcard_apt_get_update if [[ "${DISTRIBUTION}" == "Debian" ]]; then chroot_sdcard_apt_get_install firmware-brcm80211 rpi-eeprom raspi-firmware raspberrypi-sys-mods bluez-firmware bluez pi-bluetooth busybox raspi-config else chroot_sdcard_apt_get_install rpi-eeprom linux-firmware-raspi pi-bluetooth libraspberrypi-bin busybox raspi-config fi ## disable armbian repository mv "${SDCARD}"/etc/apt/sources.list.d/armbian.sources "${SDCARD}"/etc/apt/sources.list.d/armbian.sources.disabled fi } function pre_install_distribution_specific__unblock_rfkill() { # Create a systemd service to unblock rfkill cat > "${SDCARD}/etc/systemd/system/unblock-rfkill.service" <<- EOT [Unit] Description=Unblock rfkill manually (no rfkill binary) After=multi-user.target [Service] Type=oneshot ExecStart=/bin/bash -c 'for f in /sys/class/rfkill/*/state; do echo 1 > "\$f"; done' RemainAfterExit=true [Install] WantedBy=multi-user.target EOT # Enable the service to run at boot display_alert "Enabling unblock-rfkill service" "bcm2711" "info" chroot_sdcard systemctl enable unblock-rfkill.service } # Our default paritioning system is leaving esp on. Rpi3 is the only board that have issues with this. # Removing the ESP flag from the boot partition should allow the image to boot on both the RPi3 and RPi4. function pre_umount_final_image__remove_esp() { display_alert "Removing ESP flag from FAT partition" "rpi4 / rpi3" "info" run_host_command_logged parted -s "${LOOP}" set 1 esp off } # write the default config.txt config function pre_umount_final_image__write_raspi_config() { cat <<- EOD > "${MOUNT}"/boot/firmware/config.txt # For more options and information see # http://rptl.io/configtxt # Some settings may impact device functionality. See link above for details # Uncomment some or all of these to enable the optional hardware interfaces #dtparam=i2c_arm=on #dtparam=i2s=on #dtparam=spi=on # Enable audio (loads snd_bcm2835) dtparam=audio=on # Additional overlays and parameters are documented # /boot/firmware/overlays/README # Automatically load overlays for detected cameras camera_auto_detect=1 # Automatically load overlays for detected DSI displays display_auto_detect=1 # Automatically load initramfs files, if found auto_initramfs=1 # Enable DRM VC4 V3D driver dtoverlay=vc4-kms-v3d max_framebuffers=2 # Don't have the firmware create an initial video= setting in cmdline.txt. # Use the kernel's default instead. disable_fw_kms_setup=1 # Disable compensation for displays with overscan disable_overscan=1 # Run as fast as firmware / board allows arm_boost=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 [cm5] dtoverlay=dwc2,dr_mode=host [all] kernel=vmlinuz initramfs initrd.img followkernel arm_64bit=1 EOD } function pre_umount_final_image__write_raspi_cmdline() { cat <<- EOD > "${MOUNT}"/boot/firmware/cmdline.txt console=serial0,115200 console=tty1 loglevel=1 root=LABEL=${ROOT_FS_LABEL} rootfstype=${ROOTFS_TYPE} fsck.repair=yes rootwait logo.nologo cgroup_enable=cpuset cgroup_memory=1 cgroup_enable=memory EOD if [[ "${SHOW_DEBUG}" == "yes" ]]; then display_alert "Showing /boot/firmware as mounted" "bcm2711" "debug" run_host_command_logged tree "${MOUNT}"/boot/firmware fi }