Skip to content

Commit

Permalink
partition manager tweaks
Browse files Browse the repository at this point in the history
  • Loading branch information
tobozo committed Oct 11, 2023
1 parent dd67460 commit c925d1a
Show file tree
Hide file tree
Showing 11 changed files with 216 additions and 57 deletions.
1 change: 0 additions & 1 deletion .github/workflows/PlatformioBuild.yml
Original file line number Diff line number Diff line change
Expand Up @@ -105,4 +105,3 @@ jobs:
# install local version of the library
pio pkg install -e test --no-save --library file://$(realpath ../../../)
pio run -e test
7 changes: 4 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -72,11 +72,12 @@ All those are available in the [Arduino Library Manager](https://www.arduinolibr

<br />

**2) Download the [SD-Content :floppy_disk:](https://github.com/tobozo/M5Stack-SD-Updater/releases/download/v0.4.1/SD-Apps-Folder.zip) folder from the release page and unzip it into the root of the SD Card.** Then put the SD Card into the M5Stack. This zip file comes preloaded with [precompiled apps](https://github.com/tobozo/M5Stack-SD-Updater/tree/master/examples/M5Stack-SD-Menu/SD-Apps) and the relative meta information for the menu.
**outdated binaries**
~~**2) Download the [SD-Content :floppy_disk:](https://github.com/tobozo/M5Stack-SD-Updater/releases/download/v0.4.1/SD-Apps-Folder.zip) folder from the release page and unzip it into the root of the SD Card.** Then put the SD Card into the M5Stack. This zip file comes preloaded with [precompiled apps](https://github.com/tobozo/M5Stack-SD-Updater/tree/master/examples/M5Stack-SD-Menu/SD-Apps) and the relative meta information for the menu.~~

<br />

**3) Compile and flash the `M5Stack-SD-Menu.ino` example.** <br />
**2) Compile and flash the `M5Stack-SD-Menu.ino` example.** <br />
This sketch is the **menu** app. It shoul reside in the root directory of a micro SD card for persistence and also executed once.

Once flashed it will **copy itself** on OTA2 partition and on the SDCard, then rolled back and executed from the OTA2 partition.
Expand All @@ -86,7 +87,7 @@ Thanks to @Lovyan03 this self-propagation logic is very convenient: by residing

<br />

**4) Make application sketches compatible with the SD-Updater Menu .** <br />
**3) Make application sketches compatible with the SD-Updater Menu .** <br />


The snippet of code in the `M5Stack-SDLoader-Snippet.ino` sketch can be used as a model to make any ESP32 sketch compatible with the SD-Updater menu.
Expand Down
62 changes: 44 additions & 18 deletions examples/M5Stack-FW-Menu/src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -401,7 +401,8 @@ void menuItemLoadFW()
{
auto ota_num = slotPicker("Run Flash App", false); // load apps
if( ota_num > 0 ) {
SDUpdater::_message("Booting partition");
String msg = "Booting partition " + String(ota_num);
SDUpdater::_message(msg);
if( !Flash::bootPartition( ota_num ) ) {
SDUpdater::_error("Partition unbootable :(");
}
Expand Down Expand Up @@ -468,10 +469,10 @@ void menuItemPartitionsInfo()
M5.Lcd.printf("Slot: %d (%s)\n", nvs_part->ota_num, AppName.c_str());
M5.Lcd.printf("Type: 0x%02x\n", part->type);
M5.Lcd.printf("SType: 0x%02x\n", part->subtype);
M5.Lcd.printf("Addr: 0x%06x\n", part->address);
M5.Lcd.printf("Size: %d\n", part->size);
M5.Lcd.printf("Addr: 0x%06lx\n", part->address);
M5.Lcd.printf("Size: %lu\n", part->size);
M5.Lcd.printf("Used: %s\n", meta.image_len>0 ? String(meta.image_len).c_str() : "n/a");
M5.Lcd.printf("Desc: %s\n", nvs_part->desc[0]!=0?nvs_part->desc:"none");
//M5.Lcd.printf("Desc: %s\n", nvs_part->desc[0]!=0?nvs_part->desc:"none");

M5.Lcd.clearClipRect();

Expand Down Expand Up @@ -724,7 +725,7 @@ void printFlashPartition( Flash::Partition_t* sdu_partition )
}
}

Serial.printf("%-8s 0x%02x 0x%02x 0x%06x %8d %8s %8s %8s\n",
Serial.printf("%-8s 0x%02x 0x%02x 0x%06lx %8lu %8s %8s %8s\n",
String( part.label ).c_str(),
part.type,
part.subtype,
Expand All @@ -746,6 +747,7 @@ void lsFlashPartitions()
}
}

#include "base64.h"

void lsNVSpartitions()
{
Expand All @@ -758,6 +760,36 @@ void lsNVSpartitions()
Serial.printf("[%d] %s slot\n", nvs_part->ota_num, i==0?"Reserved":"Available" );
}
}
Serial.println("\nPartitions as CSV:");


size_t blob_size = (sizeof(NVS::PartitionDesc_t)*NVS::Partitions.size());
NVS::blob_partition_t *bPart = new NVS::blob_partition_t(blob_size);

if( !bPart->blob) {
log_e("Can't allocate %d bytes for blob", blob_size );
return;
}
size_t idx = 0;
for( int i=0; i<NVS::Partitions.size(); i++ ) {
idx = i*sizeof(NVS::PartitionDesc_t);
auto part = &NVS::Partitions[i];
memcpy( &bPart->blob[idx], part, sizeof(NVS::PartitionDesc_t) );
}


// https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/storage/nvs_partition_gen.html#csv-file-format
String b64 = base64::encode( (const uint8_t*)bPart->blob, blob_size );
Serial.printf("Sizeof PartitionDesc_t: %d bytes\n", sizeof(NVS::PartitionDesc_t) );
Serial.printf("Sizeof NVS blob: %d bytes\n", blob_size );
Serial.printf("Sizeof Base64: %d bytes\n", b64.length() );
Serial.println();
Serial.println("key,type,encoding,value");// <-- column header
Serial.printf("%s,namespace,,\n", NVS::PARTITION_NS ); // <-- First entry should be of type "namespace"
Serial.printf("%s,data,base64,%s\n", NVS::PARTITION_KEY, b64.c_str() );
Serial.println();
// key1,data,u8,1
// key2,file,string,/path/to/file
}


Expand All @@ -775,14 +807,15 @@ bool checkFactoryStickyPartition()
return false;
}

SDUpdater::_message("Checking factory...");
// will compare running partition with factory, and update if necessary
if( SDUpdater::saveSketchToFactory() ) {
// sketch was just saved to factory partition, mark it as bootable and restart
Flash::loadFactory(); // will trigger a restart on success
log_e("Switching to factory app failed :-(");
return false;
}

SDUpdater::_message("Checking partitions...");
if( !NVS::getPartitions() ) {
log_w("Partitions not found on NVS, creating"); // first visit!
PartitionManager::createPartitions();
Expand Down Expand Up @@ -812,7 +845,9 @@ bool checkOTAStickyPartition()

const esp_partition_t* last_partition = esp_ota_get_next_update_partition(NULL);

if( !last_partition ) return false;
if( !last_partition ) {
return false;
}

const esp_partition_t* next_partition = Flash::getNextAvailPartition( last_partition->type, last_partition->subtype );

Expand All @@ -830,15 +865,12 @@ bool checkOTAStickyPartition()
}

return check_for_migration;

}







void setup()
{
using namespace AppTheme;
Expand All @@ -860,7 +892,7 @@ void setup()

SDU_UI::resetScroll();

SDUpdater::_message("Booting factory...");
//SDUpdater::_message("Booting factory...");

if( ! checkFactoryStickyPartition() ) {
// print partitions for debug
Expand All @@ -883,12 +915,6 @@ void setup()

void loop()
{
auto ota_num = slotPicker("Run Application", false); // load apps
if( ota_num > 0 ) {
SDUpdater::_message("Booting partition");
if( !Flash::bootPartition( ota_num ) ) {
SDUpdater::_error("Partition unbootable :(");
}
}
menuItemLoadFW();
launcherPicker();
}
2 changes: 1 addition & 1 deletion src/M5StackUpdater.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@
#define resetReason (int)rtc_get_reset_reason(0)

// use `#define SDU_NO_PRAGMAS` to disable duplicate pragma messages
#if !defined SDU_NO_PRAGMAS
#if !defined SDU_NO_PRAGMAS && CORE_DEBUG_LEVEL>=ARDUHAL_LOG_LEVEL_ERROR
#define SDU_STRINGIFY(a) #a
#define SDU_PRAGMA_MESSAGE(msg) \
_Pragma( SDU_STRINGIFY( message msg ) )
Expand Down
30 changes: 17 additions & 13 deletions src/PartitionManager/NVS/NVSUtils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -81,13 +81,15 @@ namespace SDUpdaterNS
}




bool getPartitions()
{
if( Partitions.size()>0 )
Partitions.clear();
size_t blob_size;
char* out = nullptr;
bool ret = false;
blob_partition_t *bPart = nullptr;
auto err = nvs_open(PARTITION_NS, NVS_READONLY, &handle);
if( err != ESP_OK ) {
log_i("NVS Namespace not created yet");
Expand All @@ -100,22 +102,23 @@ namespace SDUpdaterNS
goto _nvs_close;
}

out = (char*)calloc(blob_size+1, sizeof(char));
if (!out ) {
log_e("Could not alloc %d bytes", blob_size+1 );
bPart = new blob_partition_t( blob_size );
if (!bPart->blob ) {
log_e("Could not alloc %d bytes", blob_size );
goto _nvs_close;
}
err = nvs_get_blob(handle, PARTITION_KEY, out, &blob_size);

err = nvs_get_blob(handle, PARTITION_KEY, bPart->blob, &blob_size);
if( err != ESP_OK ) {
log_e("Could not read blob");
goto _nvs_close;
}

ret = parsePartitions( out, blob_size-1 );
free( out );
ret = parsePartitions( bPart->blob, blob_size );

_nvs_close:
nvs_close( handle );
if( bPart!=nullptr ) delete bPart;
return ret;
}

Expand Down Expand Up @@ -145,17 +148,18 @@ namespace SDUpdaterNS
bool ret = true;
if( Partitions.size() > 0 ) {
log_d("Saving partitions");
size_t blob_size = (sizeof(PartitionDesc_t)*Partitions.size()) + 1;
char* blob = (char*)calloc(blob_size, sizeof(char));
if( !blob) {
size_t blob_size = (sizeof(PartitionDesc_t)*Partitions.size());
blob_partition_t *bPart = new blob_partition_t(blob_size);

if( !bPart->blob) {
log_e("Can't allocate %d bytes for blob", blob_size );
return false;
}
size_t idx = 0;
for( int i=0; i<Partitions.size(); i++ ) {
idx = i*sizeof(PartitionDesc_t);
auto part = &Partitions[i];
memcpy( &blob[idx], part, sizeof(PartitionDesc_t) );
memcpy( &bPart->blob[idx], part, sizeof(PartitionDesc_t) );
}

auto err = nvs_open(PARTITION_NS, NVS_READWRITE, &handle);
Expand All @@ -164,7 +168,7 @@ namespace SDUpdaterNS
return false;
}

err = nvs_set_blob(handle, PARTITION_KEY, blob, blob_size);
err = nvs_set_blob(handle, PARTITION_KEY, bPart->blob, blob_size);
if( err != ESP_OK ) {
log_e("Failed to save blob");
ret = false;
Expand All @@ -174,7 +178,7 @@ namespace SDUpdaterNS
}

nvs_close( handle );
free( blob );
delete bPart;
}
return ret;
}
Expand Down
23 changes: 22 additions & 1 deletion src/PartitionManager/NVS/NVSUtils.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,28 @@ namespace SDUpdaterNS
size_t bin_size{0}; // firmware size
uint8_t digest[32]{0}; // firmware digest
char name[40]{0}; // firmware name
char desc[40]{0}; // firmware desc
//char desc[40]{0}; // firmware desc
};

struct blob_partition_t
{
char* blob{nullptr};
bool needs_free{false};
blob_partition_t() : blob(nullptr), needs_free(false) { }
blob_partition_t( size_t blob_size ) : blob(nullptr), needs_free(false)
{
this->blob = (char*)calloc(blob_size+1, sizeof(char));
if (!this->blob ) {
log_e("Could not alloc %d bytes", blob_size );
} else {
needs_free = true;
}
}
~blob_partition_t()
{
if( needs_free )
free(this->blob);
}
};

extern nvs_handle_t handle;
Expand Down
Loading

0 comments on commit c925d1a

Please sign in to comment.