codebndr / Ariadne-Bootloader

A little less unfinished TFTP bootloader for Arduino Ethernet or Arduino with Ethernet Shield
codebender.cc
98 stars 37 forks source link

bin-file generated from PlatformIO (avr-gcc ide) does not work with Ariadne #22

Closed rwalli closed 8 years ago

rwalli commented 8 years ago

Hello!

Ariadne works fine for bin-files from various Arduino-IDE-Versions. If I try to upload a file from PlatformIO (http://platformio.org) Ariadne respond back an error (received opcode=800 sent WRQ ).

Debug output: Main: Ariadne for Arduino Uno, Version 0.5 Net: Built-in settings Net: .Address: 0xC0.0xA8.0x01.0x80 Net: . Subnet: 0xFF.0xFF.0xFF.0x00 Net: .Gateway: 0xC0.0xA8.0x01.0xFE Net: . MAC: 0xDE.0xAD.0xBE.0xEF.0xFE.0xED Net: Network init done Tftp: Init socket to port 0x0045 Tftp: TFTP server init done Tftp: .DataPort: 0xB779 Tftp: Processing packet of size 0x001D Tftp: Set up return address Tftp: This is block 0x6669 with opcode 0x0002 and data length 0x0011 Tftp: Write request Tftp: Init socket to port 0xB779 Tftp: Changed to port 0xB779 Tftp: Sent ACK Tftp: Response sent Tftp: Processing packet of size 0x020C Tftp: Set up return address Tftp: This is block 0x0001 with opcode 0x0003 and data length 0x0200 Tftp: Data block Tftp: Writing data from address 0x000000 Tftp: Packet length adjusted to 0x0200 Tftp: Response sent Tftp: Processing packet of size 0x8800 Tftp: Overflow Tftp: Set up return address Tftp: This is block 0xC19C with opcode 0x0A0B and data length 0xFE1D Tftp: Invalid opcode 0x0000 Tftp: Init socket to port 0xB779 Tftp: Response sent Tftp: Processing packet of size 0x020C Tftp: Set up return address Tftp: This is block 0x0001 with opcode 0x0003 and data length 0x0200 Tftp: Data block Tftp: Writing data from address 0x000000 Tftp: Packet length adjusted to 0x0200 Tftp: Response sent Tftp: Processing packet of size 0x8800 Tftp: Overflow Tftp: Set up return address Tftp: This is block 0xC19C with opcode 0x0A0B and data length 0xFE1D Tftp: Invalid opcode 0x0000 Tftp: Init socket to port 0xB779 Tftp: Response sent Tftp: Processing packet of size 0x020C Tftp: Set up return address Tftp: This is block 0x0001 with opcode 0x0003 and data length 0x0200 Tftp: Data block Tftp: Writing data from address 0x000000 Tftp: Packet length adjusted to 0x0200 Tftp: Response sent Tftp: Processing packet of size 0x8800 Tftp: Overflow

Robert

loathingKernel commented 8 years ago

Most probably the binary file fails to validate during the built-in checks as a proper Arduino Uno program. Programs generated by avr-gcc have table of instructions that is unique to each MCU, something we used as a validation that the user is not trying to upload "nonsense" to the microcontroller. Maybe PlatformIO is using a different way of building the binaries and such signatures are not present.

rwalli commented 8 years ago

Hello and thank you for your answer!

I can upload binaries from PlatformIO with any bootloader except Ariadne. Maybe other bootloaders do not properly check signatures. Could you tell me which part of the file you check, so i can post it on the PlatformIO site?

Here ist the .elf file of the blink example: https://drive.google.com/file/d/0B-D7L6AG-gBvR3dRc3pRNVZMNG8/view?usp=sharing and here the .hex part: https://drive.google.com/file/d/0B-D7L6AG-gBveWdDbF9xOG1ZVlk/view?usp=sharing

Robert

loathingKernel commented 8 years ago

I will take a look at your firmware and reply with more information later, I just wanted to say that no other bootloader checks for these signatures because it is not needed when you upload your program using the STK (the usual serial way) protocol, for example. To be honest, there is no proper way of checking for signatures or verifying the firmware, we just "exploited" a pattern in the generated binary to avoid uploading an image or an audio file, for example.

rwalli commented 8 years ago

Could you give me a short hint where too look for a workaround? If i disable validation ( validImage returns 1) the bootloader copies the file but won't start it up.

There seems to be no pattern in these files (first 128 bytes):

Uno blink example:

5BC00000|69C00000|67C00000|65C00000|63C00000|61C00000|5FC00000|5DC00000|
5BC00000|59C00000|57C00000|55C00000|53C00000|51C00000|4FC00000|4DC00000|
6BC00000|49C00000|47C00000|45C00000|43C00000|41C00000|3FC00000|3DC00000|
3BC00000|39C00000|00000008|00020100|00030407|00000000|00000000|01020408|

Another Uno image:

EAC00000|4FC10000|0DC10000|0BC10000|09C10000|07C10000|05C10000|04C10000|
01C10000|FFC00000|FDC00000|FBC00000|F9C00000|F7C00000|73C10000|F3C00000|
0C94801E|EFC00000|73C50000|A3C50000|E9C00000|E7C00000|E5C00000|E3C00000|
E1C00000|DFC00000|005EBCE2|613FDD83|C29C7E20|A3FD1F41|9DC3217F|FCA2401E|

Mega 2560 image:

59C20000|88C20000|86C20000|84C20000|82C20000|80C20000|7EC20000|7CC20000|
7AC20000|78C20000|76C20000|74C20000|72C20000|70C20000|6EC20000|6CC20000|
6AC20000|68C20000|66C20000|64C20000|62C20000|60C20000|5EC20000|0C94F30F|
5AC20000|0C94200D|0C94560D|54C20000|52C20000|50C20000|4EC20000|4CC20000|

Another Mega 2560 image:

AFC70000|DEC70000|DCC70000|DAC70000|D8C70000|D6C70000|D4C70000|D2C70000|
D0C70000|CEC70000|CCC70000|CAC70000|C8C70000|0C94C74C|C4C70000|C2C70000|
C0C70000|BEC70000|BCC70000|BAC70000|B8C70000|B6C70000|B4C70000|0C941A2E|
B0C70000|0C94C026|0C94F626|AAC70000|A8C70000|A6C70000|A4C70000|A2C70000|
loathingKernel commented 8 years ago

I see... Can you post here the exact version of the avr-toolchain PlatformIO is using? My blink example, compiled through codebender (last time I used arduino-ide, it was producing the same pattern), starts like this :

:10000000|0C946100|0C947E00|0C947E00|0C947E0095
:10001000|0C947E00|0C947E00|0C947E00|0C947E0068
:10002000|0C947E00|0C947E00|0C947E00|0C947E0058
:10003000|0C947E00|0C947E00|0C947E00|0C947E0048
:10004000|0C94A000|0C947E00|0C947E00|0C947E0016
:10005000|0C947E00|0C947E00|0C947E00|0C947E0028
:10006000|0C947E00|0C947E00|00000000|2400270009

You can easily see the pattern 0C94 which is a JMP instruction followed by an WXYZ address.

The pattern for Mega 2560 was a bit more complicated and the validations were disabled for Mega 2560 by default.

Since your firmware, even with the validations disabled, fails to start, there is a good chance the issue is more complicated.

rwalli commented 8 years ago

hmm... no good news.

here are the versions of the toolchain: avarice: 2.13 avr-binutils: 2.23.2 avr-gcc: 4.8.1 avr-libc: 1.8.0 avrdude: 6.0.1 gdb: 7.6.1 libusb: 0.1.12 make: 4.0 simulavr: 0.1.2.7

rwalli commented 8 years ago

I made mistake (did not find out which one). After starting from scratch the bootloader works when disabling validation and is not hanging anymore. Sorry for confusing. Is there a possibility to do a less strict validation or maybe start a watchdog in the bootloader which can be cleared in your code afterwards.

loathingKernel commented 8 years ago

Now that I am rethinking it, the best solution might be to remove the whole validation altogether, since this will allow for AVR C programs to be uploaded using the bootloader and not only Arduino programs. Watchdog is generally a bad idea since the user might forget to clear it and he will be locked out of the Arduino until he reflashes the bootloader.

rwalli commented 8 years ago

If the user forgets to clear the watchdog he will be able to upload the right code afterwards because the device will continue rebooting. If the user messed up the code so that he's not abel to reboot it by his software, the bootloader will flash it with or without validation. So maybe validation makes more troubles than it solves?

I'll comment out validation which is a good solution form me. Thank you very much for your help (and sorry for my bad english)!