Skip to content

Commit 499c1b2

Browse files
committed
helios64: defensive fixes on top of u-boot v2026.04 bump
Code-style and defensive-programming fixes to the helios64 u-boot overlay, applied on top of the pristine v2026.04 vendor bump. All changes are additive safety nets — none alter the happy-path behaviour of the previous Kobol/Armbian code. board/helios64.c: check led_get_by_label() return value in setup_leds(). Without this, led_set_state() is called on an uninitialised udevice pointer if LED lookup fails. board/sys_otp.c: - replace the || chain magic-number check in is_valid_header() with memcmp() against a const expected_magic[8] (fixes a real pre-existing bug: the || chain was always true); - introduce otp_serial() / otp_mfg_year() helpers that assemble the multi-byte values byte-by-byte, eliminating unaligned u64/u16 casts into the packed otp struct (UB per the C standard, also over-read into adjacent fields); - bounds-check otp.variant against BOARD_VARIANT_MAX before indexing var_str[], adding BOARD_VARIANT_INVALID slot; - use strnlen() when printing packed fixed-length fields; - use snprintf() with target buffer size instead of sprintf(); - retry read_otp_data() in ensure_otp_data_ready() on the first access after a failed board_early_init_r(), instead of silently skipping OTP-provided values for the whole boot. cmd-fileenv-read-string-from-file-into-env.patch: add 'depends on CMD_FAT' to the cherry-picked CMD_FILEENV Kconfig entry. do_fat_fsload() is called unconditionally from the fileenv implementation, so the dependency reflects reality. general-fix-btrfs-zstd-decompression.patch: tighten the decompression-success check to also reject short reads ('|| ret < dlen'). zstd_is_error() alone does not cover truncated output. Assisted-by: Claude:claude-opus-4-7
1 parent 0290be2 commit 499c1b2

4 files changed

Lines changed: 70 additions & 23 deletions

File tree

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

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -180,8 +180,14 @@ static int setup_boottargets(void)
180180
static void setup_leds(void)
181181
{
182182
struct udevice *dev;
183+
int ret;
184+
185+
ret = led_get_by_label("helios64::status", &dev);
186+
if (ret) {
187+
debug("%s: failed to get status LED: %d\n", __func__, ret);
188+
return;
189+
}
183190

184-
led_get_by_label("helios64::status", &dev);
185191
led_set_state(dev, LEDST_OFF);
186192
mdelay(250);
187193
led_set_state(dev, LEDST_ON);

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

Lines changed: 60 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
#include <log.h>
55
#include <env.h>
66
#include <net.h>
7+
#include <string.h>
78
#include <u-boot/crc.h>
89

910
#include "sys_otp.h"
@@ -42,16 +43,44 @@ static inline int is_data_valid(void)
4243
return data_valid;
4344
}
4445

45-
static inline int is_valid_header(void)
46+
/*
47+
* Ensure OTP data is cached and valid. If a previous read failed (for example
48+
* on a transient SPI error during board_early_init_r()), retry here so
49+
* consumers don't silently skip using OTP-provided values for the whole boot.
50+
*/
51+
static int ensure_otp_data_ready(void)
4652
{
47-
if ((otp.magic[0] == 'H') || (otp.magic[1] == '6') ||
48-
(otp.magic[2] == '4') || (otp.magic[3] == 'N') ||
49-
(otp.magic[4] == 'P') || (otp.magic[5] == 'V') ||
50-
(otp.magic[6] == '1') || (otp.magic[7] == 0))
53+
if (is_data_valid())
54+
return 0;
5155

52-
return 1;
56+
return read_otp_data();
57+
}
5358

54-
return 0;
59+
/*
60+
* Decode the 6-byte serial number into a u64. Doing a casted *(uint64_t *)
61+
* read on otp.serial_num would over-read into otp.mfg_year and is unaligned
62+
* inside the packed struct (UB per the C standard).
63+
*/
64+
static inline u64 otp_serial(void)
65+
{
66+
return ((u64)otp.serial_num[0]) |
67+
((u64)otp.serial_num[1] << 8) |
68+
((u64)otp.serial_num[2] << 16) |
69+
((u64)otp.serial_num[3] << 24) |
70+
((u64)otp.serial_num[4] << 32) |
71+
((u64)otp.serial_num[5] << 40);
72+
}
73+
74+
static inline u16 otp_mfg_year(void)
75+
{
76+
return otp.mfg_year[0] | ((u16)otp.mfg_year[1] << 8);
77+
}
78+
79+
static inline int is_valid_header(void)
80+
{
81+
static const u8 expected_magic[8] = { 'H', '6', '4', 'N', 'P', 'V', '1', 0 };
82+
83+
return memcmp(otp.magic, expected_magic, sizeof(expected_magic)) == 0;
5584
}
5685

5786
static int init_system_otp(int bus, int cs)
@@ -97,13 +126,16 @@ static void show_otp_data(void)
97126
if (!is_valid_header())
98127
return;
99128

100-
printf("Part Number: %s\n", otp.part_num);
101-
printf("Variant: %s\n", var_str[otp.variant]);
129+
printf("Part Number: %.*s\n",
130+
(int)strnlen((const char *)otp.part_num, sizeof(otp.part_num)),
131+
otp.part_num);
132+
printf("Variant: %s\n",
133+
(otp.variant < BOARD_VARIANT_MAX) ? var_str[otp.variant]
134+
: var_str[BOARD_VARIANT_INVALID]);
102135
printf("Revision: %x.%x\n", (otp.revision & 0xf0) >> 4, otp.revision & 0x0f);
103-
printf("Serial Number: %012llx\n", *((uint64_t*) otp.serial_num) &
104-
0xFFFFFFFFFFFF);
136+
printf("Serial Number: %012llx\n", otp_serial());
105137
printf("Manufacturing Date: %02X-%02X-%04X (DD-MM-YYYY)\n", otp.mfg_day,
106-
otp.mfg_month, *(u16*) otp.mfg_year);
138+
otp.mfg_month, otp_mfg_year());
107139

108140
printf("1GbE MAC Address: %02X:%02X:%02X:%02X:%02X:%02X\n",
109141
otp.mac_addr[0][0], otp.mac_addr[0][1], otp.mac_addr[0][2],
@@ -160,7 +192,13 @@ int read_otp_data(void)
160192
show_otp_data();
161193
#endif
162194

163-
has_been_read = (ret == 0) ? 1 : 0;
195+
if (ret) {
196+
debug("SPI: Failed to read OTP: %d\n", ret);
197+
/* Leave has_been_read = 0 so a later call can retry. */
198+
return ret;
199+
}
200+
has_been_read = 1;
201+
164202
if (!is_valid_header())
165203
goto data_invalid;
166204

@@ -180,7 +218,7 @@ int read_otp_data(void)
180218

181219
int get_revision(int *major, int *minor)
182220
{
183-
if (!is_data_valid())
221+
if (ensure_otp_data_ready())
184222
return -1;
185223

186224
*major = (otp.revision & 0xf0) >> 4;
@@ -191,15 +229,18 @@ int get_revision(int *major, int *minor)
191229

192230
const char *get_variant(void)
193231
{
194-
const char* var_str[BOARD_VARIANT_MAX] = {
232+
static const char * const var_str[BOARD_VARIANT_MAX] = {
195233
"Unknown",
196234
"Engineering Sample",
197235
"4GB non ECC"
198236
};
199237

238+
if (ensure_otp_data_ready())
239+
return var_str[BOARD_VARIANT_INVALID];
240+
200241
if ((otp.variant < BOARD_VARIANT_ENG_SAMPLE) ||
201242
(otp.variant >= BOARD_VARIANT_MAX))
202-
return var_str[0];
243+
return var_str[BOARD_VARIANT_INVALID];
203244

204245
return var_str[otp.variant];
205246
}
@@ -208,14 +249,13 @@ void set_board_info(void)
208249
{
209250
char env_str[13];
210251

211-
if (!is_data_valid())
252+
if (ensure_otp_data_ready())
212253
return;
213254

214255
snprintf(env_str, sizeof(env_str), "%i.%i", (otp.revision & 0xf0) >> 4, otp.revision & 0x0f);
215256
env_set("board_rev", env_str);
216257

217-
sprintf(env_str, "%012llx", *((uint64_t*) otp.serial_num) &
218-
0xFFFFFFFFFFFF);
258+
snprintf(env_str, sizeof(env_str), "%012llx", otp_serial());
219259

220260
env_set("serial#", env_str);
221261
}
@@ -224,7 +264,7 @@ int mac_read_from_otp(void)
224264
{
225265
unsigned int i;
226266

227-
if (!is_data_valid())
267+
if (ensure_otp_data_ready())
228268
return -1;
229269

230270
for (i = 0; i < MAX_NUM_PORTS; i++) {

patch/u-boot/v2026.04/board_helios64/cmd-fileenv-read-string-from-file-into-env.patch

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,13 @@ diff --git a/cmd/Kconfig b/cmd/Kconfig
1818
index 111111111111..222222222222 100644
1919
--- a/cmd/Kconfig
2020
+++ b/cmd/Kconfig
21-
@@ -1927,6 +1927,11 @@ config CMD_XXD
21+
@@ -1927,6 +1927,12 @@ config CMD_XXD
2222
help
2323
Print file as hexdump to standard output
2424

2525
+config CMD_FILEENV
2626
+ bool "fileenv"
27+
+ depends on CMD_FAT
2728
+ help
2829
+ Read a file into memory and store it to env.
2930
+

patch/u-boot/v2026.04/board_helios64/general-fix-btrfs-zstd-decompression.patch

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ diff --git a/fs/btrfs/compression.c b/fs/btrfs/compression.c
103103
+ ret = zstd_decompress_dctx(ctx, out_buf, out_len, cbuf, clen);
104104
+ free(workspace);
105105
+
106-
+ if (zstd_is_error(ret)) {
106+
+ if (zstd_is_error(ret) || ret < dlen) {
107107
+ free(tmp);
108108
+ return -1;
109109
+ }

0 commit comments

Comments
 (0)