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
next prev 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