Now that you guys have schooled me on setting the protection bits for the bootloader so it can't update, er, uh, destroy itself, I've got some more thoughts...
I'm going to try my hand at building a secure bootloader that allows me to send someone an encrypted firmware file which is then sent to the device where its bootloader will decrypt and flash it.
One goal that I have is that as I rarely need to update firmware, I don't want to put any extra time or cost in soldering components to make it work.
I've been thinking about the various ways of delivering the encrypted firmware to the device. You could use a PDIP-8 SPI EEPROM and pop it into a socket or even nicely placed holes if your PCB has the room. Or use a sdcard if you don't mind soldering on a socket and the overhead of accessing a filesystem (I think it is clawson who has an excellent project example that does this). Then I was thinking about using one of those PL2303 cheap cables somehow, but they are all 5V TTL level and my concern is that I need to support projects from 2.5V-5V.
Then I had the idea of using a very cheap PC programmer board. I've already got USB stuff developed on the AVR and PC sides, so I could use a low cost ATMEGA8U2 along with a PC side application to provide the encrypted firmware from a file on a PC. Minimal parts. One nice thing is that it would be reusable and you could just email someone the encrypted file.
I read about a BSS138 based MOSFET that can be used for level translation and I am thinking of doing a 1 wire style (but not 1 wire) communication method. The thought was that if I could use a single GPIO for communication that doesn't require any peripheral, it would be workable with most any AVR/project. Probably with PCB something like this could be made for $5 or so.
With a single data line, the programmer would only need a ground and data line. Both sides (device and programmer) would have two states - input with pullup OR output low. The BSS138 I saw had two pullups, could the pullups in each AVR replace those two? The programmer would be the higher voltage side (5V) and the device would be the lower voltage side (2.5V-5V). As far as the protocol, the PC side would be the master MOST of the time, except during device startup. Its bootloader would send out 3 bytes (cmd + crc) to see if a programmer is present and wait for a reply. No reply = start device normally, Reply = stay in bootloader mode and wait for commands. At that point the PC side would be the master and send commands to get versions, send the encrypted firmware file, etc. The PC side app does not need to be privy to the page size of the device, its bootloader could know what it needs to do to decrypt and flash the data sent to it. I've done some testing about how accurate I can sample a GPIO pin to figure out a low pulse width and I think it should be +/- 3 cycles using SBIC/RJMP to check for the pin change. I also want to tolerate up to 20% clock error. Bit 0 would be 10us, with error and +/-3 cycles this would be a range of 5-15us. Bit 1 would be 25us would be 17-33us. End of packet would be 50us or 37-63us. So I would test for <16us = 0, <35us = 1, else end of packet. With a 100us width, this would be a 10K bit rate and there will be plenty of cycles to shift the bits in from a GPIO.
For input on the programmer I can use ICP1 to get precision clock accurate captures of low pulse widths, but on devices I would want to have the option of using any GPIO so I would go with the SBIC/RJMP method.
For output I would just use timed sequences to send the 10us, 25us, or 50us pulses.
I would extend my crcsntool to support a tag in each section (application, bootloader) that contains the crc16, version, and possibly the serial number if serialized. The SN would need to be in the bootloader tag if it was used to modify the encryption key so that each firmware file could be locked to a specific serial unit.
The PC app could have a check device button which queries if a device is connected and in bootloader mode. A get status button could retrieve firmware versions, whether they have a valid crc, and a serial number if present. A load firmware button could load a file for updating and an update button would do the update.
Thoughts, ideas, improvements?