From 4f391007f0817831c54a2f36de207f71ec54e9bc Mon Sep 17 00:00:00 2001 From: Marian Buschsieweke Date: Tue, 28 Jul 2020 17:26:24 +0200 Subject: [PATCH 1/2] sys/unaligned: Add 32 bit version --- sys/include/unaligned.h | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/sys/include/unaligned.h b/sys/include/unaligned.h index 9dba9ae2fd..ced46ac328 100644 --- a/sys/include/unaligned.h +++ b/sys/include/unaligned.h @@ -48,6 +48,11 @@ typedef struct __attribute__((packed)) { uint16_t val; /**< value */ } uint16_una_t; +/** @brief Unaligned access helper struct (uint32_t version) */ +typedef struct __attribute__((packed)) { + uint32_t val; /**< value */ +} uint32_una_t; + /** * @brief Get uint16_t from possibly unaligned pointer * @@ -57,7 +62,20 @@ typedef struct __attribute__((packed)) { */ static inline uint16_t unaligned_get_u16(const void *ptr) { - const uint16_una_t *tmp = ptr; + const uint16_una_t *tmp = (const uint16_una_t *)ptr; + return tmp->val; +} + +/** + * @brief Get uint32_t from possibly unaligned pointer + * + * @param[in] ptr pointer to read from + * + * @returns value read from @p ptr + */ +static inline uint32_t unaligned_get_u32(const void *ptr) +{ + const uint32_una_t *tmp = (const uint32_una_t *)ptr; return tmp->val; } From e4387c84fd8fd1629aab78c94d32cb3a111612ab Mon Sep 17 00:00:00 2001 From: Marian Buschsieweke Date: Tue, 28 Jul 2020 17:29:51 +0200 Subject: [PATCH 2/2] core/byteorder: Fix from/to be buffers on be Big endian buffers on big endian systems are already in big endian byte order, so no byte shuffling is needed. However, byte buffers might be unaligned, so copy operations that are safe with unaligned memory accesses need to be used. --- core/include/byteorder.h | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/core/include/byteorder.h b/core/include/byteorder.h index f2acea7f60..3e018897e6 100644 --- a/core/include/byteorder.h +++ b/core/include/byteorder.h @@ -20,6 +20,7 @@ #define BYTEORDER_H #include +#include "unaligned.h" #if defined(__MACH__) # include "clang_compat.h" @@ -485,7 +486,9 @@ static inline uint16_t byteorder_bebuftohs(const uint8_t *buf) #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ return (uint16_t)((buf[0] << 8) | (buf[1] << 0)); #elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ - return (uint16_t)((buf[1] << 8) | (buf[0] << 0)); + /* big endian to big endian conversion is easy, but buffer might be + * unaligned */ + return unaligned_get_u16(buf); #endif } @@ -497,10 +500,9 @@ static inline uint32_t byteorder_bebuftohl(const uint8_t *buf) | ((uint32_t) buf[2] << 8) | ((uint32_t) buf[3] << 0)); #elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ - return (((uint32_t) buf[3] << 24) - | ((uint32_t) buf[2] << 16) - | ((uint32_t) buf[1] << 8) - | ((uint32_t) buf[0] << 0)); + /* big endian to big endian conversion is easy, but buffer might be + * unaligned */ + return unaligned_get_u32(buf); #endif } @@ -510,8 +512,9 @@ static inline void byteorder_htobebufs(uint8_t *buf, uint16_t val) buf[0] = (uint8_t)(val >> 8); buf[1] = (uint8_t)(val >> 0); #elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ - buf[1] = (uint8_t)(val >> 8); - buf[0] = (uint8_t)(val >> 0); + /* big endian to big endian conversion is easy, but buffer might be + * unaligned */ + memcpy(buf, &val, sizeof(val)); #endif } @@ -523,10 +526,9 @@ static inline void byteorder_htobebufl(uint8_t *buf, uint32_t val) buf[2] = (uint8_t)(val >> 8); buf[3] = (uint8_t)(val >> 0); #elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ - buf[3] = (uint8_t)(val >> 24); - buf[2] = (uint8_t)(val >> 16); - buf[1] = (uint8_t)(val >> 8); - buf[0] = (uint8_t)(val >> 0); + /* big endian to big endian conversion is easy, but buffer might be + * unaligned */ + memcpy(buf, &val, sizeof(val)); #endif }