Skip to content

Commit

Permalink
Support download SafeBoot image from URL
Browse files Browse the repository at this point in the history
  • Loading branch information
mathieucarbou committed Aug 12, 2024
1 parent 9d9f1d1 commit 5a8fc4b
Show file tree
Hide file tree
Showing 11 changed files with 120 additions and 6 deletions.
5 changes: 4 additions & 1 deletion .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ concurrency:

jobs:
build:
name: Build
name: Build safeboot-${{ matrix.board }}.bin
runs-on: ubuntu-latest
strategy:
matrix:
Expand Down Expand Up @@ -63,6 +63,7 @@ jobs:
pip install --upgrade platformio
SAFEBOOT_BOARD=${{ matrix.board }} pio run -e safeboot
mv .pio/build/safeboot/safeboot.bin ./safeboot-${{ matrix.board }}.bin
pio run -d test
- name: Upload
uses: actions/upload-artifact@v4
Expand Down Expand Up @@ -103,6 +104,7 @@ jobs:
title: Pre-release Builds
files: |
artifacts/*.bin
tools/factory.py
- name: Changelog
if: ${{ startsWith(github.ref, 'refs/tags/v') }}
Expand All @@ -123,5 +125,6 @@ jobs:
draft: false
files: |
artifacts/*.bin
tools/factory.py
env:
GITHUB_TOKEN: ${{ secrets.ACCESS_TOKEN }}
9 changes: 7 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
# MycilaSafeBoot

[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
[![Continuous Integration](https://github.com/mathieucarbou/MycilaSafeBoot/actions/workflows/ci.yml/badge.svg)](https://github.com/mathieucarbou/MycilaSafeBoot/actions/workflows/ci.yml)
[![PlatformIO Registry](https://badges.registry.platformio.org/packages/mathieucarbou/library/MycilaSafeBoot.svg)](https://registry.platformio.org/libraries/mathieucarbou/MycilaSafeBoot)
[![Continuous Integration](https://github.com/mathieucarbou/MycilaSafeBoot/actions/workflows/build.yml/badge.svg)](https://github.com/mathieucarbou/MycilaSafeBoot/actions/workflows/build.yml)

MycilaSafeBoot is a Web OTA recovery partition for ESP32 / Arduino.

Expand Down Expand Up @@ -126,6 +125,12 @@ board_build.partitions = partitions-4MB-safeboot.csv
custom_safeboot_dir = ../../tools/SafeBoot
```

It is also possible to use a URL to point to a remote safeboot image:

```ini
custom_safeboot_url = https://github.com/mathieucarbou/MycilaSafeBoot/releases/download/latest/safeboot-esp32dev.bin
```

## How to reboot in SafeBoot mode from the app ?

```cpp
Expand Down
3 changes: 1 addition & 2 deletions docs/index.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
# MycilaSafeBoot

[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
[![Continuous Integration](https://github.com/mathieucarbou/MycilaSafeBoot/actions/workflows/ci.yml/badge.svg)](https://github.com/mathieucarbou/MycilaSafeBoot/actions/workflows/ci.yml)
[![PlatformIO Registry](https://badges.registry.platformio.org/packages/mathieucarbou/library/MycilaSafeBoot.svg)](https://registry.platformio.org/libraries/mathieucarbou/MycilaSafeBoot)
[![Continuous Integration](https://github.com/mathieucarbou/MycilaSafeBoot/actions/workflows/build.yml/badge.svg)](https://github.com/mathieucarbou/MycilaSafeBoot/actions/workflows/build.yml)

MycilaSafeBoot is a Web OTA recovery partition for ESP32 / Arduino.

Expand Down
3 changes: 2 additions & 1 deletion examples/App/platformio.ini
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,8 @@ lib_deps =

extra_scripts = post:../../tools/factory.py
board_build.partitions = partitions-4MB-safeboot.csv
custom_safeboot_dir = ../..
# custom_safeboot_dir = ../..
custom_safeboot_url = https://github.com/mathieucarbou/MycilaSafeBoot/releases/download/latest/safeboot-esp32dev.bin

; --------------------------------------------------------------------
; ENVIRONMENTs
Expand Down
4 changes: 4 additions & 0 deletions test/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
.DS_Store
/.pio
/.vscode
/logs
3 changes: 3 additions & 0 deletions test/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# SafeBoot Example

Please refer to the SafeBoot tool documentation
7 changes: 7 additions & 0 deletions test/partitions-4MB-safeboot.csv
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# Name, Type, SubType, Offset, Size, Flags
nvs, data, nvs, 0x9000, 0x5000,
otadata, data, ota, 0xE000, 0x2000,
safeboot, app, factory, 0x10000, 0xA0000,
app, app, ota_0, 0xB0000, 0x330000,
fs, data, spiffs, 0x3E0000, 0x10000,
coredump, data, coredump, 0x3F0000, 0x10000,
7 changes: 7 additions & 0 deletions test/partitions-8MB-safeboot.csv
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# Name, Type, SubType, Offset, Size, Flags
nvs, data, nvs, 0x9000, 0x5000,
otadata, data, ota, 0xE000, 0x2000,
safeboot, app, factory, 0x10000, 0xA0000,
app, app, ota_0, 0xB0000, 0x730000,
fs, data, spiffs, 0x7E0000, 0x10000,
coredump, data, coredump, 0x7F0000, 0x10000,
36 changes: 36 additions & 0 deletions test/platformio.ini
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
; PlatformIO Project Configuration File
;
; Build options: build flags, source filter
; Upload options: custom upload port, speed and extra flags
; Library options: dependencies, extra library storages
; Advanced options: extra scripting
;
; Please visit documentation for the other options and examples
; https://docs.platformio.org/page/projectconf.html

[platformio]
name = MyAwesomeApp

[env]
platform = espressif32
framework = arduino
monitor_filters = esp32_exception_decoder, log2file
monitor_speed = 115200
upload_protocol = esptool
lib_compat_mode = strict
lib_ldf_mode = chain
lib_deps =
mathieucarbou/AsyncTCP @ 3.2.4
mathieucarbou/ESPAsyncWebServer @ 3.1.3
mathieucarbou/MycilaSystem @ 2.0.7

extra_scripts = post:../tools/factory.py
board_build.partitions = partitions-4MB-safeboot.csv
custom_safeboot_dir = ..

; --------------------------------------------------------------------
; ENVIRONMENTs
; --------------------------------------------------------------------

[env:esp32dev]
board = esp32dev
39 changes: 39 additions & 0 deletions test/src/main.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
// SPDX-License-Identifier: MIT
/*
* Copyright (C) 2023-2024 Mathieu Carbou
*/
#include <ESPAsyncWebServer.h>
#include <MycilaSystem.h>
#include <WiFi.h>

AsyncWebServer webServer(80);

String getEspID() {
uint32_t chipId = 0;
for (int i = 0; i < 17; i += 8) {
chipId |= ((ESP.getEfuseMac() >> (40 - i)) & 0xff) << i;
}
String espId = String(chipId, HEX);
espId.toUpperCase();
return espId;
}

void setup() {
WiFi.mode(WIFI_AP);
WiFi.softAP(String("MyAwesomeApp-") + getEspID());

webServer.on("/", HTTP_GET, [](AsyncWebServerRequest* request) {
request->send(200, "text/html", "<form method='POST' action='/safeboot' enctype='multipart/form-data'><input type='submit' value='Restart in SafeBoot mode'></form>");
});

webServer.on("/safeboot", HTTP_POST, [](AsyncWebServerRequest* request) {
request->send(200, "text/plain", "Restarting in SafeBoot mode... Look for an Access Point named: SafeBoot-" + getEspID());
Mycila::System.restartFactory("safeboot");
});

webServer.begin();
}

void loop() {
delay(100);
}
10 changes: 10 additions & 0 deletions tools/factory.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

import sys
import os
import urllib.request
from os.path import join, getsize

sys.path.append(join(env.PioPlatform().get_package_dir("tool-esptoolpy")))
Expand All @@ -28,6 +29,7 @@ def generateFactooryImage(source, target, env):

safeboot_offset = 0x10000
safeboot_image = ""

safeboot_project = env.GetProjectOption("custom_safeboot_dir", "")
if safeboot_project != "":
print(
Expand All @@ -42,6 +44,14 @@ def generateFactooryImage(source, target, env):
safeboot_image = join(safeboot_project, ".pio/build/safeboot/safeboot.bin")
if not os.path.isfile(safeboot_image):
raise Exception("SafeBoot image not found: %s" % safeboot_image)

safeboot_url = env.GetProjectOption("custom_safeboot_url", "")
if safeboot_url != "":
print("Downloading SafeBoot image from %s" % safeboot_url)
safeboot_image = env.subst("$BUILD_DIR/safeboot.bin")
urllib.request.urlretrieve(safeboot_url, safeboot_image)
if not os.path.isfile(safeboot_image):
raise Exception("SafeBoot image not found: %s" % safeboot_image)

if fs_offset != 0:
print("Building File System image")
Expand Down

0 comments on commit 5a8fc4b

Please sign in to comment.