` to flash the selected one. Output streams * to /var/log/pi-star/pi-star_modemflash.log; tailed via AJAX. * * The selected variant is run through escapeshellarg() before being * passed to the upgrade script (defence-in-depth — the picklist is * already constrained to script-reported names). */ require_once($_SERVER['DOCUMENT_ROOT'].'/config/security_headers.php'); require_once($_SERVER['DOCUMENT_ROOT'].'/config/csrf.php'); require_once($_SERVER['DOCUMENT_ROOT'].'/config/banner_warnings.inc'); setSecurityHeaders(); // CSRF protection — see config/csrf.php for the full rationale. // Must run BEFORE any output: bootstraps the session on GET (so // Set-Cookie ships) and rejects forged POSTs cleanly with 403 // before any state change (sed-i, fopen+fwrite, sudo cp, etc.). csrf_verify(); // Layer 2 of the default-password protection — see config/banner_warnings.inc. // MUST run BEFORE any output so header('Location: ...') works. pistar_warnings_enforce_redirect(); // Load the language support require_once('../config/language.php'); // Load the Pi-Star Release file $pistarReleaseConfig = '/etc/pistar-release'; $configPistarRelease = array(); $configPistarRelease = parse_ini_file($pistarReleaseConfig, true); // Load the Version Info require_once('../config/version.php'); // Force the Locale to the stock locale just while we run the update setlocale(LC_ALL, "LC_CTYPE=en_GB.UTF-8;LC_NUMERIC=C;LC_TIME=C;LC_COLLATE=C;LC_MONETARY=C;LC_MESSAGES=C;LC_PAPER=C;LC_NAME=C;LC_ADDRESS=C;LC_TELEPHONE=C;LC_MEASUREMENT=C;LC_IDENTIFICATION=C"); // Sanity Check that this file has been opened correctly if ($_SERVER["PHP_SELF"] == "/admin/expert/modem_fw_upgrade.php") { if ($_SERVER['REQUEST_METHOD'] === 'POST') { if (isset($_POST['modem'])) { // Whitelist-validate against the canonical modem list that // pistar-modemupgrade itself reports. The script is the // authoritative source of "what modem variants this device // knows how to flash" — POSTed values that don't appear in // that list are silently dropped (the operator just sees no // flash happen). escapeshellarg() below is still defence- // in-depth at the shell layer; this is the application-layer // gate that stops the script from being invoked with // attacker-controlled args at all. Mirrors the mmdvmcal // command whitelist in admin/calibration.php. $validModems = array_filter(array_map('trim', explode("\n", (string)shell_exec('sudo /usr/local/sbin/pistar-modemupgrade list')) )); if (in_array($_POST['modem'], $validModems, true)) { $selectedOption = $_POST['modem']; } else { error_log('Pi-Star modem_fw_upgrade.php: rejected modem=' . substr((string)$_POST['modem'], 0, 64)); } } } if (!isset($_GET['ajax'])) { // truncate creates+clears the log file in one synchronous call — // see admin/update.php for the full rationale. system('sudo truncate -s 0 /var/log/pi-star/pi-star_modemflash.log'); // No `NP=1` env-var prefix: the path-scoped sudoers refuses // env-var pass-through without a SETENV: tag, so `sudo NP=1 // pistar-modemupgrade …` was rejected outright with "you are // not allowed to set the following environment variables: NP" // and the flash silently never started. The wrapper now // auto-detects non-interactive mode via `[ -t 0 ]` (it's // backgrounded here with no controlling terminal), so the // explicit env var is no longer needed. if (isset($selectedOption)) { system('sudo /usr/local/sbin/pistar-modemupgrade ' . escapeshellarg($selectedOption) . ' > /dev/null 2>&1 &'); } } // passed sanity chk. header('Cache-Control: no-cache'); // csrf_verify() at the top of the file already started the // session via csrf_session_start(). Calling session_start() a // second time emits a PHP Notice on PHP 8.x ("Ignoring // session_start() because a session is already active") that // gets logged to nginx error.log on every page load. The // existing $_SESSION['update_offset'] log-tail logic below // works unchanged against the already-active session. if (!isset($_GET['ajax'])) { if (file_exists('/var/log/pi-star/pi-star_modemflash.log')) { $_SESSION['update_offset'] = filesize('/var/log/pi-star/pi-star_modemflash.log'); } else { $_SESSION['update_offset'] = 0; } } if (isset($_GET['ajax'])) { if (!file_exists('/var/log/pi-star/pi-star_modemflash.log')) { exit(); } $handle = fopen('/var/log/pi-star/pi-star_modemflash.log', 'rb'); if (isset($_SESSION['update_offset'])) { fseek($handle, 0, SEEK_END); if ($_SESSION['update_offset'] > ftell($handle)) //log rotated/truncated $_SESSION['update_offset'] = 0; //continue at beginning of the new log $data = stream_get_contents($handle, -1, $_SESSION['update_offset']); $_SESSION['update_offset'] += strlen($data); echo nl2br($data); } else { fseek($handle, 0, SEEK_END); $_SESSION['update_offset'] = ftell($handle); } exit(); } // Get the firmware version if (file_exists('/usr/local/bin/firmware/version.txt')) { $versionData = parse_ini_file('/usr/local/bin/firmware/version.txt', true); } if (isset($versionData['Firmware']['mmdvm_hs_version'])) { $mmdvm_hs_version = $versionData['Firmware']['mmdvm_hs_version']; $dvmega_fw_version = $versionData['Firmware']['dvmega_version']; $rpt_version = $versionData['Firmware']['rpt_version']; $fw_ver_msg = "Latest firmware version(s): Hotspot:". $mmdvm_hs_version. " DV-Mega:".$dvmega_fw_version." Repeater:".$rpt_version."."; } else { $fw_ver_msg = "Unkown (failed to retrieve firmware version)."; } ?> Pi-Star - <?php echo $lang['digital_voice']." ".$lang['dashboard']." - Modem FW ".$lang['update'];?>
Modem Firmware Upgrade Utility

Modem Firmware Upgrade Utility

This tool will attempt to upgrade your selected modem to the latest version available firmware version:

When ready, select your modem type below and click, "Upgrade Modem". Do not interrupt the process or
navigate away from the page while the process is running.

Please understand what you are doing, as well as the risks associated with flashing your modem.

(IMPORTANT: Please note, we are not firmware developers, and we offer no support for firmware.
We provide utilities to update the firmware. For firmware support, you will need to utilise other
support resources from the firmware developers/maintainers or the web.)

'MMDVM_HS_Hat (14.7456MHz TCXO) GPIO', 'hs_hat-12mhz' => 'MMDVM_HS_Hat (12.2880MHz TCXO) GPIO', 'hs_dual_hat' => 'MMDVM_HS_Dual_Hat (14.7456MHz TCXO) GPIO', 'hs_dual_hat-12mhz' => 'MMDVM_HS_Dual_Hat (12.2880MHz TCXO) GPIO', 'zum_rpi' => 'ZUMSpot RPi boards/hotspots GPIO', 'zum_rpi-duplex' => 'ZUMSpot RPi duplex GPIO board/hotspots', 'zum_usb' => 'ZUMspot USB stick', 'zum_libre' => 'ZUMspot Libre Kit or generic MMDVM_HS board', 'skybridge' => 'SkyBridge board/hotspots (14.7456MHz TCXO) GPIO', 'euronode' => 'DVMega-EuroNode hotspots (14.7456MHz TCXO) GPIO', 'nanodv_npi' => 'NANO_DV NPi GPIO by BG4TGO', 'nanodv_usb' => 'NANO_DV USB by BG4TG', 'hs_hat_ambe' => 'HS_HAT_AMBE (14.7456MHz TCXO) GPIO', 'hs_hat_lonestar-usb' => 'LoneStar LS MMDVM USB (14.7456MHz TCXO) USB', 'hs_hat_generic' => 'MMDVM_HS_GENERIC (14.7456MHz TCXO) GPIO', 'hs_hat_generic_duplex' => 'MMDVM_HS_GENERIC_DUPLEX (14.7456MHz TCXO) GPIO', 'hs_hat_generic_duplex-usb' => 'MMDVM_HS_GENERIC_DUPLEX (14.7456MHz TCXO) USB', 'hs_hat_nano_hotspot' => 'Nano_hotSPOT by BI7JTA (14.7456MHz TCXO) GPIO', 'hs_hat_nano_hotspot-duplex' => 'Nano_hotSPOT Dual by VR2VYE & BI7JTA (14.7456MHz TCXO) GPIO', 'dvmega_gpio' => 'DV-Mega Raspberry Pi Hat (Single or Dual Band) GPIO', 'dvmega_usb_uno' => 'DV-Mega Arduino Uno Shield USB (ttyUSB0)', 'dvmega_usb_mega' => 'DV-Mega Arduino Mega Shield USB (ttyUSB0)', 'rpt_nucleo-64' => 'Repeater - Nucleo64 F446RE GPIO', 'rpt_nucleo-144' => 'Repeater - Nucleo144 F767ZI GPIO', 'rpt_mmdvm_hat-0.2' => 'Repeater - MMDVM_RPT_Hat 0.2 GPIO', 'rpt_mmdvm_hat-0.3' => 'Repeater - MMDVM_RPT_Hat 0.3 GPIO', 'rpt_zum-0.9' => 'Repeater - ZUM Radio MMDVM for Pi v0.9 GPIO', 'rpt_zum-1.0' => 'Repeater - ZUM Radio MMDVM for Pi v1.0 GPIO', 'rpt_builder_v3' => 'Repeater - Repeater Builder STM32_DVM_PiHat V3 GPIO', 'rpt_builder_v4' => 'Repeater - Repeater Builder STM32_DVM_PiHat V4 GPIO', 'rpt_builder_v5' => 'Repeater - Repeater Builder STM32_DVM_PiHat V5 GPIO', //'mmdvm_pi-f7' => 'MMDVM Pi F7 Board 460800 baud (12.000MHz TCXO) GPIO', //'mmdvm_pi-f4' => 'MMDVM Pi F4 Board 460800 baud (12.000MHz TCXO) GPIO', ]; $output = shell_exec('sudo /usr/local/sbin/pistar-modemupgrade list'); if ($output !== null) { // Split the output into an array of options $options = explode("\n", trim($output)); // Create the select element echo '

'; echo csrf_field_html(); echo ''; echo ''; echo ''; echo '

'; } else { echo '

Error executing the command.

'; } ?>
Modem Flash/Upgrade Output
Starting FW Upgrade, please wait...