diff --git a/src/flashFormatter/C33FlashFormatter.cpp b/src/flashFormatter/C33FlashFormatter.cpp index da57b2f..f8bb404 100644 --- a/src/flashFormatter/C33FlashFormatter.cpp +++ b/src/flashFormatter/C33FlashFormatter.cpp @@ -7,68 +7,16 @@ */ #if defined(ARDUINO_PORTENTA_C33) #include "C33FlashFormatter.h" -#define BD_ERROR_OK 0 +#include "certificates.h" -C33FlashFormatter::C33FlashFormatter(): - _root(BlockDevice::get_default_instance()), - _sys_bd(_root, 1), - _sys_fs("sys"), - _user_bd(_root, 2), - _kvStore_bd(_root, 3) { -} - -bool C33FlashFormatter::checkPartition() +bool C33FlashFormatter::checkWiFiData() { - if (_root->init() != BD_ERROR_OK) - { - return false; - } - - if (_sys_bd.init() != BD_ERROR_OK || _sys_fs.mount(&_sys_bd) != FR_OK) - { - return false; - } - - _sys_fs.unmount(); - _sys_bd.deinit(); - - if (_user_bd.init() != BD_ERROR_OK) - { - return false; - } - - _user_bd.deinit(); - - if (_kvStore_bd.init() != BD_ERROR_OK) - { - return false; - } - - _kvStore_bd.deinit(); - _root->deinit(); - - return true; + return checkFile("/wlan", "cacert.pem"); } -bool C33FlashFormatter::formatPartition() { - MBRBlockDevice::partition(_root, 1, 0x0B, 0, 5 * 1024 * 1024); - MBRBlockDevice::partition(_root, 2, 0x0B, 5 * 1024 * 1024, 15 * 1024 * 1024); - MBRBlockDevice::partition(_root, 3, 0x0B, 15 * 1024 * 1024, 16 * 1024 * 1024); - - int err = _sys_fs.reformat(&_sys_bd); - if (err) { - return false; - } - - _sys_fs.unmount(); - _user_data_fs = new LittleFileSystem("user"); - err = _user_data_fs->reformat(&_user_bd); - if (err) { - return false; - } - _user_data_fs->unmount(); - _root->deinit(); - return true; +bool C33FlashFormatter::restoreWifiData() +{ + return writeFile("/wlan", "cacert.pem", cacert_pem, cacert_pem_len, 128); } #endif diff --git a/src/flashFormatter/C33FlashFormatter.h b/src/flashFormatter/C33FlashFormatter.h index a13d388..355ae00 100644 --- a/src/flashFormatter/C33FlashFormatter.h +++ b/src/flashFormatter/C33FlashFormatter.h @@ -6,23 +6,10 @@ file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #pragma once -#include "FlashFormatterBase.h" -#include "BlockDevice.h" -#include "MBRBlockDevice.h" -#include "LittleFileSystem.h" -#include "FATFileSystem.h" +#include "FlashFormatterQSPI.h" -class C33FlashFormatter : public FlashFormatterClass { -public: - C33FlashFormatter(); -protected: - bool checkPartition() override; - bool formatPartition() override; +class C33FlashFormatter : public FlashFormatterQSPI { private: - BlockDevice* _root; - MBRBlockDevice _sys_bd; - MBRBlockDevice _user_bd; - FATFileSystem _sys_fs; - FileSystem * _user_data_fs; - MBRBlockDevice _kvStore_bd; + bool checkWiFiData() override; + bool restoreWifiData() override; }; diff --git a/src/flashFormatter/FlashFormatter.h b/src/flashFormatter/FlashFormatter.h index 5e52a97..ccacf2e 100644 --- a/src/flashFormatter/FlashFormatter.h +++ b/src/flashFormatter/FlashFormatter.h @@ -15,5 +15,5 @@ using FlashFormatter = MBEDH7FlashFormatter; using FlashFormatter = C33FlashFormatter; #else #include "FlashFormatterBase.h" -using FlashFormatter = FlashFormatterClass; +using FlashFormatter = FlashFormatterBase; #endif diff --git a/src/flashFormatter/FlashFormatterBase.h b/src/flashFormatter/FlashFormatterBase.h index f8f83be..8ed0e3b 100644 --- a/src/flashFormatter/FlashFormatterBase.h +++ b/src/flashFormatter/FlashFormatterBase.h @@ -8,9 +8,9 @@ #pragma once #include -class FlashFormatterClass { +class FlashFormatterBase { public: - virtual ~FlashFormatterClass() = default; + virtual ~FlashFormatterBase() = default; virtual bool checkAndFormatPartition() { if(checkPartition()){ return true; @@ -22,8 +22,6 @@ class FlashFormatterClass { return checkPartition(); } - -protected: virtual bool checkPartition() { return true; }; virtual bool formatPartition() { return true; }; }; diff --git a/src/flashFormatter/FlashFormatterQSPI.cpp b/src/flashFormatter/FlashFormatterQSPI.cpp new file mode 100644 index 0000000..43d9ce7 --- /dev/null +++ b/src/flashFormatter/FlashFormatterQSPI.cpp @@ -0,0 +1,190 @@ +/* + Copyright (c) 2025 Arduino SA + + This Source Code Form is subject to the terms of the Mozilla Public + License, v. 2.0. If a copy of the MPL was not distributed with this + file, You can obtain one at http://mozilla.org/MPL/2.0/. +*/ +#if defined(ARDUINO_PORTENTA_H7_M7) || defined(ARDUINO_NICLA_VISION) \ + || defined(ARDUINO_OPTA) || defined(ARDUINO_GIGA) || defined(ARDUINO_PORTENTA_C33) +#include "FlashFormatterQSPI.h" + +FlashFormatterQSPI::FlashFormatterQSPI(): +_root(BlockDevice::get_default_instance()), +_wifiData(_root, 1), +_wifiFS("wlan"), +_otaData(_root, 2), +_otaFS("fs"), +_kvstoreData(_root, 3), +_runtimeData(_root, 4), +_runtimeFS("opt"), +_runtimeFormat(false) +{ +} + +bool FlashFormatterQSPI::checkPartition() +{ + if (_root->init() != BD_ERROR_OK) { + return false; + } + + /* check WiFi partition */ + if (_wifiData.init() != BD_ERROR_OK || _wifiFS.mount(&_wifiData) != 0) { + return false; + } + + if (!checkWiFiData()) { + return false; + } + Serial.println("WiFi partition size: " + String((unsigned int)_wifiData.size())); + + _wifiFS.unmount(); + _wifiData.deinit(); + + /* check OTA partition */ + if (_otaData.init() != BD_ERROR_OK || _otaFS.mount(&_otaData) != 0) { + return false; + } + + if (_otaData.size() < 5 * 1024 * 1024) { + return false; + } + + _otaFS.unmount(); + _otaData.deinit(); + + /* check KVStore partition */ + if (_kvstoreData.init() != BD_ERROR_OK) { + return false; + } + + if (_kvstoreData.size() < 1 * 1024 * 1024) { + return false; + } + Serial.println("KVStore partition size: " + String((unsigned int)_kvstoreData.size())); + _kvstoreData.deinit(); + + /* check PLC runtime partition */ + if (_runtimeData.init() != BD_ERROR_OK) { + Serial.println("Failed to init optData"); + _runtimeFormat = true; + return false; + } + Serial.println("Runtime partition size: " + String((unsigned int)_runtimeData.size())); + _runtimeData.deinit(); + + _root->deinit(); + return true; +} + +bool FlashFormatterQSPI::formatPartition() { + + if (_root->init() != BD_ERROR_OK) { + Serial.println("Failed to init root"); + return false; + } + + if (_root->erase(0x0, _root->get_erase_size()) != BD_ERROR_OK) { + Serial.println("Failed to erase root"); + return false; + } + + MBRBlockDevice::partition(_root, 1, 0x0B, 0, 1 * 1024 * 1024); + if (_wifiFS.reformat(&_wifiData) != 0) { + Serial.println("Failed to format wifiFS"); + return false; + } + + if (!restoreWifiData()) { + Serial.println("Failed to restore wifi data"); + return false; + } + _wifiFS.unmount(); + + MBRBlockDevice::partition(_root, 2, 0x0B, 1 * 1024 * 1024, 6 * 1024 * 1024); + if (_otaFS.reformat(&_otaData) != 0) { + Serial.println("Failed to format otaFS"); + return false; + } + _otaFS.unmount(); + + MBRBlockDevice::partition(_root, 3, 0x0B, 6 * 1024 * 1024, 7 * 1024 * 1024); + + if (_runtimeFormat) { + MBRBlockDevice::partition(_root, 4, 0x0B, 7 * 1024 * 1024, 14 * 1024 * 1024); + if (_runtimeFS.reformat(&_runtimeData) != 0) { + Serial.println("Failed to format optFS"); + return false; + } + _runtimeFS.unmount(); + } + + _root->deinit(); + + return true; +} + +bool FlashFormatterQSPI::checkFile(const char* partition, const char* filename) +{ + DIR *dir; + struct dirent *ent; + + if ((dir = opendir(partition)) == NULL) { + return false; + } + + bool foundFile = false; + while ((ent = readdir (dir)) != NULL) { + String fullname = String(partition) + "/" + String(ent->d_name); + if (fullname == String(partition) + "/" + String(filename)) { + foundFile = true; + break; + } + } + closedir (dir); + return foundFile; +} + +bool FlashFormatterQSPI::writeFile(const char* partition, const char* filename, const uint8_t* data, size_t size, size_t maxChunkSize) +{ + String fullname = String(partition) + "/" + String(filename); + FILE* fp = fopen(fullname.c_str(), "wb"); + if (!fp) { + return false; + } + + size_t chunkSize = maxChunkSize; + size_t byteCount = 0; + while (byteCount < size) { + if (byteCount + chunkSize > size) + chunkSize = size - byteCount; + int ret = fwrite(&data[byteCount], chunkSize, 1, fp); + if (ret != 1) { + fclose(fp); + return false; + } + byteCount += chunkSize; + } + size_t written = ftell(fp); + fclose(fp); + + return written == size; +} + +bool FlashFormatterQSPI::writeFlash(const uint8_t* data, size_t size, size_t offset, size_t maxChunkSize) +{ + size_t chunkSize = maxChunkSize; + size_t byteCount = 0; + while (byteCount < size) { + if(byteCount + chunkSize > size) + chunkSize = size - byteCount; + int ret = _root->program(data, offset + byteCount, chunkSize); + if (ret != 0) { + return false; + } + byteCount += chunkSize; + } + return true; +} + +#endif diff --git a/src/flashFormatter/FlashFormatterQSPI.h b/src/flashFormatter/FlashFormatterQSPI.h new file mode 100644 index 0000000..c86d006 --- /dev/null +++ b/src/flashFormatter/FlashFormatterQSPI.h @@ -0,0 +1,43 @@ +/* + Copyright (c) 2025 Arduino SA + + This Source Code Form is subject to the terms of the Mozilla Public + License, v. 2.0. If a copy of the MPL was not distributed with this + file, You can obtain one at http://mozilla.org/MPL/2.0/. +*/ +#pragma once +#include "FlashFormatterBase.h" +#include +#include +#include +#include + +#if !defined(ARDUINO_PORTENTA_C33) +using namespace mbed; +#endif + +class FlashFormatterQSPI : public FlashFormatterBase { +public: + FlashFormatterQSPI(); + bool checkPartition() override; + bool formatPartition() override; + +protected: + bool checkFile(const char* partition, const char* filename); + bool writeFile(const char* partition, const char* filename, const uint8_t* data, size_t size, size_t maxChunkSize); + bool writeFlash(const uint8_t* data, size_t size, size_t offset, size_t maxChunkSize); + +private: + virtual bool checkWiFiData() { return true; }; + virtual bool restoreWifiData() { return true; }; + BlockDevice* _root; + MBRBlockDevice _wifiData; + FATFileSystem _wifiFS; + MBRBlockDevice _otaData; + FATFileSystem _otaFS; + MBRBlockDevice _kvstoreData; + MBRBlockDevice _runtimeData; + FATFileSystem _runtimeFS; + bool _runtimeFormat; +}; + diff --git a/src/flashFormatter/H7FlashFormatter.cpp b/src/flashFormatter/H7FlashFormatter.cpp index 005d95c..a2989a9 100644 --- a/src/flashFormatter/H7FlashFormatter.cpp +++ b/src/flashFormatter/H7FlashFormatter.cpp @@ -8,171 +8,36 @@ #if defined(ARDUINO_PORTENTA_H7_M7) || defined(ARDUINO_NICLA_VISION) \ || defined(ARDUINO_OPTA) || defined(ARDUINO_GIGA) #include "H7FlashFormatter.h" -#include "wiced_resource.h" #include "certificates.h" -MBEDH7FlashFormatter::MBEDH7FlashFormatter(): -_root(mbed::BlockDevice::get_default_instance()), -_wifi_data(_root, 1), -_wifi_data_fs("wlan"), -_ota_data(_root, 2), -_ota_data_fs("fs"), -_kvstore_data(_root, 3) +bool MBEDH7FlashFormatter::checkWiFiData() { -} - -bool MBEDH7FlashFormatter::checkPartition() -{ - if (_root->init() != mbed::BD_ERROR_OK) - { - return false; - } - - if (!checkWifiPartition()) - { - return false; - } - - if (_ota_data.init() != mbed::BD_ERROR_OK || _ota_data_fs.mount(&_ota_data) != 0) - { - return false; - } - - if (_ota_data.size() < 5 * 1024 * 1024) - { - return false; - } - _ota_data_fs.unmount(); - _ota_data.deinit(); - - if (_kvstore_data.init() != mbed::BD_ERROR_OK) - { - return false; - } - - _kvstore_data.deinit(); - _root->deinit(); - - return true; -} - -bool MBEDH7FlashFormatter::formatPartition() { - _root->erase(0x0, _root->get_erase_size()); - /* Default partitioning of OPTA boards includes a 4th partition for PLC ide runtime - * This partition is not used in the context of ArduinoCloud and is not needed, - * but we try to preserve the default partitioning for compatibility. - */ -#if defined(ARDUINO_OPTA) - mbed::MBRBlockDevice::partition(_root, 1, 0x0B, 0, 1024 * 1024); - mbed::MBRBlockDevice::partition(_root, 2, 0x0B, 1024 * 1024, 6 * 1024 * 1024); - mbed::MBRBlockDevice::partition(_root, 3, 0x0B, 6 * 1024 * 1024, 7 * 1024 * 1024); -#else - mbed::MBRBlockDevice::partition(_root, 1, 0x0B, 0, 1024 * 1024); - mbed::MBRBlockDevice::partition(_root, 2, 0x0B, 1024 * 1024, 13 * 1024 * 1024); - mbed::MBRBlockDevice::partition(_root, 3, 0x0B, 13 * 1024 * 1024, 14 * 1024 * 1024); -#endif - - if(_ota_data_fs.mount(&_ota_data) != 0) { - if(_ota_data_fs.reformat(&_ota_data) != 0) { - return false; - } - }else { - _ota_data_fs.unmount(); - } - - if(!formatWifiPartition()) { + bool ret = false; + ret = checkFile("/wlan", "cacert.pem"); + if (!ret) { return false; } - _root->deinit(); - return true; -} - -long MBEDH7FlashFormatter::getFileSize(FILE *fp) { - fseek(fp, 0, SEEK_END); - int size = ftell(fp); - fseek(fp, 0, SEEK_SET); - return size; + ret = checkFile("/wlan", "4343WA1.BIN"); + return ret; } -bool MBEDH7FlashFormatter::checkWifiPartition() { - int err = _wifi_data_fs.mount(&_wifi_data); - if (err) { +bool MBEDH7FlashFormatter::restoreWifiData() +{ + bool ret = false; + extern const unsigned char wifi_firmware_image_data[]; + ret = writeFile("/wlan", "4343WA1.BIN", wifi_firmware_image_data, 421098, 1024); + if (!ret) { return false; } - DIR *dir; - struct dirent *ent; - - - if ((dir = opendir("/wlan")) == NULL) { + ret = writeFile("/wlan", "cacert.pem", cacert_pem, cacert_pem_len, 128); + if (!ret) { return false; } - bool found = false; - while ((ent = readdir (dir)) != NULL) { - String fullname = "/wlan/" + String(ent->d_name); - if (fullname == "/wlan/4343WA1.BIN") { - found = true; - break; - } - } - - closedir (dir); - _wifi_data_fs.unmount(); - return found; -} - -bool MBEDH7FlashFormatter::formatWifiPartition() { - _wifi_data_fs.reformat(&_wifi_data); - extern const unsigned char wifi_firmware_image_data[]; - extern const resource_hnd_t wifi_firmware_image; - FILE* fp = fopen("/wlan/4343WA1.BIN", "wb"); - const int file_size = 421098; - int chunck_size = 1024; - int byte_count = 0; - - while (byte_count < file_size) { - if(byte_count + chunck_size > file_size) - chunck_size = file_size - byte_count; - int ret = fwrite(&wifi_firmware_image_data[byte_count], chunck_size, 1, fp); - if (ret != 1) { - return false; - } - byte_count += chunck_size; - } - fclose(fp); - - chunck_size = 1024; - byte_count = 0; const uint32_t offset = 15 * 1024 * 1024 + 1024 * 512; - - while (byte_count < file_size) { - if(byte_count + chunck_size > file_size) - chunck_size = file_size - byte_count; - int ret = _root->program(wifi_firmware_image_data, offset + byte_count, chunck_size); - if (ret != 0) { - return false; - } - byte_count += chunck_size; - } - - chunck_size = 128; - byte_count = 0; - fp = fopen("/wlan/cacert.pem", "wb"); - - while (byte_count < cacert_pem_len) { - if(byte_count + chunck_size > cacert_pem_len) - chunck_size = cacert_pem_len - byte_count; - int ret = fwrite(&cacert_pem[byte_count], chunck_size, 1 ,fp); - if (ret != 1) { - return false; - } - byte_count += chunck_size; - } - - fclose(fp); - _wifi_data_fs.unmount(); - return true; + ret = writeFlash(wifi_firmware_image_data, 421098, offset, 1024); + return ret; } #endif diff --git a/src/flashFormatter/H7FlashFormatter.h b/src/flashFormatter/H7FlashFormatter.h index 5cf76ba..95ee659 100644 --- a/src/flashFormatter/H7FlashFormatter.h +++ b/src/flashFormatter/H7FlashFormatter.h @@ -6,28 +6,10 @@ file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #pragma once -#include "FlashFormatterBase.h" -#include -#include "MBRBlockDevice.h" -#include "LittleFileSystem.h" -#include "FATFileSystem.h" +#include "FlashFormatterQSPI.h" -class MBEDH7FlashFormatter : public FlashFormatterClass { -public: - MBEDH7FlashFormatter(); - -protected: - bool checkPartition() override; - bool formatPartition() override; +class MBEDH7FlashFormatter : public FlashFormatterQSPI { private: - mbed::BlockDevice* _root; - mbed::MBRBlockDevice _wifi_data; - mbed::FATFileSystem _wifi_data_fs; - mbed::MBRBlockDevice _ota_data; - mbed::FATFileSystem _ota_data_fs; - mbed::MBRBlockDevice _kvstore_data; - - long getFileSize(FILE *fp); - bool checkWifiPartition(); - bool formatWifiPartition(); + bool checkWiFiData() override; + bool restoreWifiData() override; };