mail archive of the barebox mailing list
 help / color / mirror / Atom feed
From: Ahmad Fatoum <a.fatoum@pengutronix.de>
To: barebox@lists.infradead.org
Cc: Ahmad Fatoum <a.fatoum@pengutronix.de>
Subject: [PATCH 06/10] scripts: add bareboxtlv host/target tool
Date: Fri, 11 Apr 2025 09:40:41 +0200	[thread overview]
Message-ID: <20250411074045.2019372-7-a.fatoum@pengutronix.de> (raw)
In-Reply-To: <20250411074045.2019372-1-a.fatoum@pengutronix.de>

In its simplest form, a barebox TLV has a 12-byte header, a sequence of
TLV entries, where each of tags and length are 2 bytes each (in big
endian), followed by a CRC.

The TLVs are easily generated. Add a tool to allow adding, removing and
verifying the header. A full fledged python-based tool is added in the
follow up commit.

Example uses:

  hex2bin tlvs | ./scripts/bareboxtlv -m 0xcfe01001 >tlv.blob
  ./scripts/bareboxtlv -m 0xcfe01001 -v tlv.blob && echo CRC correct

Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
---
 scripts/.gitignore                |   2 +
 scripts/Makefile                  |   2 +
 scripts/bareboxtlv-target.c       |   1 +
 scripts/bareboxtlv.c              | 183 ++++++++++++++++++++++++++++++
 scripts/include/asm/unaligned.h   |  21 ++++
 scripts/include/linux/build_bug.h |   8 ++
 scripts/include/linux/stringify.h |  14 +++
 7 files changed, 231 insertions(+)
 create mode 100644 scripts/bareboxtlv-target.c
 create mode 100644 scripts/bareboxtlv.c
 create mode 100644 scripts/include/asm/unaligned.h
 create mode 100644 scripts/include/linux/build_bug.h
 create mode 100644 scripts/include/linux/stringify.h

diff --git a/scripts/.gitignore b/scripts/.gitignore
index 1b760309583b..8c74d7c9f001 100644
--- a/scripts/.gitignore
+++ b/scripts/.gitignore
@@ -20,6 +20,8 @@ bareboxenv-target
 kernel-install-target
 bareboxcrc32-target
 bareboximd-target
+bareboxtlv
+bareboxtlv-target
 mk-am35xx-spi-image
 mkimage
 mxsimage
diff --git a/scripts/Makefile b/scripts/Makefile
index eb3884471bc9..85e081544553 100644
--- a/scripts/Makefile
+++ b/scripts/Makefile
@@ -10,6 +10,7 @@ hostprogs-always-y					+= bareboxenv
 hostprogs-always-y					+= bareboxcrc32
 hostprogs-always-y					+= kernel-install
 hostprogs-always-$(CONFIG_QOICONV)			+= qoiconv
+hostprogs-always-$(CONFIG_TLV)				+= bareboxtlv
 hostprogs-always-$(CONFIG_KEYTOC)			+= keytoc
 HOSTCFLAGS_keytoc.o = `$(PKG_CONFIG) --cflags openssl`
 HOSTLDLIBS_keytoc = `$(PKG_CONFIG) --libs openssl`
@@ -42,6 +43,7 @@ HOSTLDLIBS_rk-usb-loader  = `$(PKG_CONFIG) --libs libusb-1.0`
 hostprogs-always-$(CONFIG_RK_USB_LOADER)		+= rk-usb-loader
 
 userprogs-always-$(CONFIG_BAREBOXENV_TARGET)		+= bareboxenv-target
+userprogs-always-$(CONFIG_BAREBOXTLV_TARGET)		+= bareboxtlv-target
 userprogs-always-$(CONFIG_KERNEL_INSTALL_TARGET)	+= kernel-install-target
 userprogs-always-$(CONFIG_BAREBOXCRC32_TARGET)		+= bareboxcrc32-target
 userprogs-always-$(CONFIG_IMD_TARGET)			+= bareboximd-target
diff --git a/scripts/bareboxtlv-target.c b/scripts/bareboxtlv-target.c
new file mode 100644
index 000000000000..52437edef634
--- /dev/null
+++ b/scripts/bareboxtlv-target.c
@@ -0,0 +1 @@
+#include "bareboxtlv.c"
diff --git a/scripts/bareboxtlv.c b/scripts/bareboxtlv.c
new file mode 100644
index 000000000000..7b8dbfc1e845
--- /dev/null
+++ b/scripts/bareboxtlv.c
@@ -0,0 +1,183 @@
+// SPDX-License-Identifier: GPL-2.0-only
+// SPDX-FileCopyrightText: 2021 Ahmad Fatoum, Pengutronix
+
+/* bareboxtlv.c - generate a barebox TLV header */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <getopt.h>
+#include <unistd.h>
+
+#include "compiler.h"
+#include <linux/stringify.h>
+
+#define debug(...)
+#define printk_once(...)
+
+#include "../include/tlv/format.h"
+#include "../crypto/crc32.c"
+
+#include "common.h"
+#include "common.c"
+
+static void usage(char *prgname)
+{
+	fprintf(stderr,
+		"USAGE: %s [FILE]\n"
+		"Manipulate barebox TLV blobs\n"
+		"\n"
+		"options:\n"
+		"  -m        TLV magic to use (default: " __stringify(TLV_MAGIC_BAREBOX_V1) " or input magic for -s)\n"
+		"  -s        strip input TLV header from output\n"
+		"            (default is adding header to headerless input)\n"
+		"  -@        offset to start reading at\n"
+		"  -v        verify CRC\n",
+		prgname);
+}
+
+static inline ssize_t write_full_verbose(int fd, const void *buf, size_t len)
+{
+	ssize_t ret;
+
+	ret = write_full(fd, buf, len);
+	if (ret < 0)
+		perror("write");
+	return ret;
+}
+
+int main(int argc, char *argv[])
+{
+	u32 magic = 0;
+	struct tlv_header *inhdr = NULL;
+	struct tlv_header hdr;
+	size_t offset = 0, size = 0;
+	ssize_t ret;
+	bool strip_header = false, verify = false;
+	int opt, ecode = EXIT_FAILURE;
+	int infd = STDIN_FILENO;
+	const u8 *p;
+	char *endptr;
+	void *buf;
+	u32 crc = ~0;
+
+	while((opt = getopt(argc, argv, "svm:@:h")) != -1) {
+		switch (opt) {
+		case 'v':
+			verify = true;
+			/* fallthrough; */
+		case 's':
+			strip_header = true;
+			break;
+		case 'm':
+			magic = strtoul(optarg, NULL, 16);
+			if (!magic) {
+				fprintf(stderr, "invalid magic: %s\n", optarg);
+				return EXIT_FAILURE;
+			}
+			break;
+		case '@':
+			offset = strtoul(optarg, &endptr, 0);
+			if (endptr == optarg) {
+				fprintf(stderr, "invalid offset: %s\n", optarg);
+				return EXIT_FAILURE;
+			}
+			break;
+		case 'h':
+			usage(argv[0]);
+			return 0;
+		}
+	}
+
+	if (argc - optind > 1) {
+		usage(argv[0]);
+		return EXIT_FAILURE;
+	}
+
+	if (argv[optind]) {
+		infd = open(argv[optind], O_RDONLY);
+		if (infd < 0) {
+			perror("open");
+			return EXIT_FAILURE;
+		}
+		lseek(infd, offset, SEEK_SET);
+	} else if (offset) {
+		fprintf(stderr, "can't combine -@ with stdin\n");
+		return EXIT_FAILURE;
+	}
+
+	p = buf = read_fd(infd, &size);
+	if (!buf) {
+		perror("read_fd");
+		goto out;
+	}
+
+	/* validate, but skip, if header given */
+	if (strip_header) {
+		inhdr = buf;
+
+		if (size < tlv_total_len(inhdr)) {
+			fprintf(stderr, "short input: got %zu bytes, but header claims %zu\n",
+			       size, tlv_total_len(inhdr));
+			goto out;
+		}
+
+		if (!magic)
+			magic = get_unaligned_be32(p);
+
+		p += sizeof(struct tlv_header);
+		size = cpu_to_be32(inhdr->length_tlv);
+
+		if (cpu_to_be32(inhdr->length_sig) != 0) {
+			fprintf(stderr, "Signatures not yet supported\n");
+			goto out;
+		}
+
+	}
+
+	if (!magic)
+		magic = TLV_MAGIC_BAREBOX_V1;
+
+	hdr.magic = cpu_to_be32(magic);
+	hdr.length_tlv = cpu_to_be32(size);
+	hdr.length_sig = cpu_to_be32(0);
+
+	if (!verify) {
+		if (!strip_header) {
+			ret = write_full_verbose(1, &hdr, sizeof(hdr));
+			if (ret < 0)
+				goto out;
+		}
+		ret = write_full_verbose(1, p, size);
+		if (ret < 0)
+			goto out;
+	}
+
+	crc = crc32_be(crc, &hdr, sizeof(hdr));
+	crc = crc32_be(crc, p, size);
+
+	if (verify) {
+		u32 oldcrc;
+
+		oldcrc = get_unaligned_be32(p + size);
+		if (oldcrc != crc) {
+			fprintf(stderr, "CRC mismatch: expected %08x, but calculated %08x\n",
+			       oldcrc, crc);
+			goto out;
+		}
+	}
+
+	if (!strip_header) {
+		crc = cpu_to_be32(crc);
+
+		ret = write_full_verbose(1, &crc, sizeof(crc));
+		if (ret < 0)
+			goto out;
+	}
+
+	ecode = 0;
+out:
+	free(buf);
+	if (argv[optind])
+		close(infd);
+	return ecode;
+}
diff --git a/scripts/include/asm/unaligned.h b/scripts/include/asm/unaligned.h
new file mode 100644
index 000000000000..af6ccbc1bcf5
--- /dev/null
+++ b/scripts/include/asm/unaligned.h
@@ -0,0 +1,21 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#ifndef _ASM_ARM_UNALIGNED_H
+#define _ASM_ARM_UNALIGNED_H
+
+#include "../../../include/linux/unaligned/le_byteshift.h"
+#include "../../../include/linux/unaligned/be_byteshift.h"
+#include "../../../include/linux/unaligned/generic.h"
+
+/*
+ * Select endianness
+ */
+#ifdef CONFIG_CPU_BIG_ENDIAN
+#define get_unaligned	__get_unaligned_be
+#define put_unaligned	__put_unaligned_be
+#else
+#define get_unaligned	__get_unaligned_le
+#define put_unaligned	__put_unaligned_le
+#endif
+
+#endif /* _ASM_ARM_UNALIGNED_H */
diff --git a/scripts/include/linux/build_bug.h b/scripts/include/linux/build_bug.h
new file mode 100644
index 000000000000..e9bc857b15e8
--- /dev/null
+++ b/scripts/include/linux/build_bug.h
@@ -0,0 +1,8 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _LINUX_BUILD_BUG_H
+#define _LINUX_BUILD_BUG_H
+
+#define static_assert(expr, ...) __static_assert(expr, ##__VA_ARGS__, #expr)
+#define __static_assert(expr, msg, ...) _Static_assert(expr, msg)
+
+#endif	/* _LINUX_BUILD_BUG_H */
diff --git a/scripts/include/linux/stringify.h b/scripts/include/linux/stringify.h
new file mode 100644
index 000000000000..55f6d04d48b1
--- /dev/null
+++ b/scripts/include/linux/stringify.h
@@ -0,0 +1,14 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#ifndef __LINUX_STRINGIFY_H
+#define __LINUX_STRINGIFY_H
+
+/* Indirect stringification.  Doing two levels allows the parameter to be a
+ * macro itself.  For example, compile with -DFOO=bar, __stringify(FOO)
+ * converts to "bar".
+ */
+
+#define __stringify_1(x...)	#x
+#define __stringify(x...)	__stringify_1(x)
+
+#endif	/* !__LINUX_STRINGIFY_H */
-- 
2.39.5




  parent reply	other threads:[~2025-04-11  7:44 UTC|newest]

Thread overview: 15+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-04-11  7:40 [PATCH 00/10] Add barebox TLV infrastructure Ahmad Fatoum
2025-04-11  7:40 ` [PATCH 01/10] net: factor out eth_of_get_fixup_node Ahmad Fatoum
2025-04-11  7:40 ` [PATCH 02/10] net: export list of registered ethernet addresses Ahmad Fatoum
2025-04-11  7:40 ` [PATCH 03/10] common: add optional systemd.hostname generation Ahmad Fatoum
2025-04-11  7:40 ` [PATCH 04/10] common: add barebox TLV support Ahmad Fatoum
2025-04-14 14:49   ` Sascha Hauer
2025-04-14 14:57     ` Ahmad Fatoum
2025-04-14 15:06       ` Sascha Hauer
2025-04-11  7:40 ` [PATCH 05/10] commands: add TLV debugging command Ahmad Fatoum
2025-04-11  7:40 ` Ahmad Fatoum [this message]
2025-04-11  7:40 ` [PATCH 07/10] boards: add decoder for LXA TLV v1 format Ahmad Fatoum
2025-04-11  7:40 ` [PATCH 08/10] scripts: Add Barebox TLV Generator Tooling Ahmad Fatoum
2025-04-14 15:00   ` Sascha Hauer
2025-04-11  7:40 ` [PATCH 09/10] doc: Add User-Documentation for Barebox TLV Ahmad Fatoum
2025-04-11  7:40 ` [PATCH 10/10] ARM: stm32mp: lxa: enable TLV support for TAC & FairyTux2 Ahmad Fatoum

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20250411074045.2019372-7-a.fatoum@pengutronix.de \
    --to=a.fatoum@pengutronix.de \
    --cc=barebox@lists.infradead.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox