Skip to content

Latest commit

 

History

History
75 lines (57 loc) · 2.86 KB

FirmwareUpdate.md

File metadata and controls

75 lines (57 loc) · 2.86 KB

Firmware update procedure

There is two ways to write a new firmware:

  • using standard bootlader
  • placement of a custom loader in RAM

Standard boot

used for uploading main firmware

  • start programming session: 10 02, it should automatically restart ECU to boot mode
  • enter security (see below)
  • run RequestDownload with address 08001000 and length 000FF000: 34 00 44 08 00 10 00 00 0F F0 00
  • sequentially run TransferData: 36 00 ... (up to 2K bytes data per request)
  • run RequestTransferExit: 37
  • run Routine FF01 with address 08001000 length 000FF000 and checksum CC9E: 31 01 FF 01 44 08 00 10 00 00 0F F0 00 CC 9E
  • run Routine FF00 with address 08200000 length 00001000: 31 01 FF 00 44 08 20 00 00 00 00 10 00
  • run RequestDownload with address 08200000 and length 00000010:34 00 44 08 20 00 00 00 00 00 10
  • transfer 16 bytes by TransferData: 36 00 ...
  • run RequestTransferExit: 37
  • reboot ECU: 11 01

Custom loader

used to write eeprom and to read back flash/eeprom

  • start systemSupplierSpecific session: 10 60, ECU didnt switched to boot(!)
  • enter security (see below)
  • sequentially run WriteMemoryByAddress to upload custom binary at 20019800..2001B148: 3D 24 <addr 4 bytes> <len 2 bytes> <data, up to 512 bytes>
  • run Routine F000 with address 20019800: 31 01 F0 00 20 01 98 00
  • run SecurityAccess (algorithm not known)
  • now you able to run RoutineControl, ReadMemoryByAddress, WriteMemoryByAddress with some weird (crypted?) parameters. Transferred data also looks crypted.

Security access

Security access for bootloader and core fw performed with this exchange:

-> 27 01 <rnd, 1 byte>
<- 67 01 <seed, 4 bytes big endian>
-> 27 02 <key, 4 bytes big endian>
<- 67 02

Key must be calculated with this formula:

uint32_t Uds_Security_CalcKey(uint32_t secret, uint32_t seed, uint8_t rnd)
{
    if (rnd < 220)
        rnd += 35;
    else
        rnd = 255;

    for (uint8_t i = 0; i < rnd; i ++)
    {
        if ((int)seed < 0)
            seed = secret ^ seed << 1;
        else
            seed <<= 1;
    }
    return seed;
}

where secret is 0x57649392 for main app and 0xB24F5249 for bootloader.

Available routines

UDS service 31 RunRoutine supports several routines

  • F000 (only in main firmware, not available in bootloader) can start any user code: 31 01 F0 00 <addr, 4 bytes big endian>. Sample: 31 01 F0 00 20 01 98 00.
  • FF00 (probably, only in boot) can erase memory: 31 01 FF 00 44 <addr, 4 bytes> <size, 4 bytes>. Sample: 31 01 FF 00 44 08 20 00 00 00 00 10 00.
  • FF01 (also looks like only in boot) can verify checksum. Algorithm is very simple, just uint16_t with summ of all bytes: 31 01 FF 01 44 <addr, 4 bytes> <size, 4 bytes> <checksum, 2 bytes big endian>. Sample: 31 01 FF 01 44 08 00 10 00 00 0F F0 00 CC 9E