If it's possible with AVR executable images, a digital signature would solve some of the problems. As an added bonus, if the developer keeps the signing key a secret, the provenance of an image can determined.
OK, took some time today, ran a few tests with essentially some variations on the following code.
volatile char UUID[] = "<UUID=da51a9f0-9a49-11e0-aa80-0800200c9a66>";
char version[] = "UUID_TEST 0.04";
void setup()
{
Serial.begin(115200);
Serial.println(version);
UUID[0] = UUID[0];
}
void loop(){}
Then I retrieved the whole 32K image with [dosbox windows 7]
cd C:\Program Files (x86)\arduino-0021\hardware\tools\avr\bin>
avrdude -C "C:\Program Files (x86)\arduino-0022\hardware\tools\avr\etc\avrdude.conf" -v -v -v -v -p atmega328p -c stk500 -U flash:r:"C:/arduino.bin":r -P\\.\COM5 -b57600
viewing the binary easily reveals the UUID. See picture attached.
Some notes:
The UUID array must be volatile and the assignment UUID[0] = UUID[0] are needed both otherwise the compiler optimizes it away.
size without UUID string: 1908 bytes
size with UUID string: 1960 bytes
so this proof of concept implementation took 52 bytes.
- Remove the tag structure <UUID=...> (-7) => 45 bytes
- Remove - signs in the UUID (-4) => 41 bytes
- Make the UUID binary (-17) => 24 bytes.
proof is in the pudding test:
volatile uint8_t UUID[] = { 0x65, 0x65, 0x65, 0x65, 0x65, 0x65, 0x65, 0x65,
0x65, 0x65, 0x65, 0x65, 0x65, 0x65, 0x65, 0x65 }; // character e 16 times
char version[] = "UUID_TEST 0.06";
void setup()
{
Serial.begin(115200);
Serial.println(version);
UUID[0] = UUID[0];
}
void loop(){}
size without UUID uint8_t array : 1908 bytes
size with UUID uint8_t array: 1932 bytes
so UUID signature now takes 24 bytes.
OK tinkered enough
Rob
RAM is in short supply. You MUST figure out how to put the UUID in flash only (and not have it garbage collected.)
first try
#include <avr/pgmspace.h>
//volatile char UUID[] = "<UUID=da51a9f0-9a49-11e0-aa80-0800200c9a66>";
volatile uint8_t UUID[] PROGMEM =
{ 0x65, 0x65, 0x65, 0x65, 0x65, 0x65, 0x65, 0x65,
0x65, 0x65, 0x65, 0x65, 0x65, 0x65, 0x65, 0x65 };
char version[] = "UUID_TEST 0.08";
void setup()
{
Serial.begin(115200);
Serial.println(version);
uint8_t x = UUID[0];
}
void loop(){}
code size: 1928 ; so 4 bytes less but ==> 16 in PROGMEM and 4 in RAM, data still need to be referenced from RAM
gotta think deeper ....
2.5 hours and many many webpages later, dived into assembly to find out how to declare an array in assembly in flash.
- http://www.avrfreaks.net/index.php?name=PNphpBB2&file=printview&t=35337&start=0 - was the eyeopening site
char version[] = "UUID_TEST 0.10";
void setup()
{
asm volatile(
".cseg" // use code segment
"uuid: .byte 101,102,101,102,101,102,101,102,101,102,101,102,101,102,101,102"
);
Serial.begin(115200);
Serial.println(version);
}
void loop(){}
code size: 1924 ; so the 16 bytes of the UUID in flash; no reference needed
filling the "uuid array" can also be done in hex
"uuid: .byte 0x65, 0x65, 0x65, 0x65, 0x65, 0x65, 0x65, 0x65,0x65, 0x65, 0x65, 0x65, 0x65, 0x65, 0x65, 0x65"
or a bit shorter
"uuid: .word 0x6565, 0x6565, 0x6565, 0x6565, 0x6565, 0x6565, 0x6565, 0x6565"
So in the end storing a signature in the flash part of the code is only a few lines.
Thanks westfw for pushing me to the limits, I learned a few bits...
Rob
I didn't mean to make you dig deeply into advanced magics (though perhaps it was a good thing!)
It's also possible to get the linker to treat any file as "binary" to be explicitly included (maybe) in a final .elf/.hex file.
It would look something like
avr-objcopy -v -I binary -O elf32-avr -B avr mysketch.pde sourcecode.o
(objcopy is one of those utilities that is a lot more complex than you would think it would be. It handles OODLES of different formats!)