From ec4146ceac1c06ba46ed30e1e50abe0ac722d0e8 Mon Sep 17 00:00:00 2001 From: Stefan Rueger Date: Wed, 2 Aug 2023 19:32:36 +0100 Subject: [PATCH 1/7] Provide sib memory for AVR8X parts --- src/avr.c | 1 + src/avrdude.1 | 2 ++ src/avrdude.conf.in | 10 ++++++++++ src/doc/avrdude.texi | 2 ++ src/serialupdi.c | 41 +++++++++++++++++++++++++++++++++++++++++ 5 files changed, 56 insertions(+) diff --git a/src/avr.c b/src/avr.c index d51afa797..7e714283e 100644 --- a/src/avr.c +++ b/src/avr.c @@ -1405,6 +1405,7 @@ const char *avr_mem_order[100] = { "tempsense", "signature", "prodsig", "sernum", "calibration", "osccal16", "osccal20", "osc16err", "osc20err", "usersig", "userrow", "data", + "sib", }; void avr_add_mem_order(const char *str) { diff --git a/src/avrdude.1 b/src/avrdude.1 index 2399f3d48..0340c4a0c 100644 --- a/src/avrdude.1 +++ b/src/avrdude.1 @@ -835,6 +835,8 @@ Temperature sensor calibration values .It userrow Extra page of EEPROM memory that can be used for firmware settings; this memory is not erased during a chip erase +.It sib +Special system information block memory with information about AVR family, chip revision etc. .El .Pp The diff --git a/src/avrdude.conf.in b/src/avrdude.conf.in index 6509854ae..91103c87c 100644 --- a/src/avrdude.conf.in +++ b/src/avrdude.conf.in @@ -18600,6 +18600,11 @@ part # SRAM, only used to supply the offset offset = 0x1000000; ; + + memory "sib" + size = 32; + readsize = 1; + ; ; #------------------------------------------------------------ @@ -20782,6 +20787,11 @@ part # SRAM, only used to supply the offset offset = 0x1000000; ; + + memory "sib" + size = 32; + readsize = 1; + ; ; #------------------------------------------------------------ diff --git a/src/doc/avrdude.texi b/src/doc/avrdude.texi index ecbcd58d8..8de132790 100644 --- a/src/doc/avrdude.texi +++ b/src/doc/avrdude.texi @@ -878,6 +878,8 @@ Temperature sensor calibration values @item userrow Extra page of EEPROM memory that can be used for firmware settings; this memory is not erased during a chip erase +@item sib +Special system information block memory with information about AVR family, chip revision etc. @end table diff --git a/src/serialupdi.c b/src/serialupdi.c index 794e4daf6..4ac264448 100644 --- a/src/serialupdi.c +++ b/src/serialupdi.c @@ -673,15 +673,43 @@ static int serialupdi_program_enable(const PROGRAMMER *pgm, const AVRPART *p) { return -1; } +#define Return(...) do { pmsg_error(__VA_ARGS__); msg_error("\n"); return -1; } while (0) + static int serialupdi_read_byte(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM *mem, unsigned long addr, unsigned char * value) { + pmsg_debug("%s(%s, 0x%04lx)\n", __func__, mem->desc, addr); + if(mem->size < 1) + Return("cannot read byte from %s %s owing to its size %d", p->desc, mem->desc, mem->size); + + if(addr >= (unsigned long) mem->size) + Return("cannot read byte from %s %s as address 0x%04lx outside range [0, 0x%04x]", + p->desc, mem->desc, addr, mem->size-1); + + if(str_eq(mem->desc, "sib")) { + if(addr >= SIB_INFO_STRING_LENGTH) + Return("cannot read byte from %s sib as address 0x%04lx outside range [0, 0x%04x]", + p->desc, addr, SIB_INFO_STRING_LENGTH-1); + if(!*updi_get_sib_info(pgm)->sib_string) // This should never happen + Return("cannot read byte from %s sib as memory not initialised", p->desc); + *value = updi_get_sib_info(pgm)->sib_string[addr]; + return 0; + } + return updi_read_byte(pgm, mem->offset + addr, value); } static int serialupdi_write_byte(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM *mem, unsigned long addr, unsigned char value) { + pmsg_debug("%s(%s, 0x%04lx, 0x%02x)\n", __func__, mem->desc, addr, value); + if(mem->size < 1) + Return("cannot write byte to %s %s owing to its size %d", p->desc, mem->desc, mem->size); + + if(addr >= (unsigned long) mem->size) + Return("cannot write byte to %s %s as address 0x%04lx outside range [0, 0x%04x]", + p->desc, mem->desc, addr, mem->size-1); + if (strstr(mem->desc, "fuse") != 0) { return updi_nvm_write_fuse(pgm, p, mem->offset + addr, value); } @@ -698,6 +726,19 @@ static int serialupdi_write_byte(const PROGRAMMER *pgm, const AVRPART *p, const buffer[0]=value; return updi_nvm_write_flash(pgm, p, mem->offset + addr, buffer, 1); } + // Read-only memories + if(str_eq(mem->desc, "osc16err") || str_eq(mem->desc, "osccal16") || + str_eq(mem->desc, "osc20err") || str_eq(mem->desc, "osccal20") || + str_eq(mem->desc, "prodsig") || str_eq(mem->desc, "sernum") || + str_eq(mem->desc, "sib")) { + + unsigned char is; + if(serialupdi_read_byte(pgm, p, mem, addr, &is) >= 0 && is == value) + return 0; + + Return("cannot write to read-only memory %s %s", p->desc, mem->desc); + } + return updi_write_byte(pgm, mem->offset + addr, value); } From b9ccd5630056d58dd21082ac1cff1fe891240bd1 Mon Sep 17 00:00:00 2001 From: Stefan Rueger Date: Wed, 2 Aug 2023 19:54:25 +0100 Subject: [PATCH 2/7] Align spacing --- src/avrdude.conf.in | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/avrdude.conf.in b/src/avrdude.conf.in index 91103c87c..e365005d7 100644 --- a/src/avrdude.conf.in +++ b/src/avrdude.conf.in @@ -18601,10 +18601,10 @@ part offset = 0x1000000; ; - memory "sib" + memory "sib" size = 32; readsize = 1; - ; + ; ; #------------------------------------------------------------ @@ -20788,10 +20788,10 @@ part offset = 0x1000000; ; - memory "sib" + memory "sib" size = 32; readsize = 1; - ; + ; ; #------------------------------------------------------------ From 768a7891083947f10ca5029753feff3a468a1241 Mon Sep 17 00:00:00 2001 From: MCUdude Date: Thu, 3 Aug 2023 09:46:06 +0200 Subject: [PATCH 3/7] Implement SIB read and add memory boundary checks --- src/jtag3.c | 42 +++++++++++++++++++++++++++++++++++++++--- src/libavrdude.h | 2 +- 2 files changed, 40 insertions(+), 4 deletions(-) diff --git a/src/jtag3.c b/src/jtag3.c index deafaf383..62d5470dc 100644 --- a/src/jtag3.c +++ b/src/jtag3.c @@ -89,6 +89,9 @@ struct pdata bool vtarg_set; double vtarg_data; + /* SIB string cache */ + char sib_string[AVR_SIBLEN]; + /* Function to set the appropriate clock parameter */ int (*set_sck)(const PROGRAMMER *, unsigned char *); }; @@ -1430,6 +1433,12 @@ static int jtag3_initialize(const PROGRAMMER *pgm, const AVRPART *p) { free(resp); + if (pgm->read_sib) { + if (pgm->read_sib(pgm, p, PDATA(pgm)->sib_string) < 0) { + pmsg_warning("cannot read SIB string from target %s\n", p->desc); + } + } + PDATA(pgm)->boot_start = ULONG_MAX; if (p->prog_modes & PM_PDI) { // Find the border between application and boot area @@ -2081,9 +2090,18 @@ static int jtag3_read_byte(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM paddr = jtag3_memaddr(pgm, p, mem, addr); if(paddr != addr) - msg_notice2(" mapped to address: 0x%lx\n", paddr); + imsg_notice2("mapped to address: 0x%lx\n", paddr); paddr = 0; + if(mem->size < 1) { + pmsg_error("cannot read byte from %s %s owing to its size %d\n", p->desc, mem->desc, mem->size); + return -1; + } else if(addr >= (unsigned long) mem->size) { + pmsg_error("cannot read byte from %s %s as address 0x%04lx outside range [0, 0x%04x]\n", + p->desc, mem->desc, addr, mem->size-1); + return -1; + } + if (!(pgm->flag & PGM_FL_IS_DW)) if ((status = jtag3_program_enable(pgm)) < 0) return status; @@ -2153,6 +2171,13 @@ static int jtag3_read_byte(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM cmd[3] = MTYPE_OSCCAL_BYTE; if (pgm->flag & PGM_FL_IS_DW) unsupp = 1; + } else if (str_eq(mem->desc, "sib")) { + if(!*PDATA(pgm)->sib_string) { + pmsg_error("cannot read byte from %s sib as memory not initialised\n", p->desc); + return -1; + } + *value = PDATA(pgm)->sib_string[addr]; + return 0; } else if (strcmp(mem->desc, "signature") == 0) { static unsigned char signature_cache[2]; @@ -2252,7 +2277,16 @@ static int jtag3_write_byte(const PROGRAMMER *pgm, const AVRPART *p, const AVRME mapped_addr = jtag3_memaddr(pgm, p, mem, addr); if(mapped_addr != addr) - msg_notice2(" mapped to address: 0x%lx\n", mapped_addr); + imsg_notice2("mapped to address: 0x%lx\n", mapped_addr); + + if(mem->size < 1) { + pmsg_error("cannot write byte to %s %s owing to its size %d\n", p->desc, mem->desc, mem->size); + return -1; + } else if(addr >= (unsigned long) mem->size) { + pmsg_error("cannot write byte to %s %s as address 0x%04lx outside range [0, 0x%04x]\n", + p->desc, mem->desc, addr, mem->size-1); + return -1; + } cmd[0] = SCOPE_AVR; cmd[1] = CMD3_WRITE_MEMORY; @@ -2310,8 +2344,10 @@ static int jtag3_write_byte(const PROGRAMMER *pgm, const AVRPART *p, const AVRME unsupp = 1; } - if (unsupp) + if (unsupp) { + pmsg_error("debugWire interface does not support writing to memory %s\n", mem->desc); return -1; + } if (pagesize != 0) { /* flash or EEPROM write: use paged algorithm */ diff --git a/src/libavrdude.h b/src/libavrdude.h index a0b540051..58c38d362 100644 --- a/src/libavrdude.h +++ b/src/libavrdude.h @@ -219,7 +219,7 @@ typedef struct opcode { #define HAS_VAREF_ADJ 32 #define AVR_FAMILYIDLEN 7 -#define AVR_SIBLEN 16 +#define AVR_SIBLEN 32 #define CTL_STACK_SIZE 32 #define FLASH_INSTR_SIZE 3 #define EEPROM_INSTR_SIZE 20 From a1bfae3f8e443e8d088e3c26423bac7fd1b40bb8 Mon Sep 17 00:00:00 2001 From: MCUdude Date: Thu, 3 Aug 2023 14:25:53 +0200 Subject: [PATCH 4/7] Formating + better read-only memory handling --- src/jtag3.c | 30 ++++++++++++++++++++---------- 1 file changed, 20 insertions(+), 10 deletions(-) diff --git a/src/jtag3.c b/src/jtag3.c index 62d5470dc..75da7b013 100644 --- a/src/jtag3.c +++ b/src/jtag3.c @@ -1896,7 +1896,7 @@ static int jtag3_paged_write(const PROGRAMMER *pgm, const AVRPART *p, const AVRM block_size = jtag3_memaddr(pgm, p, m, addr); if(block_size != addr) - msg_notice2(" mapped to address: 0x%04x\n", block_size); + imsg_notice2("mapped to address: 0x%04x\n", block_size); block_size = 0; if (!(pgm->flag & PGM_FL_IS_DW) && jtag3_program_enable(pgm) < 0) @@ -2004,7 +2004,7 @@ static int jtag3_paged_load(const PROGRAMMER *pgm, const AVRPART *p, const AVRME block_size = jtag3_memaddr(pgm, p, m, addr); if(block_size != addr) - msg_notice2(" mapped to address: 0x%04x\n", block_size); + imsg_notice2("mapped to address: 0x%04x\n", block_size); block_size = 0; if (!(pgm->flag & PGM_FL_IS_DW) && jtag3_program_enable(pgm) < 0) @@ -2089,14 +2089,15 @@ static int jtag3_read_byte(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM pmsg_notice2("jtag3_read_byte(.., %s, 0x%lx, ...)\n", mem->desc, addr); paddr = jtag3_memaddr(pgm, p, mem, addr); - if(paddr != addr) + if (paddr != addr) imsg_notice2("mapped to address: 0x%lx\n", paddr); paddr = 0; - if(mem->size < 1) { + if (mem->size < 1) { pmsg_error("cannot read byte from %s %s owing to its size %d\n", p->desc, mem->desc, mem->size); return -1; - } else if(addr >= (unsigned long) mem->size) { + } + if (addr >= (unsigned long) mem->size) { pmsg_error("cannot read byte from %s %s as address 0x%04lx outside range [0, 0x%04x]\n", p->desc, mem->desc, addr, mem->size-1); return -1; @@ -2343,11 +2344,20 @@ static int jtag3_write_byte(const PROGRAMMER *pgm, const AVRPART *p, const AVRME if (pgm->flag & PGM_FL_IS_DW) unsupp = 1; } - - if (unsupp) { - pmsg_error("debugWire interface does not support writing to memory %s\n", mem->desc); - return -1; - } + // Read-only memories or unsupported by debugWire + if(str_eq(mem->desc, "osc16err") || str_eq(mem->desc, "osccal16") || + str_eq(mem->desc, "osc20err") || str_eq(mem->desc, "osccal20") || + str_eq(mem->desc, "prodsig") || str_eq(mem->desc, "sernum") || + str_eq(mem->desc, "sib") || unsupp) { + unsigned char is; + if(jtag3_read_byte(pgm, p, mem, addr, &is) >= 0 && is == data) + return 0; + if (unsupp && pgm->flag & PGM_FL_IS_DW) + pmsg_error("debugWire interface does not support writing to memory %s\n", mem->desc); + else + pmsg_error("cannot write to read-only memory %s %s\n", p->desc, mem->desc); + return -1; + } if (pagesize != 0) { /* flash or EEPROM write: use paged algorithm */ From 1e4d78f17dc6151bc813630982ecec3445b08b96 Mon Sep 17 00:00:00 2001 From: MCUdude Date: Thu, 3 Aug 2023 14:42:37 +0200 Subject: [PATCH 5/7] Prevent reading more bytes than the SIB memory has --- src/jtag3.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/jtag3.c b/src/jtag3.c index 75da7b013..f7927fea9 100644 --- a/src/jtag3.c +++ b/src/jtag3.c @@ -2173,6 +2173,11 @@ static int jtag3_read_byte(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM if (pgm->flag & PGM_FL_IS_DW) unsupp = 1; } else if (str_eq(mem->desc, "sib")) { + if(addr >= AVR_SIBLEN) { + pmsg_error("cannot read byte from %s sib as address 0x%04lx outside range [0, 0x%04x]\n", + p->desc, addr, AVR_SIBLEN-1); + return -1; + } if(!*PDATA(pgm)->sib_string) { pmsg_error("cannot read byte from %s sib as memory not initialised\n", p->desc); return -1; From 0314e2158a6ade7ad647e0236efa7ff88d010ef1 Mon Sep 17 00:00:00 2001 From: Stefan Rueger Date: Thu, 3 Aug 2023 15:01:59 +0100 Subject: [PATCH 6/7] Add signature to read-only memories in serialupdi_write_byte() --- src/serialupdi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/serialupdi.c b/src/serialupdi.c index 4ac264448..94babd917 100644 --- a/src/serialupdi.c +++ b/src/serialupdi.c @@ -730,7 +730,7 @@ static int serialupdi_write_byte(const PROGRAMMER *pgm, const AVRPART *p, const if(str_eq(mem->desc, "osc16err") || str_eq(mem->desc, "osccal16") || str_eq(mem->desc, "osc20err") || str_eq(mem->desc, "osccal20") || str_eq(mem->desc, "prodsig") || str_eq(mem->desc, "sernum") || - str_eq(mem->desc, "sib")) { + str_eq(mem->desc, "signature") || str_eq(mem->desc, "sib")) { unsigned char is; if(serialupdi_read_byte(pgm, p, mem, addr, &is) >= 0 && is == value) From 7b90253aa1e9add887fe28dff20e63afdca25089 Mon Sep 17 00:00:00 2001 From: MCUdude Date: Thu, 3 Aug 2023 20:00:31 +0200 Subject: [PATCH 7/7] deal with more read-only memories --- src/jtag3.c | 19 +++++-------------- 1 file changed, 5 insertions(+), 14 deletions(-) diff --git a/src/jtag3.c b/src/jtag3.c index f7927fea9..08b0777cd 100644 --- a/src/jtag3.c +++ b/src/jtag3.c @@ -2334,26 +2334,17 @@ static int jtag3_write_byte(const PROGRAMMER *pgm, const AVRPART *p, const AVRME } else if (strcmp(mem->desc, "usersig") == 0 || strcmp(mem->desc, "userrow") == 0) { cmd[3] = MTYPE_USERSIG; - } else if (strcmp(mem->desc, "prodsig") == 0) { - cmd[3] = MTYPE_PRODSIG; } else if (str_starts(mem->desc, "lock")) { cmd[3] = MTYPE_LOCK_BITS; if (pgm->flag & PGM_FL_IS_DW) unsupp = 1; - } else if (strcmp(mem->desc, "calibration") == 0) { - cmd[3] = MTYPE_OSCCAL_BYTE; - if (pgm->flag & PGM_FL_IS_DW) - unsupp = 1; - } else if (strcmp(mem->desc, "signature") == 0) { - cmd[3] = MTYPE_SIGN_JTAG; - if (pgm->flag & PGM_FL_IS_DW) - unsupp = 1; } // Read-only memories or unsupported by debugWire - if(str_eq(mem->desc, "osc16err") || str_eq(mem->desc, "osccal16") || - str_eq(mem->desc, "osc20err") || str_eq(mem->desc, "osccal20") || - str_eq(mem->desc, "prodsig") || str_eq(mem->desc, "sernum") || - str_eq(mem->desc, "sib") || unsupp) { + if(str_eq(mem->desc, "calibration") || str_eq(mem->desc, "osc16err") || + str_eq(mem->desc, "osccal16") || str_eq(mem->desc, "osc20err") || + str_eq(mem->desc, "osccal20") || str_eq(mem->desc, "prodsig") || + str_eq(mem->desc, "sernum") || str_eq(mem->desc, "sib") || + str_eq(mem->desc, "signature") || str_eq(mem->desc, "temperature") || unsupp) { unsigned char is; if(jtag3_read_byte(pgm, p, mem, addr, &is) >= 0 && is == data) return 0;