* [RFC PATCH 1/6] dt-bindings: display: add a device tree supplied boot logo
2026-07-31 21:50 [RFC PATCH 0/6] Boot logo supplied by the device tree Max Pedraza
@ 2026-07-31 21:50 ` Max Pedraza
2026-07-31 21:50 ` [RFC PATCH 2/6] video: logo: allow the boot logo to come from the device tree Max Pedraza
` (6 subsequent siblings)
7 siblings, 0 replies; 18+ messages in thread
From: Max Pedraza @ 2026-07-31 21:50 UTC (permalink / raw)
To: Helge Deller
Cc: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Thomas Zimmermann,
Maxime Ripard, linux-fbdev, dri-devel, devicetree, linux-kernel,
Max Pedraza
Embedded products frequently need a product specific boot logo. Today the
only way to get one is to replace one of the logo_*_clut224.ppm files in
the kernel source tree, which bakes the image into the kernel image: a
change of branding, or a second product sharing the same board support,
requires a separate kernel build.
Add a binding for a "linux,boot-logo-clut224" node, which carries the logo
in the same paletted format the built-in CLUT224 logos already use, plus a
few optional properties describing where on the screen it is drawn.
The palette size is derived from the length of the "clut" property rather
than spelled out separately, and "data" holds plain palette indices; the
32 entry offset the frame buffer layer reserves for the console is an
implementation detail and is applied by the kernel, not by the binding.
Signed-off-by: Max Pedraza <maximpedraza@gmail.com>
---
.../display/linux,boot-logo-clut224.yaml | 108 ++++++++++++++++++
MAINTAINERS | 1 +
2 files changed, 109 insertions(+)
create mode 100644 Documentation/devicetree/bindings/display/linux,boot-logo-clut224.yaml
diff --git a/Documentation/devicetree/bindings/display/linux,boot-logo-clut224.yaml b/Documentation/devicetree/bindings/display/linux,boot-logo-clut224.yaml
new file mode 100644
index 000000000..10845378d
--- /dev/null
+++ b/Documentation/devicetree/bindings/display/linux,boot-logo-clut224.yaml
@@ -0,0 +1,108 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/display/linux,boot-logo-clut224.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Boot logo supplied by the device tree
+
+maintainers:
+ - Max Pedraza <maximpedraza@gmail.com>
+
+description: |
+ Embedded systems commonly need a product specific boot logo. Today the only
+ way to get one is to replace one of the logo_*_clut224.ppm files in the
+ kernel source tree, which means the image is baked into the kernel image and
+ a new kernel has to be built and deployed to change it.
+
+ This node lets the boot logo be described by the device tree instead, so that
+ a single kernel image can serve several products, or several revisions of the
+ same product, that only differ in branding.
+
+ The image is stored in the same paletted format the in-kernel CLUT224 logos
+ use: a palette of at most 224 RGB entries plus one palette index per pixel.
+
+properties:
+ compatible:
+ const: linux,boot-logo-clut224
+
+ width:
+ $ref: /schemas/types.yaml#/definitions/uint32
+ description: Logo width in pixels.
+ minimum: 1
+ maximum: 65535
+
+ height:
+ $ref: /schemas/types.yaml#/definitions/uint32
+ description: Logo height in pixels.
+ minimum: 1
+ maximum: 65535
+
+ clut:
+ $ref: /schemas/types.yaml#/definitions/uint8-array
+ description:
+ Colour lookup table, as consecutive red, green and blue bytes per entry.
+ The number of entries is derived from the property length and must not
+ exceed 224.
+ minItems: 3
+ maxItems: 672
+
+ data:
+ $ref: /schemas/types.yaml#/definitions/uint8-array
+ description:
+ One byte per pixel, left to right and top to bottom, each byte being an
+ index into the colour lookup table. The property length must be equal to
+ width multiplied by height.
+
+ logo-position:
+ $ref: /schemas/types.yaml#/definitions/uint32-array
+ description:
+ X and Y coordinates, in pixels, of the top left corner of the logo.
+ Defaults to the top left corner of the screen.
+ items:
+ - description: X coordinate
+ - description: Y coordinate
+
+ logo-offset:
+ $ref: /schemas/types.yaml#/definitions/int32-array
+ description:
+ X and Y displacement, in pixels, applied after the logo has been placed.
+ Mostly useful together with logo-centered.
+ items:
+ - description: X displacement
+ - description: Y displacement
+
+ logo-centered:
+ type: boolean
+ description:
+ Centre the logo on the screen, overriding logo-position.
+
+ logo-rotation:
+ $ref: /schemas/types.yaml#/definitions/string
+ description: Rotation applied to the logo before it is drawn.
+ enum: [none, cw, ccw, ud]
+ default: none
+
+required:
+ - compatible
+ - width
+ - height
+ - clut
+ - data
+
+additionalProperties: false
+
+examples:
+ - |
+ // A 4x2 logo using three colours, centred on the screen.
+ logo {
+ compatible = "linux,boot-logo-clut224";
+ width = <4>;
+ height = <2>;
+ clut = /bits/ 8 <0xff 0x00 0x00
+ 0x00 0xff 0x00
+ 0x00 0x00 0xff>;
+ data = /bits/ 8 <0x00 0x01 0x01 0x00
+ 0x02 0x00 0x00 0x02>;
+ logo-centered;
+ };
diff --git a/MAINTAINERS b/MAINTAINERS
index e08767323..3f0ede165 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -9951,6 +9951,7 @@ L: dri-devel@lists.freedesktop.org
S: Maintained
Q: http://patchwork.kernel.org/project/linux-fbdev/list/
T: git git://git.kernel.org/pub/scm/linux/kernel/git/deller/linux-fbdev.git
+F: Documentation/devicetree/bindings/display/linux,boot-logo-clut224.yaml
F: Documentation/fb/
F: drivers/video/
F: include/linux/fb.h
--
2.39.5
^ permalink raw reply related [flat|nested] 18+ messages in thread* [RFC PATCH 2/6] video: logo: allow the boot logo to come from the device tree
2026-07-31 21:50 [RFC PATCH 0/6] Boot logo supplied by the device tree Max Pedraza
2026-07-31 21:50 ` [RFC PATCH 1/6] dt-bindings: display: add a device tree supplied boot logo Max Pedraza
@ 2026-07-31 21:50 ` Max Pedraza
2026-07-31 21:50 ` [RFC PATCH 3/6] fbdev: honour the device tree boot logo placement properties Max Pedraza
` (5 subsequent siblings)
7 siblings, 0 replies; 18+ messages in thread
From: Max Pedraza @ 2026-07-31 21:50 UTC (permalink / raw)
To: Helge Deller
Cc: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Thomas Zimmermann,
Maxime Ripard, linux-fbdev, dri-devel, devicetree, linux-kernel,
Max Pedraza
With CONFIG_LOGO_DT_CLUT224 enabled, look for a node compatible with
"linux,boot-logo-clut224" and, when one is present and enabled, use the
image it carries in preference to the logos built into the kernel image.
This lets a single kernel image serve several products, or several
revisions of one product, that differ only in branding, at the cost of a
larger device tree blob.
The image is validated while it is parsed: the palette must be at most 224
entries, the pixel data length must match the declared geometry, and every
pixel must reference an existing palette entry. A malformed node is
reported and ignored, falling back to the built-in logo.
The two allocations live for as long as the built-in logos do; they are
released from fb_logo_late_init(), next to where the __initdata logos are
marked as freed.
If the node is absent or disabled, behaviour is unchanged.
Signed-off-by: Max Pedraza <maximpedraza@gmail.com>
---
drivers/video/logo/Kconfig | 13 +++
drivers/video/logo/logo.c | 157 +++++++++++++++++++++++++++++++++++++
2 files changed, 170 insertions(+)
diff --git a/drivers/video/logo/Kconfig b/drivers/video/logo/Kconfig
index ce6bb7535..4af349b20 100644
--- a/drivers/video/logo/Kconfig
+++ b/drivers/video/logo/Kconfig
@@ -70,4 +70,17 @@ config LOGO_SUPERH_CLUT224
depends on SUPERH
default y
+config LOGO_DT_CLUT224
+ bool "224-color logo supplied by the device tree"
+ depends on OF
+ help
+ Look for a boot logo in the device tree, in a node compatible with
+ "linux,boot-logo-clut224", instead of using one of the logos built
+ into the kernel image. This allows a single kernel image to be used
+ by several products that only differ in branding, at the cost of
+ making the device tree blob larger.
+
+ If no such node is present, or it is disabled, the built-in logo
+ selected above is used, so saying Y here is safe. If unsure, say N.
+
endif # LOGO
diff --git a/drivers/video/logo/logo.c b/drivers/video/logo/logo.c
index 141f15a9a..b4f533df0 100644
--- a/drivers/video/logo/logo.c
+++ b/drivers/video/logo/logo.c
@@ -11,6 +11,9 @@
*/
#include <linux/linux_logo.h>
+#include <linux/of.h>
+#include <linux/sizes.h>
+#include <linux/slab.h>
#include <linux/stddef.h>
#include <linux/module.h>
@@ -22,6 +25,155 @@ static bool nologo;
module_param(nologo, bool, 0);
MODULE_PARM_DESC(nologo, "Disables startup logo");
+#ifdef CONFIG_LOGO_DT_CLUT224
+
+#define LOGO_DT_COMPATIBLE "linux,boot-logo-clut224"
+#define LOGO_DT_MAX_CLUT 224
+/*
+ * The first 32 palette entries are reserved for the console, so the logo
+ * colours start at index 32. That is an implementation detail of the frame
+ * buffer layer rather than a property of the image, so the device tree stores
+ * plain indices and the offset is applied here.
+ */
+#define LOGO_DT_CLUT_OFFSET 32
+/* Sanity limit on the image size, a device tree is not a good place for more */
+#define LOGO_DT_MAX_PIXELS SZ_32M
+
+static struct linux_logo logo_dt_clut224 = {
+ .type = LINUX_LOGO_CLUT224,
+};
+
+static unsigned char *logo_dt_clut;
+static unsigned char *logo_dt_data;
+
+static int logo_dt_parse(struct device_node *np)
+{
+ unsigned int clutsize, npixels, i;
+ unsigned char *clut, *data;
+ u32 width, height;
+ int len, ret;
+
+ ret = of_property_read_u32(np, "width", &width);
+ if (ret)
+ return ret;
+
+ ret = of_property_read_u32(np, "height", &height);
+ if (ret)
+ return ret;
+
+ if (!width || !height || (u64)width * height > LOGO_DT_MAX_PIXELS)
+ return -EINVAL;
+
+ npixels = width * height;
+
+ len = of_property_count_u8_elems(np, "clut");
+ if (len < 3 || len % 3)
+ return -EINVAL;
+
+ clutsize = len / 3;
+ if (clutsize > LOGO_DT_MAX_CLUT)
+ return -EINVAL;
+
+ ret = of_property_count_u8_elems(np, "data");
+ if (ret < 0)
+ return ret;
+ if ((unsigned int)ret != npixels)
+ return -EINVAL;
+
+ clut = kmalloc(len, GFP_KERNEL);
+ if (!clut)
+ return -ENOMEM;
+
+ data = kmalloc(npixels, GFP_KERNEL);
+ if (!data) {
+ ret = -ENOMEM;
+ goto err_free_clut;
+ }
+
+ ret = of_property_read_u8_array(np, "clut", clut, len);
+ if (ret)
+ goto err_free_data;
+
+ ret = of_property_read_u8_array(np, "data", data, npixels);
+ if (ret)
+ goto err_free_data;
+
+ for (i = 0; i < npixels; i++) {
+ if (data[i] >= clutsize) {
+ ret = -ERANGE;
+ goto err_free_data;
+ }
+ data[i] += LOGO_DT_CLUT_OFFSET;
+ }
+
+ logo_dt_clut = clut;
+ logo_dt_data = data;
+
+ logo_dt_clut224.width = width;
+ logo_dt_clut224.height = height;
+ logo_dt_clut224.clutsize = clutsize;
+ logo_dt_clut224.clut = clut;
+ logo_dt_clut224.data = data;
+
+ return 0;
+
+err_free_data:
+ kfree(data);
+err_free_clut:
+ kfree(clut);
+ return ret;
+}
+
+static const struct linux_logo *logo_dt_find(void)
+{
+ static bool probed;
+ struct device_node *np;
+ int ret;
+
+ if (probed)
+ return logo_dt_data ? &logo_dt_clut224 : NULL;
+
+ probed = true;
+
+ np = of_find_compatible_node(NULL, NULL, LOGO_DT_COMPATIBLE);
+ if (!np)
+ return NULL;
+
+ if (of_device_is_available(np)) {
+ ret = logo_dt_parse(np);
+ if (ret)
+ pr_warn("logo: ignoring malformed %pOF node (%d)\n",
+ np, ret);
+ }
+
+ of_node_put(np);
+
+ return logo_dt_data ? &logo_dt_clut224 : NULL;
+}
+
+static void logo_dt_free(void)
+{
+ logo_dt_clut224.clut = NULL;
+ logo_dt_clut224.data = NULL;
+
+ kfree(logo_dt_clut);
+ logo_dt_clut = NULL;
+
+ kfree(logo_dt_data);
+ logo_dt_data = NULL;
+}
+
+#else /* !CONFIG_LOGO_DT_CLUT224 */
+
+static inline const struct linux_logo *logo_dt_find(void)
+{
+ return NULL;
+}
+
+static inline void logo_dt_free(void) { }
+
+#endif /* CONFIG_LOGO_DT_CLUT224 */
+
/*
* Logos are located in the initdata, and will be freed in kernel_init.
* Use late_init to mark the logos as freed to prevent any further use.
@@ -32,6 +184,7 @@ static bool logos_freed;
static int __init fb_logo_late_init(void)
{
logos_freed = true;
+ logo_dt_free();
return 0;
}
@@ -71,6 +224,10 @@ const struct linux_logo * __ref fb_find_logo(int depth)
}
if (depth >= 8) {
+ /* A logo supplied by the device tree wins over the built-in ones */
+ logo = logo_dt_find();
+ if (logo)
+ return logo;
#ifdef CONFIG_LOGO_LINUX_CLUT224
/* Generic Linux logo */
logo = &logo_linux_clut224;
--
2.39.5
^ permalink raw reply related [flat|nested] 18+ messages in thread* [RFC PATCH 3/6] fbdev: honour the device tree boot logo placement properties
2026-07-31 21:50 [RFC PATCH 0/6] Boot logo supplied by the device tree Max Pedraza
2026-07-31 21:50 ` [RFC PATCH 1/6] dt-bindings: display: add a device tree supplied boot logo Max Pedraza
2026-07-31 21:50 ` [RFC PATCH 2/6] video: logo: allow the boot logo to come from the device tree Max Pedraza
@ 2026-07-31 21:50 ` Max Pedraza
2026-07-31 21:50 ` [RFC PATCH 4/6] dt-bindings: display: allow the boot logo in a reserved memory region Max Pedraza
` (4 subsequent siblings)
7 siblings, 0 replies; 18+ messages in thread
From: Max Pedraza @ 2026-07-31 21:50 UTC (permalink / raw)
To: Helge Deller
Cc: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Thomas Zimmermann,
Maxime Ripard, linux-fbdev, dri-devel, devicetree, linux-kernel,
Max Pedraza
A logo supplied by the device tree describes a specific product, so where
it lands on the panel matters in a way it does not for the built-in Tux.
Honour the optional "logo-position", "logo-offset", "logo-centered" and
"logo-rotation" properties of the "linux,boot-logo-clut224" node.
The rotation is folded into the rotate argument at the entry points, so
fb_prepare_logo() reserves the right amount of space and fb_do_show_logo()
tiles in the same direction the image was rotated in.
Placement is applied after fb_rotate_logo(), since a rotation swaps the
image width and height and centring needs the final dimensions.
fb_prepare_logo() has to grow its reservation to cover wherever the logo
ends up, the way fb_center_logo already does: fbcon only leaves the first
n rows alone, so a logo placed further down is drawn and then immediately
cleared by the console.
"logo-centered" is deliberately close to the existing fb_center_logo, but
it is per device tree rather than per fbcon command line, and it composes
with "logo-offset" so that a logo can be centred and then nudged. That
combination is what panels with a partially visible area need, where the
usable region is not the centre of the mode.
Signed-off-by: Max Pedraza <maximpedraza@gmail.com>
---
drivers/video/fbdev/core/fb_logo.c | 174 +++++++++++++++++++++++++++++
1 file changed, 174 insertions(+)
diff --git a/drivers/video/fbdev/core/fb_logo.c b/drivers/video/fbdev/core/fb_logo.c
index 0bab8352b..bfc1b72ce 100644
--- a/drivers/video/fbdev/core/fb_logo.c
+++ b/drivers/video/fbdev/core/fb_logo.c
@@ -2,12 +2,178 @@
#include <linux/fb.h>
#include <linux/linux_logo.h>
+#include <linux/of.h>
#include "fb_internal.h"
bool fb_center_logo __read_mostly;
int fb_logo_count __read_mostly = -1;
+#ifdef CONFIG_LOGO_DT_CLUT224
+
+/*
+ * Placement of a logo supplied by the device tree. The image itself is parsed
+ * by drivers/video/logo/logo.c, here we only care about where it goes.
+ */
+struct fb_logo_dt_placement {
+ bool valid;
+ bool centered;
+ bool has_position;
+ int rotation; /* FB_ROTATE_*, or -1 when unspecified */
+ u32 x, y;
+ s32 offset_x, offset_y;
+};
+
+static struct fb_logo_dt_placement fb_logo_dt;
+
+static int fb_logo_dt_parse_rotation(const char *rotation)
+{
+ if (!strcmp(rotation, "none"))
+ return FB_ROTATE_UR;
+ if (!strcmp(rotation, "cw"))
+ return FB_ROTATE_CW;
+ if (!strcmp(rotation, "ud"))
+ return FB_ROTATE_UD;
+ if (!strcmp(rotation, "ccw"))
+ return FB_ROTATE_CCW;
+
+ return -EINVAL;
+}
+
+static void fb_logo_dt_read(void)
+{
+ struct fb_logo_dt_placement *p = &fb_logo_dt;
+ static bool read_done;
+ struct device_node *np;
+ const char *rotation;
+ u32 val[2];
+ int rot;
+
+ if (read_done)
+ return;
+
+ read_done = true;
+
+ np = of_find_compatible_node(NULL, NULL, "linux,boot-logo-clut224");
+ if (!np)
+ return;
+
+ if (!of_device_is_available(np))
+ goto out;
+
+ p->valid = true;
+ p->rotation = -1;
+ p->centered = of_property_read_bool(np, "logo-centered");
+
+ if (!of_property_read_u32_array(np, "logo-position", val, 2)) {
+ p->has_position = true;
+ p->x = val[0];
+ p->y = val[1];
+ }
+
+ if (!of_property_read_u32_array(np, "logo-offset", val, 2)) {
+ p->offset_x = (s32)val[0];
+ p->offset_y = (s32)val[1];
+ }
+
+ if (!of_property_read_string(np, "logo-rotation", &rotation)) {
+ rot = fb_logo_dt_parse_rotation(rotation);
+ if (rot < 0)
+ pr_warn("fb: %pOF: unknown logo-rotation \"%s\"\n",
+ np, rotation);
+ else
+ p->rotation = rot;
+ }
+
+out:
+ of_node_put(np);
+}
+
+static int fb_logo_dt_rotation(int rotate)
+{
+ fb_logo_dt_read();
+
+ if (fb_logo_dt.valid && fb_logo_dt.rotation >= 0)
+ return fb_logo_dt.rotation;
+
+ return rotate;
+}
+
+/* Top edge of the logo, in the coordinate space the caller works in */
+static int fb_logo_dt_top(unsigned int yres, unsigned int logo_height)
+{
+ struct fb_logo_dt_placement *p = &fb_logo_dt;
+ int top;
+
+ if (p->centered)
+ top = ((int)yres - (int)logo_height) / 2;
+ else if (p->has_position)
+ top = p->y;
+ else
+ top = 0;
+
+ return max(top + p->offset_y, 0);
+}
+
+static void fb_logo_dt_place(struct fb_info *info, struct fb_image *image)
+{
+ struct fb_logo_dt_placement *p = &fb_logo_dt;
+ int dx;
+
+ fb_logo_dt_read();
+
+ if (!p->valid)
+ return;
+
+ if (p->centered)
+ dx = ((int)info->var.xres - (int)image->width) / 2;
+ else if (p->has_position)
+ dx = p->x;
+ else
+ dx = image->dx;
+
+ image->dx = max(dx + p->offset_x, 0);
+ image->dy = fb_logo_dt_top(info->var.yres, image->height);
+}
+
+/*
+ * fbcon only leaves the first @height rows of the screen alone, so a logo
+ * placed further down would be drawn and then immediately cleared. Grow the
+ * reservation to cover wherever the logo actually ends up, the same way
+ * fb_center_logo does.
+ */
+static int fb_logo_dt_reserve(unsigned int yres, unsigned int logo_height,
+ int height)
+{
+ fb_logo_dt_read();
+
+ if (!fb_logo_dt.valid)
+ return height;
+
+ return max(height, fb_logo_dt_top(yres, logo_height) +
+ (int)logo_height);
+}
+
+#else /* !CONFIG_LOGO_DT_CLUT224 */
+
+static inline int fb_logo_dt_rotation(int rotate)
+{
+ return rotate;
+}
+
+static inline void fb_logo_dt_place(struct fb_info *info,
+ struct fb_image *image)
+{
+}
+
+static inline int fb_logo_dt_reserve(unsigned int yres,
+ unsigned int logo_height, int height)
+{
+ return height;
+}
+
+#endif /* CONFIG_LOGO_DT_CLUT224 */
+
static inline unsigned int safe_shift(unsigned int d, int n)
{
return n < 0 ? d >> -n : d << n;
@@ -350,6 +516,9 @@ static int fb_show_logo_line(struct fb_info *info, int rotate,
fb_rotate_logo(info, logo_rotate, &image, rotate);
}
+ /* Done last, image dimensions are only final after the rotation */
+ fb_logo_dt_place(info, &image);
+
fb_do_show_logo(info, &image, rotate, n);
kfree(palette);
@@ -423,6 +592,8 @@ int fb_prepare_logo(struct fb_info *info, int rotate)
memset(&fb_logo, 0, sizeof(struct logo_data));
+ rotate = fb_logo_dt_rotation(rotate);
+
if (info->flags & FBINFO_MISC_TILEBLITTING ||
info->fbops->owner || !fb_logo_count)
return 0;
@@ -483,6 +654,7 @@ int fb_prepare_logo(struct fb_info *info, int rotate)
height = fb_logo.logo->height;
if (fb_center_logo)
height += (yres - fb_logo.logo->height) / 2;
+ height = fb_logo_dt_reserve(yres, fb_logo.logo->height, height);
#ifdef CONFIG_FB_LOGO_EXTRA
height = fb_prepare_extra_logos(info, height, yres);
#endif
@@ -498,6 +670,8 @@ int fb_show_logo(struct fb_info *info, int rotate)
if (!fb_logo_count)
return 0;
+ rotate = fb_logo_dt_rotation(rotate);
+
count = fb_logo_count < 0 ? num_online_cpus() : fb_logo_count;
y = fb_show_logo_line(info, rotate, fb_logo.logo, 0, count);
#ifdef CONFIG_FB_LOGO_EXTRA
--
2.39.5
^ permalink raw reply related [flat|nested] 18+ messages in thread* [RFC PATCH 4/6] dt-bindings: display: allow the boot logo in a reserved memory region
2026-07-31 21:50 [RFC PATCH 0/6] Boot logo supplied by the device tree Max Pedraza
` (2 preceding siblings ...)
2026-07-31 21:50 ` [RFC PATCH 3/6] fbdev: honour the device tree boot logo placement properties Max Pedraza
@ 2026-07-31 21:50 ` Max Pedraza
2026-07-31 21:50 ` [RFC PATCH 5/6] video: logo: allow the boot logo to come from " Max Pedraza
` (3 subsequent siblings)
7 siblings, 0 replies; 18+ messages in thread
From: Max Pedraza @ 2026-07-31 21:50 UTC (permalink / raw)
To: Helge Deller
Cc: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Thomas Zimmermann,
Maxime Ripard, linux-fbdev, dri-devel, devicetree, linux-kernel,
Max Pedraza
Carrying the image in the device tree ties it to the device tree, but the
image and where it goes on screen are independent axes of variation. One
board sold to several customers wants several device trees that differ in
the logo; one customer with several products built on that board wants the
same logo placed differently on each panel. The second case would otherwise
mean duplicating the same image into every device tree.
Let the node point at a reserved memory region filled in by the bootloader
instead, so one image can be shared by device trees that differ only in
placement. The region starts with a small header carrying a magic number
and the geometry, so the kernel can tell a logo from an empty or stale
region and bounds check everything against the reservation.
A phandle to a declared region is used rather than a bare address: the
reservation is what makes the memory safe to read and what gives the kernel
a size to validate against. The two ways of supplying the image are
mutually exclusive.
Signed-off-by: Max Pedraza <maximpedraza@gmail.com>
---
.../display/linux,boot-logo-clut224.yaml | 52 +++++++++++++++++--
1 file changed, 48 insertions(+), 4 deletions(-)
diff --git a/Documentation/devicetree/bindings/display/linux,boot-logo-clut224.yaml b/Documentation/devicetree/bindings/display/linux,boot-logo-clut224.yaml
index 10845378d..c40683f3a 100644
--- a/Documentation/devicetree/bindings/display/linux,boot-logo-clut224.yaml
+++ b/Documentation/devicetree/bindings/display/linux,boot-logo-clut224.yaml
@@ -54,6 +54,23 @@ properties:
index into the colour lookup table. The property length must be equal to
width multiplied by height.
+ memory-region:
+ maxItems: 1
+ description: |
+ Reserved memory region holding the logo, as an alternative to carrying
+ it in the width, height, clut and data properties. The bootloader is
+ expected to have placed the image there before starting the kernel.
+
+ This lets one image be shared by several device trees that differ only
+ in where the logo goes, which is what a family of products built on the
+ same board but with different panels needs.
+
+ The region starts with a header of four little endian 32 bit words:
+ the magic number 0x4f474f4c ("LOGO"), the width, the height and the
+ number of palette entries. The palette follows, as consecutive red,
+ green and blue bytes per entry, and then one byte per pixel, each an
+ index into that palette.
+
logo-position:
$ref: /schemas/types.yaml#/definitions/uint32-array
description:
@@ -85,10 +102,17 @@ properties:
required:
- compatible
- - width
- - height
- - clut
- - data
+
+# The image either lives in the device tree or in a reserved memory region,
+# never both.
+oneOf:
+ - required:
+ - width
+ - height
+ - clut
+ - data
+ - required:
+ - memory-region
additionalProperties: false
@@ -106,3 +130,23 @@ examples:
0x02 0x00 0x00 0x02>;
logo-centered;
};
+ - |
+ // The same logo taken from a region the bootloader filled in, centred on
+ // a panel whose usable area is not the centre of the mode.
+ reserved-memory {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges;
+
+ logo_mem: logo@9c000000 {
+ reg = <0x9c000000 0x100000>;
+ no-map;
+ };
+ };
+
+ logo {
+ compatible = "linux,boot-logo-clut224";
+ memory-region = <&logo_mem>;
+ logo-centered;
+ logo-offset = <0 120>;
+ };
--
2.39.5
^ permalink raw reply related [flat|nested] 18+ messages in thread* [RFC PATCH 5/6] video: logo: allow the boot logo to come from a reserved memory region
2026-07-31 21:50 [RFC PATCH 0/6] Boot logo supplied by the device tree Max Pedraza
` (3 preceding siblings ...)
2026-07-31 21:50 ` [RFC PATCH 4/6] dt-bindings: display: allow the boot logo in a reserved memory region Max Pedraza
@ 2026-07-31 21:50 ` Max Pedraza
2026-07-31 21:50 ` [RFC PATCH 6/6] video: logo: add ppmtodtlogo host tool Max Pedraza
` (2 subsequent siblings)
7 siblings, 0 replies; 18+ messages in thread
From: Max Pedraza @ 2026-07-31 21:50 UTC (permalink / raw)
To: Helge Deller
Cc: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Thomas Zimmermann,
Maxime Ripard, linux-fbdev, dri-devel, devicetree, linux-kernel,
Max Pedraza
Take the image from the region a "memory-region" phandle points at, when
the node has one, instead of from the width, height, clut and data
properties.
Only a declared region is accepted, never a bare physical address. That
matters for more than tidiness: the region is reserved before the allocator
starts, so the logo code can never be pointed at memory the kernel is using
for something else, and a size is known, so every field can be bounds
checked. The region is mapped with memremap(), which copes with a no-map
reservation and fails cleanly instead of handing back a bogus pointer the
way phys_to_virt() on an arbitrary address would.
The image is validated and copied out rather than used in place: the magic
number has to match, the geometry has to be sane, the palette and pixels
have to fit inside the reserved region, and every pixel has to reference an
existing palette entry. Anything else is reported and ignored, falling back
to the built-in logo. Copying also means nothing that happens to the region
afterwards can affect what has already been validated, and it keeps the
pixel data in the same shape both paths produce.
Signed-off-by: Max Pedraza <maximpedraza@gmail.com>
---
drivers/video/logo/logo.c | 171 ++++++++++++++++++++++++++++++--------
1 file changed, 135 insertions(+), 36 deletions(-)
diff --git a/drivers/video/logo/logo.c b/drivers/video/logo/logo.c
index b4f533df0..95d75b905 100644
--- a/drivers/video/logo/logo.c
+++ b/drivers/video/logo/logo.c
@@ -10,8 +10,10 @@
* Copyright (C) 2003 Geert Uytterhoeven <geert@linux-m68k.org>
*/
+#include <linux/io.h>
#include <linux/linux_logo.h>
#include <linux/of.h>
+#include <linux/of_reserved_mem.h>
#include <linux/sizes.h>
#include <linux/slab.h>
#include <linux/stddef.h>
@@ -38,6 +40,15 @@ MODULE_PARM_DESC(nologo, "Disables startup logo");
#define LOGO_DT_CLUT_OFFSET 32
/* Sanity limit on the image size, a device tree is not a good place for more */
#define LOGO_DT_MAX_PIXELS SZ_32M
+/* "LOGO", little endian, at the start of a handed over memory region */
+#define LOGO_DT_MAGIC 0x4f474f4c
+
+struct logo_dt_header {
+ __le32 magic;
+ __le32 width;
+ __le32 height;
+ __le32 clutsize;
+};
static struct linux_logo logo_dt_clut224 = {
.type = LINUX_LOGO_CLUT224,
@@ -46,58 +57,41 @@ static struct linux_logo logo_dt_clut224 = {
static unsigned char *logo_dt_clut;
static unsigned char *logo_dt_data;
-static int logo_dt_parse(struct device_node *np)
+/* Reject geometries that cannot describe a sane image before using them */
+static int logo_dt_check_geometry(u32 width, u32 height, u32 clutsize)
{
- unsigned int clutsize, npixels, i;
- unsigned char *clut, *data;
- u32 width, height;
- int len, ret;
-
- ret = of_property_read_u32(np, "width", &width);
- if (ret)
- return ret;
-
- ret = of_property_read_u32(np, "height", &height);
- if (ret)
- return ret;
-
if (!width || !height || (u64)width * height > LOGO_DT_MAX_PIXELS)
return -EINVAL;
- npixels = width * height;
-
- len = of_property_count_u8_elems(np, "clut");
- if (len < 3 || len % 3)
+ if (!clutsize || clutsize > LOGO_DT_MAX_CLUT)
return -EINVAL;
- clutsize = len / 3;
- if (clutsize > LOGO_DT_MAX_CLUT)
- return -EINVAL;
+ return 0;
+}
- ret = of_property_count_u8_elems(np, "data");
- if (ret < 0)
- return ret;
- if ((unsigned int)ret != npixels)
- return -EINVAL;
+/*
+ * Take a private copy of an image that has already been range checked, so
+ * that nothing else can change it under us, and shift the pixels into the
+ * palette slots the frame buffer layer leaves to the logo.
+ */
+static int logo_dt_store(u32 width, u32 height, u32 clutsize,
+ const u8 *clut_src, const u8 *data_src)
+{
+ unsigned int npixels = width * height;
+ unsigned char *clut, *data;
+ unsigned int i;
+ int ret;
- clut = kmalloc(len, GFP_KERNEL);
+ clut = kmemdup(clut_src, clutsize * 3, GFP_KERNEL);
if (!clut)
return -ENOMEM;
- data = kmalloc(npixels, GFP_KERNEL);
+ data = kmemdup(data_src, npixels, GFP_KERNEL);
if (!data) {
ret = -ENOMEM;
goto err_free_clut;
}
- ret = of_property_read_u8_array(np, "clut", clut, len);
- if (ret)
- goto err_free_data;
-
- ret = of_property_read_u8_array(np, "data", data, npixels);
- if (ret)
- goto err_free_data;
-
for (i = 0; i < npixels; i++) {
if (data[i] >= clutsize) {
ret = -ERANGE;
@@ -124,6 +118,111 @@ static int logo_dt_parse(struct device_node *np)
return ret;
}
+static int logo_dt_parse_properties(struct device_node *np)
+{
+ const u8 *clut, *data;
+ u32 width, height;
+ int len, ret;
+
+ ret = of_property_read_u32(np, "width", &width);
+ if (ret)
+ return ret;
+
+ ret = of_property_read_u32(np, "height", &height);
+ if (ret)
+ return ret;
+
+ len = of_property_count_u8_elems(np, "clut");
+ if (len < 3 || len % 3)
+ return -EINVAL;
+
+ ret = logo_dt_check_geometry(width, height, len / 3);
+ if (ret)
+ return ret;
+
+ if (of_property_count_u8_elems(np, "data") != width * height)
+ return -EINVAL;
+
+ clut = of_get_property(np, "clut", NULL);
+ data = of_get_property(np, "data", NULL);
+ if (!clut || !data)
+ return -EINVAL;
+
+ return logo_dt_store(width, height, len / 3, clut, data);
+}
+
+/*
+ * Image handed over by the bootloader in a reserved memory region. Only a
+ * region the device tree declared is accepted, never a bare address, so the
+ * kernel can never be pointed at memory it is using for something else, and
+ * so that a size is known and every access can be bounds checked.
+ */
+static int logo_dt_parse_memory_region(struct device_node *np)
+{
+ u32 width, height, clutsize;
+ const struct logo_dt_header *hdr;
+ struct device_node *mem_np;
+ struct reserved_mem *rmem;
+ size_t clutlen, datalen;
+ const u8 *payload;
+ void *mem;
+ int ret;
+
+ mem_np = of_parse_phandle(np, "memory-region", 0);
+ if (!mem_np)
+ return -ENOENT;
+
+ rmem = of_reserved_mem_lookup(mem_np);
+ of_node_put(mem_np);
+ if (!rmem)
+ return -EINVAL;
+
+ if (rmem->size < sizeof(*hdr))
+ return -EINVAL;
+
+ mem = memremap(rmem->base, rmem->size, MEMREMAP_WB);
+ if (!mem)
+ return -ENOMEM;
+
+ hdr = mem;
+ if (le32_to_cpu(hdr->magic) != LOGO_DT_MAGIC) {
+ ret = -EINVAL;
+ goto out_unmap;
+ }
+
+ width = le32_to_cpu(hdr->width);
+ height = le32_to_cpu(hdr->height);
+ clutsize = le32_to_cpu(hdr->clutsize);
+
+ ret = logo_dt_check_geometry(width, height, clutsize);
+ if (ret)
+ goto out_unmap;
+
+ clutlen = (size_t)clutsize * 3;
+ datalen = (size_t)width * height;
+
+ /* Everything the header promises has to fit inside the region */
+ if (sizeof(*hdr) + clutlen + datalen > rmem->size) {
+ ret = -EINVAL;
+ goto out_unmap;
+ }
+
+ payload = (const u8 *)(hdr + 1);
+ ret = logo_dt_store(width, height, clutsize, payload, payload + clutlen);
+
+out_unmap:
+ memunmap(mem);
+ return ret;
+}
+
+static int logo_dt_parse(struct device_node *np)
+{
+ if (of_property_present(np, "memory-region"))
+ return logo_dt_parse_memory_region(np);
+
+ return logo_dt_parse_properties(np);
+}
+
static const struct linux_logo *logo_dt_find(void)
{
static bool probed;
--
2.39.5
^ permalink raw reply related [flat|nested] 18+ messages in thread* [RFC PATCH 6/6] video: logo: add ppmtodtlogo host tool
2026-07-31 21:50 [RFC PATCH 0/6] Boot logo supplied by the device tree Max Pedraza
` (4 preceding siblings ...)
2026-07-31 21:50 ` [RFC PATCH 5/6] video: logo: allow the boot logo to come from " Max Pedraza
@ 2026-07-31 21:50 ` Max Pedraza
2026-08-01 8:08 ` [RFC PATCH 0/6] Boot logo supplied by the device tree Uwe Kleine-König
2026-08-04 13:58 ` Geert Uytterhoeven
7 siblings, 0 replies; 18+ messages in thread
From: Max Pedraza @ 2026-07-31 21:50 UTC (permalink / raw)
To: Helge Deller
Cc: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Thomas Zimmermann,
Maxime Ripard, linux-fbdev, dri-devel, devicetree, linux-kernel,
Max Pedraza
The byte arrays a "linux,boot-logo-clut224" node carries are not meant to
be written by hand. Add a host tool that converts a PPM image into the
node, along the lines of the existing pnmtologo: plain C, no dependencies,
and no quantization of its own -- the image must already use at most 224
distinct colours, and the tool points at ImageMagick when it does not.
Three output flavours:
ppmtodtlogo logo.ppm a complete overlay
ppmtodtlogo -t dtsi logo.ppm a bare node, for inclusion
ppmtodtlogo -t bin -o logo.bin ... the blob for a reserved memory
region, header included
The devicetree outputs also carry the optional placement properties,
commented out unless requested on the command line, so the generated file
documents what can be tuned without regenerating the image.
The tool is built when CONFIG_LOGO_DT_CLUT224 is enabled but is not used
by the kernel build itself.
Signed-off-by: Max Pedraza <maximpedraza@gmail.com>
---
drivers/video/logo/Makefile | 6 +-
drivers/video/logo/ppmtodtlogo.c | 402 +++++++++++++++++++++++++++++++
2 files changed, 407 insertions(+), 1 deletion(-)
create mode 100644 drivers/video/logo/ppmtodtlogo.c
diff --git a/drivers/video/logo/Makefile b/drivers/video/logo/Makefile
index 895c60b84..e7c77bf7e 100644
--- a/drivers/video/logo/Makefile
+++ b/drivers/video/logo/Makefile
@@ -18,7 +18,11 @@ obj-$(CONFIG_SPU_BASE) += logo_spe_clut224.o
# How to generate logo's
-hostprogs := pnmtologo
+hostprogs := pnmtologo ppmtodtlogo
+
+# Not used by the build itself: converts a user's image into the devicetree
+# node or memory blob the "linux,boot-logo-clut224" binding consumes.
+always-$(CONFIG_LOGO_DT_CLUT224) += ppmtodtlogo
# Create commands like "pnmtologo -t mono -n logo_mac_mono -o ..."
quiet_cmd_logo = LOGO $@
diff --git a/drivers/video/logo/ppmtodtlogo.c b/drivers/video/logo/ppmtodtlogo.c
new file mode 100644
index 000000000..de823131a
--- /dev/null
+++ b/drivers/video/logo/ppmtodtlogo.c
@@ -0,0 +1,402 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Convert a PPM image into a devicetree boot logo node, or into the binary
+ * blob the "linux,boot-logo-clut224" binding reads from a reserved memory
+ * region.
+ *
+ * Like pnmtologo, this tool does not quantize: the image must already use
+ * at most 224 distinct colours. Reduce it first if needed, for instance:
+ *
+ * magick logo.png -colors 224 logo.ppm
+ *
+ * The devicetree output stores plain palette indices; the 32 entry offset
+ * the frame buffer layer reserves for the console is applied by the kernel.
+ */
+
+#include <ctype.h>
+#include <errno.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#define MAX_CLUT_COLORS 224
+#define MAX_PIXELS (32U * 1024 * 1024)
+#define BLOB_MAGIC 0x4f474f4cU /* "LOGO", little endian */
+#define BYTES_PER_LINE 12
+
+static const char *programname;
+static const char *filename;
+static const char *outputname;
+static FILE *out;
+
+enum output_type {
+ OUTPUT_DTS, /* complete overlay */
+ OUTPUT_DTSI, /* bare node, for inclusion */
+ OUTPUT_BIN, /* blob for a reserved memory region */
+};
+
+static enum output_type output_type = OUTPUT_DTS;
+
+/* Placement options, emitted into the node */
+static int opt_centered;
+static char *opt_position;
+static char *opt_offset;
+static const char *opt_rotation;
+
+struct color {
+ unsigned char red;
+ unsigned char green;
+ unsigned char blue;
+};
+
+static unsigned int logo_width;
+static unsigned int logo_height;
+static unsigned char *logo_data;
+static struct color logo_clut[MAX_CLUT_COLORS];
+static unsigned int logo_clutsize;
+
+static void die(const char *fmt, ...)
+{
+ va_list ap;
+
+ va_start(ap, fmt);
+ vfprintf(stderr, fmt, ap);
+ va_end(ap);
+ exit(1);
+}
+
+static void usage(void)
+{
+ die("Usage: %s [options] <filename>\n"
+ "\n"
+ "Convert a PPM image into a \"linux,boot-logo-clut224\" node.\n"
+ "The image must use at most %d distinct colours.\n"
+ "\n"
+ " -o <output> write to file instead of stdout\n"
+ " -t <type> dts (default), dtsi or bin\n"
+ " -c centre the logo (logo-centered)\n"
+ " -p <x>,<y> logo-position\n"
+ " -f <dx>,<dy> logo-offset\n"
+ " -r <rotation> logo-rotation: cw, ccw, ud or none\n"
+ " -h this help\n",
+ programname, MAX_CLUT_COLORS);
+}
+
+static unsigned int get_number(FILE *fp)
+{
+ int c;
+ unsigned int val;
+
+ /* Skip leading whitespace */
+ do {
+ c = fgetc(fp);
+ if (c == EOF)
+ die("%s: end of file\n", filename);
+ if (c == '#') {
+ /* Ignore comments 'till end of line */
+ do {
+ c = fgetc(fp);
+ if (c == EOF)
+ die("%s: end of file\n", filename);
+ } while (c != '\n');
+ }
+ } while (isspace(c));
+
+ if (!isdigit(c))
+ die("%s: expected a number\n", filename);
+
+ /* Parse decimal number */
+ val = 0;
+ while (isdigit(c)) {
+ val = 10 * val + c - '0';
+ c = fgetc(fp);
+ if (c == EOF)
+ break;
+ }
+ return val;
+}
+
+static unsigned char get_byte(FILE *fp)
+{
+ int c = fgetc(fp);
+
+ if (c == EOF)
+ die("%s: end of file\n", filename);
+ return c;
+}
+
+static unsigned int find_clut_entry(struct color color)
+{
+ unsigned int i;
+
+ for (i = 0; i < logo_clutsize; i++)
+ if (logo_clut[i].red == color.red &&
+ logo_clut[i].green == color.green &&
+ logo_clut[i].blue == color.blue)
+ return i;
+
+ if (logo_clutsize == MAX_CLUT_COLORS)
+ die("%s: more than %d colors, reduce the image first, e.g.\n"
+ " magick %s -colors %d out.ppm\n",
+ filename, MAX_CLUT_COLORS, filename, MAX_CLUT_COLORS);
+
+ logo_clut[logo_clutsize] = color;
+ return logo_clutsize++;
+}
+
+static void read_image(void)
+{
+ unsigned int i, npixels, maxval;
+ int magic, raw;
+ FILE *fp;
+
+ fp = fopen(filename, "rb");
+ if (!fp)
+ die("Cannot open file %s: %s\n", filename, strerror(errno));
+
+ if (fgetc(fp) != 'P')
+ die("%s is not a PPM file\n", filename);
+
+ magic = fgetc(fp);
+ switch (magic) {
+ case '3':
+ raw = 0;
+ break;
+ case '6':
+ raw = 1;
+ break;
+ default:
+ die("%s is not a PPM file (only P3 and P6 are supported)\n",
+ filename);
+ }
+
+ logo_width = get_number(fp);
+ logo_height = get_number(fp);
+ maxval = get_number(fp);
+ if (maxval != 255)
+ die("%s: maximum color value must be 255\n", filename);
+
+ if (!logo_width || !logo_height)
+ die("%s: zero sized image\n", filename);
+ if ((unsigned long long)logo_width * logo_height > MAX_PIXELS)
+ die("%s: image too large\n", filename);
+
+ npixels = logo_width * logo_height;
+ logo_data = malloc(npixels);
+ if (!logo_data)
+ die("%s\n", strerror(errno));
+
+ for (i = 0; i < npixels; i++) {
+ struct color color;
+
+ if (raw) {
+ color.red = get_byte(fp);
+ color.green = get_byte(fp);
+ color.blue = get_byte(fp);
+ } else {
+ color.red = get_number(fp);
+ color.green = get_number(fp);
+ color.blue = get_number(fp);
+ }
+ logo_data[i] = find_clut_entry(color);
+ }
+
+ fclose(fp);
+}
+
+static void write_bytes(const unsigned char *data, unsigned int len,
+ const char *indent)
+{
+ unsigned int i;
+
+ for (i = 0; i < len; i++) {
+ if (i % BYTES_PER_LINE == 0)
+ fprintf(out, "%s%s", i ? "\n" : "", indent);
+ else
+ fputc(' ', out);
+ fprintf(out, "0x%02x", data[i]);
+ }
+}
+
+static void write_placement(const char *indent)
+{
+ fprintf(out, "%s/* Placement. logo-centered and logo-position are exclusive;\n",
+ indent);
+ fprintf(out, "%s * logo-offset is added after either of the two. */\n",
+ indent);
+
+ fprintf(out, "%s%slogo-centered;\n", indent, opt_centered ? "" : "// ");
+ fprintf(out, "%s%slogo-position = <%s>;\n", indent,
+ opt_position ? "" : "// ", opt_position ? opt_position : "0 0");
+ fprintf(out, "%s%slogo-offset = <%s>;\n", indent,
+ opt_offset ? "" : "// ", opt_offset ? opt_offset : "0 0");
+ fprintf(out, "%s%slogo-rotation = \"%s\";\t/* cw, ccw, ud, none */\n",
+ indent, opt_rotation ? "" : "// ",
+ opt_rotation ? opt_rotation : "ccw");
+}
+
+static void write_node(const char *indent)
+{
+ char subindent[16];
+
+ snprintf(subindent, sizeof(subindent), "%s\t\t", indent);
+
+ fprintf(out, "%scompatible = \"linux,boot-logo-clut224\";\n", indent);
+ fprintf(out, "\n");
+ write_placement(indent);
+ fprintf(out, "\n");
+ fprintf(out, "%swidth = <%u>;\n", indent, logo_width);
+ fprintf(out, "%sheight = <%u>;\n", indent, logo_height);
+ fprintf(out, "\n");
+ fprintf(out, "%sclut = /bits/ 8 <", indent);
+ write_bytes((const unsigned char *)logo_clut, logo_clutsize * 3,
+ subindent);
+ fprintf(out, ">;\n");
+ fprintf(out, "\n");
+ fprintf(out, "%sdata = /bits/ 8 <", indent);
+ write_bytes(logo_data, logo_width * logo_height, subindent);
+ fprintf(out, ">;\n");
+}
+
+static void write_header_comment(void)
+{
+ fprintf(out, "/*\n");
+ fprintf(out, " * Boot logo generated by ppmtodtlogo from %s\n",
+ filename);
+ fprintf(out, " * %ux%u pixels, %u colours.\n", logo_width, logo_height,
+ logo_clutsize);
+ fprintf(out, " */\n");
+}
+
+static void write_dts(void)
+{
+ fprintf(out, "/dts-v1/;\n/plugin/;\n\n");
+ write_header_comment();
+ fprintf(out, "\n");
+ fprintf(out, "/ {\n");
+ fprintf(out, "\tfragment@101 {\n");
+ fprintf(out, "\t\ttarget-path = \"/\";\n");
+ fprintf(out, "\n");
+ fprintf(out, "\t\t__overlay__ {\n");
+ fprintf(out, "\t\t\tlogo {\n");
+ write_node("\t\t\t\t");
+ fprintf(out, "\t\t\t};\n");
+ fprintf(out, "\t\t};\n");
+ fprintf(out, "\t};\n");
+ fprintf(out, "};\n");
+}
+
+static void write_dtsi(void)
+{
+ write_header_comment();
+ fprintf(out, "\n");
+ fprintf(out, "logo {\n");
+ write_node("\t");
+ fprintf(out, "};\n");
+}
+
+static void put_le32(unsigned int val)
+{
+ fputc(val & 0xff, out);
+ fputc((val >> 8) & 0xff, out);
+ fputc((val >> 16) & 0xff, out);
+ fputc((val >> 24) & 0xff, out);
+}
+
+static void write_bin(void)
+{
+ put_le32(BLOB_MAGIC);
+ put_le32(logo_width);
+ put_le32(logo_height);
+ put_le32(logo_clutsize);
+ fwrite(logo_clut, 3, logo_clutsize, out);
+ fwrite(logo_data, 1, logo_width * logo_height, out);
+}
+
+int main(int argc, char *argv[])
+{
+ int opt;
+ char *p;
+
+ programname = argv[0];
+
+ while ((opt = getopt(argc, argv, "o:t:cp:f:r:h")) != -1) {
+ switch (opt) {
+ case 'o':
+ outputname = optarg;
+ break;
+ case 't':
+ if (!strcmp(optarg, "dts"))
+ output_type = OUTPUT_DTS;
+ else if (!strcmp(optarg, "dtsi"))
+ output_type = OUTPUT_DTSI;
+ else if (!strcmp(optarg, "bin"))
+ output_type = OUTPUT_BIN;
+ else
+ usage();
+ break;
+ case 'c':
+ opt_centered = 1;
+ break;
+ case 'p':
+ opt_position = optarg;
+ break;
+ case 'f':
+ opt_offset = optarg;
+ break;
+ case 'r':
+ if (strcmp(optarg, "cw") && strcmp(optarg, "ccw") &&
+ strcmp(optarg, "ud") && strcmp(optarg, "none"))
+ usage();
+ opt_rotation = optarg;
+ break;
+ default:
+ usage();
+ }
+ }
+ if (optind != argc - 1)
+ usage();
+ filename = argv[optind];
+
+ /* "10,20" and "10 20" are both accepted for -p and -f */
+ for (p = opt_position; p && *p; p++)
+ if (*p == ',')
+ *p = ' ';
+ for (p = opt_offset; p && *p; p++)
+ if (*p == ',')
+ *p = ' ';
+
+ read_image();
+
+ if (outputname) {
+ out = fopen(outputname,
+ output_type == OUTPUT_BIN ? "wb" : "w");
+ if (!out)
+ die("Cannot create file %s: %s\n", outputname,
+ strerror(errno));
+ } else {
+ out = stdout;
+ }
+
+ switch (output_type) {
+ case OUTPUT_DTS:
+ write_dts();
+ break;
+ case OUTPUT_DTSI:
+ write_dtsi();
+ break;
+ case OUTPUT_BIN:
+ write_bin();
+ break;
+ }
+
+ if (outputname)
+ fclose(out);
+
+ fprintf(stderr, "%s: %ux%u pixels, %u colours\n", filename, logo_width,
+ logo_height, logo_clutsize);
+
+ return 0;
+}
--
2.39.5
^ permalink raw reply related [flat|nested] 18+ messages in thread* Re: [RFC PATCH 0/6] Boot logo supplied by the device tree
2026-07-31 21:50 [RFC PATCH 0/6] Boot logo supplied by the device tree Max Pedraza
` (5 preceding siblings ...)
2026-07-31 21:50 ` [RFC PATCH 6/6] video: logo: add ppmtodtlogo host tool Max Pedraza
@ 2026-08-01 8:08 ` Uwe Kleine-König
2026-08-01 20:44 ` Helge Deller
2026-08-03 12:39 ` Ulrich Ölmann
2026-08-04 13:58 ` Geert Uytterhoeven
7 siblings, 2 replies; 18+ messages in thread
From: Uwe Kleine-König @ 2026-08-01 8:08 UTC (permalink / raw)
To: Max Pedraza
Cc: Helge Deller, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Thomas Zimmermann, Maxime Ripard, linux-fbdev, dri-devel,
devicetree, linux-kernel, kernel
[-- Attachment #1: Type: text/plain, Size: 3170 bytes --]
Hello Max,
On Fri, Jul 31, 2026 at 11:50:37PM +0200, Max Pedraza wrote:
> Embedded products routinely need their own boot logo. Today the only way to
> get one is to replace one of the logo_*_clut224.ppm files in the kernel
> source tree, which bakes the image into the kernel image. Two products that
> share a board support package but differ in branding therefore need two
> kernel builds, and rebranding an existing product means rebuilding and
> requalifying a kernel for what is purely a cosmetic change.
>
> This series lets the logo be described by the device tree instead: a node
> compatible with "linux,boot-logo-clut224" supplies the image in the same
> paletted format the built-in CLUT224 logos already use, and the kernel
> prefers it over the built-in ones when it is present and enabled. If the
> node is absent or disabled, nothing changes.
>
> The image can come from the node itself (patches 1-2) or from a reserved
> memory region the bootloader filled in (patches 4-5), because the image and
> its placement are independent axes of variation. One board sold to several
> customers wants several device trees differing in the logo. One customer
> with several products built on that board, with different panels, wants the
> same logo placed differently on each: there the image belongs in a shared
> binary and only the placement belongs in the device tree. Patch 3 adds that
> placement.
>
> We have been carrying a cruder version of this downstream on an AM335x
> product since 2020, across a handful of board revisions, and it has removed
> a real maintenance burden for us. This is an attempt to find out whether
> something along these lines is wanted upstream, and if so in what shape --
> hence RFC.
>
> I am aware of the contentious part: a bitmap is not hardware, and the device
> tree is not an obvious place to put one. The argument for it is that the
> logo identifies the board in the same way the model property does, it is
> available before any filesystem is mounted, and it is per board rather than
> per kernel. The argument against is presumably that this is policy and
> belongs in userspace or in the bootloader. I would rather hear that
> explicitly than keep the patch downstream on a guess, and if the concept is
> rejected I would still like to know whether a smaller subset -- say the
> placement properties driven from the fbcon command line, without any image
> in the device tree -- would be worth submitting separately.
My 0.02€: Usually you want to use the display using drm and not fb once
the machine is fully booted. If you're using fb during boot to display a
logo, it's hardly possible to switch to drm later in the boot process
without flicker.
So my recommendation for your usecase is to not use the kernel boot logo
stuff, but something like https://github.com/pengutronix/platsch. Then
all the configuration is in userspace and modifyable using kernel
parameters. Or you create your own application using libplatsch that
selects the image based on the actual product derived from the dt
compatible or some EEPROM's content.
Best regards
Uwe
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]
^ permalink raw reply [flat|nested] 18+ messages in thread* Re: [RFC PATCH 0/6] Boot logo supplied by the device tree
2026-08-01 8:08 ` [RFC PATCH 0/6] Boot logo supplied by the device tree Uwe Kleine-König
@ 2026-08-01 20:44 ` Helge Deller
2026-08-01 22:01 ` Màxim Pedraza Padilla
2026-08-03 12:39 ` Ulrich Ölmann
1 sibling, 1 reply; 18+ messages in thread
From: Helge Deller @ 2026-08-01 20:44 UTC (permalink / raw)
To: Max Pedraza, Uwe Kleine-König, Max Pedraza
Cc: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Thomas Zimmermann,
Maxime Ripard, linux-fbdev, dri-devel, devicetree, linux-kernel,
kernel
Hello Max,
On 8/1/26 10:08, Uwe Kleine-König wrote:
> On Fri, Jul 31, 2026 at 11:50:37PM +0200, Max Pedraza wrote:
>> Embedded products routinely need their own boot logo. Today the only way to
>> get one is to replace one of the logo_*_clut224.ppm files in the kernel
>> source tree, which bakes the image into the kernel image. Two products that
>> share a board support package but differ in branding therefore need two
>> kernel builds, and rebranding an existing product means rebuilding and
>> requalifying a kernel for what is purely a cosmetic change.
>>
>> This series lets the logo be described by the device tree instead: a node
>> compatible with "linux,boot-logo-clut224" supplies the image in the same
>> paletted format the built-in CLUT224 logos already use, and the kernel
>> prefers it over the built-in ones when it is present and enabled. If the
>> node is absent or disabled, nothing changes.
>>
>> The image can come from the node itself (patches 1-2) or from a reserved
>> memory region the bootloader filled in (patches 4-5), because the image and
>> its placement are independent axes of variation. One board sold to several
>> customers wants several device trees differing in the logo. One customer
>> with several products built on that board, with different panels, wants the
>> same logo placed differently on each: there the image belongs in a shared
>> binary and only the placement belongs in the device tree. Patch 3 adds that
>> placement.
>>
>> We have been carrying a cruder version of this downstream on an AM335x
>> product since 2020, across a handful of board revisions, and it has removed
>> a real maintenance burden for us. This is an attempt to find out whether
>> something along these lines is wanted upstream, and if so in what shape --
>> hence RFC.
>>
>> I am aware of the contentious part: a bitmap is not hardware, and the device
>> tree is not an obvious place to put one. The argument for it is that the
>> logo identifies the board in the same way the model property does, it is
>> available before any filesystem is mounted, and it is per board rather than
>> per kernel. The argument against is presumably that this is policy and
>> belongs in userspace or in the bootloader. I would rather hear that
>> explicitly than keep the patch downstream on a guess, and if the concept is
>> rejected I would still like to know whether a smaller subset -- say the
>> placement properties driven from the fbcon command line, without any image
>> in the device tree -- would be worth submitting separately.
>
> My 0.02€: Usually you want to use the display using drm and not fb once
> the machine is fully booted. If you're using fb during boot to display a
> logo, it's hardly possible to switch to drm later in the boot process
> without flicker.
>
> So my recommendation for your usecase is to not use the kernel boot logo
> stuff, but something like https://github.com/pengutronix/platsch. Then
> all the configuration is in userspace and modifyable using kernel
> parameters. Or you create your own application using libplatsch that
> selects the image based on the actual product derived from the dt
> compatible or some EEPROM's content.
Max, is this a viable option for your usecase?
Helge
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [RFC PATCH 0/6] Boot logo supplied by the device tree
2026-08-01 20:44 ` Helge Deller
@ 2026-08-01 22:01 ` Màxim Pedraza Padilla
2026-08-02 13:35 ` Uwe Kleine-König
0 siblings, 1 reply; 18+ messages in thread
From: Màxim Pedraza Padilla @ 2026-08-01 22:01 UTC (permalink / raw)
To: Helge Deller
Cc: Uwe Kleine-König, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Thomas Zimmermann, Maxime Ripard, linux-fbdev,
dri-devel, devicetree, linux-kernel, kernel
Uwe Kleine-König wrote:
> My 0.02€: Usually you want to use the display using drm and not fb once
> the machine is fully booted. If you're using fb during boot to display a
> logo, it's hardly possible to switch to drm later in the boot process
> without flicker.
>
> So my recommendation for your usecase is to not use the kernel boot logo
> stuff, but something like https://github.com/pengutronix/platsch.
Thanks for the pointer, I did not know platsch and it looks like a good
fit for the problem it solves. It does not solve mine, though, and I
think the reason is worth spelling out, because it is not about how the
image gets drawn but about when.
These are industrial units, and the requirement is time to first pixel
after power is applied. If the panel stays dark for more than a moment
the unit reads as dead, and that is a support call. Anything running in
userspace is by construction later than the kernel: it needs the kernel
booted, the rootfs mounted and init far enough along to exec it. I can
measure the exact difference on our hardware if that is useful for the
discussion.
We do already paint a BMP from U-Boot, which is as early as we can
possibly be. The problem is the gap that follows: once the display
driver probes, the panel is cleared, and nothing puts anything back
until userspace is running. Moving the logo further out into userspace
widens that gap rather than closing it. The kernel boot logo is what
fills it, and that is the whole reason this series exists.
For completeness, since it is the usual answer to the U-Boot handover
problem: a simple-framebuffer node plus simpledrm does keep the
bootloader image on screen. It moves the gap rather than removing it,
though, because the real driver still has to take over at some point,
and it makes the logo a property of the bootloader instead of the board
description. The two are complementary rather than alternatives:
simpledrm covers up to the driver handover, the boot logo covers from
there.
> If you're using fb during boot to display a logo, it's hardly possible
> to switch to drm later in the boot process without flicker.
You are right in the general case, but I should be precise about what
happens here, because there is no fbdev to DRM switch on this hardware.
The display driver is tilcdc, which is a DRM driver; the logo ends up in
the fbdev emulation that drm_fb_helper provides, so DRM is scanning out
from the first pixel. Userspace then takes DRM over directly. The
transition that remains is the same one any solution has when the
application starts.
> Max, is this a viable option for your usecase?
Not for the reason above, no. Let me also be explicit about something
the cover letter only mentions in passing, because it is directly
relevant to Uwe's point and I would rather raise it myself.
This series does not draw anything anywhere new. It only teaches the
existing fbdev logo code where the image may come from: a device tree
node instead of a built-in PPM. With CONFIG_FRAMEBUFFER_CONSOLE the
drawing is still done by fbcon, exactly as it is today.
The piece that matters for a product with no text console is a separate
two patch series I have deliberately not posted yet. It exports a
fb_draw_logo() helper from fbdev and calls it from drm_fb_helper when
fbcon is not built in. I am aware that is pushing against the direction
fbdev dependencies are being removed from DRM, which is precisely why I
kept it out of this series: I did not want that discussion to decide the
fate of the binding.
So the honest summary of where I stand: if the device tree part is
acceptable I will post the drawing part separately to dri-devel and let
it be judged on its own merits. If the conclusion there is that DRM
should grow its own way to put an image on screen before userspace
exists, rather than reaching into fbdev, I would rather help build that
than carry a hook downstream forever. What I cannot do is wait for
userspace.
Thanks both for looking at this,
Max
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [RFC PATCH 0/6] Boot logo supplied by the device tree
2026-08-01 22:01 ` Màxim Pedraza Padilla
@ 2026-08-02 13:35 ` Uwe Kleine-König
2026-08-02 22:56 ` Màxim Pedraza Padilla
0 siblings, 1 reply; 18+ messages in thread
From: Uwe Kleine-König @ 2026-08-02 13:35 UTC (permalink / raw)
To: Màxim Pedraza Padilla
Cc: Helge Deller, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Thomas Zimmermann, Maxime Ripard, linux-fbdev, dri-devel,
devicetree, linux-kernel, kernel
[-- Attachment #1: Type: text/plain, Size: 1924 bytes --]
Hello Màxim,
On Sun, Aug 02, 2026 at 12:01:58AM +0200, Màxim Pedraza Padilla wrote:
> Uwe Kleine-König wrote:
> > My 0.02€: Usually you want to use the display using drm and not fb once
> > the machine is fully booted. If you're using fb during boot to display a
> > logo, it's hardly possible to switch to drm later in the boot process
> > without flicker.
> >
> > So my recommendation for your usecase is to not use the kernel boot logo
> > stuff, but something like https://github.com/pengutronix/platsch.
>
> Thanks for the pointer, I did not know platsch and it looks like a good
> fit for the problem it solves. It does not solve mine, though, and I
> think the reason is worth spelling out, because it is not about how the
> image gets drawn but about when.
>
> These are industrial units, and the requirement is time to first pixel
> after power is applied. If the panel stays dark for more than a moment
> the unit reads as dead, and that is a support call. Anything running in
> userspace is by construction later than the kernel: it needs the kernel
> booted, the rootfs mounted and init far enough along to exec it. I can
> measure the exact difference on our hardware if that is useful for the
> discussion.
No need to wait for init, the idea is to use init=/usr/sbin/platsch so
it starts before init (and once the display is setup execve()s
/sbin/init). Also you can put it in an initramfs which gets rid of the
dependency on "rootfs mounted". And if your kernel is modular apart from
what is needed for the display the time difference between kernel boot
image and platsch might be negligible compared to the simplification of
the software architecture.
Having said that, I'm against putting boot splash info in the device
tree as the pointed out alternative is IMHO good enough. But my opinion
probably isn't the one that eventually counts.
Best regards
Uwe
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [RFC PATCH 0/6] Boot logo supplied by the device tree
2026-08-02 13:35 ` Uwe Kleine-König
@ 2026-08-02 22:56 ` Màxim Pedraza Padilla
0 siblings, 0 replies; 18+ messages in thread
From: Màxim Pedraza Padilla @ 2026-08-02 22:56 UTC (permalink / raw)
To: Uwe Kleine-König
Cc: Helge Deller, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Thomas Zimmermann, Maxime Ripard, linux-fbdev, dri-devel,
devicetree, linux-kernel, kernel
Hi Uwe,
El dom, 2 ago 2026 a las 15:35, Uwe Kleine-König
(<u.kleine-koenig@baylibre.com>) escribió:
> No need to wait for init, the idea is to use init=/usr/sbin/platsch so
> it starts before init (and once the display is setup execve()s
> /sbin/init).
I think I caused a misunderstanding here: when I wrote "init" I meant
PID 1 itself, not the init system getting far enough to start a service.
Running platsch as PID 1 does not change the part that hurts, because
PID 1 is exactly what I am waiting for.
Numbers from a shipping board, our 4.19 product kernel on an AM335x:
[ 1.065931] tilcdc 4830e000.lcdc: fb0: DRM emulated frame buffer device
[ 3.522118] Run /sbin/init as init process
The display is up and can be drawn on at 1.07 s. PID 1 does not exist
until 3.52 s. Whatever runs as PID 1, platsch included, is roughly 2.4 s
late on this hardware. That gap is the entire problem: the panel is
alive and black while the customer is looking at it.
> Also you can put it in an initramfs which gets rid of the dependency on
> "rootfs mounted".
Agreed, and that would remove part of those 2.4 s. But not the shape of
it: PID 1 runs after the built-in initcalls have finished, while the
logo is drawn as soon as the display driver's own probe is done. Any
userspace solution is structurally behind that point, and an initramfs
moves it closer without crossing it.
> And if your kernel is modular apart from what is needed for the display
> the time difference between kernel boot image and platsch might be
> negligible compared to the simplification of the software architecture.
That is worth evaluating, and it may well be the right choice for a new
design. It does not change the ordering, though: the display driver has
to stay built in either way, so its probe finishes before PID 1 exists.
Making the rest modular moves PID 1 closer to that moment without ever
reaching it. The kernel logo draws at the earliest point where there is
something to draw on, and nothing in userspace can be earlier than that.
To be clear about what I am not claiming: platsch is the better answer
for anything that can tolerate the delay, it is more flexible, and I
will very likely use it for the parts of our UI that come after the
splash. The kernel logo is not competing with it, it covers the window
platsch cannot reach.
> Having said that, I'm against putting boot splash info in the device
> tree as the pointed out alternative is IMHO good enough. But my opinion
> probably isn't the one that eventually counts.
Understood, and thanks for saying it plainly, it is useful to know where
you stand. For what it is worth, the objection I expected was exactly
that one and I would rather have it on the record than guess at it. If
the conclusion is that a bitmap does not belong in the device tree, the
fallback I would still like to explore is keeping the placement
properties and the reserved memory path while dropping the in-tree
image, since that removes the "bitmap in DT" part while keeping the
early drawing. But that is for Helge and the DT maintainers to weigh.
Thanks for taking the time,
Max
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [RFC PATCH 0/6] Boot logo supplied by the device tree
2026-08-01 8:08 ` [RFC PATCH 0/6] Boot logo supplied by the device tree Uwe Kleine-König
2026-08-01 20:44 ` Helge Deller
@ 2026-08-03 12:39 ` Ulrich Ölmann
2026-08-03 22:04 ` Màxim Pedraza Padilla
1 sibling, 1 reply; 18+ messages in thread
From: Ulrich Ölmann @ 2026-08-03 12:39 UTC (permalink / raw)
To: Max Pedraza
Cc: Uwe Kleine-König, Rob Herring, Conor Dooley, kernel,
devicetree, Helge Deller, linux-fbdev, Maxime Ripard,
linux-kernel, dri-devel, Thomas Zimmermann, Krzysztof Kozlowski
Hi Màxim,
On Sat, Aug 01 2026 at 10:08 +0200, Uwe Kleine-König <u.kleine-koenig@baylibre.com> wrote:
> Hello Max,
>
> On Fri, Jul 31, 2026 at 11:50:37PM +0200, Max Pedraza wrote:
>> Embedded products routinely need their own boot logo. Today the only way to
>> get one is to replace one of the logo_*_clut224.ppm files in the kernel
>> source tree, which bakes the image into the kernel image. Two products that
>> share a board support package but differ in branding therefore need two
>> kernel builds, and rebranding an existing product means rebuilding and
>> requalifying a kernel for what is purely a cosmetic change.
>>
>> This series lets the logo be described by the device tree instead: a node
>> compatible with "linux,boot-logo-clut224" supplies the image in the same
>> paletted format the built-in CLUT224 logos already use, and the kernel
>> prefers it over the built-in ones when it is present and enabled. If the
>> node is absent or disabled, nothing changes.
>>
>> The image can come from the node itself (patches 1-2) [...]
independently of the specific implementation, please keep in mind that
the kernel is distributed under the GPLv2, which may have implications
for a proprietary image embedded in the device tree. That doesn't
necessarily have to be a deal-breaker, but it's probably something that
should be considered carefully.
Best regards,
Ulrich
>> [...] or from a reserved
>> memory region the bootloader filled in (patches 4-5), because the image and
>> its placement are independent axes of variation. One board sold to several
>> customers wants several device trees differing in the logo. One customer
>> with several products built on that board, with different panels, wants the
>> same logo placed differently on each: there the image belongs in a shared
>> binary and only the placement belongs in the device tree. Patch 3 adds that
>> placement.
>>
>> We have been carrying a cruder version of this downstream on an AM335x
>> product since 2020, across a handful of board revisions, and it has removed
>> a real maintenance burden for us. This is an attempt to find out whether
>> something along these lines is wanted upstream, and if so in what shape --
>> hence RFC.
>>
>> I am aware of the contentious part: a bitmap is not hardware, and the device
>> tree is not an obvious place to put one. The argument for it is that the
>> logo identifies the board in the same way the model property does, it is
>> available before any filesystem is mounted, and it is per board rather than
>> per kernel. The argument against is presumably that this is policy and
>> belongs in userspace or in the bootloader. I would rather hear that
>> explicitly than keep the patch downstream on a guess, and if the concept is
>> rejected I would still like to know whether a smaller subset -- say the
>> placement properties driven from the fbcon command line, without any image
>> in the device tree -- would be worth submitting separately.
>
> My 0.02€: Usually you want to use the display using drm and not fb once
> the machine is fully booted. If you're using fb during boot to display a
> logo, it's hardly possible to switch to drm later in the boot process
> without flicker.
>
> So my recommendation for your usecase is to not use the kernel boot logo
> stuff, but something like https://github.com/pengutronix/platsch. Then
> all the configuration is in userspace and modifyable using kernel
> parameters. Or you create your own application using libplatsch that
> selects the image based on the actual product derived from the dt
> compatible or some EEPROM's content.
>
> Best regards
> Uwe
--
Pengutronix e.K. | Ulrich Ölmann |
Industrial Linux Solutions | http://www.pengutronix.de/ |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0 |
Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 |
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [RFC PATCH 0/6] Boot logo supplied by the device tree
2026-08-03 12:39 ` Ulrich Ölmann
@ 2026-08-03 22:04 ` Màxim Pedraza Padilla
2026-08-04 5:25 ` Ulrich Ölmann
0 siblings, 1 reply; 18+ messages in thread
From: Màxim Pedraza Padilla @ 2026-08-03 22:04 UTC (permalink / raw)
To: Ulrich Ölmann
Cc: Uwe Kleine-König, Rob Herring, Conor Dooley, kernel,
devicetree, Helge Deller, linux-fbdev, Maxime Ripard,
linux-kernel, dri-devel, Thomas Zimmermann, Krzysztof Kozlowski
El lun, 3 ago 2026 a las 14:39, Ulrich Ölmann
(<u.oelmann@pengutronix.de>) escribió:
> independently of the specific implementation, please keep in mind that
> the kernel is distributed under the GPLv2, which may have implications
> for a proprietary image embedded in the device tree. That doesn't
> necessarily have to be a deal-breaker, but it's probably something that
> should be considered carefully.
Good point, I had not considered it.
A warning could be added to the binding documentation about the licensing
implications of a proprietary logo, aimed at anyone thinking of
submitting a device tree carrying one to the kernel tree. I am happy to
add that in v2 if it is considered useful.
Patches 4 and 5 also avoid the question by construction: there the image
is a separate binary the bootloader loads, and the device tree carries
only a phandle to the reserved region.
In any case, whether such device trees are accepted is ultimately for the
device tree maintainers to decide.
Best regards,
Max
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [RFC PATCH 0/6] Boot logo supplied by the device tree
2026-08-03 22:04 ` Màxim Pedraza Padilla
@ 2026-08-04 5:25 ` Ulrich Ölmann
2026-08-04 15:59 ` Màxim Pedraza Padilla
0 siblings, 1 reply; 18+ messages in thread
From: Ulrich Ölmann @ 2026-08-04 5:25 UTC (permalink / raw)
To: Màxim Pedraza Padilla
Cc: Rob Herring, Conor Dooley, Thomas Zimmermann, devicetree,
Helge Deller, linux-fbdev, Maxime Ripard, linux-kernel,
Uwe Kleine-König, dri-devel, kernel, Krzysztof Kozlowski
Hi Max,
On Tue, Aug 04 2026 at 00:04 +0200, Màxim Pedraza Padilla <maximpedraza@gmail.com> wrote:
> El lun, 3 ago 2026 a las 14:39, Ulrich Ölmann
> (<u.oelmann@pengutronix.de>) escribió:
>> independently of the specific implementation, please keep in mind that
>> the kernel is distributed under the GPLv2, which may have implications
>> for a proprietary image embedded in the device tree. That doesn't
>> necessarily have to be a deal-breaker, but it's probably something that
>> should be considered carefully.
>
> Good point, I had not considered it.
>
> A warning could be added to the binding documentation about the licensing
> implications of a proprietary logo, aimed at anyone thinking of
> submitting a device tree carrying one to the kernel tree. I am happy to
> add that in v2 if it is considered useful.
I think the issue is broader than upstream submissions. Once such a
device tree is shipped as part of a GPL kernel in a product, the GPL
obligations already apply to that distribution. Therefore, the licensing
implications of embedding a proprietary logo are not limited to upstream
acceptance, they also affect downstream product distributions.
> Patches 4 and 5 also avoid the question by construction: there the image
> is a separate binary the bootloader loads, and the device tree carries
> only a phandle to the reserved region.
Right, here everything is clearly uncoupled.
> In any case, whether such device trees are accepted is ultimately for the
> device tree maintainers to decide.
As mentioned above, the issue also extends to deployed products.
Those were just my thoughts on the licensing aspect.
Best regards,
Ulrich
> Best regards,
> Max
--
Pengutronix e.K. | Ulrich Ölmann |
Industrial Linux Solutions | http://www.pengutronix.de/ |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0 |
Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 |
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [RFC PATCH 0/6] Boot logo supplied by the device tree
2026-08-04 5:25 ` Ulrich Ölmann
@ 2026-08-04 15:59 ` Màxim Pedraza Padilla
0 siblings, 0 replies; 18+ messages in thread
From: Màxim Pedraza Padilla @ 2026-08-04 15:59 UTC (permalink / raw)
To: Ulrich Ölmann
Cc: Rob Herring, Conor Dooley, Thomas Zimmermann, devicetree,
Helge Deller, linux-fbdev, Maxime Ripard, linux-kernel,
Uwe Kleine-König, dri-devel, kernel, Krzysztof Kozlowski
El mar, 4 ago 2026 a las 7:25, Ulrich Ölmann
(<u.oelmann@pengutronix.de>) escribió:
> I think the issue is broader than upstream submissions. Once such a
> device tree is shipped as part of a GPL kernel in a product, the GPL
> obligations already apply to that distribution. Therefore, the licensing
> implications of embedding a proprietary logo are not limited to upstream
> acceptance, they also affect downstream product distributions.
Point taken, thanks for spelling it out. I am not qualified to argue the
legal side and will not try to, but I follow the reasoning.
In practice it reinforces the reserved memory path, which is the one we
ship: there the device tree carries only a phandle and the placement,
and the image stays a separate file with its own licensing, handled like
any other asset in the product.
Max
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [RFC PATCH 0/6] Boot logo supplied by the device tree
2026-07-31 21:50 [RFC PATCH 0/6] Boot logo supplied by the device tree Max Pedraza
` (6 preceding siblings ...)
2026-08-01 8:08 ` [RFC PATCH 0/6] Boot logo supplied by the device tree Uwe Kleine-König
@ 2026-08-04 13:58 ` Geert Uytterhoeven
2026-08-04 22:37 ` Màxim Pedraza Padilla
7 siblings, 1 reply; 18+ messages in thread
From: Geert Uytterhoeven @ 2026-08-04 13:58 UTC (permalink / raw)
To: Max Pedraza
Cc: Helge Deller, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Thomas Zimmermann, Maxime Ripard, linux-fbdev, dri-devel,
devicetree, linux-kernel
Hi Max,
On Fri, 31 Jul 2026 at 23:56, Max Pedraza <maximpedraza@gmail.com> wrote:
> Embedded products routinely need their own boot logo. Today the only way to
> get one is to replace one of the logo_*_clut224.ppm files in the kernel
> source tree, which bakes the image into the kernel image. Two products that
> share a board support package but differ in branding therefore need two
> kernel builds, and rebranding an existing product means rebuilding and
> requalifying a kernel for what is purely a cosmetic change.
>
> This series lets the logo be described by the device tree instead: a node
> compatible with "linux,boot-logo-clut224" supplies the image in the same
> paletted format the built-in CLUT224 logos already use, and the kernel
> prefers it over the built-in ones when it is present and enabled. If the
> node is absent or disabled, nothing changes.
>
> The image can come from the node itself (patches 1-2) or from a reserved
> memory region the bootloader filled in (patches 4-5), because the image and
> its placement are independent axes of variation. One board sold to several
> customers wants several device trees differing in the logo. One customer
> with several products built on that board, with different panels, wants the
> same logo placed differently on each: there the image belongs in a shared
> binary and only the placement belongs in the device tree. Patch 3 adds that
> placement.
>
> We have been carrying a cruder version of this downstream on an AM335x
> product since 2020, across a handful of board revisions, and it has removed
> a real maintenance burden for us. This is an attempt to find out whether
> something along these lines is wanted upstream, and if so in what shape --
> hence RFC.
Thanks for your series!
> I am aware of the contentious part: a bitmap is not hardware, and the device
> tree is not an obvious place to put one. The argument for it is that the
> logo identifies the board in the same way the model property does, it is
> available before any filesystem is mounted, and it is per board rather than
> per kernel. The argument against is presumably that this is policy and
> belongs in userspace or in the bootloader. I would rather hear that
> explicitly than keep the patch downstream on a guess, and if the concept is
> rejected I would still like to know whether a smaller subset -- say the
> placement properties driven from the fbcon command line, without any image
> in the device tree -- would be worth submitting separately.
The standard location for configuration that is not hardware
description is under /chosen...
IIRC, real Open Firmware used to have some logo configuration, too...
Yep, /options/oem-logo on CHRP LongTrail[1].
And it's even documented[2], but fixed to 64x64 monochrome.
[1] http://g33rt.be/migrated/Linux/PPC/DeviceTree.html
[2] https://www.djc.id.au/2008/IEEE1275-1994.pdf
Gr{oetje,eeting}s,
Geert
--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org
In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
-- Linus Torvalds
^ permalink raw reply [flat|nested] 18+ messages in thread* Re: [RFC PATCH 0/6] Boot logo supplied by the device tree
2026-08-04 13:58 ` Geert Uytterhoeven
@ 2026-08-04 22:37 ` Màxim Pedraza Padilla
0 siblings, 0 replies; 18+ messages in thread
From: Màxim Pedraza Padilla @ 2026-08-04 22:37 UTC (permalink / raw)
To: Geert Uytterhoeven
Cc: Helge Deller, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Thomas Zimmermann, Maxime Ripard, linux-fbdev, dri-devel,
devicetree, linux-kernel
El mar, 4 ago 2026 a las 15:59, Geert Uytterhoeven
(<geert@linux-m68k.org>) escribió:
> The standard location for configuration that is not hardware
> description is under /chosen...
>
> IIRC, real Open Firmware used to have some logo configuration, too...
> Yep, /options/oem-logo on CHRP LongTrail[1].
> And it's even documented[2], but fixed to 64x64 monochrome.
Thank you, that is the answer I was missing. I had written the "a bitmap
is not hardware" objection into the cover letter as something to defend
against, and /chosen turns it into a matter of putting the node in the
right place instead.
v2 moves it there, and I will post it shortly: the node is a child of
/chosen and the kernel looks it up with of_get_compatible_child(of_chosen,
...). The binding now says why, and points at the oem-logo precedent. It
also puts the node in the same company as simple-framebuffer, which lives
under /chosen for the same reason.
Thanks as well for the references, the CHRP one was new to me.
Max
^ permalink raw reply [flat|nested] 18+ messages in thread