Skip to content

Commit

Permalink
stm32/mboot: Add support for 64-bit mboot address space for reads.
Browse files Browse the repository at this point in the history
If enabled via MBOOT_ADDRESS_SPACE_64BIT (it's disabled by default) then
read addresses will be 64-bit.

Signed-off-by: Damien George <damien@micropython.org>
  • Loading branch information
dpgeorge committed Mar 22, 2022
1 parent a92d45c commit 9b07d38
Show file tree
Hide file tree
Showing 8 changed files with 66 additions and 31 deletions.
6 changes: 5 additions & 1 deletion ports/stm32/mboot/README.md
Expand Up @@ -137,9 +137,13 @@ are located and what filename to program. The elements to use are:

* MOUNT: type=2, len=10, payload=(<mount-point:u8> <fs-type:u8> <base-addr:u32> <byte-len:u32>)

* MOUNT: type=2, len=14, payload=(<mount-point:u8> <fs-type:u8> <base-addr:u32> <byte-len:u32> <block-size:u32>)

* MOUNT: type=2, len=22, payload=(<mount-point:u8> <fs-type:u8> <base-addr:u64> <byte-len:u64> <block-size:u32>)

* FSLOAD: type=3, len=1+n, payload=(<mount-point:u8> <filename...>)

`u32` means unsigned 32-bit little-endian integer.
`u32`/`u64` mean unsigned 32-bit/64-bit little-endian integers.

The firmware to load must be a gzip'd DfuSe file (.dfu.gz) and stored within a
FAT or littlefs formatted partition.
Expand Down
27 changes: 18 additions & 9 deletions ports/stm32/mboot/fsload.c
Expand Up @@ -222,20 +222,29 @@ int fsload_process(void) {
// End of elements.
return -MBOOT_ERRNO_FSLOAD_NO_MOUNT;
}
uint32_t block_size;
if (elem[-1] == 10) {
// No block size given, use default.
block_size = MBOOT_FSLOAD_DEFAULT_BLOCK_SIZE;
} else if (elem[-1] == 14) {
// Block size given, extract it.
block_size = get_le32(&elem[10]);
mboot_addr_t base_addr;
mboot_addr_t byte_len;
uint32_t block_size = MBOOT_FSLOAD_DEFAULT_BLOCK_SIZE;
if (elem[-1] == 10 || elem[-1] == 14) {
// 32-bit base and length given, extract them.
base_addr = get_le32(&elem[2]);
byte_len = get_le32(&elem[6]);
if (elem[-1] == 14) {
// Block size given, extract it.
block_size = get_le32(&elem[10]);
}
#if MBOOT_ADDRESS_SPACE_64BIT
} else if (elem[-1] == 22) {
// 64-bit base and length given, and block size, so extract them.
base_addr = get_le64(&elem[2]);
byte_len = get_le64(&elem[10]);
block_size = get_le32(&elem[18]);
#endif
} else {
// Invalid MOUNT element.
return -MBOOT_ERRNO_FSLOAD_INVALID_MOUNT;
}
if (elem[0] == mount_point) {
uint32_t base_addr = get_le32(&elem[2]);
uint32_t byte_len = get_le32(&elem[6]);
int ret;
union {
#if MBOOT_VFS_FAT
Expand Down
7 changes: 5 additions & 2 deletions ports/stm32/mboot/fwupdate.py
Expand Up @@ -227,7 +227,9 @@ def _create_element(kind, body):
return bytes([kind, len(body)]) + body


def update_mpy(filename, fs_base, fs_len, fs_type=VFS_FAT, fs_blocksize=0, status_addr=None):
def update_mpy(
filename, fs_base, fs_len, fs_type=VFS_FAT, fs_blocksize=0, status_addr=None, addr_64bit=False
):
# Check firmware is of .dfu or .dfu.gz type
try:
with open(filename, "rb") as f:
Expand All @@ -243,9 +245,10 @@ def update_mpy(filename, fs_base, fs_len, fs_type=VFS_FAT, fs_blocksize=0, statu
raise Exception("littlefs requires fs_blocksize parameter")

mount_point = 1
mount_encoding = "<BBQQL" if addr_64bit else "<BBLLL"
elems = _create_element(
_ELEM_TYPE_MOUNT,
struct.pack("<BBLLL", mount_point, fs_type, fs_base, fs_len, fs_blocksize),
struct.pack(mount_encoding, mount_point, fs_type, fs_base, fs_len, fs_blocksize),
)
elems += _create_element(
_ELEM_TYPE_FSLOAD, struct.pack("<B", mount_point) + bytes(filename, "ascii")
Expand Down
11 changes: 8 additions & 3 deletions ports/stm32/mboot/main.c
Expand Up @@ -117,6 +117,11 @@ uint32_t get_le32(const uint8_t *b) {
return b[0] | b[1] << 8 | b[2] << 16 | b[3] << 24;
}

uint64_t get_le64(const uint8_t *b) {
return (uint64_t)b[0] | (uint64_t)b[1] << 8 | (uint64_t)b[2] << 16 | (uint64_t)b[3] << 24
| (uint64_t)b[4] << 32 | (uint64_t)b[5] << 40 | (uint64_t)b[6] << 48 | (uint64_t)b[7] << 56;
}

mp_uint_t mp_hal_ticks_ms(void) {
return systick_ms;
}
Expand Down Expand Up @@ -636,7 +641,7 @@ int hw_page_erase(uint32_t addr, uint32_t *next_addr) {
return ret;
}

void hw_read(uint32_t addr, int len, uint8_t *buf) {
void hw_read(mboot_addr_t addr, size_t len, uint8_t *buf) {
led0_state(LED0_STATE_FAST_FLASH);
#if defined(MBOOT_SPIFLASH_ADDR)
if (MBOOT_SPIFLASH_ADDR <= addr && addr < MBOOT_SPIFLASH_ADDR + MBOOT_SPIFLASH_BYTE_SIZE) {
Expand All @@ -650,7 +655,7 @@ void hw_read(uint32_t addr, int len, uint8_t *buf) {
#endif
{
// Other addresses, just read directly from memory
memcpy(buf, (void*)addr, len);
memcpy(buf, (void *)(uintptr_t)addr, len);
}
led0_state(LED0_STATE_SLOW_FLASH);
}
Expand Down Expand Up @@ -688,7 +693,7 @@ int do_page_erase(uint32_t addr, uint32_t *next_addr) {
#endif
}

void do_read(uint32_t addr, int len, uint8_t *buf) {
void do_read(mboot_addr_t addr, size_t len, uint8_t *buf) {
#if MBOOT_ENABLE_PACKING
// Read disabled on packed (encrypted) mode.
dfu_context.status = DFU_STATUS_ERROR_FILE;
Expand Down
16 changes: 14 additions & 2 deletions ports/stm32/mboot/mboot.h
Expand Up @@ -42,6 +42,10 @@
#define MBOOT_BOARD_ENTRY_INIT mboot_entry_init
#endif

#ifndef MBOOT_ADDRESS_SPACE_64BIT
#define MBOOT_ADDRESS_SPACE_64BIT (0)
#endif

enum {
MBOOT_ERRNO_FLASH_ERASE_DISALLOWED = 200,
MBOOT_ERRNO_FLASH_ERASE_FAILED,
Expand Down Expand Up @@ -86,21 +90,29 @@ enum {
ELEM_MOUNT_LFS2,
};

// Configure the type used to hold an address in the mboot address space.
#if MBOOT_ADDRESS_SPACE_64BIT
typedef uint64_t mboot_addr_t;
#else
typedef uint32_t mboot_addr_t;
#endif

extern uint8_t _estack[ELEM_DATA_SIZE];

void systick_init(void);
void led_init(void);
void SystemClock_Config(void);

uint32_t get_le32(const uint8_t *b);
uint64_t get_le64(const uint8_t *b);
void led_state_all(unsigned int mask);

int hw_page_erase(uint32_t addr, uint32_t *next_addr);
void hw_read(uint32_t addr, int len, uint8_t *buf);
void hw_read(mboot_addr_t addr, size_t len, uint8_t *buf);
int hw_write(uint32_t addr, const uint8_t *src8, size_t len);

int do_page_erase(uint32_t addr, uint32_t *next_addr);
void do_read(uint32_t addr, int len, uint8_t *buf);
void do_read(mboot_addr_t addr, size_t len, uint8_t *buf);
int do_write(uint32_t addr, const uint8_t *src8, size_t len);

const uint8_t *elem_search(const uint8_t *elem, uint8_t elem_id);
Expand Down
14 changes: 7 additions & 7 deletions ports/stm32/mboot/vfs.h
Expand Up @@ -34,15 +34,15 @@
#include "lib/oofatfs/ff.h"

typedef struct _vfs_fat_context_t {
uint32_t bdev_base_addr;
uint32_t bdev_byte_len;
mboot_addr_t bdev_base_addr;
uint32_t bdev_num_blocks;
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);
int vfs_fat_mount(vfs_fat_context_t *ctx, mboot_addr_t base_addr, mboot_addr_t byte_len);

#endif

Expand All @@ -55,7 +55,7 @@ int vfs_fat_mount(vfs_fat_context_t *ctx, uint32_t base_addr, uint32_t byte_len)
#define LFS_LOOKAHEAD_SIZE (32)

typedef struct _vfs_lfs1_context_t {
uint32_t bdev_base_addr;
mboot_addr_t bdev_base_addr;
struct lfs1_config config;
lfs1_t lfs;
struct lfs1_file_config filecfg;
Expand All @@ -65,7 +65,7 @@ typedef struct _vfs_lfs1_context_t {

extern const stream_methods_t vfs_lfs1_stream_methods;

int vfs_lfs1_mount(vfs_lfs1_context_t *ctx, uint32_t base_addr, uint32_t byte_len, uint32_t block_size);
int vfs_lfs1_mount(vfs_lfs1_context_t *ctx, mboot_addr_t base_addr, mboot_addr_t byte_len, uint32_t block_size);

#endif

Expand All @@ -79,7 +79,7 @@ int vfs_lfs1_mount(vfs_lfs1_context_t *ctx, uint32_t base_addr, uint32_t byte_le
#define LFS_LOOKAHEAD_SIZE (32)

typedef struct _vfs_lfs2_context_t {
uint32_t bdev_base_addr;
mboot_addr_t bdev_base_addr;
struct lfs2_config config;
lfs2_t lfs;
struct lfs2_file_config filecfg;
Expand All @@ -89,7 +89,7 @@ typedef struct _vfs_lfs2_context_t {

extern const stream_methods_t vfs_lfs2_stream_methods;

int vfs_lfs2_mount(vfs_lfs2_context_t *ctx, uint32_t base_addr, uint32_t byte_len, uint32_t block_size);
int vfs_lfs2_mount(vfs_lfs2_context_t *ctx, mboot_addr_t base_addr, mboot_addr_t byte_len, uint32_t block_size);

#endif

Expand Down
11 changes: 6 additions & 5 deletions ports/stm32/mboot/vfs_fat.c
Expand Up @@ -41,8 +41,9 @@
DRESULT disk_read(void *pdrv, BYTE *buf, DWORD sector, UINT count) {
vfs_fat_context_t *ctx = pdrv;

if (0 <= sector && sector < ctx->bdev_byte_len / 512) {
hw_read(ctx->bdev_base_addr + sector * SECSIZE, count * SECSIZE, buf);
if (0 <= sector && sector < ctx->bdev_num_blocks) {
mboot_addr_t addr = ctx->bdev_base_addr + (mboot_addr_t)sector * (mboot_addr_t)SECSIZE;
hw_read(addr, count * SECSIZE, buf);
return RES_OK;
}

Expand All @@ -57,7 +58,7 @@ DRESULT disk_ioctl(void *pdrv, BYTE cmd, void *buf) {
return RES_OK;

case GET_SECTOR_COUNT:
*((DWORD*)buf) = ctx->bdev_byte_len / SECSIZE;
*((DWORD*)buf) = ctx->bdev_num_blocks;
return RES_OK;

case GET_SECTOR_SIZE:
Expand All @@ -78,9 +79,9 @@ 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) {
int vfs_fat_mount(vfs_fat_context_t *ctx, mboot_addr_t base_addr, mboot_addr_t byte_len) {
ctx->bdev_base_addr = base_addr;
ctx->bdev_byte_len = byte_len;
ctx->bdev_num_blocks = byte_len / SECSIZE;
ctx->fatfs.drv = ctx;
FRESULT res = f_mount(&ctx->fatfs);
if (res != FR_OK) {
Expand Down
5 changes: 3 additions & 2 deletions ports/stm32/mboot/vfs_lfs.c
Expand Up @@ -70,7 +70,8 @@ static uint8_t lfs_lookahead_buffer[LFS_LOOKAHEAD_SIZE];
static int dev_read(const struct LFSx_API (config) * c, LFSx_API(block_t) block, LFSx_API(off_t) off, void *buffer, LFSx_API(size_t) size) {
VFS_LFSx_CONTEXT_T *ctx = c->context;
if (0 <= block && block < ctx->config.block_count) {
hw_read(ctx->bdev_base_addr + block * ctx->config.block_size + off, size, buffer);
mboot_addr_t addr = ctx->bdev_base_addr + (mboot_addr_t)block * (mboot_addr_t)ctx->config.block_size + (mboot_addr_t)off;
hw_read(addr, size, buffer);
return LFSx_MACRO(_ERR_OK);
}
return LFSx_MACRO(_ERR_IO);
Expand All @@ -88,7 +89,7 @@ static int dev_sync(const struct LFSx_API (config) * c) {
return LFSx_MACRO(_ERR_OK);
}

int VFS_LFSx_MOUNT(VFS_LFSx_CONTEXT_T *ctx, uint32_t base_addr, uint32_t byte_len, uint32_t block_size) {
int VFS_LFSx_MOUNT(VFS_LFSx_CONTEXT_T *ctx, mboot_addr_t base_addr, mboot_addr_t byte_len, uint32_t block_size) {
ctx->bdev_base_addr = base_addr;

struct LFSx_API (config) *config = &ctx->config;
Expand Down

0 comments on commit 9b07d38

Please sign in to comment.