Blackbox device type 'file' (SITL) considered working when file handler is available
[inav.git] / src / main / fc / firmware_update.c
blobd6f3f65f62a37951bef6f2bc6c7f6e6151c2a4eb
1 /*
2 * This file is part of INAV.
4 * INAV is free software. You can redistribute this software
5 * and/or modify this software under the terms of the
6 * GNU General Public License as published by the Free Software
7 * Foundation, either version 3 of the License, or (at your option)
8 * any later version.
10 * INAV is distributed in the hope that they will be
11 * useful, but WITHOUT ANY WARRANTY; without even the implied
12 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13 * See the GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this software.
18 * If not, see <http://www.gnu.org/licenses/>.
21 #include <stdbool.h>
22 #include <stdint.h>
23 #include <string.h>
25 #include "platform.h"
27 #include "common/crc.h"
29 #include "drivers/flash.h"
30 #include "drivers/light_led.h"
31 #include "drivers/persistent.h"
32 #include "drivers/system.h"
34 #include "fc/firmware_update.h"
35 #include "fc/firmware_update_common.h"
36 #include "fc/runtime_config.h"
38 #include "io/asyncfatfs/asyncfatfs.h"
41 #ifdef MSP_FIRMWARE_UPDATE
43 #if !(defined(USE_FLASHFS) || defined(USE_SDCARD))
44 #error No storage backend available
45 #endif
47 static firmwareUpdateMetadata_t updateMetadata;
48 static uint8_t updateFirmwareCalcCRC = 0;
49 static uint32_t receivedSize = 0;
50 static bool rollbackPrepared = false;
52 #if defined(USE_SDCARD)
53 static uint32_t firmwareSize;
54 static afatfsFilePtr_t updateFile = NULL;
55 static afatfsFilePtr_t backupFile = NULL;
57 static void updateFileOpenCallback(afatfsFilePtr_t file)
59 updateFile = file;
62 static void backupFileOpenCallback(afatfsFilePtr_t file)
64 backupFile = file;
67 #elif defined(USE_FLASHFS)
68 static uint32_t flashStartAddress, flashOverflowAddress;
70 #endif
72 static bool fullBackup(void)
74 const uint8_t *const backupSrcEnd = (const uint8_t*)FLASH_END;
75 uint8_t *backupSrcPtr = (uint8_t*)&__firmware_start;
76 uint32_t counter = 0;
77 updateMetadata.backupCRC = 0;
79 LED0_OFF;
80 LED1_OFF;
82 #if defined(USE_SDCARD)
83 if ((afatfs_getFilesystemState() != AFATFS_FILESYSTEM_STATE_READY) || !afatfs_fopen(FIRMWARE_UPDATE_BACKUP_FILENAME, "w+", backupFileOpenCallback)) return false;
85 while (backupSrcPtr < backupSrcEnd) {
87 const uint16_t writeBlockSize = 512;
88 uint32_t justWritten = afatfs_fwriteSync(backupFile, backupSrcPtr, writeBlockSize);
89 updateMetadata.backupCRC = crc8_dvb_s2_update(updateMetadata.backupCRC, backupSrcPtr, justWritten);
91 afatfs_poll();
92 backupSrcPtr += justWritten;
94 if (++counter % (50*1024/512) == 0) {
95 LED0_TOGGLE;
96 LED1_TOGGLE;
101 afatfs_fcloseSync(backupFile);
103 #elif defined(USE_FLASHFS)
104 flashPartition_t *flashPartition = flashPartitionFindByType(FLASH_PARTITION_TYPE_FULL_BACKUP);
105 if (!flashPartition) return false;
107 const flashGeometry_t *flashGeometry = flashGetGeometry();
108 const uint32_t flashSectorSize = flashGeometry->sectorSize;
109 const uint32_t flashPartitionSize = (flashPartition->endSector - flashPartition->startSector + 1) * flashSectorSize;
110 const uint32_t backupSize = AVAILABLE_FIRMWARE_SPACE;
111 if (backupSize > flashPartitionSize) return false;
113 uint32_t flashAddress = flashPartition->startSector * flashSectorSize;
115 const uint32_t flashPageSize = flashGeometry->pageSize;
116 while (backupSrcPtr < backupSrcEnd) {
118 if (flashAddress % flashSectorSize == 0) {
119 flashEraseSector(flashAddress);
120 flashWaitForReady(1000);
123 flashPageProgram(flashAddress, backupSrcPtr, flashPageSize);
124 updateMetadata.backupCRC = crc8_dvb_s2_update(updateMetadata.backupCRC, backupSrcPtr, flashPageSize);
126 flashAddress += flashPageSize;
127 backupSrcPtr += flashPageSize;
129 if (++counter % (10*1024/256) == 0) {
130 LED0_TOGGLE;
131 LED1_TOGGLE;
136 #endif
138 return true;
141 static bool backupIsValid(void)
143 if (!firmwareUpdateMetadataRead(&updateMetadata) || (updateMetadata.magic != FIRMWARE_UPDATE_METADATA_MAGIC)) {
144 return false;
147 LED0_OFF;
148 LED1_OFF;
150 uint32_t counter = 0;
151 uint8_t calcCRC = 0;
153 #if defined(USE_SDCARD)
154 #define SD_BACKUP_FILE_BLOCK_READ_SIZE 512
155 if ((afatfs_getFilesystemState() != AFATFS_FILESYSTEM_STATE_READY) || !afatfs_fopen(FIRMWARE_UPDATE_BACKUP_FILENAME, "w+", backupFileOpenCallback)) return false;
157 uint32_t totalRead = 0;
159 uint8_t buffer[SD_BACKUP_FILE_BLOCK_READ_SIZE];
160 while (!afatfs_feof(backupFile)) {
162 uint32_t readBytes = afatfs_freadSync(backupFile, buffer, SD_BACKUP_FILE_BLOCK_READ_SIZE);
163 calcCRC = crc8_dvb_s2_update(calcCRC, buffer, readBytes);
165 totalRead += readBytes;
167 if (++counter % (50*1024/SD_BACKUP_FILE_BLOCK_READ_SIZE) == 0) {
168 LED0_TOGGLE;
169 LED1_TOGGLE;
174 afatfs_fcloseSync(backupFile);
176 #elif defined(USE_FLASHFS)
177 flashPartition_t *flashPartition = flashPartitionFindByType(FLASH_PARTITION_TYPE_FULL_BACKUP);
178 if (!flashPartition) return false;
180 const flashGeometry_t *flashGeometry = flashGetGeometry();
181 const uint32_t flashSectorSize = flashGeometry->sectorSize;
182 const uint32_t flashPartitionSize = (flashPartition->endSector - flashPartition->startSector + 1) * flashSectorSize;
183 const uint32_t backupSize = FLASH_END - (uint32_t)&__firmware_start;
184 if (backupSize > flashPartitionSize) return false;
186 uint32_t flashAddress = flashPartition->startSector * flashSectorSize;
187 const uint32_t flashEndAddress = flashAddress + backupSize;
189 uint8_t buffer[256];
190 while (flashAddress < flashEndAddress) {
192 flashReadBytes(flashAddress, buffer, sizeof(buffer));
193 calcCRC = crc8_dvb_s2_update(calcCRC, buffer, sizeof(buffer));
195 flashAddress += sizeof(buffer);
197 if (++counter % (10*1024/256) == 0) {
198 LED0_TOGGLE;
199 LED1_TOGGLE;
204 #endif
206 return (calcCRC == updateMetadata.backupCRC);
209 bool firmwareUpdatePrepare(uint32_t updateSize)
211 if (ARMING_FLAG(ARMED) || (updateSize > AVAILABLE_FIRMWARE_SPACE)) return false;
213 #if defined(USE_SDCARD)
214 if ((afatfs_getFilesystemState() != AFATFS_FILESYSTEM_STATE_READY) || !afatfs_fopen(FIRMWARE_UPDATE_FIRMWARE_FILENAME, "w+", updateFileOpenCallback)) return false;
216 firmwareSize = updateSize;
218 #elif defined(USE_FLASHFS)
219 flashPartition_t *flashUpdatePartition = flashPartitionFindByType(FLASH_PARTITION_TYPE_UPDATE_FIRMWARE);
220 if (!flashUpdatePartition) return false;
222 const flashGeometry_t *flashGeometry = flashGetGeometry();
224 flashStartAddress = flashUpdatePartition->startSector * flashGeometry->sectorSize;
225 flashOverflowAddress = ((flashUpdatePartition->endSector + 1) * flashGeometry->sectorSize);
226 receivedSize = 0;
228 uint32_t partitionSize = (flashUpdatePartition->endSector - flashUpdatePartition->startSector + 1) * (flashGeometry->sectorSize * flashGeometry->pageSize);
230 if (updateSize > partitionSize) {
231 return false;
234 updateMetadata.firmwareSize = updateSize;
236 #endif
238 updateFirmwareCalcCRC = 0;
240 return true;
243 bool firmwareUpdateStore(uint8_t *data, uint16_t length)
245 if (ARMING_FLAG(ARMED)) {
246 return false;
249 #if defined(USE_SDCARD)
251 if (!updateFile || !firmwareSize || (receivedSize + length > firmwareSize)
252 || (afatfs_fwriteSync(updateFile, data, length) != length)) {
253 return false;
256 #elif defined(USE_FLASHFS)
257 if (!updateMetadata.firmwareSize || (receivedSize + length > updateMetadata.firmwareSize)) return false;
259 const uint32_t flashAddress = flashStartAddress + receivedSize;
261 if ((flashAddress + length > flashOverflowAddress) || (receivedSize + length > updateMetadata.firmwareSize)) {
262 updateMetadata.firmwareSize = 0;
263 return false;
266 const flashGeometry_t *flashGeometry = flashGetGeometry();
267 const uint32_t flashSectorSize = flashGeometry->sectorSize;
269 if (flashAddress % flashSectorSize == 0) {
270 flashEraseSector(flashAddress);
271 flashWaitForReady(1000);
274 flashPageProgram(flashAddress, data, length);
276 #endif
278 updateFirmwareCalcCRC = crc8_dvb_s2_update(updateFirmwareCalcCRC, data, length);
279 receivedSize += length;
281 return true;
284 void firmwareUpdateExec(uint8_t expectCRC)
286 if (ARMING_FLAG(ARMED)) return;
288 #if defined(USE_SDCARD)
289 if (!afatfs_fclose(updateFile, NULL)) return;
290 if (firmwareSize && (receivedSize == firmwareSize) &&
291 (updateFirmwareCalcCRC == expectCRC) && fullBackup() && firmwareUpdateMetadataWrite(&updateMetadata)) {
292 systemResetRequest(RESET_BOOTLOADER_FIRMWARE_UPDATE);
294 #elif defined(USE_FLASHFS)
295 if (updateMetadata.firmwareSize && (receivedSize == updateMetadata.firmwareSize) &&
296 (updateFirmwareCalcCRC == expectCRC) && fullBackup() && firmwareUpdateMetadataWrite(&updateMetadata)) {
297 systemResetRequest(RESET_BOOTLOADER_FIRMWARE_UPDATE);
299 #endif
303 bool firmwareUpdateRollbackPrepare(void)
305 if (ARMING_FLAG(ARMED) || !(rollbackPrepared || backupIsValid())) return false;
307 rollbackPrepared = true;
308 return true;
311 void firmwareUpdateRollbackExec(void)
313 if (ARMING_FLAG(ARMED) || !firmwareUpdateRollbackPrepare()) return;
315 systemResetRequest(RESET_BOOTLOADER_FIRMWARE_ROLLBACK);
318 #endif