Files
templates/c/set-protocol/src/set_firmware.c

168 lines
6.2 KiB
C

#include "set_firmware.h"
#include <string.h>
size_t setp_fw_begin_encode(const setp_fw_begin_t *value, uint8_t *out, size_t capacity)
{
size_t total;
if ((value == NULL) || (out == NULL)
|| (value->block_size == 0U)
|| (value->block_size > SETP_MAX_PAYLOAD - SETP_FW_DATA_HEADER_SIZE)
|| ((value->signature_length != 0U) && (value->signature == NULL))) {
return 0U;
}
total = (size_t)SETP_FW_BEGIN_FIXED_SIZE + value->signature_length;
if ((total > SETP_MAX_PAYLOAD) || (capacity < total)
|| (((value->flags & SETP_FW_FLAG_SIGNED) != 0U)
&& (value->signature_length == 0U))) {
return 0U;
}
setp_put_u32(&out[0], value->image_size);
setp_put_u32(&out[4], value->image_crc32);
setp_put_u32(&out[8], value->image_version);
setp_put_u32(&out[12], value->base_address);
out[16] = value->slot;
out[17] = value->flags;
setp_put_u16(&out[18], value->block_size);
(void)memcpy(&out[20], value->sha256, SETP_SHA256_SIZE);
setp_put_u32(&out[52], value->signing_key_id);
setp_put_u16(&out[56], value->signature_length);
if (value->signature_length != 0U) {
(void)memcpy(&out[SETP_FW_BEGIN_FIXED_SIZE], value->signature,
value->signature_length);
}
return total;
}
bool setp_fw_begin_decode(const uint8_t *payload, uint16_t length, setp_fw_begin_t *out)
{
uint16_t signature_length;
if ((payload == NULL) || (out == NULL) || (length < SETP_FW_BEGIN_FIXED_SIZE)) {
return false;
}
out->image_size = setp_get_u32(&payload[0]);
out->image_crc32 = setp_get_u32(&payload[4]);
out->image_version = setp_get_u32(&payload[8]);
out->base_address = setp_get_u32(&payload[12]);
out->slot = payload[16];
out->flags = payload[17];
out->block_size = setp_get_u16(&payload[18]);
(void)memcpy(out->sha256, &payload[20], SETP_SHA256_SIZE);
out->signing_key_id = setp_get_u32(&payload[52]);
signature_length = setp_get_u16(&payload[56]);
if (length != SETP_FW_BEGIN_FIXED_SIZE + signature_length) {
return false;
}
out->signature_length = signature_length;
out->signature = signature_length != 0U ? &payload[SETP_FW_BEGIN_FIXED_SIZE] : NULL;
return (out->block_size != 0U)
&& (out->block_size <= SETP_MAX_PAYLOAD - SETP_FW_DATA_HEADER_SIZE)
&& (((out->flags & SETP_FW_FLAG_SIGNED) == 0U) || (signature_length != 0U));
}
size_t setp_fw_data_encode(uint32_t offset, uint16_t flags,
const uint8_t *data, uint16_t data_length,
uint8_t *out, size_t capacity)
{
size_t total = (size_t)SETP_FW_DATA_HEADER_SIZE + data_length;
if ((data == NULL) || (out == NULL) || (data_length == 0U)
|| (total > SETP_MAX_PAYLOAD) || (capacity < total)) {
return 0U;
}
setp_put_u32(&out[0], offset);
setp_put_u16(&out[4], data_length);
setp_put_u16(&out[6], flags);
setp_put_u32(&out[8], setp_crc32(data, data_length));
(void)memcpy(&out[SETP_FW_DATA_HEADER_SIZE], data, data_length);
return total;
}
bool setp_fw_data_decode(const uint8_t *payload, uint16_t length, setp_fw_data_t *out)
{
uint16_t data_length;
if ((payload == NULL) || (out == NULL) || (length < SETP_FW_DATA_HEADER_SIZE)) {
return false;
}
data_length = setp_get_u16(&payload[4]);
if ((data_length == 0U) || (length != SETP_FW_DATA_HEADER_SIZE + data_length)) {
return false;
}
out->offset = setp_get_u32(&payload[0]);
out->data_length = data_length;
out->flags = setp_get_u16(&payload[6]);
out->data_crc32 = setp_get_u32(&payload[8]);
out->data = &payload[SETP_FW_DATA_HEADER_SIZE];
return setp_crc32(out->data, out->data_length) == out->data_crc32;
}
size_t setp_fw_end_encode(const setp_fw_end_t *value, uint8_t *out, size_t capacity)
{
if ((value == NULL) || (out == NULL) || (capacity < SETP_FW_END_SIZE)) {
return 0U;
}
setp_put_u32(&out[0], value->image_size);
setp_put_u32(&out[4], value->image_crc32);
(void)memcpy(&out[8], value->sha256, SETP_SHA256_SIZE);
return SETP_FW_END_SIZE;
}
bool setp_fw_end_decode(const uint8_t *payload, uint16_t length, setp_fw_end_t *out)
{
if ((payload == NULL) || (out == NULL) || (length != SETP_FW_END_SIZE)) {
return false;
}
out->image_size = setp_get_u32(&payload[0]);
out->image_crc32 = setp_get_u32(&payload[4]);
(void)memcpy(out->sha256, &payload[8], SETP_SHA256_SIZE);
return true;
}
size_t setp_fw_status_encode(const setp_fw_status_t *value, uint8_t *out, size_t capacity)
{
if ((value == NULL) || (out == NULL) || (capacity < SETP_FW_STATUS_SIZE)) {
return 0U;
}
out[0] = value->state;
out[1] = value->active_slot;
setp_put_u16(&out[2], value->max_block_size);
setp_put_u32(&out[4], value->next_offset);
setp_put_u32(&out[8], value->image_size);
setp_put_u16(&out[12], value->last_error);
setp_put_u16(&out[14], value->flags);
return SETP_FW_STATUS_SIZE;
}
bool setp_fw_status_decode(const uint8_t *payload, uint16_t length, setp_fw_status_t *out)
{
if ((payload == NULL) || (out == NULL) || (length != SETP_FW_STATUS_SIZE)) {
return false;
}
out->state = payload[0];
out->active_slot = payload[1];
out->max_block_size = setp_get_u16(&payload[2]);
out->next_offset = setp_get_u32(&payload[4]);
out->image_size = setp_get_u32(&payload[8]);
out->last_error = setp_get_u16(&payload[12]);
out->flags = setp_get_u16(&payload[14]);
return true;
}
size_t setp_fw_manifest_encode(const setp_fw_begin_t *value,
uint8_t *out, size_t capacity)
{
static const uint8_t prefix[8] = {
'S', 'E', 'T', 'P', 'F', 'W', '2', 0U
};
if ((value == NULL) || (out == NULL) || (capacity < SETP_FW_MANIFEST_SIZE)) {
return 0U;
}
(void)memcpy(out, prefix, sizeof(prefix));
setp_put_u32(&out[8], value->image_size);
setp_put_u32(&out[12], value->image_crc32);
setp_put_u32(&out[16], value->image_version);
setp_put_u32(&out[20], value->base_address);
out[24] = value->slot;
(void)memcpy(&out[25], value->sha256, SETP_SHA256_SIZE);
return SETP_FW_MANIFEST_SIZE;
}