* [PATCH v2 0/3] bootcount: Small clean-up and fix, and dm_i2c single-word support
@ 2026-02-04 13:17 niko.mauno
2026-02-04 13:17 ` [PATCH v2 1/3] bootcount: Use predefined count/magic bit masks niko.mauno
` (3 more replies)
0 siblings, 4 replies; 5+ messages in thread
From: niko.mauno @ 2026-02-04 13:17 UTC (permalink / raw)
To: u-boot; +Cc: trini, Niko Mauno
From: Niko Mauno <niko.mauno@vaisala.com>
In this series, we first introduce a clean-up where we switch to use
predefined bit masks instead of hard-coded values for count and magic
halves in the single-word (32-bit) boot count scheme.
Then we fix a case of missing boot count value masking in single-word
scenario in bootcount.c, which allowed clobbering of the magic half
when storing the value. With this change the clobbering preventing
behavior becomes consistent with existing single word bootcount storing
implementations in bootcount_at91.c and bootcount_davinci.c.
Finally, we enable the DM I2C bootcount driver to work also in single
word (4 byte) mode, in addition to the pre-existing half-word (2 byte)
mode. By default the driver still operates in half word mode as so far,
but can now be used alternatively in single word mode by adding
'size = <0x4>;' in the associated device tree node.
Signed-off-by: Niko Mauno <niko.mauno@vaisala.com>
--
Niko Mauno (3):
bootcount: Use predefined count/magic bit masks
bootcount: Fix potential clobbering issue
bootcount: dm_i2c: Support also single word mode
drivers/bootcount/bootcount.c | 14 ++---
drivers/bootcount/bootcount_at91.c | 7 +--
drivers/bootcount/bootcount_davinci.c | 6 +--
drivers/bootcount/bootcount_dm_i2c.c | 74 +++++++++++++++++++--------
include/bootcount.h | 5 ++
5 files changed, 74 insertions(+), 32 deletions(-)
--
2.47.3
^ permalink raw reply [flat|nested] 5+ messages in thread
* [PATCH v2 1/3] bootcount: Use predefined count/magic bit masks
2026-02-04 13:17 [PATCH v2 0/3] bootcount: Small clean-up and fix, and dm_i2c single-word support niko.mauno
@ 2026-02-04 13:17 ` niko.mauno
2026-02-04 13:17 ` [PATCH v2 2/3] bootcount: Fix potential clobbering issue niko.mauno
` (2 subsequent siblings)
3 siblings, 0 replies; 5+ messages in thread
From: niko.mauno @ 2026-02-04 13:17 UTC (permalink / raw)
To: u-boot; +Cc: trini, Niko Mauno
From: Niko Mauno <niko.mauno@vaisala.com>
Use predefined bit masks in operations where only the magic half or
only the count half of the 32-bit value are processed.
Signed-off-by: Niko Mauno <niko.mauno@vaisala.com>
---
drivers/bootcount/bootcount.c | 12 ++++++------
drivers/bootcount/bootcount_at91.c | 7 ++++---
drivers/bootcount/bootcount_davinci.c | 6 +++---
include/bootcount.h | 5 +++++
4 files changed, 18 insertions(+), 12 deletions(-)
diff --git a/drivers/bootcount/bootcount.c b/drivers/bootcount/bootcount.c
index 343b8a34414..454e50591df 100644
--- a/drivers/bootcount/bootcount.c
+++ b/drivers/bootcount/bootcount.c
@@ -19,7 +19,7 @@ __weak void bootcount_store(ulong a)
uintptr_t flush_end;
#if defined(CONFIG_SYS_BOOTCOUNT_SINGLEWORD)
- raw_bootcount_store(reg, (CONFIG_SYS_BOOTCOUNT_MAGIC & 0xffff0000) | a);
+ raw_bootcount_store(reg, (CONFIG_SYS_BOOTCOUNT_MAGIC & BOOTCOUNT_MAGIC_MASK) | a);
flush_end = roundup(CONFIG_SYS_BOOTCOUNT_ADDR + 4,
CONFIG_SYS_CACHELINE_SIZE);
@@ -40,10 +40,10 @@ __weak ulong bootcount_load(void)
#if defined(CONFIG_SYS_BOOTCOUNT_SINGLEWORD)
u32 tmp = raw_bootcount_load(reg);
- if ((tmp & 0xffff0000) != (CONFIG_SYS_BOOTCOUNT_MAGIC & 0xffff0000))
+ if ((tmp & BOOTCOUNT_MAGIC_MASK) != (CONFIG_SYS_BOOTCOUNT_MAGIC & BOOTCOUNT_MAGIC_MASK))
return 0;
else
- return (tmp & 0x0000ffff);
+ return (tmp & BOOTCOUNT_COUNT_MASK);
#else
if (raw_bootcount_load(reg + 4) != CONFIG_SYS_BOOTCOUNT_MAGIC)
return 0;
@@ -74,10 +74,10 @@ static int bootcount_mem_get(struct udevice *dev, u32 *a)
if (priv->singleword) {
u32 tmp = raw_bootcount_load(reg);
- if ((tmp & 0xffff0000) != (magic & 0xffff0000))
+ if ((tmp & BOOTCOUNT_MAGIC_MASK) != (magic & BOOTCOUNT_MAGIC_MASK))
return -ENODEV;
- *a = (tmp & 0x0000ffff);
+ *a = (tmp & BOOTCOUNT_COUNT_MASK);
} else {
if (raw_bootcount_load(reg + 4) != magic)
return -ENODEV;
@@ -98,7 +98,7 @@ static int bootcount_mem_set(struct udevice *dev, const u32 a)
uintptr_t flush_end;
if (priv->singleword) {
- raw_bootcount_store(reg, (magic & 0xffff0000) | a);
+ raw_bootcount_store(reg, (magic & BOOTCOUNT_MAGIC_MASK) | a);
flush_end = roundup(priv->base + 4,
CONFIG_SYS_CACHELINE_SIZE);
} else {
diff --git a/drivers/bootcount/bootcount_at91.c b/drivers/bootcount/bootcount_at91.c
index 1a06db1fb74..1322abe921e 100644
--- a/drivers/bootcount/bootcount_at91.c
+++ b/drivers/bootcount/bootcount_at91.c
@@ -3,6 +3,7 @@
#include <asm/io.h>
#include <asm/arch/hardware.h>
#include <asm/arch/at91_gpbr.h>
+#include <bootcount.h>
/*
* We combine the CONFIG_SYS_BOOTCOUNT_MAGIC and bootcount in one 32-bit
@@ -13,7 +14,7 @@ void bootcount_store(ulong a)
{
at91_gpbr_t *gpbr = (at91_gpbr_t *) ATMEL_BASE_GPBR;
- writel((CONFIG_SYS_BOOTCOUNT_MAGIC & 0xffff0000) | (a & 0x0000ffff),
+ writel((CONFIG_SYS_BOOTCOUNT_MAGIC & BOOTCOUNT_MAGIC_MASK) | (a & BOOTCOUNT_COUNT_MASK),
&gpbr->reg[AT91_GPBR_INDEX_BOOTCOUNT]);
}
@@ -22,8 +23,8 @@ ulong bootcount_load(void)
at91_gpbr_t *gpbr = (at91_gpbr_t *) ATMEL_BASE_GPBR;
ulong val = readl(&gpbr->reg[AT91_GPBR_INDEX_BOOTCOUNT]);
- if ((val & 0xffff0000) != (CONFIG_SYS_BOOTCOUNT_MAGIC & 0xffff0000))
+ if ((val & BOOTCOUNT_MAGIC_MASK) != (CONFIG_SYS_BOOTCOUNT_MAGIC & BOOTCOUNT_MAGIC_MASK))
return 0;
else
- return val & 0x0000ffff;
+ return val & BOOTCOUNT_COUNT_MASK;
}
diff --git a/drivers/bootcount/bootcount_davinci.c b/drivers/bootcount/bootcount_davinci.c
index 6326957d7b0..a03d160a4cd 100644
--- a/drivers/bootcount/bootcount_davinci.c
+++ b/drivers/bootcount/bootcount_davinci.c
@@ -24,7 +24,7 @@ void bootcount_store(ulong a)
writel(RTC_KICK0R_WE, ®->kick0r);
writel(RTC_KICK1R_WE, ®->kick1r);
raw_bootcount_store(®->scratch2,
- (CONFIG_SYS_BOOTCOUNT_MAGIC & 0xffff0000) | (a & 0x0000ffff));
+ (CONFIG_SYS_BOOTCOUNT_MAGIC & BOOTCOUNT_MAGIC_MASK) | (a & BOOTCOUNT_COUNT_MASK));
}
ulong bootcount_load(void)
@@ -34,8 +34,8 @@ ulong bootcount_load(void)
(struct davinci_rtc *)CONFIG_SYS_BOOTCOUNT_ADDR;
val = raw_bootcount_load(®->scratch2);
- if ((val & 0xffff0000) != (CONFIG_SYS_BOOTCOUNT_MAGIC & 0xffff0000))
+ if ((val & BOOTCOUNT_MAGIC_MASK) != (CONFIG_SYS_BOOTCOUNT_MAGIC & BOOTCOUNT_MAGIC_MASK))
return 0;
else
- return val & 0x0000ffff;
+ return val & BOOTCOUNT_COUNT_MASK;
}
diff --git a/include/bootcount.h b/include/bootcount.h
index 847c0f02d98..86474569d36 100644
--- a/include/bootcount.h
+++ b/include/bootcount.h
@@ -10,6 +10,7 @@
#include <asm/io.h>
#include <asm/byteorder.h>
#include <env.h>
+#include <linux/bitops.h>
#ifdef CONFIG_DM_BOOTCOUNT
@@ -59,6 +60,10 @@ int dm_bootcount_set(struct udevice *dev, u32 bootcount);
#endif
+/* Bit masks for magic and count parts in single word scheme */
+#define BOOTCOUNT_MAGIC_MASK GENMASK(31, 16)
+#define BOOTCOUNT_COUNT_MASK GENMASK(15, 0)
+
/** bootcount_store() - store the current bootcount */
void bootcount_store(ulong);
--
2.47.3
^ permalink raw reply related [flat|nested] 5+ messages in thread
* [PATCH v2 2/3] bootcount: Fix potential clobbering issue
2026-02-04 13:17 [PATCH v2 0/3] bootcount: Small clean-up and fix, and dm_i2c single-word support niko.mauno
2026-02-04 13:17 ` [PATCH v2 1/3] bootcount: Use predefined count/magic bit masks niko.mauno
@ 2026-02-04 13:17 ` niko.mauno
2026-02-04 13:17 ` [PATCH v2 3/3] bootcount: dm_i2c: Support also single word mode niko.mauno
2026-02-19 0:15 ` [PATCH v2 0/3] bootcount: Small clean-up and fix, and dm_i2c single-word support Tom Rini
3 siblings, 0 replies; 5+ messages in thread
From: niko.mauno @ 2026-02-04 13:17 UTC (permalink / raw)
To: u-boot; +Cc: trini, Niko Mauno
From: Niko Mauno <niko.mauno@vaisala.com>
When storing the single word bootcount value, apply the bootcount count
mask to prevent clobbering the magic half of the value.
Signed-off-by: Niko Mauno <niko.mauno@vaisala.com>
---
drivers/bootcount/bootcount.c | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/drivers/bootcount/bootcount.c b/drivers/bootcount/bootcount.c
index 454e50591df..2c0114d9705 100644
--- a/drivers/bootcount/bootcount.c
+++ b/drivers/bootcount/bootcount.c
@@ -19,7 +19,8 @@ __weak void bootcount_store(ulong a)
uintptr_t flush_end;
#if defined(CONFIG_SYS_BOOTCOUNT_SINGLEWORD)
- raw_bootcount_store(reg, (CONFIG_SYS_BOOTCOUNT_MAGIC & BOOTCOUNT_MAGIC_MASK) | a);
+ raw_bootcount_store(reg, (CONFIG_SYS_BOOTCOUNT_MAGIC & BOOTCOUNT_MAGIC_MASK)
+ | (a & BOOTCOUNT_COUNT_MASK));
flush_end = roundup(CONFIG_SYS_BOOTCOUNT_ADDR + 4,
CONFIG_SYS_CACHELINE_SIZE);
@@ -98,7 +99,8 @@ static int bootcount_mem_set(struct udevice *dev, const u32 a)
uintptr_t flush_end;
if (priv->singleword) {
- raw_bootcount_store(reg, (magic & BOOTCOUNT_MAGIC_MASK) | a);
+ raw_bootcount_store(reg, (magic & BOOTCOUNT_MAGIC_MASK)
+ | (a & BOOTCOUNT_COUNT_MASK));
flush_end = roundup(priv->base + 4,
CONFIG_SYS_CACHELINE_SIZE);
} else {
--
2.47.3
^ permalink raw reply related [flat|nested] 5+ messages in thread
* [PATCH v2 3/3] bootcount: dm_i2c: Support also single word mode
2026-02-04 13:17 [PATCH v2 0/3] bootcount: Small clean-up and fix, and dm_i2c single-word support niko.mauno
2026-02-04 13:17 ` [PATCH v2 1/3] bootcount: Use predefined count/magic bit masks niko.mauno
2026-02-04 13:17 ` [PATCH v2 2/3] bootcount: Fix potential clobbering issue niko.mauno
@ 2026-02-04 13:17 ` niko.mauno
2026-02-19 0:15 ` [PATCH v2 0/3] bootcount: Small clean-up and fix, and dm_i2c single-word support Tom Rini
3 siblings, 0 replies; 5+ messages in thread
From: niko.mauno @ 2026-02-04 13:17 UTC (permalink / raw)
To: u-boot; +Cc: trini, Niko Mauno
From: Niko Mauno <niko.mauno@vaisala.com>
In addition to pre-existing half-word (2 byte) mode, add support for
the driver to work also in single word (4 byte) mode by adding
'size = <0x4>;' in the device tree node.
Signed-off-by: Niko Mauno <niko.mauno@vaisala.com>
---
drivers/bootcount/bootcount_dm_i2c.c | 74 ++++++++++++++++++++--------
1 file changed, 54 insertions(+), 20 deletions(-)
diff --git a/drivers/bootcount/bootcount_dm_i2c.c b/drivers/bootcount/bootcount_dm_i2c.c
index e27034cbeb0..07359ecfa6c 100644
--- a/drivers/bootcount/bootcount_dm_i2c.c
+++ b/drivers/bootcount/bootcount_dm_i2c.c
@@ -15,6 +15,7 @@
struct bootcount_i2c_priv {
struct udevice *bcdev;
unsigned int offset;
+ unsigned int size;
};
static int bootcount_i2c_set(struct udevice *dev, const u32 val)
@@ -22,13 +23,22 @@ static int bootcount_i2c_set(struct udevice *dev, const u32 val)
int ret;
struct bootcount_i2c_priv *priv = dev_get_priv(dev);
- ret = dm_i2c_reg_write(priv->bcdev, priv->offset, BC_MAGIC);
- if (ret < 0)
- goto err_exit;
-
- ret = dm_i2c_reg_write(priv->bcdev, priv->offset + 1, val & 0xff);
- if (ret < 0)
- goto err_exit;
+ if (priv->size == 4) {
+ u32 bc = (CONFIG_SYS_BOOTCOUNT_MAGIC & BOOTCOUNT_MAGIC_MASK)
+ | (val & BOOTCOUNT_COUNT_MASK);
+
+ ret = dm_i2c_write(priv->bcdev, priv->offset, (uint8_t *)&bc, sizeof(bc));
+ if (ret < 0)
+ goto err_exit;
+ } else {
+ ret = dm_i2c_reg_write(priv->bcdev, priv->offset, BC_MAGIC);
+ if (ret < 0)
+ goto err_exit;
+
+ ret = dm_i2c_reg_write(priv->bcdev, priv->offset + 1, val & 0xff);
+ if (ret < 0)
+ goto err_exit;
+ }
return 0;
@@ -42,21 +52,39 @@ static int bootcount_i2c_get(struct udevice *dev, u32 *val)
int ret;
struct bootcount_i2c_priv *priv = dev_get_priv(dev);
- ret = dm_i2c_reg_read(priv->bcdev, priv->offset);
- if (ret < 0)
- goto err_exit;
-
- if ((ret & 0xff) != BC_MAGIC) {
- log_debug("%s: Invalid Magic, reset bootcounter.\n", __func__);
- *val = 0;
- return bootcount_i2c_set(dev, 0);
+ if (priv->size == 4) {
+ u32 bc;
+
+ ret = dm_i2c_read(priv->bcdev, priv->offset, (uint8_t *)&bc, sizeof(bc));
+ if (ret < 0)
+ goto err_exit;
+
+ if ((bc & BOOTCOUNT_MAGIC_MASK) !=
+ (CONFIG_SYS_BOOTCOUNT_MAGIC & BOOTCOUNT_MAGIC_MASK)) {
+ log_debug("%s: Invalid Magic, reset bootcounter.\n", __func__);
+ *val = 0;
+ return bootcount_i2c_set(dev, 0);
+ }
+
+ *val = (bc & BOOTCOUNT_COUNT_MASK);
+ } else {
+ ret = dm_i2c_reg_read(priv->bcdev, priv->offset);
+ if (ret < 0)
+ goto err_exit;
+
+ if ((ret & 0xff) != BC_MAGIC) {
+ log_debug("%s: Invalid Magic, reset bootcounter.\n", __func__);
+ *val = 0;
+ return bootcount_i2c_set(dev, 0);
+ }
+
+ ret = dm_i2c_reg_read(priv->bcdev, priv->offset + 1);
+ if (ret < 0)
+ goto err_exit;
+
+ *val = ret;
}
- ret = dm_i2c_reg_read(priv->bcdev, priv->offset + 1);
- if (ret < 0)
- goto err_exit;
-
- *val = ret;
return 0;
err_exit:
@@ -73,6 +101,12 @@ static int bootcount_i2c_probe(struct udevice *dev)
if (ret)
goto exit;
+ priv->size = dev_read_u32_default(dev, "size", 2);
+ if (priv->size != 2 && priv->size != 4) {
+ ret = -EINVAL;
+ goto exit;
+ }
+
ret = i2c_get_chip_by_phandle(dev, "i2cbcdev", &priv->bcdev);
exit:
--
2.47.3
^ permalink raw reply related [flat|nested] 5+ messages in thread
* Re: [PATCH v2 0/3] bootcount: Small clean-up and fix, and dm_i2c single-word support
2026-02-04 13:17 [PATCH v2 0/3] bootcount: Small clean-up and fix, and dm_i2c single-word support niko.mauno
` (2 preceding siblings ...)
2026-02-04 13:17 ` [PATCH v2 3/3] bootcount: dm_i2c: Support also single word mode niko.mauno
@ 2026-02-19 0:15 ` Tom Rini
3 siblings, 0 replies; 5+ messages in thread
From: Tom Rini @ 2026-02-19 0:15 UTC (permalink / raw)
To: u-boot, niko.mauno
On Wed, 04 Feb 2026 15:17:34 +0200, niko.mauno@vaisala.com wrote:
> From: Niko Mauno <niko.mauno@vaisala.com>
>
> In this series, we first introduce a clean-up where we switch to use
> predefined bit masks instead of hard-coded values for count and magic
> halves in the single-word (32-bit) boot count scheme.
>
> Then we fix a case of missing boot count value masking in single-word
> scenario in bootcount.c, which allowed clobbering of the magic half
> when storing the value. With this change the clobbering preventing
> behavior becomes consistent with existing single word bootcount storing
> implementations in bootcount_at91.c and bootcount_davinci.c.
>
> [...]
Applied to u-boot/next, thanks!
[1/3] bootcount: Use predefined count/magic bit masks
commit: 27e1924ffaa9361542d4cf75a9b73613fa45d007
[2/3] bootcount: Fix potential clobbering issue
commit: 05b56599b5b13a504d8ed66db27a4446f8b9acc5
[3/3] bootcount: dm_i2c: Support also single word mode
commit: f97642853cd379ef69d00bca6c3928bce226dc5e
--
Tom
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2026-02-19 0:15 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-02-04 13:17 [PATCH v2 0/3] bootcount: Small clean-up and fix, and dm_i2c single-word support niko.mauno
2026-02-04 13:17 ` [PATCH v2 1/3] bootcount: Use predefined count/magic bit masks niko.mauno
2026-02-04 13:17 ` [PATCH v2 2/3] bootcount: Fix potential clobbering issue niko.mauno
2026-02-04 13:17 ` [PATCH v2 3/3] bootcount: dm_i2c: Support also single word mode niko.mauno
2026-02-19 0:15 ` [PATCH v2 0/3] bootcount: Small clean-up and fix, and dm_i2c single-word support Tom Rini
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox