# common-raspberrypi Common Buildroot BR2_EXTERNAL tree for Raspberry Pi projects. This repository provides shared board support, packages, rootfs overlays, and patches that are used across multiple projects. Supported boards: - Raspberry Pi 1 Model B+ - Raspberry Pi Zero W This repository also pins the upstream Buildroot version as a git submodule, serving as the single source of truth for which Buildroot release is used. When a project pulls in this repo, it transitively gets the tested Buildroot version. ## Repository layout ``` common-raspberrypi/ ├── external.desc Buildroot external tree descriptor (name: RPI_COMMON) ├── external.mk Includes all common package .mk files ├── Config.in Top-level Kconfig menu for common packages ├── Makefile Wrapper for standalone build invocations ├── flash.sh SD card flashing helper script ├── buildroot/ [submodule] Upstream Buildroot, pinned to release tag ├── board/ │ └── raspberrypi/ │ ├── post-build.sh Shared post-build script (mdev rules, networking, build-info) │ ├── post-image.sh Shared post-image script (genimage invocation) │ ├── genimage.cfg.in SD card partition layout template │ ├── config_common.txt Raspberry Pi firmware config.txt │ ├── cmdline_common.txt Kernel command line │ ├── extlinux.conf U-Boot extlinux boot configuration │ ├── linux_defconfig Custom Linux kernel configuration │ ├── uboot_defconfig Custom U-Boot configuration │ ├── device_table.txt File permission fixups (SSH keys, mdev scripts) │ ├── dtoverlay/ Custom device tree overlays │ ├── uboot-patches/ Patches applied to U-Boot (DT overlay support) │ └── rootfs-overlay/ Shared rootfs overlay (copied into target rootfs) │ ├── etc/ │ │ ├── ssh/ Development SSH host keys │ │ └── wpa_supplicant.conf │ └── lib/ │ └── mdev/ Hotplug scripts (USB modeswitch, WLAN setup) ├── package/ Shared Buildroot packages ├── patches/ Patches to upstream Buildroot packages └── configs/ └── raspberrypi_common_defconfig Defconfig for standalone builds ``` ## Boot architecture The system boots through the Raspberry Pi firmware into U-Boot, which then loads the Linux kernel via extlinux: 1. **Raspberry Pi firmware** (`bootcode.bin`, `start.elf`) — reads `config.txt` (generated from `config_common.txt`), loads `u-boot.bin`. 2. **U-Boot** — reads `extlinux/extlinux.conf`, loads the kernel (`zImage`), device tree, and device tree overlays. 3. **Linux kernel** — boots with the command line from `extlinux.conf`. U-Boot is patched (via `uboot-patches/`) to support device tree overlays. The `genimage.cfg.in` template is expanded at build time by `post-image.sh` to produce the final SD card image with a FAT boot partition and an ext4 rootfs partition. ### Board selection The default device tree targets the Raspberry Pi 1 B+. To build for the Raspberry Pi Zero W, edit `config_common.txt` and `extlinux.conf` to uncomment the Zero W device tree and comment out the B+ one. See the comments in those files for details. ## Standalone setup Use this to develop and test the common tree without any project-specific additions. This is also what CI should run on every commit to this repo. ### Prerequisites A Linux host with standard Buildroot dependencies installed. See the Buildroot manual for the full list. On Debian/Ubuntu: ```sh sudo apt-get install -y build-essential gcc g++ bash patch gzip bzip2 \ perl tar cpio unzip rsync file bc wget libncurses-dev git ``` ### Clone and initialize ```sh git clone git@github.com:your-org/common-raspberrypi.git cd common-raspberrypi git submodule update --init ``` This pulls the Buildroot source into `buildroot/` at the pinned release tag. ### Build the image The wrapper Makefile passes any target through to Buildroot: ```sh make raspberrypi_common_defconfig # Load the defconfig make # Build the full image (takes a while on first run) ``` The SD card image will be at `output/images/sdcard.img`. ### Flash the SD card ```sh sudo ./flash.sh /dev/sdX ``` The script validates that the target device is removable, unmounts any mounted partitions, and writes the image with progress output. ### Useful build commands ```sh make menuconfig # Open Buildroot configuration menu make savedefconfig # Save current .config back to the defconfig make linux-rebuild # Rebuild just the kernel (any Buildroot target works) make clean # Clean build artifacts ``` Any valid Buildroot target is passed through directly by the Makefile. ## Creating a new project A project is a separate git repository that uses this common tree as a submodule. Each project is its own BR2_EXTERNAL and contains only project-specific packages, overlays, defconfigs, and board overrides. ### Step 1: Create the project repository ```sh mkdir myproject-raspberrypi cd myproject-raspberrypi git init ``` ### Step 2: Add common as a submodule ```sh git submodule add git@github.com:your-org/common-raspberrypi.git common git submodule update --init --recursive ``` The `--recursive` is important because it also pulls common's own Buildroot submodule into `common/buildroot/`. ### Step 3: Create the BR2_EXTERNAL descriptor Create `external.desc` at the project root. The name must be unique across all external trees and must be a valid C identifier (uppercase, underscores only): ``` name: MY_PROJECT desc: My project-specific Buildroot configuration ``` ### Step 4: Create supporting directories ```sh mkdir -p rootfs-overlay/etc mkdir -p package mkdir -p configs echo '/output/' > .gitignore ``` ### Step 5: Create external.mk This file includes only the project's own packages. The common packages are handled by the common tree's own `external.mk` — Buildroot merges them automatically because both trees are passed as separate BR2_EXTERNAL paths. ```makefile include $(sort $(wildcard $(BR2_EXTERNAL_MY_PROJECT_PATH)/package/*/*.mk)) ``` ### Step 6: Create Config.in Same principle — only source the project's own package configs. This file can start empty and be populated as packages are added: ``` menu "My Project packages" endmenu ``` ### Step 7: Create a project defconfig Create `configs/raspberrypi_myproject_defconfig`. Start by copying the common defconfig and modify it: ```sh cp common/configs/raspberrypi_common_defconfig configs/raspberrypi_myproject_defconfig ``` Edit the defconfig to add both overlays (common first, then project-specific): ``` BR2_ROOTFS_OVERLAY="$(BR2_EXTERNAL_RPI_COMMON_PATH)/board/raspberrypi/rootfs-overlay $(BR2_EXTERNAL_MY_PROJECT_PATH)/rootfs-overlay" ``` ### Step 8: Create the wrapper Makefile Create a `Makefile` at the project root. Like the common Makefile, it uses a catch-all rule to pass any Buildroot target through directly: ```makefile BUILDROOT_DIR := $(CURDIR)/common/buildroot OUTPUT_DIR := $(CURDIR)/output BR2_EXTERNAL := $(CURDIR)/common:$(CURDIR) CONFIG_EXISTS := $(wildcard $(OUTPUT_DIR)/.config) .PHONY: all all: ifeq ($(CONFIG_EXISTS),) @echo "No .config found. Load a defconfig first, e.g.:" @echo " make raspberrypi_myproject_defconfig" @exit 1 endif $(MAKE) -C $(BUILDROOT_DIR) BR2_EXTERNAL=$(BR2_EXTERNAL) O=$(OUTPUT_DIR) %: $(MAKE) -C $(BUILDROOT_DIR) BR2_EXTERNAL=$(BR2_EXTERNAL) O=$(OUTPUT_DIR) $@ ``` Note the key differences from the common Makefile: - `BUILDROOT_DIR` points to `common/buildroot/` (nested submodule) - `BR2_EXTERNAL` lists both trees, colon-separated: `common:project` ### Step 9: Commit and build ```sh git add -A git commit -m "Initial project skeleton" make raspberrypi_myproject_defconfig make ``` ### Project directory structure After following these steps, your project should look like this: ``` myproject-raspberrypi/ ├── external.desc ├── external.mk ├── Config.in ├── Makefile ├── .gitmodules ├── .gitignore ├── common/ [submodule -> common-raspberrypi] │ ├── buildroot/ [nested submodule -> upstream Buildroot] │ ├── board/raspberrypi/ │ ├── package/ │ └── ... ├── configs/ │ └── raspberrypi_myproject_defconfig ├── rootfs-overlay/ Project-specific rootfs overlay ├── package/ Project-specific packages └── output/ Build output (gitignored) ``` ## Wireless networking The build includes support for USB Wi-Fi adapters based on the Realtek RTL8821CU chipset, as well as the Raspberry Pi Zero W's built-in Wi-Fi (Broadcom BCM43430). Both paths end with wpa_supplicant handling authentication and DHCP providing an IP address. ### Raspberry Pi Zero W (built-in Wi-Fi) The Zero W's Broadcom BCM43430 is connected via SDIO. The `brcmfmac` driver and firmware blobs (included via `BR2_PACKAGE_BRCMFMAC_SDIO_FIRMWARE_RPI`) are loaded at boot. The `wlan0` interface is brought up automatically by the `auto wlan0` stanza in `/etc/network/interfaces` (appended by `post-build.sh`), which starts `wpa_supplicant` and obtains an IP via DHCP. ### USB RTL8821CU adapters RTL8821CU adapters require an extra USB modeswitch step, handled through mdev hotplug rules: 1. **USB modeswitch** — the adapter initially enumerates as a CD-ROM device (`0bda:1a2b`). An mdev rule triggers `usb_modeswitch` to switch it into Wi-Fi mode (`0bda:c820`). 2. **WLAN setup** — once the Wi-Fi device appears, a second mdev rule runs `wlan_setup.sh`, which brings up `wlan0` and starts `wpa_supplicant`. 3. **DHCP** — the interface obtains an IP address via DHCP. ### Configuring Wi-Fi credentials Edit `board/raspberrypi/rootfs-overlay/etc/wpa_supplicant.conf` with the target network's SSID and passphrase: ``` network={ ssid="MyNetwork" psk="MyPassphrase" } ``` ### Post-build rootfs modifications The `post-build.sh` script makes the following modifications to the target rootfs at build time: - Adds mdev rules for USB modeswitch (`rtl8821cu_usb_modeswitch.sh`) and WLAN setup (`wlan_setup.sh`). - Appends `wlan0` configuration to `/etc/network/interfaces` (DHCP with wpa_supplicant). - Generates `/etc/build-info` with the build user, date, and git revision. ## Adding a new shared package 1. Create a directory under `package/` with the package name. 2. Add a `Config.in` with the Kconfig entry. 3. Add a `.mk` file with the Buildroot package recipe. 4. Source the new `Config.in` in the top-level `Config.in`. 5. Enable the package in `configs/raspberrypi_common_defconfig`. 6. Build and verify: `make my-new-package-rebuild`. ## Adding patches to upstream Buildroot packages Place patch files under `patches//`. Buildroot automatically applies patches from `BR2_EXTERNAL_RPI_COMMON_PATH/patches//` during the package build. Patches must follow Buildroot's naming convention: `NNNN-description.patch` (e.g., `0001-fix-cross-compilation.patch`). U-Boot patches live separately under `board/raspberrypi/uboot-patches/` and are applied via the `BR2_TARGET_UBOOT_PATCH` defconfig option.