From 249e092967195b38b2fb466f310cc0b7611791b9 Mon Sep 17 00:00:00 2001 From: Alexander Amelkin Date: Fri, 20 Jul 2018 19:41:44 +0300 Subject: [PATCH] general: Make byteswapping arch-independent ipmiXXtoh() and htoipmiXX() functions were broken and only worked properly for big-endian hosts. This commit makes them endianness-independent. Signed-off-by: Alexander Amelkin --- include/ipmitool/helper.h | 59 +++++++++++++++++++++++++++++++++++---- 1 file changed, 53 insertions(+), 6 deletions(-) diff --git a/include/ipmitool/helper.h b/include/ipmitool/helper.h index e8624e0..48873ef 100644 --- a/include/ipmitool/helper.h +++ b/include/ipmitool/helper.h @@ -118,16 +118,31 @@ static inline uint16_t ipmi16toh(void *ipmi16) uint8_t *ipmi = (uint8_t *)ipmi16; uint16_t h; + /* + * ipmi16 address may be word-wise misaligned, so don't + * use type-pun and instead explicity shift corresponding bytes + * to where they belong. + */ +#if WORDS_BIGENDIAN + h = ipmi[0] << 8; /* MSB */ + h |= ipmi[1]; /* LSB */ +#else h = ipmi[1] << 8; /* MSB */ h |= ipmi[0]; /* LSB */ +#endif return h; } static inline void htoipmi16(uint16_t h, uint8_t *ipmi) { +#if WORDS_BIGENDIAN ipmi[0] = h & 0xFF; /* LSB */ ipmi[1] = h >> 8; /* MSB */ +#else + ipmi[1] = h & 0xFF; /* LSB */ + ipmi[0] = h >> 8; /* MSB */ +#endif } static inline uint32_t ipmi24toh(void *ipmi24) @@ -135,26 +150,58 @@ static inline uint32_t ipmi24toh(void *ipmi24) uint8_t *ipmi = (uint8_t *)ipmi24; uint32_t h = 0; - h = ipmi[2] << 16; +#if WORDS_BIGENDIAN + h = ipmi[0] << 16; /* LSB */ h |= ipmi[1] << 8; - h |= ipmi[0]; + h |= ipmi[2]; /* MSB */ +#else + h = ipmi[2] << 16; /* LSB */ + h |= ipmi[1] << 8; + h |= ipmi[0]; /* MSB */ +#endif return h; } static inline uint32_t ipmi32toh(void *ipmi32) { - uint8_t *ipmi = (uint8_t *)ipmi32; + uint8_t *ipmi = ipmi32; uint32_t h; - h = ipmi[3] << 24; + /* + * ipmi32 address may be dword-wise misaligned, so don't + * use type-pun and instead explicity shift corresponding bytes + * to where they belong. + */ +#if WORDS_BIGENDIAN + h = ipmi[0] << 24; /* LSB */ + h |= ipmi[1] << 16; + h |= ipmi[2] << 8; + h |= ipmi[3]; /* MSB */ +#else + h = ipmi[3] << 24; /* LSB */ h |= ipmi[2] << 16; h |= ipmi[1] << 8; - h |= ipmi[0]; - + h |= ipmi[0]; /* MSB */ +#endif return h; } +static inline void htoipmi32(uint32_t h, uint8_t *ipmi) +{ +#if WORDS_BIGENDIAN + ipmi[0] = h & 0xFF; /* LSB */ + ipmi[1] = (h >> 8) & 0xFF; + ipmi[2] = (h >> 16) & 0xFF; + ipmi[3] = (h >> 24) & 0xFF; /* MSB */ +#else + ipmi[3] = h & 0xFF; /* LSB */ + ipmi[2] = (h >> 8) & 0xFF; + ipmi[1] = (h >> 16) & 0xFF; + ipmi[0] = (h >> 24) & 0xFF; /* MSB */ +#endif +} + #define ipmi_open_file_read(file) ipmi_open_file(file, 0) #define ipmi_open_file_write(file) ipmi_open_file(file, 1)