Skip to content

Commit 023a5c6

Browse files
committed
u-boot: v2026.04: helios64: avoid unaligned 8-byte read on OTP serial_num
Per CodeRabbit review on PR armbian#9675: *((uint64_t *) otp.serial_num) & 0xFFFFFFFFFFFF reads 8 bytes from a 6-byte field inside a __packed__ struct (over-reads into mfg_year), and is unaligned. UB per the C standard, and would fault on stricter alignment requirements. Same pattern affects two call sites the bot pointed at (lines 103-104 and 217-218 of the original vendor file). The bot did not flag it but *(u16 *) otp.mfg_year on the next line has the same problem - packed field, unaligned access - so fix it together. Replace the casts with two small inline helpers that decode the bytes explicitly little-endian (RK3399 is LE, matches the vendor's original intent): otp_serial() - assemble 6 bytes into a u64 otp_mfg_year() - assemble 2 bytes into a u16 This is pre-existing Kobol vendor code carried forward through every U-Boot bump; this PR migrates the board files to v2026.04, so it is the right place to fix it.
1 parent 94196a5 commit 023a5c6

1 file changed

Lines changed: 23 additions & 5 deletions

File tree

  • patch/u-boot/v2026.04/board_helios64/board

patch/u-boot/v2026.04/board_helios64/board/sys_otp.c

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,26 @@ static inline int is_data_valid(void)
4343
return data_valid;
4444
}
4545

46+
/*
47+
* Decode the 6-byte serial number into a u64. Doing a casted *(uint64_t *)
48+
* read on otp.serial_num would over-read into otp.mfg_year and is unaligned
49+
* inside the packed struct (UB per the C standard).
50+
*/
51+
static inline u64 otp_serial(void)
52+
{
53+
return ((u64)otp.serial_num[0]) |
54+
((u64)otp.serial_num[1] << 8) |
55+
((u64)otp.serial_num[2] << 16) |
56+
((u64)otp.serial_num[3] << 24) |
57+
((u64)otp.serial_num[4] << 32) |
58+
((u64)otp.serial_num[5] << 40);
59+
}
60+
61+
static inline u16 otp_mfg_year(void)
62+
{
63+
return otp.mfg_year[0] | ((u16)otp.mfg_year[1] << 8);
64+
}
65+
4666
static inline int is_valid_header(void)
4767
{
4868
static const u8 expected_magic[8] = { 'H', '6', '4', 'N', 'P', 'V', '1', 0 };
@@ -96,10 +116,9 @@ static void show_otp_data(void)
96116
printf("Part Number: %s\n", otp.part_num);
97117
printf("Variant: %s\n", var_str[otp.variant]);
98118
printf("Revision: %x.%x\n", (otp.revision & 0xf0) >> 4, otp.revision & 0x0f);
99-
printf("Serial Number: %012llx\n", *((uint64_t*) otp.serial_num) &
100-
0xFFFFFFFFFFFF);
119+
printf("Serial Number: %012llx\n", otp_serial());
101120
printf("Manufacturing Date: %02X-%02X-%04X (DD-MM-YYYY)\n", otp.mfg_day,
102-
otp.mfg_month, *(u16*) otp.mfg_year);
121+
otp.mfg_month, otp_mfg_year());
103122

104123
printf("1GbE MAC Address: %02X:%02X:%02X:%02X:%02X:%02X\n",
105124
otp.mac_addr[0][0], otp.mac_addr[0][1], otp.mac_addr[0][2],
@@ -210,8 +229,7 @@ void set_board_info(void)
210229
snprintf(env_str, sizeof(env_str), "%i.%i", (otp.revision & 0xf0) >> 4, otp.revision & 0x0f);
211230
env_set("board_rev", env_str);
212231

213-
sprintf(env_str, "%012llx", *((uint64_t*) otp.serial_num) &
214-
0xFFFFFFFFFFFF);
232+
sprintf(env_str, "%012llx", otp_serial());
215233

216234
env_set("serial#", env_str);
217235
}

0 commit comments

Comments
 (0)