From 17739b7ef510917471409d71fb45d8eaf6a1e1fb Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <rafal@milecki.pl>
Date: Thu, 9 Dec 2021 07:14:20 +0100
Subject: [PATCH] Support 'r' format for printing raw bytes with fdtget
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

FT is sometimes used for storing raw data. That is quite common for
U-Boot FIT images.

Extracting such data is not trivial currently. Using type 's' (string)
will replace every 0x00 (NUL) with 0x20 (space). Using type 'x' will
print bytes but in xxd incompatible format.

This commit adds support for 'r' (raw) format. Example usage:
fdtget -t r firmware.itb /images/foo data > image.raw

Support for encoding isn't added as there isn't any clean way of passing
binary data as command line argument.

Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
Message-Id: <20211209061420.29466-1-zajec5@gmail.com>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
---
 Documentation/manual.txt | 2 +-
 fdtget.c                 | 5 +++++
 fdtput.c                 | 2 ++
 tests/run_tests.sh       | 2 ++
 tests/utilfdt_test.c     | 5 ++++-
 util.c                   | 4 ++--
 util.h                   | 3 ++-
 7 files changed, 18 insertions(+), 5 deletions(-)

--- a/Documentation/manual.txt
+++ b/Documentation/manual.txt
@@ -712,7 +712,7 @@ The syntax of the fdtget command is:
 
 where options are:
 
-    <type>    s=string, i=int, u=unsigned, x=hex
+    <type>    s=string, i=int, u=unsigned, x=hex, r=raw
         Optional modifier prefix:
             hh or b=byte, h=2 byte, l=4 byte (default)
 
--- a/fdtget.c
+++ b/fdtget.c
@@ -91,6 +91,11 @@ static int show_data(struct display_info
 	if (len == 0)
 		return 0;
 
+	if (disp->type == 'r') {
+		fwrite(data, 1, len, stdout);
+		return 0;
+	}
+
 	is_string = (disp->type) == 's' ||
 		(!disp->type && util_is_printable_string(data, len));
 	if (is_string) {
--- a/fdtput.c
+++ b/fdtput.c
@@ -433,6 +433,8 @@ int main(int argc, char *argv[])
 			if (utilfdt_decode_type(optarg, &disp.type,
 					&disp.size))
 				usage("Invalid type string");
+			if (disp.type == 'r')
+				usage("Unsupported raw data type");
 			break;
 
 		case 'v':
--- a/tests/run_tests.sh
+++ b/tests/run_tests.sh
@@ -852,6 +852,8 @@ fdtget_tests () {
     run_fdtget_test 8000 -tx $dtb /cpus/PowerPC,970@1 d-cache-size
     run_fdtget_test "61 62 63 0" -tbx $dtb /randomnode tricky1
     run_fdtget_test "a b c d de ea ad be ef" -tbx $dtb /randomnode blob
+    run_fdtget_test "MyBoardName\0MyBoardFamilyName\0" -tr $dtb / compatible
+    run_fdtget_test "\x0a\x0b\x0c\x0d\xde\xea\xad\xbe\xef" -tr $dtb /randomnode blob
 
     # Here the property size is not a multiple of 4 bytes, so it should fail
     run_wrap_error_test $DTGET -tlx $dtb /randomnode mixed
--- a/tests/utilfdt_test.c
+++ b/tests/utilfdt_test.c
@@ -73,6 +73,9 @@ static void check_sizes(char *modifier,
 
 	*ptr = 's';
 	check(fmt, 's', -1);
+
+	*ptr = 'r';
+	check(fmt, 'r', -1);
 }
 
 static void test_utilfdt_decode_type(void)
@@ -90,7 +93,7 @@ static void test_utilfdt_decode_type(voi
 	/* try every other character */
 	checkfail("");
 	for (ch = ' '; ch < 127; ch++) {
-		if (!strchr("iuxs", ch)) {
+		if (!strchr("iuxsr", ch)) {
 			*fmt = ch;
 			fmt[1] = '\0';
 			checkfail(fmt);
--- a/util.c
+++ b/util.c
@@ -353,11 +353,11 @@ int utilfdt_decode_type(const char *fmt,
 	}
 
 	/* we should now have a type */
-	if ((*fmt == '\0') || !strchr("iuxs", *fmt))
+	if ((*fmt == '\0') || !strchr("iuxsr", *fmt))
 		return -1;
 
 	/* convert qualifier (bhL) to byte size */
-	if (*fmt != 's')
+	if (*fmt != 's' && *fmt != 'r')
 		*size = qualifier == 'b' ? 1 :
 				qualifier == 'h' ? 2 :
 				qualifier == 'l' ? 4 : -1;
--- a/util.h
+++ b/util.h
@@ -143,6 +143,7 @@ int utilfdt_write_err(const char *filena
  *		i	signed integer
  *		u	unsigned integer
  *		x	hex
+ *		r	raw
  *
  * TODO: Implement ll modifier (8 bytes)
  * TODO: Implement o type (octal)
@@ -160,7 +161,7 @@ int utilfdt_decode_type(const char *fmt,
  */
 
 #define USAGE_TYPE_MSG \
-	"<type>\ts=string, i=int, u=unsigned, x=hex\n" \
+	"<type>\ts=string, i=int, u=unsigned, x=hex, r=raw\n" \
 	"\tOptional modifier prefix:\n" \
 	"\t\thh or b=byte, h=2 byte, l=4 byte (default)";
 
