summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDamien George <damien@micropython.org>2020-06-23 22:57:16 +1000
committerDamien George <damien@micropython.org>2020-06-26 21:15:30 +1000
commit390f32922d81b56495198d3d93b7258f450c03b6 (patch)
treee0151ad054bd40f5d19a542f65fbce0eb58e373e
parent763bd448a4348b36db08cbae41337507e47cb892 (diff)
stm32/mboot: Decouple stream, filesystem and top-level loading code.
This commit factors the code for files and streaming to separate source files (vfs_fat.c and gzstream.c respectively) and introduces an abstract gzstream interface to make it easier to plug in different filesystems. Signed-off-by: Damien George <damien@micropython.org>
-rwxr-xr-xports/stm32/mboot/Makefile3
-rw-r--r--ports/stm32/mboot/fsload.c110
-rw-r--r--ports/stm32/mboot/gzstream.c94
-rw-r--r--ports/stm32/mboot/gzstream.h45
-rw-r--r--ports/stm32/mboot/mboot.h5
-rw-r--r--ports/stm32/mboot/vfs.h43
-rw-r--r--ports/stm32/mboot/vfs_fat.c (renamed from ports/stm32/mboot/diskio.c)54
7 files changed, 256 insertions, 98 deletions
diff --git a/ports/stm32/mboot/Makefile b/ports/stm32/mboot/Makefile
index a72b752ac..9ab186412 100755
--- a/ports/stm32/mboot/Makefile
+++ b/ports/stm32/mboot/Makefile
@@ -102,7 +102,8 @@ SRC_C = \
main.c \
elem.c \
fsload.c \
- diskio.c \
+ gzstream.c \
+ vfs_fat.c \
drivers/bus/softspi.c \
drivers/bus/softqspi.c \
drivers/memory/spiflash.c \
diff --git a/ports/stm32/mboot/fsload.c b/ports/stm32/mboot/fsload.c
index 12f39c65b..dc40a28ea 100644
--- a/ports/stm32/mboot/fsload.c
+++ b/ports/stm32/mboot/fsload.c
@@ -27,81 +27,18 @@
#include <string.h>
#include "py/mphal.h"
-#include "lib/oofatfs/ff.h"
-#include "extmod/uzlib/uzlib.h"
#include "mboot.h"
+#include "vfs.h"
#if MBOOT_FSLOAD
-#define DICT_SIZE (1 << 15)
-
-typedef struct _gz_stream_t {
- FIL fp;
- TINF_DATA tinf;
- uint8_t buf[512];
- uint8_t dict[DICT_SIZE];
-} gz_stream_t;
-
-static gz_stream_t gz_stream SECTION_NOZERO_BSS;
-
-static int gz_stream_read_src(TINF_DATA *tinf) {
- UINT n;
- FRESULT res = f_read(&gz_stream.fp, gz_stream.buf, sizeof(gz_stream.buf), &n);
- if (res != FR_OK) {
- return -1;
- }
- if (n == 0) {
- return -1;
- }
- tinf->source = gz_stream.buf + 1;
- tinf->source_limit = gz_stream.buf + n;
- return gz_stream.buf[0];
-}
-
-static int gz_stream_open(FATFS *fatfs, const char *filename) {
- FRESULT res = f_open(fatfs, &gz_stream.fp, filename, FA_READ);
- if (res != FR_OK) {
- return -1;
- }
- memset(&gz_stream.tinf, 0, sizeof(gz_stream.tinf));
- gz_stream.tinf.readSource = gz_stream_read_src;
-
- int st = uzlib_gzip_parse_header(&gz_stream.tinf);
- if (st != TINF_OK) {
- f_close(&gz_stream.fp);
- return -1;
- }
-
- uzlib_uncompress_init(&gz_stream.tinf, gz_stream.dict, DICT_SIZE);
-
- return 0;
-}
-
-static int gz_stream_read(size_t len, uint8_t *buf) {
- gz_stream.tinf.dest = buf;
- gz_stream.tinf.dest_limit = buf + len;
- int st = uzlib_uncompress_chksum(&gz_stream.tinf);
- if (st == TINF_DONE) {
- return 0;
- }
- if (st < 0) {
- return st;
- }
- return gz_stream.tinf.dest - buf;
-}
-
-static int fsload_program_file(FATFS *fatfs, const char *filename, bool write_to_flash) {
- int res = gz_stream_open(fatfs, filename);
- if (res != 0) {
- return res;
- }
-
+static int fsload_program_file(bool write_to_flash) {
// Parse DFU
uint8_t buf[512];
size_t file_offset;
// Read file header, <5sBIB
- res = gz_stream_read(11, buf);
+ int res = gz_stream_read(11, buf);
if (res != 11) {
return -1;
}
@@ -204,26 +141,23 @@ static int fsload_program_file(FATFS *fatfs, const char *filename, bool write_to
return 0;
}
-static int fsload_process_fatfs(uint32_t base_addr, uint32_t byte_len, const char *fname) {
- fsload_bdev_t bdev = {base_addr, byte_len};
- FATFS fatfs;
- fatfs.drv = &bdev;
- FRESULT res = f_mount(&fatfs);
- if (res != FR_OK) {
- return -1;
- }
-
- // Validate firmware
- led_state_all(2);
- int r = fsload_program_file(&fatfs, fname, false);
-
- if (r == 0) {
- // Firmware is valid, program it
- led_state_all(4);
- r = fsload_program_file(&fatfs, fname, true);
+static int fsload_validate_and_program_file(void *stream, const stream_methods_t *meth, const char *fname) {
+ // First pass verifies the file, second pass programs it
+ for (unsigned int pass = 0; pass <= 1; ++pass) {
+ led_state_all(pass == 0 ? 2 : 4);
+ int res = meth->open(stream, fname);
+ if (res == 0) {
+ res = gz_stream_init(stream, meth->read);
+ if (res == 0) {
+ res = fsload_program_file(pass == 0 ? false : true);
+ }
+ }
+ meth->close(stream);
+ if (res != 0) {
+ return res;
+ }
}
-
- return r;
+ return 0;
}
int fsload_process(void) {
@@ -250,7 +184,11 @@ int fsload_process(void) {
uint32_t base_addr = get_le32(&elem[2]);
uint32_t byte_len = get_le32(&elem[6]);
if (elem[1] == ELEM_MOUNT_FAT) {
- int ret = fsload_process_fatfs(base_addr, byte_len, fname);
+ vfs_fat_context_t ctx;
+ int ret = vfs_fat_mount(&ctx, base_addr, byte_len);
+ if (ret == 0) {
+ ret = fsload_validate_and_program_file(&ctx, &vfs_fat_stream_methods, fname);
+ }
// Flash LEDs based on success/failure of update
for (int i = 0; i < 4; ++i) {
if (ret == 0) {
diff --git a/ports/stm32/mboot/gzstream.c b/ports/stm32/mboot/gzstream.c
new file mode 100644
index 000000000..20ba33045
--- /dev/null
+++ b/ports/stm32/mboot/gzstream.c
@@ -0,0 +1,94 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2019-2020 Damien P. George
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include <string.h>
+
+#include "py/mphal.h"
+#include "extmod/uzlib/uzlib.h"
+#include "gzstream.h"
+#include "mboot.h"
+
+#if MBOOT_FSLOAD
+
+#define DICT_SIZE (1 << 15)
+
+typedef struct _gz_stream_t {
+ void *stream_data;
+ stream_read_t stream_read;
+ TINF_DATA tinf;
+ uint8_t buf[512];
+ uint8_t dict[DICT_SIZE];
+} gz_stream_t;
+
+static gz_stream_t gz_stream SECTION_NOZERO_BSS;
+
+static int gz_stream_read_src(TINF_DATA *tinf) {
+ int n = gz_stream.stream_read(gz_stream.stream_data, gz_stream.buf, sizeof(gz_stream.buf));
+ if (n < 0) {
+ // Stream error
+ return -1;
+ }
+ if (n == 0) {
+ // No data / EOF
+ return -1;
+ }
+
+ tinf->source = gz_stream.buf + 1;
+ tinf->source_limit = gz_stream.buf + n;
+ return gz_stream.buf[0];
+}
+
+int gz_stream_init(void *stream_data, stream_read_t stream_read) {
+ gz_stream.stream_data = stream_data;
+ gz_stream.stream_read = stream_read;
+
+ memset(&gz_stream.tinf, 0, sizeof(gz_stream.tinf));
+ gz_stream.tinf.readSource = gz_stream_read_src;
+
+ int st = uzlib_gzip_parse_header(&gz_stream.tinf);
+ if (st != TINF_OK) {
+ return -1;
+ }
+
+ uzlib_uncompress_init(&gz_stream.tinf, gz_stream.dict, DICT_SIZE);
+
+ return 0;
+}
+
+int gz_stream_read(size_t len, uint8_t *buf) {
+ gz_stream.tinf.dest = buf;
+ gz_stream.tinf.dest_limit = buf + len;
+ int st = uzlib_uncompress_chksum(&gz_stream.tinf);
+ if (st == TINF_DONE) {
+ return 0;
+ }
+ if (st < 0) {
+ return st;
+ }
+ return gz_stream.tinf.dest - buf;
+}
+
+#endif // MBOOT_FSLOAD
diff --git a/ports/stm32/mboot/gzstream.h b/ports/stm32/mboot/gzstream.h
new file mode 100644
index 000000000..ec11ba79b
--- /dev/null
+++ b/ports/stm32/mboot/gzstream.h
@@ -0,0 +1,45 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2019-2020 Damien P. George
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+#ifndef MICROPY_INCLUDED_STM32_MBOOT_GZSTREAM_H
+#define MICROPY_INCLUDED_STM32_MBOOT_GZSTREAM_H
+
+#include <stddef.h>
+#include <stdint.h>
+
+typedef int (*stream_open_t)(void *stream, const char *fname);
+typedef void (*stream_close_t)(void *stream);
+typedef int (*stream_read_t)(void *stream, uint8_t *buf, size_t len);
+
+typedef struct _stream_methods_t {
+ stream_open_t open;
+ stream_close_t close;
+ stream_read_t read;
+} stream_methods_t;
+
+int gz_stream_init(void *stream_data, stream_read_t stream_read);
+int gz_stream_read(size_t len, uint8_t *buf);
+
+#endif // MICROPY_INCLUDED_STM32_MBOOT_GZSTREAM_H
diff --git a/ports/stm32/mboot/mboot.h b/ports/stm32/mboot/mboot.h
index 7dc1ada0c..ef9af7854 100644
--- a/ports/stm32/mboot/mboot.h
+++ b/ports/stm32/mboot/mboot.h
@@ -44,11 +44,6 @@ enum {
ELEM_MOUNT_FAT = 1,
};
-typedef struct _fsload_bdev_t {
- uint32_t base_addr;
- uint32_t byte_len;
-} fsload_bdev_t;
-
extern uint8_t _estack[ELEM_DATA_SIZE];
uint32_t get_le32(const uint8_t *b);
diff --git a/ports/stm32/mboot/vfs.h b/ports/stm32/mboot/vfs.h
new file mode 100644
index 000000000..9ee1c5ff3
--- /dev/null
+++ b/ports/stm32/mboot/vfs.h
@@ -0,0 +1,43 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2019-2020 Damien P. George
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+#ifndef MICROPY_INCLUDED_STM32_MBOOT_VFS_H
+#define MICROPY_INCLUDED_STM32_MBOOT_VFS_H
+
+#include "lib/oofatfs/ff.h"
+#include "gzstream.h"
+
+typedef struct _vfs_fat_context_t {
+ uint32_t bdev_base_addr;
+ uint32_t bdev_byte_len;
+ FATFS fatfs;
+ FIL fp;
+} vfs_fat_context_t;
+
+extern const stream_methods_t vfs_fat_stream_methods;
+
+int vfs_fat_mount(vfs_fat_context_t *ctx, uint32_t base_addr, uint32_t byte_len);
+
+#endif // MICROPY_INCLUDED_STM32_MBOOT_VFS_H
diff --git a/ports/stm32/mboot/diskio.c b/ports/stm32/mboot/vfs_fat.c
index 5f68f26a8..20994c8b4 100644
--- a/ports/stm32/mboot/diskio.c
+++ b/ports/stm32/mboot/vfs_fat.c
@@ -3,7 +3,7 @@
*
* The MIT License (MIT)
*
- * Copyright (c) 2019 Damien P. George
+ * Copyright (c) 2019-2020 Damien P. George
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -28,6 +28,7 @@
#include "lib/oofatfs/ff.h"
#include "lib/oofatfs/diskio.h"
#include "mboot.h"
+#include "vfs.h"
#if MBOOT_FSLOAD
@@ -38,10 +39,10 @@
#endif
DRESULT disk_read(void *pdrv, BYTE *buf, DWORD sector, UINT count) {
- fsload_bdev_t *bdev = pdrv;
+ vfs_fat_context_t *ctx = pdrv;
- if (0 <= sector && sector < bdev->byte_len / 512) {
- do_read(bdev->base_addr + sector * SECSIZE, count * SECSIZE, buf);
+ if (0 <= sector && sector < ctx->bdev_byte_len / 512) {
+ do_read(ctx->bdev_base_addr + sector * SECSIZE, count * SECSIZE, buf);
return RES_OK;
}
@@ -49,14 +50,14 @@ DRESULT disk_read(void *pdrv, BYTE *buf, DWORD sector, UINT count) {
}
DRESULT disk_ioctl(void *pdrv, BYTE cmd, void *buf) {
- fsload_bdev_t *bdev = pdrv;
+ vfs_fat_context_t *ctx = pdrv;
switch (cmd) {
case CTRL_SYNC:
return RES_OK;
case GET_SECTOR_COUNT:
- *((DWORD*)buf) = bdev->byte_len / SECSIZE;
+ *((DWORD*)buf) = ctx->bdev_byte_len / SECSIZE;
return RES_OK;
case GET_SECTOR_SIZE:
@@ -77,4 +78,45 @@ DRESULT disk_ioctl(void *pdrv, BYTE cmd, void *buf) {
}
}
+int vfs_fat_mount(vfs_fat_context_t *ctx, uint32_t base_addr, uint32_t byte_len) {
+ ctx->bdev_base_addr = base_addr;
+ ctx->bdev_byte_len = byte_len;
+ ctx->fatfs.drv = ctx;
+ FRESULT res = f_mount(&ctx->fatfs);
+ if (res != FR_OK) {
+ return -1;
+ }
+ return 0;
+}
+
+static int vfs_fat_stream_open(void *stream_in, const char *fname) {
+ vfs_fat_context_t *stream = stream_in;
+ FRESULT res = f_open(&stream->fatfs, &stream->fp, fname, FA_READ);
+ if (res != FR_OK) {
+ return -1;
+ }
+ return 0;
+}
+
+static void vfs_fat_stream_close(void *stream_in) {
+ vfs_fat_context_t *stream = stream_in;
+ f_close(&stream->fp);
+}
+
+static int vfs_fat_stream_read(void *stream_in, uint8_t *buf, size_t len) {
+ vfs_fat_context_t *stream = stream_in;
+ UINT n;
+ FRESULT res = f_read(&stream->fp, buf, len, &n);
+ if (res != FR_OK) {
+ return -1;
+ }
+ return n;
+}
+
+const stream_methods_t vfs_fat_stream_methods = {
+ vfs_fat_stream_open,
+ vfs_fat_stream_close,
+ vfs_fat_stream_read,
+};
+
#endif // MBOOT_FSLOAD