stefanrueger / urboot

Small AVR bootloader using urprotocol
GNU General Public License v3.0
67 stars 11 forks source link

Erase flash from top to bottom #18

Closed stefanrueger closed 1 year ago

stefanrueger commented 1 year ago

This PR addresses a vulnerability for vector bootloaders during chip erase: As the bootloader needs to erase page-by-page in order to not delete the bootloader itself the process lasts around 4-5 ms times the number of available flash pages, typically in the order of seconds. Any reset during this chip erase might leave the reset vector at position 0 unprogrammed risking the bootloader to be bricked.

The solution is simple: erase flash from top to bottom. This leaves the page with the reset vector to be erased last. Once all pages below the bootloader are erased, there is no longer a risk of bricking: Empty flash acts like sbrs r31,7 (skip instruction if bit 7 in register 31 is set) so a reset will eventually end up in the bootloader.

This PR has restructures the chip erase function in the bootloader (if present) to erase from flash to to flash bottom. Turns out this also saves 2 bytes!

The change is simple and easy to understand. However, it's better is this was tested in a few parts, eg, ATmega2560, ATmega1284P, one 4-page-erase ATtiny1634 and a couple of other chips. Could you help, please @mcuee or @MCUdude?

mcuee commented 1 year ago

It works fine for ATmega2560, using autobaud vector bootloader.

PS C:\work\avr\urboot_pr18> git branch -a
* ce_top2bottom
  main
  remotes/origin/HEAD -> origin/main
  remotes/origin/ce_top2bottom
  remotes/origin/main

PS C:\work\avr\avrdude_test\avrdude_bin> .\avrdude -c usbasp -p m2560 -U lfuse:r:-:h -U hfuse:r:-:h -U efuse:r:-:h -qq
0xf7
0xd7
0xfd

PS C:\work\avr\avrdude_test\avrdude_bin> .\avrdude -c usbasp -p m2560 -U flash:w:C:\work\avr\urboot_pr18\bootloaders\atmega2560\autobaud\urboot_atmega2560_autobaud_ee_led+b7_fr_ce_ur_vbl.hex:i -qq && echo OK
OK

PS C:\work\avr\avrdude_test\avrdude_bin> .\avrdude -c urclock -P COM18 -p m2560 -xshowall

avrdude: AVR device initialized and ready to accept instructions
0000ffffffff 0000-00-00 00.00  application 0 store 0 meta 0 boot 512 u7.7 weu-jPrac vector 40 (SPM_READY) ATmega2560
PS C:\work\avr\avrdude_test\avrdude_bin> .\avrdude -c urclock -P COM18 -b 125000 -p m2560 -U .\hex\Blink.ino.mega.hex

avrdude: AVR device initialized and ready to accept instructions
avrdude: device signature = 0x1e9801 (probably m2560)
avrdude: Note: flash memory has been specified, an erase cycle will be performed.
         To disable this feature, specify the -D option.
avrdude: erasing chip
avrdude: reading input file .\hex\Blink.ino.mega.hex for flash
         with 1536 bytes in 1 section within [0, 0x5ff]
         using 6 pages and 0 pad bytes
avrdude: preparing flash input for device bootloader
avrdude: writing 1536 bytes flash ...

Writing | ################################################## | 100% 0.23 s

avrdude: 1536 bytes of flash written
avrdude: verifying flash memory against .\hex\Blink.ino.mega.hex

Reading | ################################################## | 100% 0.17 s

avrdude: 1536 bytes of flash verified

avrdude done.  Thank you.

PS C:\work\avr\avrdude_test\avrdude_bin> .\avrdude -c urclock -P COM18 -p m2560 -xshowall

avrdude: AVR device initialized and ready to accept instructions
0000ffffffff 2022-06-03 19.03 Blink.ino.mega.hex 1536 store 260062 meta 34 boot 512 u7.7 weu-jPrac vector 40 (SPM_READY) ATmega2560
mcuee commented 1 year ago

Another test using hardware bootloader.

PS C:\work\avr\avrdude_test\avrdude_bin> .\avrdude -c usbasp -p m2560 -U lfuse:r:-:h -U hfuse:r:-:h -U efuse:r:-:h -qq
0xf7
0xd6
0xfd

PS C:\work\avr\avrdude_test\avrdude_bin> .\avrdude -c usbasp -p m2560 -U flash:w:C:\work\avr\urboot_pr18\bootloaders\atmega2560\autobaud\urboot_atmega2560_autobaud_ee_led+b7_fr_ce_ur.hex:i -qq && echo OK
OK

PS C:\work\avr\avrdude_test\avrdude_bin> .\avrdude -c urclock -P COM18 -p m2560 -xshowall

avrdude: AVR device initialized and ready to accept instructions
0000ffffffff 0000-00-00 00.00  application 0 store 0 meta 0 boot 1024 u7.7 weu-hprac vector 0 (RESET) ATmega2560
PS C:\work\avr\avrdude_test\avrdude_bin> .\avrdude -c urclock -P COM18 -b 125000 -p m2560 -U .\hex\Blink.ino.mega.hex

avrdude: AVR device initialized and ready to accept instructions
avrdude: device signature = 0x1e9801 (probably m2560)
avrdude: Note: flash memory has been specified, an erase cycle will be performed.
         To disable this feature, specify the -D option.
avrdude: erasing chip
avrdude: reading input file .\hex\Blink.ino.mega.hex for flash
         with 1536 bytes in 1 section within [0, 0x5ff]
         using 6 pages and 0 pad bytes
avrdude: preparing flash input for device bootloader
avrdude: writing 1536 bytes flash ...

Writing | ################################################## | 100% 0.23 s

avrdude: 1536 bytes of flash written
avrdude: verifying flash memory against .\hex\Blink.ino.mega.hex

Reading | ################################################## | 100% 0.17 s

avrdude: 1536 bytes of flash verified

avrdude done.  Thank you.

PS C:\work\avr\avrdude_test\avrdude_bin> .\avrdude -c urclock -P COM18 -p m2560 -xshowall

avrdude: AVR device initialized and ready to accept instructions
0000ffffffff 2022-06-03 19.03 Blink.ino.mega.hex 1536 store 259550 meta 34 boot 1024 u7.7 weu-hprac vector 0 (RESET) ATmega2560
mcuee commented 1 year ago

Tested ATmega328PB as well.

PS C:\work\avr\avrdude_test\avrdude_bin> .\avrdude -c usbasp -p m328pb -U lfuse:r:-:h -U hfuse:r:-:h -U efuse:r:-:h -qq
0xff
0xd7
0xf5

PS C:\work\avr\avrdude_test\avrdude_bin> .\avrdude -c usbasp -p m328pb -U flash:w:C:\work\avr\urboot_pr18\bootloaders\atmega328pb\autobaud\urboot_atmega328pb_autobaud_ee_lednop_fr_ce_ur_vbl.hex:i -qq && echo OK
OK

PS C:\work\avr\avrdude_test\avrdude_bin> .\avrdude -c urclock -P COM18 -p m328pb -xshowall

avrdude: AVR device initialized and ready to accept instructions
0000ffffffff 0000-00-00 00.00  application 0 store 0 meta 0 boot 384 u7.7 weu-jPrac vector 25 (SPM_Ready) ATmega328PB
PS C:\work\avr\avrdude_test\avrdude_bin> .\avrdude -c urclock -P COM18 -b 125000 -p m328pb -U .\Blink.ino_m328pb.hex

avrdude: AVR device initialized and ready to accept instructions
avrdude: device signature = 0x1e9516 (probably m328pb)
avrdude: Note: flash memory has been specified, an erase cycle will be performed.
         To disable this feature, specify the -D option.
avrdude: erasing chip
avrdude: reading input file .\Blink.ino_m328pb.hex for flash
         with 1232 bytes in 1 section within [0, 0x4cf]
         using 10 pages and 48 pad bytes
avrdude: preparing flash input for device bootloader
avrdude: writing 1232 bytes flash ...

Writing | ################################################## | 100% 0.21 s

avrdude: 1232 bytes of flash written
avrdude: verifying flash memory against .\Blink.ino_m328pb.hex

Reading | ################################################## | 100% 0.17 s

avrdude: 1232 bytes of flash verified

avrdude done.  Thank you.

PS C:\work\avr\avrdude_test\avrdude_bin> .\avrdude -c urclock -P COM18 -p m328pb -xshowall

avrdude: AVR device initialized and ready to accept instructions
0000ffffffff 2022-12-24 14.18 Blink.ino_m328pb.hex 1232 store 31120 meta 32 boot 384 u7.7 weu-jPrac vector 25 (SPM_Ready) ATmega328PB