* [PATCH v4 0/2] nvmem-reboot-mode: support small reboot mode magic
@ 2025-02-28 18:03 Jennifer Berringer
2025-02-28 18:03 ` [PATCH v4 1/2] nvmem: core: add nvmem_cell_size() Jennifer Berringer
2025-02-28 18:03 ` [PATCH v4 2/2] power: reset: nvmem-reboot-mode: support smaller magic Jennifer Berringer
0 siblings, 2 replies; 5+ messages in thread
From: Jennifer Berringer @ 2025-02-28 18:03 UTC (permalink / raw)
To: Srinivas Kandagatla, Sebastian Reichel
Cc: linux-kernel, linux-pm, Jennifer Berringer
Hi all,
These patches allow nvmem-reboot-mode to handle devices with a
reboot-mode cell smaller than 4 bytes, such as Qualcomm SA8775P. Without
this change, nvmem_reboot_mode_write() tries to write 4 bytes to a
1-byte nvmem cell and fails with the message "update reboot mode bits
failed" on affected devices.
This issue previously resulted in an out-of-bounds heap write but, after
one of my patches from v3 of this series was accepted, it results in
that error message instead.
[1]
https://lore.kernel.org/all/20241104152312.3813601-2-jberring@redhat.com/
v4:
- Excluded one patch which was accepted from v3 [1]:
"nvmem: core: improve range check for nvmem_cell_write()"
- Handle truncation of the reboot mode magic in nvmem-reboot-mode
instead of in nvmem core.
- Introduced nvmem_cell_size().
v3:
- Accepted suggestion for changing nvmem_cell_write bounds check
v2:
- Added missing function definition for CONFIG_NVMEM=n
Jennifer Berringer (2):
nvmem: core: add nvmem_cell_size()
power: reset: nvmem-reboot-mode: support smaller magic
drivers/nvmem/core.c | 18 ++++++++++++++++++
drivers/power/reset/nvmem-reboot-mode.c | 9 ++++++++-
include/linux/nvmem-consumer.h | 6 ++++++
3 files changed, 32 insertions(+), 1 deletion(-)
base-commit: ffd294d346d185b70e28b1a28abe367bbfe53c04
--
2.47.1
^ permalink raw reply [flat|nested] 5+ messages in thread
* [PATCH v4 1/2] nvmem: core: add nvmem_cell_size()
2025-02-28 18:03 [PATCH v4 0/2] nvmem-reboot-mode: support small reboot mode magic Jennifer Berringer
@ 2025-02-28 18:03 ` Jennifer Berringer
2025-03-07 17:42 ` Srinivas Kandagatla
2025-02-28 18:03 ` [PATCH v4 2/2] power: reset: nvmem-reboot-mode: support smaller magic Jennifer Berringer
1 sibling, 1 reply; 5+ messages in thread
From: Jennifer Berringer @ 2025-02-28 18:03 UTC (permalink / raw)
To: Srinivas Kandagatla, Sebastian Reichel
Cc: linux-kernel, linux-pm, Jennifer Berringer
This function allows nvmem consumers to know the size of an nvmem cell
before calling nvmem_cell_write() or nvmem_cell_read(), which is helpful
for drivers that may need to handle devices with different cell sizes.
Signed-off-by: Jennifer Berringer <jberring@redhat.com>
---
drivers/nvmem/core.c | 18 ++++++++++++++++++
include/linux/nvmem-consumer.h | 6 ++++++
2 files changed, 24 insertions(+)
diff --git a/drivers/nvmem/core.c b/drivers/nvmem/core.c
index d6494dfc20a7..4d0cbd20da48 100644
--- a/drivers/nvmem/core.c
+++ b/drivers/nvmem/core.c
@@ -1624,6 +1624,24 @@ void nvmem_cell_put(struct nvmem_cell *cell)
}
EXPORT_SYMBOL_GPL(nvmem_cell_put);
+/**
+ * nvmem_cell_size() - Get nvmem cell size in bytes.
+ *
+ * @cell: nvmem cell.
+ *
+ * Return: size of the nvmem cell.
+ */
+size_t nvmem_cell_size(struct nvmem_cell *cell)
+{
+ struct nvmem_cell_entry *entry = cell->entry;
+
+ if (!entry)
+ return 0;
+
+ return entry->bytes;
+}
+EXPORT_SYMBOL_GPL(nvmem_cell_size);
+
static void nvmem_shift_read_buffer_in_place(struct nvmem_cell_entry *cell, void *buf)
{
u8 *p, *b;
diff --git a/include/linux/nvmem-consumer.h b/include/linux/nvmem-consumer.h
index 34c0e58dfa26..a2020527d2d3 100644
--- a/include/linux/nvmem-consumer.h
+++ b/include/linux/nvmem-consumer.h
@@ -54,6 +54,7 @@ struct nvmem_cell *nvmem_cell_get(struct device *dev, const char *id);
struct nvmem_cell *devm_nvmem_cell_get(struct device *dev, const char *id);
void nvmem_cell_put(struct nvmem_cell *cell);
void devm_nvmem_cell_put(struct device *dev, struct nvmem_cell *cell);
+size_t nvmem_cell_size(struct nvmem_cell *cell);
void *nvmem_cell_read(struct nvmem_cell *cell, size_t *len);
int nvmem_cell_write(struct nvmem_cell *cell, void *buf, size_t len);
int nvmem_cell_read_u8(struct device *dev, const char *cell_id, u8 *val);
@@ -117,6 +118,11 @@ static inline void nvmem_cell_put(struct nvmem_cell *cell)
{
}
+static inline size_t nvmem_cell_size(struct nvmem_cell *cell)
+{
+ return 0;
+}
+
static inline void *nvmem_cell_read(struct nvmem_cell *cell, size_t *len)
{
return ERR_PTR(-EOPNOTSUPP);
--
2.47.1
^ permalink raw reply related [flat|nested] 5+ messages in thread
* [PATCH v4 2/2] power: reset: nvmem-reboot-mode: support smaller magic
2025-02-28 18:03 [PATCH v4 0/2] nvmem-reboot-mode: support small reboot mode magic Jennifer Berringer
2025-02-28 18:03 ` [PATCH v4 1/2] nvmem: core: add nvmem_cell_size() Jennifer Berringer
@ 2025-02-28 18:03 ` Jennifer Berringer
1 sibling, 0 replies; 5+ messages in thread
From: Jennifer Berringer @ 2025-02-28 18:03 UTC (permalink / raw)
To: Srinivas Kandagatla, Sebastian Reichel
Cc: linux-kernel, linux-pm, Jennifer Berringer
Some devices, such as Qualcomm sa8775p, have an nvmem reboot mode cell
that is only 1 byte, which resulted in nvmem_reboot_mode_write() failing
when it attempts to write a 4-byte magic. Checking the nvmem cell size
and writing only the lower bits of the reboot mode magic is needed for
these devices.
Signed-off-by: Jennifer Berringer <jberring@redhat.com>
---
drivers/power/reset/nvmem-reboot-mode.c | 9 ++++++++-
1 file changed, 8 insertions(+), 1 deletion(-)
diff --git a/drivers/power/reset/nvmem-reboot-mode.c b/drivers/power/reset/nvmem-reboot-mode.c
index 41530b70cfc4..112e6cf77d1b 100644
--- a/drivers/power/reset/nvmem-reboot-mode.c
+++ b/drivers/power/reset/nvmem-reboot-mode.c
@@ -20,11 +20,18 @@ static int nvmem_reboot_mode_write(struct reboot_mode_driver *reboot,
unsigned int magic)
{
int ret;
+ u8 *magic_ptr = (u8 *) &magic;
+ size_t cell_size;
struct nvmem_reboot_mode *nvmem_rbm;
nvmem_rbm = container_of(reboot, struct nvmem_reboot_mode, reboot);
+ cell_size = nvmem_cell_size(nvmem_rbm->cell);
- ret = nvmem_cell_write(nvmem_rbm->cell, &magic, sizeof(magic));
+ /* Use magic's low-order bytes when writing to a smaller cell. */
+ if (IS_ENABLED(CONFIG_CPU_BIG_ENDIAN) && cell_size < sizeof(magic))
+ magic_ptr += sizeof(magic) - cell_size;
+
+ ret = nvmem_cell_write(nvmem_rbm->cell, magic_ptr, MIN(cell_size, sizeof(magic)));
if (ret < 0)
dev_err(reboot->dev, "update reboot mode bits failed\n");
--
2.47.1
^ permalink raw reply related [flat|nested] 5+ messages in thread
* Re: [PATCH v4 1/2] nvmem: core: add nvmem_cell_size()
2025-02-28 18:03 ` [PATCH v4 1/2] nvmem: core: add nvmem_cell_size() Jennifer Berringer
@ 2025-03-07 17:42 ` Srinivas Kandagatla
2025-03-08 4:38 ` Jennifer Berringer
0 siblings, 1 reply; 5+ messages in thread
From: Srinivas Kandagatla @ 2025-03-07 17:42 UTC (permalink / raw)
To: Jennifer Berringer, Sebastian Reichel; +Cc: linux-kernel, linux-pm
Hi Jennifer,
On 28/02/2025 18:03, Jennifer Berringer wrote:
> This function allows nvmem consumers to know the size of an nvmem cell
> before calling nvmem_cell_write() or nvmem_cell_read(), which is helpful
> for drivers that may need to handle devices with different cell sizes.
>
> Signed-off-by: Jennifer Berringer <jberring@redhat.com>
> ---
> drivers/nvmem/core.c | 18 ++++++++++++++++++
> include/linux/nvmem-consumer.h | 6 ++++++
> 2 files changed, 24 insertions(+)
>
> diff --git a/drivers/nvmem/core.c b/drivers/nvmem/core.c
> index d6494dfc20a7..4d0cbd20da48 100644
> --- a/drivers/nvmem/core.c
> +++ b/drivers/nvmem/core.c
> @@ -1624,6 +1624,24 @@ void nvmem_cell_put(struct nvmem_cell *cell)
> }
> EXPORT_SYMBOL_GPL(nvmem_cell_put);
>
> +/**
> + * nvmem_cell_size() - Get nvmem cell size in bytes.
> + *
> + * @cell: nvmem cell.
> + *
> + * Return: size of the nvmem cell.
> + */
> +size_t nvmem_cell_size(struct nvmem_cell *cell)
> +{
> + struct nvmem_cell_entry *entry = cell->entry;
> +
> + if (!entry)
> + return 0;
> +
> + return entry->bytes;
> +}
> +EXPORT_SYMBOL_GPL(nvmem_cell_size);
> +
There is a similar patch on the list, could you take a look and see if
that is usable in power reset driver.
https://lore.kernel.org/lkml/20250306093900.2199442-3-o.rempel@pengutronix.de/T/#m97bbb1870d7140661894a4e806a695e563588524
--srini
> static void nvmem_shift_read_buffer_in_place(struct nvmem_cell_entry *cell, void *buf)
> {
> u8 *p, *b;
> diff --git a/include/linux/nvmem-consumer.h b/include/linux/nvmem-consumer.h
> index 34c0e58dfa26..a2020527d2d3 100644
> --- a/include/linux/nvmem-consumer.h
> +++ b/include/linux/nvmem-consumer.h
> @@ -54,6 +54,7 @@ struct nvmem_cell *nvmem_cell_get(struct device *dev, const char *id);
> struct nvmem_cell *devm_nvmem_cell_get(struct device *dev, const char *id);
> void nvmem_cell_put(struct nvmem_cell *cell);
> void devm_nvmem_cell_put(struct device *dev, struct nvmem_cell *cell);
> +size_t nvmem_cell_size(struct nvmem_cell *cell);
> void *nvmem_cell_read(struct nvmem_cell *cell, size_t *len);
> int nvmem_cell_write(struct nvmem_cell *cell, void *buf, size_t len);
> int nvmem_cell_read_u8(struct device *dev, const char *cell_id, u8 *val);
> @@ -117,6 +118,11 @@ static inline void nvmem_cell_put(struct nvmem_cell *cell)
> {
> }
>
> +static inline size_t nvmem_cell_size(struct nvmem_cell *cell)
> +{
> + return 0;
> +}
> +
> static inline void *nvmem_cell_read(struct nvmem_cell *cell, size_t *len)
> {
> return ERR_PTR(-EOPNOTSUPP);
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH v4 1/2] nvmem: core: add nvmem_cell_size()
2025-03-07 17:42 ` Srinivas Kandagatla
@ 2025-03-08 4:38 ` Jennifer Berringer
0 siblings, 0 replies; 5+ messages in thread
From: Jennifer Berringer @ 2025-03-08 4:38 UTC (permalink / raw)
To: Srinivas Kandagatla, Sebastian Reichel; +Cc: linux-kernel, linux-pm
Hello,
On 3/7/25 12:42, Srinivas Kandagatla wrote:
> Hi Jennifer,
>
> There is a similar patch on the list, could you take a look and see if that is usable in power reset driver.
>
> https://lore.kernel.org/lkml/20250306093900.2199442-3-o.rempel@pengutronix.de/T/#m97bbb1870d7140661894a4e806a695e563588524
>
> --srini
Yes, the nvmem_cell_get_size() function defined in that patch would make my own nvmem_cell_size() function in this patch redundant. I can update my reboot mode driver change to depend on that patch instead of introducing my own function for the same purpose.
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2025-03-08 4:38 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-02-28 18:03 [PATCH v4 0/2] nvmem-reboot-mode: support small reboot mode magic Jennifer Berringer
2025-02-28 18:03 ` [PATCH v4 1/2] nvmem: core: add nvmem_cell_size() Jennifer Berringer
2025-03-07 17:42 ` Srinivas Kandagatla
2025-03-08 4:38 ` Jennifer Berringer
2025-02-28 18:03 ` [PATCH v4 2/2] power: reset: nvmem-reboot-mode: support smaller magic Jennifer Berringer
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox