This is an automated email from the ASF dual-hosted git repository. jerzy pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/mynewt-core.git
commit 5b547eb1a8450aea2c4cb4778cff8b6030aefb73 Author: Jerzy Kasenberg <[email protected]> AuthorDate: Wed May 29 15:50:04 2024 +0200 tinyusb/msc_fat_view: Add update handler Update handler in separate file, code was part of msc_fat_view.c --- hw/usb/tinyusb/msc_fat_view/pkg.yml | 3 + hw/usb/tinyusb/msc_fat_view/src/update_handler.c | 250 +++++++++++++++++++++++ 2 files changed, 253 insertions(+) diff --git a/hw/usb/tinyusb/msc_fat_view/pkg.yml b/hw/usb/tinyusb/msc_fat_view/pkg.yml index 42ba4c9f2..a03134786 100644 --- a/hw/usb/tinyusb/msc_fat_view/pkg.yml +++ b/hw/usb/tinyusb/msc_fat_view/pkg.yml @@ -65,6 +65,9 @@ pkg.source_files.MSC_FAT_VIEW_MYNEWT_SHORTCUT: pkg.source_files.MSC_FAT_VIEW_CONFIG: - src/entry_config.c +pkg.source_files.MSC_FAT_VIEW_UPDATE_HANDLER: + - src/update_handler.c + pkg.link_tables: - msc_fat_view_root_entry - msc_fat_view_write_handlers diff --git a/hw/usb/tinyusb/msc_fat_view/src/update_handler.c b/hw/usb/tinyusb/msc_fat_view/src/update_handler.c new file mode 100644 index 000000000..7512518a2 --- /dev/null +++ b/hw/usb/tinyusb/msc_fat_view/src/update_handler.c @@ -0,0 +1,250 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#include <assert.h> +#include <bsp/bsp.h> +#include <sysflash/sysflash.h> +#include <tusb.h> +#include <class/msc/msc.h> +#include <msc_fat_view/msc_fat_view.h> +#include <img_mgmt/img_mgmt.h> +#include <bootutil/image.h> +#include <modlog/modlog.h> +#include <hal/hal_flash.h> + +#if MYNEWT_VAL(BOOT_LOADER) +#define BOOT_LOADER 1 +#define FLASH_AREA_IMAGE FLASH_AREA_IMAGE_0 +#else +#define BOOT_LOADER 0 +#ifdef FLASH_AREA_IMAGE_1 +#define FLASH_AREA_IMAGE FLASH_AREA_IMAGE_1 +#endif +#endif + +/* If true, test image will be confirmed on root directory read */ +static bool confirmed; + +typedef enum { + MEDIUM_NOT_PRESENT, + REPORT_MEDIUM_CHANGE, + MEDIUM_RELOAD, + MEDIUM_PRESENT, +} medium_state_t; + +static medium_state_t medium_state; + +struct unallocated_write { + uint32_t first_sector; + uint32_t last_sector; + enum { + NOT_TOUCHED_YET = 0, + WRITE_IN_PROGRESS = 1, + NOT_AN_IMAGE = -1, + CURRENT_IMAGE_NOT_CONFIRMED = -2, + WRITE_EXCEEDED_SPACE = -3, + WRITE_NOT_IN_SEQUENCE = -4, + } write_status; +} unallocated_write; + +static int write_status; +static const char *write_result_text[] = { + "File that was written was not a valid image.", + "Current image not confirmed, new image rejected.", + "File write error.", +}; + +static uint32_t +flash_result_create_content(struct MemFile *file) +{ + int ix = abs(write_status) - 1; + if (ix > 2) { + ix = 2; + } + fwrite(write_result_text[ix], 1, strlen(write_result_text[ix]), &file->file); + + return file->bytes_written; +} + +static uint32_t +flash_result_size(const file_entry_t *file_entry) +{ + struct MemFile sector_file; + + (void)file_entry; + fmemopen_w(§or_file, (char *)NULL, 0); + + flash_result_create_content(§or_file); + + return sector_file.bytes_written; +} + +static void +flash_result_read(const struct file_entry *entry, uint32_t file_sector, uint8_t buffer[512]) +{ + struct MemFile sector_file; + int written = 0; + (void)entry; + + if (file_sector == 0) { + fmemopen_w(§or_file, (char *)buffer, 512); + flash_result_create_content(§or_file); + written = sector_file.bytes_written; + } + + memset(buffer + written, 0, 512 - written); +} + +static const file_entry_t flash_result = { + .name = "Write error.txt", + .attributes = FAT_FILE_ENTRY_ATTRIBUTE_READ_ONLY, + .size = flash_result_size, + .read_sector = flash_result_read, +}; + +static int +image_write_sector(struct msc_fat_view_write_handler *handler, uint32_t sector, uint8_t *buffer) +{ +#ifdef FLASH_AREA_IMAGE + const struct flash_area *fa; + uint32_t write_offset; + int rc; + + if (unallocated_write.write_status < 0) { + return 0; + } + flash_area_open(FLASH_AREA_IMAGE, &fa); + if (unallocated_write.write_status == NOT_TOUCHED_YET) { + if (BOOT_LOADER) { + if (((struct image_header *)buffer)->ih_magic == IMAGE_MAGIC) { + unallocated_write.write_status = WRITE_IN_PROGRESS; + /* TODO: unmount and add error file */ + + } + } else if ((img_mgmt_state_flags(0) & IMG_MGMT_STATE_F_CONFIRMED) == 0) { + MSC_FAT_VIEW_LOG_ERROR("Image not confirmed, write rejected\n"); + + /* Image in slot 0 not confirmed, do not write */ + unallocated_write.write_status = CURRENT_IMAGE_NOT_CONFIRMED; + } else if (((struct image_header *)buffer)->ih_magic == IMAGE_MAGIC) { + unallocated_write.write_status = WRITE_IN_PROGRESS; + } + if (unallocated_write.write_status == WRITE_IN_PROGRESS) { + MSC_FAT_VIEW_LOG_INFO("Image writing detected\n"); + unallocated_write.first_sector = sector; + unallocated_write.last_sector = sector; + } + } else if (unallocated_write.write_status == WRITE_IN_PROGRESS) { + if (sector != unallocated_write.last_sector + 1) { + /* + * Unallocated space written without order, code will not be able to used + * it sensible. + */ + unallocated_write.write_status = WRITE_NOT_IN_SEQUENCE; + MSC_FAT_VIEW_LOG_ERROR("Not continuous writes to unallocated space rejected\n"); + } + } + if (unallocated_write.write_status == WRITE_IN_PROGRESS) { + write_offset = (sector - unallocated_write.first_sector) * SECTOR_SIZE; + if (!hal_flash_isempty_no_buf(fa->fa_device_id, fa->fa_off + write_offset, SECTOR_SIZE)) { + flash_area_erase(fa, write_offset, SECTOR_SIZE); + } + + if ((rc = flash_area_write(fa, write_offset, buffer, SECTOR_SIZE)) < 0) { + MSC_FAT_VIEW_LOG_ERROR("Flash write error, following writes will be rejected %d 0x%08x\n", + rc, fa->fa_off + write_offset); + unallocated_write.write_status = WRITE_EXCEEDED_SPACE; + } + } + flash_area_close(fa); + if (unallocated_write.write_status == WRITE_IN_PROGRESS) { + unallocated_write.last_sector = sector; + } + return 512; +#else + return 0; +#endif +} + +static int +image_file_written(struct msc_fat_view_write_handler *handler, uint32_t size, + uint32_t sector, bool first_sector) +{ + struct image_version version; + uint32_t flags; + + if (unallocated_write.write_status == WRITE_IN_PROGRESS) { + if (unallocated_write.first_sector == sector && first_sector) { + MSC_FAT_VIEW_LOG_INFO("New file detected\n"); + if (BOOT_LOADER) { + img_mgmt_state_confirm(); + hal_system_reset(); + } else { + if (img_mgmt_read_info(1, &version, NULL, &flags) == 0) { + MSC_FAT_VIEW_LOG_INFO("New image OK, resetting\n"); + img_mgmt_state_set_pending(1, 0); + hal_system_reset(); + } else { + MSC_FAT_VIEW_LOG_ERROR("New file not an valid image\n"); + } + } + } else { + MSC_FAT_VIEW_LOG_ERROR( + "New file not ready to flash new sectors (%d-%d), (sector %d)\n", + unallocated_write.first_sector, unallocated_write.last_sector, sector); + } + } else { + if ((int)unallocated_write.write_status < 0) { + MSC_FAT_VIEW_LOG_ERROR("Write failed, reloading medium\n"); + medium_state = MEDIUM_RELOAD; + } + } + if (unallocated_write.write_status < 0) { + write_status = unallocated_write.write_status; + msc_fat_view_add_dir_entry(&flash_result); + } + unallocated_write.write_status = NOT_TOUCHED_YET; + return 0; +} + +MSC_FAT_VIEW_WRITE_HANDLER(update_handler, image_write_sector, image_file_written); + +static int +invalid_fun(const struct file_entry *entry) +{ + (void)entry; + + /* Image auto-confirmation enabled */ + if (MYNEWT_VAL(MSC_FAT_VIEW_AUTOCONFIRM)) { + /* Image not confirmed yet or confirmation state not checked */ + if (!confirmed) { + /* Image actually not confirmed yet */ + if ((img_mgmt_state_flags(0) & IMG_MGMT_STATE_F_CONFIRMED) == 0) { + /* Mark as confirmed */ + img_mgmt_state_confirm(); + confirmed = true; + } + } + } + + /* Return MSC_FAT_VIEW_FILE_ENTRY_NOT_VALID to prevent from adding entry */ + return MSC_FAT_VIEW_FILE_ENTRY_NOT_VALID; +} + +ROOT_DIR_ENTRY(ghost_entry, "", 0, NULL, NULL, NULL, NULL, invalid_fun);
