diff --git a/src/drivers/bootloaders/CMakeLists.txt b/src/drivers/bootloaders/CMakeLists.txt index f5bc89a5d9..47e0df1942 100644 --- a/src/drivers/bootloaders/CMakeLists.txt +++ b/src/drivers/bootloaders/CMakeLists.txt @@ -1,6 +1,6 @@ ############################################################################ # -# Copyright (c) 2017 PX4 Development Team. All rights reserved. +# Copyright (c) 2017, 2021 PX4 Development Team. All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions @@ -48,7 +48,7 @@ if(NOT "${PX4_BOARD_LABEL}" MATCHES "canbootloader") set(SW_MAJOR ${uavcanblid_sw_version_major}) set(SW_MINOR ${uavcanblid_sw_version_minor}) - string(REPLACE "\"" "" HWNAME ${uavcanblid_name}) + math(EXPR HWBOARD_ID "(${HW_MAJOR} << 8) + ${HW_MINOR}") execute_process( COMMAND git rev-list HEAD --max-count=1 --abbrev=8 --abbrev-commit @@ -60,12 +60,16 @@ if(NOT "${PX4_BOARD_LABEL}" MATCHES "canbootloader") if ("${uavcanbl_git_desc}" STREQUAL "") set(uavcanbl_git_desc ffffffff) endif() - set(uavcan_bl_imange_name ${HWNAME}-${HW_MAJOR}.${HW_MINOR}-${SW_MAJOR}.${SW_MINOR}.${uavcanbl_git_desc}.uavcan.bin) + set(uavcan_bl_imange_name ${HWBOARD_ID}-${SW_MAJOR}.${SW_MINOR}.${uavcanbl_git_desc}.uavcan.bin) message(STATUS "Generating UAVCAN Bootable as ${uavcan_bl_imange_name}") - add_custom_command(OUTPUT ${uavcan_bl_imange_name} + add_custom_command(OUTPUT ${uavcan_bl_imange_name} deploy/${HWBOARD_ID}.bin COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/make_can_boot_descriptor.py - -v --use-git-hash ${PX4_BINARY_DIR}/${PX4_BOARD}.bin ${uavcan_bl_imange_name} + -v --use-git-hash ${PX4_BOARD}.bin ${uavcan_bl_imange_name} + COMMAND + COMMAND ${CMAKE_COMMAND} -E make_directory deploy + COMMAND + ${CMAKE_COMMAND} -E copy ${uavcan_bl_imange_name} deploy/${HWBOARD_ID}.bin DEPENDS ${PX4_BINARY_DIR}/${PX4_BOARD}.bin ${CMAKE_CURRENT_SOURCE_DIR}/make_can_boot_descriptor.py diff --git a/src/drivers/uavcan/libuavcan b/src/drivers/uavcan/libuavcan index b1dc99279a..c445d90d37 160000 --- a/src/drivers/uavcan/libuavcan +++ b/src/drivers/uavcan/libuavcan @@ -1 +1 @@ -Subproject commit b1dc99279a468ae0de31dbc608d3090c7d73d16b +Subproject commit c445d90d370cb61e11d26ba46b86256b63b25561 diff --git a/src/drivers/uavcan/uavcan_module.hpp b/src/drivers/uavcan/uavcan_module.hpp index 4d8247ccb3..ea7420482a 100644 --- a/src/drivers/uavcan/uavcan_module.hpp +++ b/src/drivers/uavcan/uavcan_module.hpp @@ -49,12 +49,13 @@ // firmware paths #define UAVCAN_MAX_PATH_LENGTH (128 + 40) -#define UAVCAN_FIRMWARE_PATH "/fs/microsd/fw" +#define UAVCAN_SD_ROOT_PATH "/fs/microsd/" +#define UAVCAN_FIRMWARE_PATH UAVCAN_SD_ROOT_PATH"ufw" #define UAVCAN_ROMFS_FW_PATH "/etc/uavcan/fw" #define UAVCAN_ROMFS_FW_PREFIX "_" // logging -#define UAVCAN_NODE_DB_PATH "/fs/microsd/uavcan.db" +#define UAVCAN_NODE_DB_PATH UAVCAN_SD_ROOT_PATH"/uavcan.db" #define UAVCAN_LOG_FILE UAVCAN_NODE_DB_PATH"/trace.log" // device files diff --git a/src/drivers/uavcan/uavcan_servers.cpp b/src/drivers/uavcan/uavcan_servers.cpp index ec7bd11657..827374d84b 100644 --- a/src/drivers/uavcan/uavcan_servers.cpp +++ b/src/drivers/uavcan/uavcan_servers.cpp @@ -38,6 +38,7 @@ #include #include +#include #include #include #include @@ -73,8 +74,6 @@ * UavcanNode */ -#define UAVCAN_FIRMWARE_CACHE_PATH UAVCAN_FIRMWARE_PATH"/c/" - UavcanServers *UavcanServers::_instance; UavcanServers::UavcanServers(uavcan::INode &main_node) : @@ -211,7 +210,7 @@ UavcanServers::init() * Initialize the fw version checker. * giving it its path */ - ret = _fw_version_checker.createFwPaths(UAVCAN_FIRMWARE_PATH); + ret = _fw_version_checker.createFwPaths(UAVCAN_FIRMWARE_PATH, UAVCAN_ROMFS_FW_PATH); if (ret < 0) { PX4_ERR("FirmwareVersionChecker init: %d, errno: %d", ret, errno); @@ -220,7 +219,7 @@ UavcanServers::init() /* Start fw file server back */ - ret = _fw_server.start(UAVCAN_FIRMWARE_CACHE_PATH); + ret = _fw_server.start(UAVCAN_FIRMWARE_PATH, UAVCAN_ROMFS_FW_PATH); if (ret < 0) { PX4_ERR("BasicFileServer init: %d, errno: %d", ret, errno); @@ -266,7 +265,7 @@ UavcanServers::init() } /* Start the fw version checker */ - ret = _fw_upgrade_trigger.start(_node_info_retriever, _fw_version_checker.getFirmwarePath()); + ret = _fw_upgrade_trigger.start(_node_info_retriever); if (ret < 0) { PX4_ERR("FirmwareUpdateTrigger init: %d", ret); @@ -285,10 +284,10 @@ UavcanServers::run(pthread_addr_t) Lock lock(_subnode_mutex); /* - Copy any firmware bundled in the ROMFS to the appropriate location on the - SD card, unless the user has copied other firmware for that device. + Check for firmware in the root directory, move it to appropriate location on + the SD card, as defined by the APDesc. */ - unpackFwFromROMFS(UAVCAN_FIRMWARE_PATH, UAVCAN_ROMFS_FW_PATH); + migrateFWFromRoot(UAVCAN_FIRMWARE_PATH, UAVCAN_SD_ROOT_PATH); /* the subscribe call needs to happen in the same thread, * so not in the constructor */ @@ -952,259 +951,84 @@ UavcanServers::cb_enumeration_save(const uavcan::ServiceCallResultd_type)) { - continue; + if (rv != 0) { + PX4_ERR("dev: couldn't create '%s'", sd_path); + return; } - - // Make sure the path fits - size_t dev_dirname_len = strlen(dev_dirent->d_name); - size_t srcpath_dev_len = romfs_path_len + 1 + dev_dirname_len; - - if (srcpath_dev_len > maxlen) { - PX4_WARN("dev: srcpath '%s/%s' too long", romfs_path, dev_dirent->d_name); - continue; - } - - size_t dstpath_dev_len = sd_path_len + 1 + dev_dirname_len; - - if (dstpath_dev_len > maxlen) { - PX4_WARN("dev: dstpath '%s/%s' too long", sd_path, dev_dirent->d_name); - continue; - } - - // Create the device name directory on the SD card if it doesn't already exist - dstpath[sd_path_len] = '/'; - memcpy(&dstpath[sd_path_len + 1], dev_dirent->d_name, dev_dirname_len + 1); - - if (stat(dstpath, &sb) != 0 || !S_ISDIR(sb.st_mode)) { - rv = mkdir(dstpath, S_IRWXU | S_IRWXG | S_IRWXO); - - if (rv != 0) { - PX4_ERR("dev: couldn't create '%s'", dstpath); - continue; - } - } - - // Set up the source path - srcpath[romfs_path_len] = '/'; - memcpy(&srcpath[romfs_path_len + 1], dev_dirent->d_name, dev_dirname_len + 1); - - DIR *const dev_dir = opendir(srcpath); - - if (!dev_dir) { - PX4_ERR("dev: couldn't open '%s'", srcpath); - continue; - } - - // Iterate over all version directories in the current ROMFS device directory - struct dirent *ver_dirent = NULL; - - while ((ver_dirent = readdir(dev_dir)) != NULL) { - // Skip if not a directory - if (!DIRENT_ISDIRECTORY(ver_dirent->d_type)) { - continue; - } - - // Make sure the path fits - size_t ver_dirname_len = strlen(ver_dirent->d_name); - size_t srcpath_ver_len = srcpath_dev_len + 1 + ver_dirname_len; - - if (srcpath_ver_len > maxlen) { - PX4_ERR("ver: srcpath '%s/%s' too long", srcpath, ver_dirent->d_name); - continue; - } - - size_t dstpath_ver_len = dstpath_dev_len + 1 + ver_dirname_len; - - if (dstpath_ver_len > maxlen) { - PX4_ERR("ver: dstpath '%s/%s' too long", dstpath, ver_dirent->d_name); - continue; - } - - // Create the device version directory on the SD card if it doesn't already exist - dstpath[dstpath_dev_len] = '/'; - memcpy(&dstpath[dstpath_dev_len + 1], ver_dirent->d_name, ver_dirname_len + 1); - - if (stat(dstpath, &sb) != 0 || !S_ISDIR(sb.st_mode)) { - rv = mkdir(dstpath, S_IRWXU | S_IRWXG | S_IRWXO); - - if (rv != 0) { - PX4_ERR("ver: couldn't create '%s'", dstpath); - continue; - } - } - - // Set up the source path - srcpath[srcpath_dev_len] = '/'; - memcpy(&srcpath[srcpath_dev_len + 1], ver_dirent->d_name, ver_dirname_len + 1); - - // Find the name of the bundled firmware file, or move on to the - // next directory if there's no file here. - DIR *const src_ver_dir = opendir(srcpath); - - if (!src_ver_dir) { - PX4_ERR("ver: couldn't open '%s'", srcpath); - continue; - } - - struct dirent *src_fw_dirent = NULL; - - while ((src_fw_dirent = readdir(src_ver_dir)) != NULL && - !DIRENT_ISFILE(src_fw_dirent->d_type)); - - if (!src_fw_dirent) { - (void)closedir(src_ver_dir); - continue; - } - - size_t fw_len = strlen(src_fw_dirent->d_name); - - bool copy_fw = true; - - // Clear out any romfs_ files in the version directory on the SD card - DIR *const dst_ver_dir = opendir(dstpath); - - if (!dst_ver_dir) { - PX4_ERR("unlink: couldn't open '%s'", dstpath); - - } else { - struct dirent *fw_dirent = NULL; - - while ((fw_dirent = readdir(dst_ver_dir)) != NULL) { - // Skip if not a file - if (!DIRENT_ISFILE(fw_dirent->d_type)) { - continue; - } - - if (!memcmp(&fw_dirent->d_name, src_fw_dirent->d_name, fw_len)) { - /* - * Exact match between SD card filename and ROMFS filename; must be the same version - * so don't bother deleting and rewriting it. - */ - copy_fw = false; - - } else if (!memcmp(fw_dirent->d_name, UAVCAN_ROMFS_FW_PREFIX, sizeof(UAVCAN_ROMFS_FW_PREFIX) - 1)) { - size_t dst_fw_len = strlen(fw_dirent->d_name); - size_t dstpath_fw_len = dstpath_ver_len + dst_fw_len; - - if (dstpath_fw_len > maxlen) { - // sizeof(prefix) includes trailing NUL, cancelling out the +1 for the path separator - PX4_ERR("unlink: path '%s/%s' too long", dstpath, fw_dirent->d_name); - - } else { - // File name starts with "_", delete it. - dstpath[dstpath_ver_len] = '/'; - memcpy(&dstpath[dstpath_ver_len + 1], fw_dirent->d_name, dst_fw_len + 1); - unlink(dstpath); - PX4_ERR("unlink: removed '%s'", dstpath); - } - - } else { - // User file, don't copy firmware - copy_fw = false; - } - } - - (void)closedir(dst_ver_dir); - } - - // If we need to, copy the file from ROMFS to the SD card - if (copy_fw) { - size_t srcpath_fw_len = srcpath_ver_len + 1 + fw_len; - size_t dstpath_fw_len = dstpath_ver_len + fw_len; - - if (srcpath_fw_len > maxlen) { - PX4_ERR("copy: srcpath '%s/%s' too long", srcpath, src_fw_dirent->d_name); - - } else if (dstpath_fw_len > maxlen) { - PX4_ERR("copy: dstpath '%s/%s' too long", dstpath, src_fw_dirent->d_name); - - } else { - // All OK, make the paths and copy the file - srcpath[srcpath_ver_len] = '/'; - memcpy(&srcpath[srcpath_ver_len + 1], src_fw_dirent->d_name, fw_len + 1); - - dstpath[dstpath_ver_len] = '/'; - memcpy(&dstpath[dstpath_ver_len + 1], src_fw_dirent->d_name, fw_len + 1); - - rv = copyFw(dstpath, srcpath); - - if (rv != 0) { - PX4_ERR("copy: '%s' -> '%s' failed: %d", srcpath, dstpath, rv); - - } else { - PX4_INFO("copy: '%s' -> '%s' succeeded", srcpath, dstpath); - } - } - } - - (void)closedir(src_ver_dir); - } - - (void)closedir(dev_dir); } - (void)closedir(romfs_dir); + // Iterate over all bin files in root directory + struct dirent *dev_dirent = NULL; + + while ((dev_dirent = readdir(sd_root_dir)) != nullptr) { + + uavcan_posix::FirmwareVersionChecker::AppDescriptor descriptor; + + // Looking for all uavcan.bin files. + + if (DIRENT_ISFILE(dev_dirent->d_type) && strstr(dev_dirent->d_name, ".bin") != nullptr) { + + // Make sure the path fits + + size_t filename_len = strlen(dev_dirent->d_name); + size_t srcpath_len = sd_root_path_len + 1 + filename_len; + + if (srcpath_len > maxlen) { + PX4_WARN("file: srcpath '%s%s' too long", sd_root_path, dev_dirent->d_name); + continue; + } + + snprintf(srcpath, sizeof(srcpath), "%s%s", sd_root_path, dev_dirent->d_name); + + if (uavcan_posix::FirmwareVersionChecker::getFileInfo(srcpath, descriptor, 1024) != 0) { + continue; + } + + if (descriptor.image_crc == 0) { + continue; + } + + snprintf(dstpath, sizeof(dstpath), "%s/%d.bin", sd_path, descriptor.board_id); + + if (copyFw(dstpath, srcpath) >= 0) { + unlink(srcpath); + } + } + } + + if (dev_dirent != nullptr) { + (void)closedir(dev_dirent); + } } int diff --git a/src/drivers/uavcan/uavcan_servers.hpp b/src/drivers/uavcan/uavcan_servers.hpp index 9fed3ec28b..15fa6cabeb 100644 --- a/src/drivers/uavcan/uavcan_servers.hpp +++ b/src/drivers/uavcan/uavcan_servers.hpp @@ -220,5 +220,6 @@ private: uavcan::ServiceClient _enumeration_save_client; void unpackFwFromROMFS(const char *sd_path, const char *romfs_path); + void migrateFWFromRoot(const char *sd_path, const char *sd_root_path); int copyFw(const char *dst, const char *src); };