From dce931fd18355257247ffca65a9293a928c12f4c Mon Sep 17 00:00:00 2001 From: dragonmux Date: Wed, 30 Oct 2024 12:05:25 +0000 Subject: [PATCH 1/6] hosted/bmp_libusb: Fixed pre-v1.7 firmware identification where the firmware does not include a version string in the product string --- src/platforms/hosted/bmp_libusb.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/platforms/hosted/bmp_libusb.c b/src/platforms/hosted/bmp_libusb.c index 14815e9d09d..adf563596d3 100644 --- a/src/platforms/hosted/bmp_libusb.c +++ b/src/platforms/hosted/bmp_libusb.c @@ -142,6 +142,12 @@ void bmp_read_product_version(libusb_device_descriptor_s *device_descriptor, lib (void)manufacturer; *product = get_device_descriptor_string(handle, device_descriptor->iProduct); + /* Check if the product name does not contain a version string */ + if (strcmp(*product, "Black Magic Probe") == 0) { + *version = strdup("Unknown"); + return; + } + char *start_of_version = strrchr(*product, ' '); if (start_of_version == NULL) { *version = NULL; From 7d8701ce88e324a4318daf0ee0cb5babef8799e4 Mon Sep 17 00:00:00 2001 From: dragonmux Date: Sun, 3 Nov 2024 00:06:10 +0000 Subject: [PATCH 2/6] hosted/bmp_libusb: Implement `strndup()` for Windows as this function is not found in the stdlib there --- src/platforms/hosted/bmp_libusb.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/src/platforms/hosted/bmp_libusb.c b/src/platforms/hosted/bmp_libusb.c index adf563596d3..2eda92f348e 100644 --- a/src/platforms/hosted/bmp_libusb.c +++ b/src/platforms/hosted/bmp_libusb.c @@ -80,6 +80,23 @@ static const debugger_device_s debugger_devices[] = { {0, 0, PROBE_TYPE_NONE, NULL, ""}, }; +#if defined(_WIN32) || defined(__CYGWIN__) +static char *strndup(const char *const src, const size_t size) +{ + /* Determine how many bytes to copy to the new string, including the NULL terminator */ + const size_t length = MIN(size, strlen(src)) + 1U; + /* Try to allocate storage for the new string */ + char *result = malloc(length); + if (!result) + return NULL; + /* Now we have storage, copy the bytes over */ + memcpy(result, src, length - 1U); + /* And finally terminate the string to return */ + result[length - 1U] = '\0'; + return result; +} +#endif + const debugger_device_s *get_debugger_device_from_vid_pid(const uint16_t probe_vid, const uint16_t probe_pid) { /* Iterate over the list excluding the last entry (PROBE_TYPE_NONE) */ From 168eb7b647ea0616c805405514d4ecffbf8b929f Mon Sep 17 00:00:00 2001 From: dragonmux Date: Wed, 30 Oct 2024 12:26:22 +0000 Subject: [PATCH 3/6] hosted/bmp_libusb: Improved the handling of the product string from BMP to properly handle the intricacies of the possible values it can take --- src/platforms/hosted/bmp_libusb.c | 69 +++++++++++++++++++++++-------- 1 file changed, 51 insertions(+), 18 deletions(-) diff --git a/src/platforms/hosted/bmp_libusb.c b/src/platforms/hosted/bmp_libusb.c index 2eda92f348e..c0d060cbb13 100644 --- a/src/platforms/hosted/bmp_libusb.c +++ b/src/platforms/hosted/bmp_libusb.c @@ -48,7 +48,9 @@ typedef int_least16_t char16_t; #include "utils.h" #include "hex_utils.h" -#define NO_SERIAL_NUMBER "" +#define NO_SERIAL_NUMBER "" +#define BMP_PRODUCT_STRING "Black Magic Probe" +#define BMP_PRODUCT_STRING_LENGTH ARRAY_LENGTH(BMP_PRODUCT_STRING) void bmp_read_product_version(libusb_device_descriptor_s *device_descriptor, libusb_device *device, libusb_device_handle *handle, char **product, char **manufacturer, char **serial, char **version); @@ -157,27 +159,58 @@ void bmp_read_product_version(libusb_device_descriptor_s *device_descriptor, lib (void)device; (void)serial; (void)manufacturer; - *product = get_device_descriptor_string(handle, device_descriptor->iProduct); + const char *const description = get_device_descriptor_string(handle, device_descriptor->iProduct); + const size_t description_len = strlen(description) + 1U; - /* Check if the product name does not contain a version string */ - if (strcmp(*product, "Black Magic Probe") == 0) { - *version = strdup("Unknown"); - return; - } + /* + * Black Magic Debug product strings are in one of the following forms: + * Recent: Black Magic Probe v1.10.0-1273-g2b1ce9aee + * : Black Magic Probe (ST-Link v2) v1.10.0-1273-g2b1ce9aee + * Old : Black Magic Probe + * From this we want to extract two main things: version (if available), and the product name + */ - char *start_of_version = strrchr(*product, ' '); - if (start_of_version == NULL) { - *version = NULL; - return; + /* Let's start out easy - check to see if the string contains an opening paren (alternate platform) */ + const char *const opening_paren = strchr(description + BMP_PRODUCT_STRING_LENGTH, '('); + /* If there isn't one, we're dealing with nominally a native probe */ + if (!opening_paren) { + /* Knowing this, let's see if there are enough bytes for a version string, and if there are.. extract it */ + if (description_len > BMP_PRODUCT_STRING_LENGTH) { + const char *version_begin = strrchr(description, ' '); + /* Thankfully, this can't fail, so just grab the version string from what we got */ + *version = strdup(version_begin + 1U); + /* Now extract the remaining chunk of the description as the product string */ + *product = strndup(description, version_begin - description); + } else { + /* We don't know the version (pre v1.7) and the description string is the product string */ + *version = strdup("Unknown"); + *product = strdup(description); + } + } else { + /* Otherwise, we've got a non-native probe, so find the closing paren for the probe type */ + const char *const closing_paren = strchr(opening_paren, ')'); + /* If we didn't find one, we've got a problem */ + if (!closing_paren) { + DEBUG_ERROR("Production description for device is invalid, founding opening '(' but no closing ')'\n"); + *version = strdup("Unknown"); + *product = strdup("Invalid"); + } else { + /* If we did find the closing ')', then see if we've got a version string*/ + const char *const version_begin = strchr(closing_paren, ' '); + /* If we do, then extract whatever's left of the string as the version string */ + if (version_begin) + *version = strdup(version_begin + 1U); + else + *version = strdup("Unknown"); + /* Now we've dealt with the version information, use everything up to the ')' as the product string */ + *product = strndup(description, (closing_paren - description) + 1U); + } } - while (start_of_version[0] == ' ' && start_of_version != *product) - --start_of_version; - start_of_version[1U] = '\0'; - start_of_version += 2U; - while (start_of_version[0] == ' ') - ++start_of_version; - *version = strdup(start_of_version); +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wcast-qual" + free((void *)description); +#pragma GCC diagnostic pop } /* From 2b29f4c9e5a5dcb20b57b3ff507f623e4484adb3 Mon Sep 17 00:00:00 2001 From: dragonmux Date: Wed, 30 Oct 2024 20:52:55 +0000 Subject: [PATCH 4/6] efm32: Fixed a couple of format string errors --- src/target/efm32.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/target/efm32.c b/src/target/efm32.c index 0f123f34bd3..e2ae72dfa3d 100644 --- a/src/target/efm32.c +++ b/src/target/efm32.c @@ -30,7 +30,8 @@ * * EFR32BG13P532F512GM32 (EFR Blue Gecko) */ -/* Refer to the family reference manuals: +/* + * Refer to the family reference manuals: * * Also refer to AN0062 "Programming Internal Flash Over the Serial Wire Debug Interface" * http://www.silabs.com/Support%20Documents/TechnicalDocs/an0062.pdf @@ -98,7 +99,7 @@ const command_s efm32_cmd_list[] = { /* Flash Information Area */ /* -------------------------------------------------------------------------- */ -#define EFM32_INFO 0x0fe00000U +#define EFM32_INFO UINT32_C(0x0fe00000) #define EFM32_USER_DATA (EFM32_INFO + 0x0000U) #define EFM32_LOCK_BITS (EFM32_INFO + 0x4000U) #define EFM32_V1_DI (EFM32_INFO + 0x8000U) @@ -766,11 +767,11 @@ static bool efm32_cmd_efm_info(target_s *t, int argc, const char **argv) switch (di_version) { case 1: - tc_printf(t, "DI version 1 (silabs remix?) base 0x%08" PRIx16 "\n\n", EFM32_V1_DI); + tc_printf(t, "DI version 1 (silabs remix?) base 0x%08" PRIx32 "\n\n", EFM32_V1_DI); break; case 2: - tc_printf(t, "DI version 2 (energy micro remix?) base 0x%08" PRIx16 "\n\n", EFM32_V2_DI); + tc_printf(t, "DI version 2 (energy micro remix?) base 0x%08" PRIx32 "\n\n", EFM32_V2_DI); break; default: From 17d21567f2beae5af4aa06d6e81da2bac327293f Mon Sep 17 00:00:00 2001 From: dragonmux Date: Wed, 30 Oct 2024 20:53:11 +0000 Subject: [PATCH 5/6] stm32l0: Fixed a couple of format string errors --- src/target/stm32l0.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/target/stm32l0.c b/src/target/stm32l0.c index b19087ac50e..0c66a8d78d5 100644 --- a/src/target/stm32l0.c +++ b/src/target/stm32l0.c @@ -765,16 +765,16 @@ static bool stm32lx_cmd_option(target_s *const target, const int argc, const cha const size_t read_protection = stm32lx_prot_level(options); if (stm32lx_is_stm32l1(target)) { tc_printf(target, - "OPTR: 0x%08" PRIx32 ", RDPRT %" PRIu32 ", SPRMD %u, BOR %" PRIu32 " , WDG_SW %u" + "OPTR: 0x%08" PRIx32 ", RDPRT %" PRIu32 ", SPRMD %u, BOR %" PRIu32 ", WDG_SW %u" ", nRST_STP %u, nRST_STBY %u, nBFB2 %u\n", - options, (uint32_t)read_protection, (options & STM32L1_FLASH_OPTR_SPRMOD) ? 1 : 0, + options, (uint32_t)read_protection, (options & STM32L1_FLASH_OPTR_SPRMOD) ? 1U : 0U, (options >> STM32L1_FLASH_OPTR_BOR_LEV_SHIFT) & STM32L1_FLASH_OPTR_BOR_LEV_MASK, - (options & STM32Lx_FLASH_OPTR_WDG_SW) ? 1 : 0, (options & STM32L1_FLASH_OPTR_nRST_STOP) ? 1 : 0, - (options & STM32L1_FLASH_OPTR_nRST_STDBY) ? 1 : 0, (options & STM32L1_FLASH_OPTR_nBFB2) ? 1 : 0); + (options & STM32Lx_FLASH_OPTR_WDG_SW) ? 1U : 0U, (options & STM32L1_FLASH_OPTR_nRST_STOP) ? 1U : 0U, + (options & STM32L1_FLASH_OPTR_nRST_STDBY) ? 1U : 0U, (options & STM32L1_FLASH_OPTR_nBFB2) ? 1U : 0U); } else { - tc_printf(target, "OPTR: 0x%08" PRIx32 ", RDPROT %" PRIu32 ", WPRMOD %" PRIu16 ", WDG_SW %u, BOOT1 %u\n", - options, (uint32_t)read_protection, (options & STM32L0_FLASH_OPTR_WPRMOD) ? 1 : 0, - (options & STM32Lx_FLASH_OPTR_WDG_SW) ? 1 : 0, (options & STM32L0_FLASH_OPTR_BOOT1) ? 1 : 0); + tc_printf(target, "OPTR: 0x%08" PRIx32 ", RDPROT %" PRIu32 ", WPRMOD %u, WDG_SW %u, BOOT1 %u\n", options, + (uint32_t)read_protection, (options & STM32L0_FLASH_OPTR_WPRMOD) ? 1U : 0U, + (options & STM32Lx_FLASH_OPTR_WDG_SW) ? 1U : 0U, (options & STM32L0_FLASH_OPTR_BOOT1) ? 1U : 0U); } goto done; From 47e2ed1a5e9269b1d3cc4720ed614c86152b0112 Mon Sep 17 00:00:00 2001 From: dragonmux Date: Wed, 30 Oct 2024 20:53:52 +0000 Subject: [PATCH 6/6] stm32l4: Improved the device lookup handling on attach by using the copy stored in the private structure --- src/target/stm32l4.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/target/stm32l4.c b/src/target/stm32l4.c index 7734338f348..75a7dc8b09a 100644 --- a/src/target/stm32l4.c +++ b/src/target/stm32l4.c @@ -744,8 +744,8 @@ static bool stm32l4_attach(target_s *const target) if (!cortexm_attach(target) || !stm32l4_configure_dbgmcu(target, NULL)) return false; - /* Retrieve device information, and locate the device ID register */ - const stm32l4_device_info_s *device = stm32l4_get_device_info(target->part_id); + /* Extract the device structure from the priv storage and enable the Flash if on an L55 part */ + const stm32l4_device_info_s *const device = ((stm32l4_priv_s *)target->priv)->device; if (device->family == STM32L4_FAMILY_L55x) stm32l5_flash_enable(target);