AI & MACHINE LEARNING
BESPOKE DATA VISUALISATIONS
CUSTOM SOFTWARE DEVELOPMENT
CLOUD & OPERATIONS
DATA & ANALYTICS
EMBEDDED & ENGINEERING
IOT & CLOUD
Bringing up a new operating system on embedded hardware often requires navigating through fragmented documentation, configuring build environments, and troubleshooting unexpected issues. prplOS, an open-source operating system based on OpenWrt, is designed for carrier-grade networking devices, offering modularity, security, and interoperability.
This guide provides a structured walkthrough for setting up prplOS on the Banana Pi R3, covering essential steps such as cloning the repository, configuring the build, compiling the system, and flashing the image onto the device. While prplOS offers a wide range of advanced features, this article focuses on the fundamental setup required to get the system running efficiently.
The prpl Foundation is an open-source community that brings together service providers, OEMs, silicon vendors, ISVs, and developers to create standardized solutions for carrier-grade Customer Premises Equipment (CPE). The foundation is structured into several working groups, each focusing on a specific aspect of the ecosystem:
This article focuses specifically on prplOS, an open-source operating system designed to meet the requirements of telecommunications and network service providers. Built on OpenWrt, prplOS provides a flexible, modular foundation for developing and deploying custom networking solutions.
While much of the technical detail about prplOS can be found directly in the source code, additional documentation is available to help navigate its structure and features. Many prplOS modules include a README.md file within their respective Git repositories, serving as a valuable starting point for understanding their functionality.
For more in-depth information, the prplMesh wiki provides documentation on specific aspects of the project:
Additionally, prpl Foundation’s YouTube channel contains presentations and discussions covering broader organizational and technical topics related to prplOS and its ecosystem.
PrplOS git repository can be found at gitlab:
https://gitlab.com/prpl-foundation/prplos/prplos
We can clone it via command
git clone git@gitlab.com:prpl-foundation/prplos/prplos.git
Then in prplos directory we have everything to start compiling for any existing target or prepare new profiles to build our own targets. As we plan to build for banana pi R3 device we need to create a profile for that target. Profile is special yml file that provides build parameters like what is the target and what are compilation options. Here is the list of profiles:
debug.yml
ipq40xx.yml
ipq807x.yml
mvebu.yml
mxl_wlan_hostap_ng_gw.yml
mxl_wlan_hostap_ng_wav700.yml
mxl_wlan_hostap_ng.yml
mxl_wlan.yml
mxl_x86_osp_tb341_v2.yml
mxl_x86_osp_tb341.yml
mxl_x86_sec.yml
mxl_x86.yml
prpl.yml
qca_ipq95xx.yml
security.yml
x86_64.yml
To apply one or more profiles, we must run following script:
./scripts/gen_config.py
Here also we can list available profiles:
./scripts/gen_config.py list
Profiles in profiles
mxl_x86_osp_tb341_v2
debug
x86_64
mvebu
prpl
mxl_x86
security
mxl_wlan_hostap_ng_gw
qca_ipq95xx
mxl_wlan_hostap_ng_wav700
mxl_x86_osp_tb341
mxl_wlan
mxl_x86_sec
ipq807x
ipq40xx
mxl_wlan_hostap_ng
Usage of that script is quite intuitive, for example if we want to build for x86 target, built with plplmesh and enabled debuging tools and logs, we can use such command:
./scripts/gen_config.py x86_64 prpl debug
This script will take care of all configurations, so .config file will be prepared, all needed packages will be updated and installed in build project. Once the gen_config script completes, the only remaining step is to build the project using make.
make -j$(nproc)
In case of build problems, we can rerun it with that command:
make -j1 V=sc
to see what the problem is.
Before we start to build project for a new platform, we have to prepare a profile yml file.
In that yml profile file we can distinguish the following sections:
After preparing build configuration of prplOS for banana pi R3 device it can be run:
./scripts/gen_config.py bpi-r3 prpl debug
then
make -j$(nproc)
Successful build will generate few types of images.
~/bin/targets/mediatek/filogic$ ls -1
config.buildinfo
feeds.buildinfo
packages
profiles.json
prplos-mediatek-filogic-bananapi_bpi-r3.bom.cdx.json
prplos-mediatek-filogic-bananapi_bpi-r3-emmc-bl31-uboot.fip
prplos-mediatek-filogic-bananapi_bpi-r3-emmc-preloader.bin
prplos-mediatek-filogic-bananapi_bpi-r3-initramfs-recovery.itb
prplos-mediatek-filogic-bananapi_bpi-r3.manifest
prplos-mediatek-filogic-bananapi_bpi-r3-nor-bl31-uboot.fip
prplos-mediatek-filogic-bananapi_bpi-r3-nor-preloader.bin
prplos-mediatek-filogic-bananapi_bpi-r3-sdcard.img.gz
prplos-mediatek-filogic-bananapi_bpi-r3-snand-bl31-uboot.fip
prplos-mediatek-filogic-bananapi_bpi-r3-snand-preloader.bin
prplos-mediatek-filogic-bananapi_bpi-r3-squashfs-sysupgrade.itb
sha256sums
version.buildinfo
version.prplos.buildinfo
One of them is sdcard image, which can be written to sdcard and then used in banana pi R3 board to boot prplOS for the first time.
BusyBox v1.36.1 (2024-11-27 22:30:14 UTC) built-in shell (ash)
_ ___ ____
_ __ _ __ _ __ | |/ _ \/ ___|
| ‘_ \| ‘__| ‘_ \| | | | \___ \
| |_) | | | |_) | | |_| |___) |
| .__/|_| | .__/|_|\___/|____/
|_| |_| based on OpenWrt
——————————–
prplOS 3.2.0-6024faa2
——————————–
=== WARNING! =====================================
There is no root password defined on this device!
Use the “passwd” command to set up a new password
in order to prevent unauthorized SSH logins.
————————————————–
root@prplOS:/#
Some configuration parameters need to be set up by uci entry prplmesh:
root@prplOS:/# uci show prplmesh
prplmesh.config=prplmesh
prplmesh.config.management_mode=’Multi-AP-Controller-and-Agent’
prplmesh.config.operating_mode=’Gateway’
prplmesh.config.enable=’1′
prplmesh.config.onboarding=’0′
prplmesh.config.master=’1′
prplmesh.config.gateway=’1′
prplmesh.config.rdkb_extensions=’0′
prplmesh.config.band_steering=’0′
prplmesh.config.client_roaming=’0′
prplmesh.config.dfs_reentry=’0′
prplmesh.config.passive_mode=’1′
prplmesh.config.wired_backhaul=’0′
prplmesh.config.operational=’0′
prplmesh.config.ssid=’test_ssid’
prplmesh.config.mode_enabled=’WPA2-Personal’
prplmesh.config.wep_key=’123456789a’
prplmesh.config.key_passphrase=’test_passphrase’
prplmesh.config.mem_only_psk=’0′
prplmesh.config.backhaul_band=’auto’
prplmesh.config.certification_mode=’0′
prplmesh.config.stop_on_failure_attempts=’1′
prplmesh.config.backhaul_wire_iface=’none’
prplmesh.config.channel_select_task_enabled=’1′
prplmesh.config.client_11k_roaming=’1′
prplmesh.config.dfs_task_enabled=’1′
prplmesh.config.diagnostics_measurements=’1′
prplmesh.config.diagnostics_measurements_polling_rate_sec=’10’
prplmesh.config.health_check_enabled=’0′
prplmesh.config.ire_roaming=’1′
prplmesh.config.link_metrics_request_interval_sec=’60’
prplmesh.config.load_balancing=’0′
prplmesh.config.optimal_path_prefer_signal_strenght=’0′
prplmesh.config.roaming_hysteresis_percent_bonus=’10’
prplmesh.config.steering_disassoc_timer_msec=’200′
prplmesh.config.daisy_chaining_disabled=’0′
prplmesh.config.rssi_measurements_timeout=’1000′
prplmesh.config.clients_persistent_db_max_size=’256′
prplmesh.config.steer_history_db_max_size=’24’
prplmesh.config.max_timelife_delay_minutes=’10000′
prplmesh.config.unfriendly_device_max_timelife_delay_minutes=’1000′
prplmesh.config.persistent_db_aging_interval_sec=’3600′
prplmesh.config.commit_changes_interval=’10’
prplmesh.config.unsuccessful_assoc_report_policy=’1′
prplmesh.config.unsuccessful_assoc_max_reporting_rate=’30’
prplmesh.config.beacon_measurements_timeout=’6000′
prplmesh.radio0=wifi-device
prplmesh.radio0.hostap_iface=’wlan0.1′
prplmesh.radio0.sta_iface=’wlan0′
prplmesh.radio0.dcs_enable=’0′
prplmesh.radio0.dcs_channel_pool=’1,6,11′
prplmesh.radio0.dcs_interval_sec=’15’
prplmesh.radio0.dcs_dwell_msec=’40’
prplmesh.radio0.dcs_refresh_sec=’86400′
prplmesh.radio1=wifi-device
prplmesh.radio1.hostap_iface=’wlan1.1′
prplmesh.radio1.sta_iface=’wlan1′
prplmesh.radio1.dcs_enable=’0′
prplmesh.radio1.dcs_channel_pool=’36-48,149-165′
prplmesh.radio1.dcs_interval_sec=’15’
prplmesh.radio1.dcs_dwell_msec=’40’
prplmesh.radio1.dcs_refresh_sec=’86400′
After flashing prepared prplos firmware not everything might be set. So missing parameters should be setup accordingly, like:
uci set prplmesh.radio0.sta_iface=’wlan0′
uci set prplmesh.config.steer_history_db_max_size=24
My bpi-r3 device after upgrading with already prepared prplOS boots up in agent mode:
management_mode: Multi-AP-Agent
operating_mode: WDS-Repeater
This is the default mode after first boot.
Other router parameters can be set via data model. There are few ways of doing that.
One way is to use ubus-cli tool:
root@prplOS:/# ubus-cli -h
ubus-cli [OPTIONS] [COMMANDS]
Options:
-h –help Print usage help and exits.
-H –HELP Shows available commands and exits.
-u <role> –user <role> Enable ACL checking and use specified role.
-j –json Set output format to JSON.
-s <file> –script <file> Sets the initialization script.
-a –automated Do not go in interactive mode.
-l –less Do not repeat commands, only print values or json.
— Indicates end of cli options.
Use command ‘-H’ to see available list of commands.
Example:
set channel for radio1
ubus-cli “WiFi.Radio.1.Channel=1”
get channel for radio2
root@prplOS:/# ubus-cli “WiFi.Radio.2.Channel?0”
> WiFi.Radio.2.Channel?0
WiFi.Radio.2.Channel=36
The second way is to use data model dmtui tool, which is accessible only via ssh connection not serial console.
To do this we need IP address of br-lan interface:
root@prplOS:/# ip address show br-lan
14: br-lan: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
link/ether be:06:df:8d:3b:9f brd ff:ff:ff:ff:ff:ff
inet 192.168.1.2/24 scope global br-lan
valid_lft forever preferred_lft forever
inet6 fe80::bc06:dfff:fe8d:3b9f/64 scope link
valid_lft forever preferred_lft forever
Then
ssh root@192.168.1.2
and
dmtui
Generally, all configuration of prplOS router should be done via data model except prplmesh parameters set up via uci.
At the beginning we have serial port access to the board. To use ssh via ethernet we must setup IP address of br-lan interface. The default IP address is 192.168.1.1. But as we plan to have few such devices, and our test network has already a different IP addresses range, it would be good to change that IP address.
We can do this via command:
ubus call “IP.Interface.3.IPv4Address.1” _set ‘{ “parameters”: { “IPAddress”: “192.168.10.1” } }’
Then after connecting ethernet cable from our PC to BPI-R3 lan port, we can start using ssh:
EasyMesh specify two types of devices:
So, let’s start with first type of device.
This can be done via uci commands:
uci set prplmesh.config.management_mode=’Multi-AP-Controller-and-Agent’
uci set prplmesh.config.operating_mode=’Gateway’
uci set prplmesh.config.master=1
uci set prplmesh.config.gateway=1
uci set prplmesh.config.wired_backhaul=’0′
uci set prplmesh.config.backhaul_band=’auto’
uci set prplmesh.config.backhaul_wire_iface=’none’
uci commit prplmesh
This can be verified like that:
/etc/init.d/prplmesh status
enable: 1
management_mode: Multi-AP-Controller-and-Agent
operating_mode: Gateway
WLAN Ready
/opt/prplmesh/scripts/prplmesh_utils.sh: status
2838 beerocks_contro
2839 beerocks_agent
2929 beerocks_fronth
2931 beerocks_fronth
executing operational test using bml
operational test success!
OK Main radio agent operational
OK wlan0 radio agent operational
OK wlan1 radio agent operational
So now when multi-ap controller is setup and running we can start configuring WiFi interfaces.
BPI-R3 device has two wifi cards, so we have two radios. We can start setting up regulatory domain for those radios:
ubus-cli WiFi.Radio.1.RegulatoryDomain=”PL”
ubus-cli WiFi.Radio.2.RegulatoryDomain=”PL”
then we can set channel for each radio:
ubus-cli “WiFi.Radio.1.Channel=1”
ubus-cli “WiFi.Radio.2.Channel=36”
And SSID.
For 2.4G band:
ubus-cli Device.WiFi.SSID.1.SSID=”test_ap”
For 5G band:
ubus-cli Device.WiFi.SSID.4.SSID=”test_ap”
Then we just need to enable access points:
ubus-cli “WiFi.AccessPoint.*.Enable=1”
And at the end we enable all radios:
ubus-cli “WiFi.Radio.*.Enable=1”
At this moment we have single wireless access point working on prplOS. And this is just beginning, we can start working on more sophisticated functionalities that are possible to run on prplOS. To list only few:
prplMesh – functionality to setup EasyMesh network,
LCM(Life Cycle Management) – functionality to give operators flexible and efficient way to manage the lifecycle of applications and services on embedded devices,
Remote management – functionality implementing standardized by Broadband Forum like TR-069 or TR-369.
Setting up prplOS on the Banana Pi R3 involves cloning the repository, configuring a build profile, compiling the system image, and flashing it onto the board. Once installed, additional runtime parameters can be adjusted via UCI or ubus to align with specific network requirements.
Beyond basic setup, prplOS includes advanced features such as prplMesh for EasyMesh networking, Life-Cycle Management (LCM) for remote software updates, and standardized remote management interfaces. These capabilities enable flexible deployment and integration into carrier-grade environments.
For further customization, the official documentation and source repositories provide additional resources on configuration, debugging, and feature expansion.
Senior Software Engineer
At Holisticon Connect, our core values of Passion and Execution drive us toward a Promising Future. We are a hands-on tech company that places people at the centre of everything we do. Specializing in Custom Software Development, Cloud and Operations, Bespoke Data Visualisations, Engineering & Embedded services, we build trust through our promise to deliver and a no-drama approach. We are committed to delivering reliable and effective solutions, ensuring our clients can count on us to meet their needs with integrity and excellence.
Let’s talk about your project needs. Send us a message and will get back to you as soon as possible.