FWU API

To complete a firmware update (FWU) the firmware image is transferred from a client to a device using various links e.g. serial (HDLC) or Ethernet (TCP).

This image can be sent in one or more data chunks depending on type of link along with client and the device resources available.

Each step in FWU is acknowledged by the device before client is allowed to proceed. This is to allow the device to throttle data transfer giving the device time to process the received data.

For safety reasons a list of devices allowed in a specific firmware is embedded in the firmware image. This means that only devices, which are intended for a firmware, can be firmware updated with the image.

FWU Process

Initialize FWU by sending total size of the firmware image. Target will respond with acknowledge if it is ready or not. This includes checks for e.g. battery level, charging, flash size etc.

Data is transferred in chunks, where the maximum chunk size is dictated by the target device during FWU initialization. Each FWU data chunk is acknowledged to provide the device enough time to process the data e.g. storing it in memory or writing to flash.

Anytime during the image transfer, the client is allowed to send FwuAbortReq command. However, once the device has started applying the update {state: ERASING_FLASH} the FWU cannot be aborted. If device encounters an error it will abort FWU by sending FwuStateInd with the error state.

In responses messages the Status is SUCCESS if the message was successfully received and all other Status values means the message was not successful.

FWU Serial

Below is an example of how a 10MB FWU image is transferred to a device where the device has dictated a maximum chunk size of 1kB.

msc {
client,device;
hscale=3;
vspacing=5;

client->device: FwuInitReq\n\-\{size: 10485760, ...\};
device->device: \-bytes_remaining=10485760;
client<-device: FwuInitRes\n\-\{status: SUCCESS, state: RECEIVING_DATA, max_chunk_size: 1024\};
client<-device: FwuStateInd\n\-\{state: RECEIVING_DATA\};
client->device: FwuChunkReq\-(1024 bytes);
device->device: \-bytes_remaining=10484736;
client<-device: FwuChunkRes\n\-\{status: SUCCESS\};
client->device: FwuChunkReq\-(1024 bytes);
device->device: \-bytes_remaining=10483712;
client<-device: FwuChunkRes\n\-\{status: SUCCESS\};

...;
...;
client->device: FwuChunkReq\-(1024 bytes);
device->device: \-bytes_remaining=0;
client<-device: FwuChunkRes\n\-\{status: SUCCESS\};
client<-device: FwuStateInd\n\-\{state: PROCESSING_IMAGE\};
|||;
---: Target cannot be stopped after this point;
|||;
client<-device: FwuStateInd\n\-\{state: ERASING_FLASH\};
client<-device: FwuStateInd\n\-\{state: WRITING_FLASH\};
client<-device: FwuStateInd\n\-\{state: VERIFY_FLASH\};
client<-device: FwuStateInd\n\-\{state: FWU_COMPLETE\};
}

FWU Ethernet

Same procedure as above, but during FWU via ethernet the target device may dictate larger maximum chunk sizes. Note that transfer with only one chunk is possible. Below is an example of FWU with only one chunk with 10MB data.

msc {
client,device;
hscale=3;
vspacing=5;

client->device: FwuInitReq\n\-\{size: 10485760, ...\};
device->device: \-bytes_remaining=10485760;
client<-device: FwuInitRes\n\-\{status: SUCCESS, state: RECEIVING_DATA, max_chunk_size=10485760\};
client<-device: FwuStateInd\n\-\{state: RECEIVING_DATA\};
client->device: FwuChunkReq\-(10485760 bytes);
device->device: \-bytes_remaining=0;
client<-device: FwuChunkRes\n\-\{status: SUCCESS\};
client<-device: FwuStateInd\n\-\{state: PROCESSING_IMAGE\};
|||;
---: Target cannot be stopped after this point;
|||;
client<-device: FwuStateInd\n\-\{state: ERASING_FLASH\};
client<-device: FwuStateInd\n\-\{state: WRITING_FLASH\};
client<-device: FwuStateInd\n\-\{state: VERIFY_FLASH\};
client<-device: FwuStateInd\n\-\{state: FWU_COMPLETE\};
}

FWU error handling

Size of firmware image too big or the device is not ready to do FWU.

msc {
client,device;
hscale=3;
vspacing=5;

client->device: FwuInitReq\n\-\{size: 10485760, ...\};
device->device: \-Firmware too large;
client<-device [color=red]: FwuInitRes\n\-\{status: ERR_SIZE, state: ERROR, ...\};
}

Firmware image contains a list of allowed devices for the specific firmware. For this reason the FWU may be aborted after this information has been received in the transfer.

msc {
client,device;
hscale=3;
vspacing=5;

client->device: FwuInitReq\n\-\{size: 10485760, ...\};
client<-device: FwuInitRes\n\-\{status: SUCCESS, state: RECEIVING_DATA, max_chunk_size: 1024\};
client<-device: FwuStateInd\n\-\{state: RECEIVING_DATA\};
client->device: FwuChunkReq\-(1024 bytes);
device->device: \-Firmware not approved for this device;
client<-device [color=red]: FwuChunkRes\n\-\{status: ERR_NOT_SUPPORTED\};
client<-device: FwuStateInd\n\-\{state: ERROR\};
}

Received more bytes than expected.

msc {
client,device;
hscale=3;
vspacing=5;

client->device: FwuInitReq\n\-\{size: 10485760, ...\};
device->device: \-bytes_remaining=10485760;
client<-device: FwuInitRes\n\-\{status: SUCCESS, state: RECEIVING_DATA, , max_chunk_size: 10485760\};
client<-device: FwuStateInd\n\-\{state: RECEIVING_DATA\};
client->device: FwuChunkReq\-(10485660 bytes);
device->device: \-bytes_remaining=100;
client<-device: FwuChunkRes\n\-\{status: SUCCESS\};
client->device: FwuChunkReq\-(1024 bytes);
device->device: \-Too many bytes received;
client<-device: FwuChunkRes\n\-\{status: ERR_SIZE\};
client<-device [color=red]: FwuStateInd\n\-\{state: ERROR\};
}

Client aborts during transfer.

msc {
client,device;
hscale=3;
vspacing=5;

client->device: FwuInitReq\n\-\{size: 10485760, ...\};
device->device: \-bytes_remaining=10485760;
client<-device: FwuInitRes\n\-\{status: SUCCESS, state: RECEIVING_DATA, , max_chunk_size: 1024\};
client<-device: FwuStateInd\n\-\{state: RECEIVING_DATA\};
client->device: FwuChunkReq\-(1024 bytes);
device->device: \-bytes_remaining=10484736;
client<-device: FwuChunkRes\n\-\{status: SUCCESS\};

client->device: FwuChunkReq\-(1024 bytes);
device->device: \-bytes_remaining=10483712;
client->device [color=red]: FwuAbortReq;
client<-device: FwuAbortRes\n\-\{status: SUCCESS, state: IDLE\};
}

Client aborts too late in the process and the device will complete the FWU.

msc {
client,device;
hscale=3;
vspacing=5;

client->device: FwuInitReq\n\-\{size: 10485760, ...\};
device->device: \-bytes_remaining=10485760;
client<-device: FwuInitRes\n\-\{status: SUCCESS, state: RECEIVING_DATA, , max_chunk_size: 10485760\};
client<-device: FwuStateInd\n\-\{state: RECEIVING_DATA\};
client->device: FwuChunkReq\-(10485760 bytes);
device->device: \-bytes_remaining=0;
client<-device: FwuChunkRes\n\-\{status: SUCCESS\};
client<-device: FwuStateInd\n\-\{state: PROCESSING_IMAGE\};
|||;
---: Target cannot be stopped after this point;
|||;
client<-device: FwuStateInd\n\-\{state: ERASING_FLASH\};
client->device [color=red]: FwuAbortReq;
client<-device [color=red]: FwuAbortRes\n\-\{status: ERR_NOT_READY, state: ERASING_FLASH\};
client<-device: FwuStateInd\n\-\{state: WRITING_FLASH\};
client<-device: FwuStateInd\n\-\{state: VERIFY_FLASH\};
client<-device: FwuStateInd\n\-\{state: FWU_COMPLETE\};
}

Target fails to respond with an acknowledge on a chunk.

msc {
client,device;
hscale=3;
vspacing=5;

client->device: FwuInitReq\n\-\{size: 10485760, ...\};
device->device: \-bytes_remaining=10485760;
client<-device: FwuInitRes\n\-\{status: SUCCESS, state: RECEIVING_DATA, , max_chunk_size: 1024\};
client<-device: FwuStateInd\n\-\{state: RECEIVING_DATA\};
client->device: FwuChunkReq\-(1024 bytes);
device->device: \-bytes_remaining=10484736;
device-xc [color=red]: FwuChunkRes;
...;
...;
---: When client has waited \"long enough\" it will abort;
|||;
client->device [color=red]: FwuAbortReq;
client<-device: FwuAbortRes\n\-\{status: SUCCESS, state: IDLE\};
}

Client stops sending FWU image chunks and the FWU is aborted after a timeout period.

msc {
client,device;
hscale=3;
vspacing=5;

client->device: FwuInitReq\n\-\{size: 10485760, ...\};
device->device: \-bytes_remaining=10485760;
client<-device: FwuInitRes\n\-\{status: SUCCESS, state: RECEIVING_DATA, , max_chunk_size: 1024\};
client<-device: FwuStateInd\n\-\{state: RECEIVING_DATA\};
client->device: FwuChunkReq\-(1024 bytes);
device->device: \-bytes_remaining=10484736;
client<-device: FwuChunkRes\n\-\{status: SUCCESS\};
...;
...;
--- [color=red]: Client stops sending FWU data chunks and time passes;
...;
...;
client<-device: FwuStateInd\n\-\{state: IDLE\};
}

If a new FWU is started while another is being processed then the first is aborted and the new session is started.

msc {
client,device;
hscale=3;
vspacing=5;

client->device: FwuInitReq\n\-\{size: 10485760, ...\};
device->device: \-bytes_remaining=10485760;
client<-device: FwuInitRes\n\-\{status: SUCCESS, state: RECEIVING_DATA, , max_chunk_size: 1024\};
client<-device: FwuStateInd\n\-\{state: RECEIVING_DATA\};
client->device: FwuChunkReq\-(1024 bytes);
device->device: \-bytes_remaining=10484736;
client<-device: FwuChunkRes\n\-\{status: SUCCESS\};

client->device: FwuInitReq\n\-\{size: 10485760, ...\};
device->device: \-bytes_remaining=10485760;
client<-device: FwuInitRes\n\-\{status: SUCCESS, state: RECEIVING_DATA, , max_chunk_size: 1024\};
client<-device: FwuStateInd\n\-\{state: RECEIVING_DATA\};
client->device: FwuChunkReq\-(1024 bytes);
device->device: \-bytes_remaining=10484736;
client<-device: FwuChunkRes\n\-\{status: SUCCESS\};

client->device: FwuChunkReq\-(1024 bytes);
device->device: \-bytes_remaining=10483712;
client<-device: FwuChunkRes\n\-\{status: SUCCESS\};

...;
...;
client->device: FwuChunkReq\-(1024 bytes);
device->device: \-bytes_remaining=0;
client<-device: FwuChunkRes\n\-\{status: SUCCESS\};

client<-device: FwuStateInd\n\-\{state: PROCESSING_IMAGE\};
|||;
---: Target cannot be stopped after this point;
|||;
client<-device: FwuStateInd\n\-\{state: ERASING_FLASH\};
client<-device: FwuStateInd\n\-\{state: WRITING_FLASH\};
client<-device: FwuStateInd\n\-\{state: VERIFY_FLASH\};
client<-device: FwuStateInd\n\-\{state: FWU_COMPLETE\};
}

Checksum calculation fails on image received. Please note that in this situation the device may have an invalid image and unable to operate. Client must retry FWU.

msc {
client,device;
hscale=3;
vspacing=5;

client->device: FwuInitReq\n\-\{size: 10485760, ...\};
device->device: \-bytes_remaining=10485760;
client<-device: FwuInitRes\n\-\{status: SUCCESS, state: RECEIVING_DATA, , max_chunk_size: 10485760\};
client<-device: FwuStateInd\n\-\{state: RECEIVING_DATA\};
client->device: FwuChunkReq\-(10485760 bytes);
device->device: \-bytes_remaining=0;
client<-device: FwuChunkRes\n\-\{status: SUCCESS\};
client<-device: FwuStateInd\n\-\{state: PROCESSING_IMAGE\};
client<-device: FwuStateInd\n\-\{state: ERASING_FLASH\};
client<-device: FwuStateInd\n\-\{state: WRITING_FLASH\};
client<-device: FwuStateInd\n\-\{state: VERIFY_FLASH\};
client<-device [color=red]: FwuStateInd\n\-\{state: ERROR\};
|||;
--- [color=red]: Client should initialize a new FWU\nTarget may be in a non-working state;
|||;
}

Protobuf specification

The following documentation is generated from the Protobuf specification in src/protobuf/mdif/fwu/fwu.proto.

Table of Contents

mdif/common.proto

Common to all mdif protobuffers.

Status

Defines the status of a request

Name

Number

Description

SUCCESS

0

The request was successful

FAILURE

1

The request failed

ERR_INVALID

2

The request was invalid

ERR_NOT_SUPPORTED

3

The request is not supported

ERR_NOT_IMPLEMENTED

4

The request is not implemented

ERR_NOT_READY

5

The device is not ready to process the request

ERR_SIZE

6

The device cannot process the size

mdif/fwu/fwu.proto

Message allocation for the FWU component are in the range:

Start

End

Radix

0x20

0x2F

Hex

32

47

Dec

FwuService

Defines the relationship between requests and responses in the FWU component

Method Name

Request Type

Response Type

Description

FwuInit

FwuInitReq

FwuInitRes

Used to initialize FWU

FwuAbort

FwuAbortReq

FwuAbortRes

Used to abort an active FWU

FwuChunk

FwuChunkReq

FwuChunkRes

Used to transmit a chunk with firmware data

FwuAbortReq

Abort FWU process

FwuAbortRes

Response on FwuAbortReq

Field

Type

Description

status

mdif.common.Status

The status of the request

state

State

FWU state of the device

FwuChunkReq

Chunk data contains part of FWU image

Field

Type

Description

data

bytes

Section of firmware image

FwuChunkRes

Response on FwuChunkReq

Field

Type

Description

status

mdif.common.Status

The status of the request

FwuInitReq

Initialize Firmware Update with size of firmware image.

‘force’ flag will skip any update guards in code making it possible to up/downgrade using firmware which is not directly supported by the device. Note this will void warranty if used without written approval from MyDefence.

Field

Type

Description

size

uint32

Size of FWU image

force

bool

Note using this flag could brik the device

FwuInitRes

Response on FwuInitReq

Field

Type

Description

status

mdif.common.Status

The status of the request

state

State

If in State.RECEIVING_DATA the device is ready to proceed

max_chunk_size

uint32

Max chunk size in bytes

FwuMsg

FWU wire format message

This message dictates the final format on the wire for FWU messages. It is a oneof construct to wrap a single message at a time.

Every request (req) has a corresponding response (res). The req/res pairs are defined in the FwuService below through RPC patterns.

Indications (ind) are pushed without a request at any time

Field

Type

Description

fwu_init_req

FwuInitReq

Request FWU initialization

fwu_init_res

FwuInitRes

FWU init response

fwu_chunk_req

FwuChunkReq

Request with FWU image chunk of data

fwu_chunk_res

FwuChunkRes

FWU chunk data response

fwu_state_ind

FwuStateInd

FWU state indication

fwu_abort_req

FwuAbortReq

Request FWU to abort

fwu_abort_res

FwuAbortRes

FWU abort response

FwuStateInd

Indication with current FWU state of the device

Field

Type

Description

state

State

FWU state of the device

State

Enumeration of possible states of FWU

End-states means the FWU process has terminated

Name

Number

Description

IDLE

0

FWU not started (end-state)

RECEIVING_DATA

1

Data is being transfered to the device

PROCESSING_IMAGE

2

Processing received firmware data

ERASING_FLASH

3

Flash is being erased

WRITING_FLASH

4

Firmware is being written to flash

VERIFYING_FLASH

5

Written firmware is verified in flash

FWU_COMPLETE

6

FWU is successfully completed (end-state)

ERROR

7

An error has occured and FWU was not completed (end-state)

Scalar Value Types

.proto Type

Notes

C++

Java

Python

Go

C#

PHP

Ruby

double

double

double

float

float64

double

float

Float

float

float

float

float

float32

float

float

Float

int32

Uses variable-length encoding. Inefficient for encoding negative numbers – if your field is likely to have negative values, use sint32 instead.

int32

int

int

int32

int

integer

Bignum or Fixnum (as required)

int64

Uses variable-length encoding. Inefficient for encoding negative numbers – if your field is likely to have negative values, use sint64 instead.

int64

long

int/long

int64

long

integer/string

Bignum

uint32

Uses variable-length encoding.

uint32

int

int/long

uint32

uint

integer

Bignum or Fixnum (as required)

uint64

Uses variable-length encoding.

uint64

long

int/long

uint64

ulong

integer/string

Bignum or Fixnum (as required)

sint32

Uses variable-length encoding. Signed int value. These more efficiently encode negative numbers than regular int32s.

int32

int

int

int32

int

integer

Bignum or Fixnum (as required)

sint64

Uses variable-length encoding. Signed int value. These more efficiently encode negative numbers than regular int64s.

int64

long

int/long

int64

long

integer/string

Bignum

fixed32

Always four bytes. More efficient than uint32 if values are often greater than 2^28.

uint32

int

int

uint32

uint

integer

Bignum or Fixnum (as required)

fixed64

Always eight bytes. More efficient than uint64 if values are often greater than 2^56.

uint64

long

int/long

uint64

ulong

integer/string

Bignum

sfixed32

Always four bytes.

int32

int

int

int32

int

integer

Bignum or Fixnum (as required)

sfixed64

Always eight bytes.

int64

long

int/long

int64

long

integer/string

Bignum

bool

bool

boolean

boolean

bool

bool

boolean

TrueClass/FalseClass

string

A string must always contain UTF-8 encoded or 7-bit ASCII text.

string

String

str/unicode

string

string

string

String (UTF-8)

bytes

May contain any arbitrary sequence of bytes.

string

ByteString

str

[]byte

ByteString

string

String (ASCII-8BIT)