boot: Unify the interpretation of TLV entry fields
Modify the definition of certain shared data TLV entry header fields to
be aligned with the image TLV's behaviour (the meaning of the tlv_len
field was different) and achieve unified interpretation.
Modify some macro definitions that use bitwise shift operators to
prevent certain errors from occurring due to implementation-defined
behaviour.
Change-Id: Ib736703a391d390a87d629a8ac4e77e1789120a5
Signed-off-by: David Vincze <david.vincze@linaro.org>
diff --git a/boot/bootutil/include/bootutil/boot_status.h b/boot/bootutil/include/bootutil/boot_status.h
index ecf4683..0364870 100644
--- a/boot/bootutil/include/bootutil/boot_status.h
+++ b/boot/bootutil/include/bootutil/boot_status.h
@@ -1,5 +1,6 @@
/*
* Copyright (c) 2018-2020 Arm Limited
+ * Copyright (c) 2020 Linaro Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -38,8 +39,9 @@
* header structure: struct shared_data_tlv_entry and the data. In the entry
* header is a type field (tly_type) which identify the consumer of the
* entry in the runtime SW and specify the subtype of that data item. There
- * is a size field (tlv_len) which covers the size of the entry header and
- * the data. After this structure comes the actual data.
+ * is a size field (tlv_len) which covers the size of the the data. After
+ * this structure comes the actual data.
+ *
* - Arbitrary number and size of data entry can be in the shared memory area.
*
* This table gives of overview about the tlv_type field in the entry header.
@@ -68,9 +70,10 @@
#define MINOR_MASK 0xFFF /* 12 bit */
#define SET_TLV_TYPE(major, minor) \
- ((((major) & MAJOR_MASK) << MAJOR_POS) | ((minor) & MINOR_MASK))
-#define GET_MAJOR(tlv_type) ((tlv_type) >> MAJOR_POS)
-#define GET_MINOR(tlv_type) ((tlv_type) & MINOR_MASK)
+ (((uint16_t)((major) & MAJOR_MASK) << MAJOR_POS) \
+ | ((minor) & MINOR_MASK))
+#define GET_MAJOR(tlv_type) ((uint16_t)(tlv_type) >> MAJOR_POS)
+#define GET_MINOR(tlv_type) ((tlv_type) & MINOR_MASK)
/* Magic value which marks the beginning of shared data area in memory */
#define SHARED_DATA_TLV_INFO_MAGIC 0x2016
@@ -98,9 +101,10 @@
#define CLAIM_MASK 0x3F /* 6 bit */
#define MEASUREMENT_CLAIM_POS 3 /* 3 bit */
-#define GET_IAS_MODULE(tlv_type) (GET_MINOR(tlv_type) >> MODULE_POS)
-#define GET_IAS_CLAIM(tlv_type) (GET_MINOR(tlv_type) & CLAIM_MASK)
-#define SET_IAS_MINOR(sw_module, claim) (((sw_module) << 6) | (claim))
+#define GET_IAS_MODULE(tlv_type) ((uint16_t)GET_MINOR(tlv_type) >> MODULE_POS)
+#define GET_IAS_CLAIM(tlv_type) (GET_MINOR(tlv_type) & CLAIM_MASK)
+#define SET_IAS_MINOR(sw_module, claim) \
+ (((uint16_t)(sw_module) << MODULE_POS) | (claim))
/**
* Shared data TLV header. All fields in little endian.
@@ -127,7 +131,7 @@
*/
struct shared_data_tlv_entry {
uint16_t tlv_type;
- uint16_t tlv_len; /* size of single TLV entry (including this header). */
+ uint16_t tlv_len; /* TLV data length (not including this header). */
};
#define SHARED_DATA_ENTRY_HEADER_SIZE sizeof(struct shared_data_tlv_entry)
diff --git a/boot/bootutil/src/boot_record.c b/boot/bootutil/src/boot_record.c
index 655ee7e..0494972 100644
--- a/boot/bootutil/src/boot_record.c
+++ b/boot/bootutil/src/boot_record.c
@@ -1,5 +1,6 @@
/*
* Copyright (c) 2018-2020 Arm Limited
+ * Copyright (c) 2020 Linaro Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -87,21 +88,23 @@
/* Iterates over the TLV section looks for the same entry if found then
* returns with error: SHARED_MEMORY_OVERWRITE
*/
- for (; offset < tlv_end; offset += tlv_entry.tlv_len) {
+ while (offset < tlv_end) {
/* Create local copy to avoid unaligned access */
memcpy(&tlv_entry, (const void *)offset, SHARED_DATA_ENTRY_HEADER_SIZE);
if (GET_MAJOR(tlv_entry.tlv_type) == major_type &&
GET_MINOR(tlv_entry.tlv_type) == minor_type) {
return SHARED_MEMORY_OVERWRITE;
}
+
+ offset += SHARED_DATA_ENTRY_SIZE(tlv_entry.tlv_len);
}
/* Add TLV entry */
tlv_entry.tlv_type = SET_TLV_TYPE(major_type, minor_type);
- tlv_entry.tlv_len = SHARED_DATA_ENTRY_SIZE(size);
+ tlv_entry.tlv_len = size;
if (!boot_u16_safe_add(&boot_data_size, boot_data->header.tlv_tot_len,
- tlv_entry.tlv_len)) {
+ SHARED_DATA_ENTRY_SIZE(size))) {
return SHARED_MEMORY_GEN_ERROR;
}
@@ -116,7 +119,7 @@
offset += SHARED_DATA_ENTRY_HEADER_SIZE;
memcpy((void *)offset, data, size);
- boot_data->header.tlv_tot_len += tlv_entry.tlv_len;
+ boot_data->header.tlv_tot_len += SHARED_DATA_ENTRY_SIZE(size);
return SHARED_MEMORY_OK;
}