Skip to contentSkip to conversation

env: add ENV_IS_ANYWHERE

PATCH New Rob Clark 3 participants 9 messages Jul 31, 2017 – Aug 3, 2017

Subsystems (2)
lore
Share & tools
lore

Rob Clark

author
#0 lore raw

PATCH 1/1 env: add ENV_IS_ANYWHERE

Useful for devices which would otherwise have to use ENV_IS_NOWHERE. Tries to find and load uboot.env from any block device (which may be, for example, hot-pluggable sd-card, SATA or USB disk, so the exact location is not known at the time u-boot is compiled).

---
 cmd/bootefi.c         |   5 ++
 cmd/nvedit.c          |   6 +-
 cmd/usb.c             |   4 +-
 common/Kconfig        |  11 ++++
 common/Makefile       |   1 +
 common/board_r.c      |  11 ++++
 common/env_anywhere.c | 156 ++++++++++++++++++++++++++++++++++++++++++++++++++
 include/environment.h |   5 ++
 8 files changed, 196 insertions(+), 3 deletions(-)
 create mode 100644 common/env_anywhere.c
cmd/bootefi.c +5 -0
index 765383bc95..80611e1412 100644
@@ -10,6 +10,7 @@
 #include <command.h>
 #include <dm.h>
 #include <efi_loader.h>
+#include <environment.h>
 #include <errno.h>
 #include <libfdt.h>
 #include <libfdt_env.h>
@@ -318,6 +319,10 @@ void efi_set_bootdev(const char *dev, const char *devnr, const char *path)
 		part = parse_partnum(devnr);
 
 		bootefi_device_path = efi_dp_from_part(desc, part);
+
+#ifdef CONFIG_ENV_IS_ANYWHERE
+		env_set_location(desc, part);
+#endif
 	} else {
 #ifdef CONFIG_NET
 		bootefi_device_path = efi_dp_from_eth();
cmd/nvedit.c +4 -2
index cd17db6409..cab7ed2565 100644
@@ -53,9 +53,11 @@ DECLARE_GLOBAL_DATA_PTR;
 	!defined(CONFIG_ENV_IS_IN_SPI_FLASH)	&& \
 	!defined(CONFIG_ENV_IS_IN_REMOTE)	&& \
 	!defined(CONFIG_ENV_IS_IN_UBI)		&& \
-	!defined(CONFIG_ENV_IS_NOWHERE)
+	!defined(CONFIG_ENV_IS_NOWHERE)		&& \
+	!defined(CONFIG_ENV_IS_ANYWHERE)
 # error Define one of CONFIG_ENV_IS_IN_{EEPROM|FLASH|DATAFLASH|MMC|FAT|EXT4|\
-NAND|NVRAM|ONENAND|SATA|SPI_FLASH|REMOTE|UBI} or CONFIG_ENV_IS_NOWHERE
+NAND|NVRAM|ONENAND|SATA|SPI_FLASH|REMOTE|UBI} or CONFIG_ENV_IS_NOWHERE or \
+CONFIG_ENV_IS_ANYWHERE
 #endif
 
 /*
cmd/usb.c +3 -1
index 4fa456e318..d3347301ca 100644
@@ -23,7 +23,7 @@
 #include <usb.h>
 
 #ifdef CONFIG_USB_STORAGE
-static int usb_stor_curr_dev = -1; /* current device */
+int usb_stor_curr_dev = -1; /* current device */
 #endif
 #if defined(CONFIG_USB_HOST_ETHER) && !defined(CONFIG_DM_ETH)
 static int __maybe_unused usb_ether_curr_dev = -1; /* current ethernet device */
@@ -567,6 +567,7 @@ static void do_usb_start(void)
 {
 	bootstage_mark_name(BOOTSTAGE_ID_USB_START, "usb_start");
 
+#ifndef CONFIG_ENV_IS_ANYWHERE
 	if (usb_init() < 0)
 		return;
 
@@ -575,6 +576,7 @@ static void do_usb_start(void)
 	/* try to recognize storage devices immediately */
 	usb_stor_curr_dev = usb_stor_scan(1);
 # endif
+#endif
 #ifndef CONFIG_DM_USB
 # ifdef CONFIG_USB_KEYBOARD
 	drv_usb_kbd_init();
common/Kconfig +11 -0
index 361346b092..e5f8b5ed3f 100644
@@ -210,6 +210,17 @@ config ENV_IS_NOWHERE
 	  Define this if you don't want to or can't have an environment stored
 	  on a storage medium
 
+config ENV_IS_ANYWHERE
+	bool "Environment is on any partition"
+	depends on BLK
+	help
+	  Define this if you want to store the environment on the first
+	  partition found containing /uboot.env.  Environment will be saved
+	  to same partition it was loaded from.  This is suitable for boards
+	  which may be booting from various removable devices (ie. sd-card,
+	  usb-disk, etc) and you don't know@the time u-boot is built what
+	  the boot media will be.
+
 endchoice
 
 config ENV_OFFSET
common/Makefile +1 -0
index 17a92ea2d7..dd5046b78f 100644
@@ -51,6 +51,7 @@ obj-$(CONFIG_ENV_IS_IN_SPI_FLASH) += env_sf.o
 obj-$(CONFIG_ENV_IS_IN_REMOTE) += env_remote.o
 obj-$(CONFIG_ENV_IS_IN_UBI) += env_ubi.o
 obj-$(CONFIG_ENV_IS_NOWHERE) += env_nowhere.o
+obj-$(CONFIG_ENV_IS_ANYWHERE) += env_anywhere.o
 
 obj-$(CONFIG_CMD_BEDBUG) += bedbug.o
 obj-$(CONFIG_$(SPL_)OF_LIBFDT) += fdt_support.o
common/board_r.c +11 -0
index ecca1edb04..1a47f6cf1f 100644
@@ -693,6 +693,14 @@ static int run_main_loop(void)
 	return 0;
 }
 
+#ifdef CONFIG_ENV_IS_ANYWHERE
+static int env_relocate_late(void)
+{
+	env_relocate_spec_late();
+	return 0;
+}
+#endif
+
 /*
  * Over time we hope to remove these functions with code fragments and
  * stub funtcions, and instead call the relevant function directly.
@@ -898,6 +906,9 @@ static init_fnc_t init_sequence_r[] = {
 #ifdef CONFIG_PS2KBD
 	initr_kbd,
 #endif
+#ifdef CONFIG_ENV_IS_ANYWHERE
+	env_relocate_late,
+#endif
 	run_main_loop,
 };
 
common/env_anywhere.c new file +156 -0

156 lines not on this page · raw message

include/environment.h +5 -0
index 6f94986c6b..57f03fe9ad 100644
@@ -177,6 +177,11 @@ extern env_t *env_ptr;
 extern void env_relocate_spec(void);
 extern unsigned char env_get_char_spec(int);
 
+#ifdef CONFIG_ENV_IS_ANYWHERE
+void env_relocate_spec_late(void);
+void env_set_location(struct blk_desc *desc, int part);
+#endif
+
 #if defined(CONFIG_NEEDS_MANUAL_RELOC)
 extern void env_reloc(void);
 #endif
Signature · 1 line
2.13.0
author
#1 lore raw

PATCH 1/1 vsprintf.c: add wide string (%ls) support

This is convenient for efi_loader which deals a lot with utf16.

---
 lib/vsprintf.c | 39 +++++++++++++++++++++++++++++++++++++--
 1 file changed, 37 insertions(+), 2 deletions(-)
lib/vsprintf.c +37 -2
index 874a2951f7..84e157ecb1 100644
@@ -270,6 +270,35 @@ static char *string(char *buf, char *end, char *s, int field_width,
 	return buf;
 }
 
+static size_t strnlen16(const u16* s, size_t count)
+{
+	const u16 *sc;
+
+	for (sc = s; count-- && *sc; ++sc)
+		/* nothing */;
+	return sc - s;
+}
+
+static char *string16(char *buf, char *end, u16 *s, int field_width,
+		int precision, int flags)
+{
+	int len, i;
+
+	if (s == NULL)
+		s = L"<NULL>";
+
+	len = strnlen16(s, precision);
+
+	if (!(flags & LEFT))
+		while (len < field_width--)
+			ADDCH(buf, ' ');
+	for (i = 0; i < len; ++i)
+		ADDCH(buf, *s++);
+	while (len < field_width--)
+		ADDCH(buf, ' ');
+	return buf;
+}
+
 #ifdef CONFIG_CMD_NET
 static const char hex_asc[] = "0123456789abcdef";
 #define hex_asc_lo(x)	hex_asc[((x) & 0x0f)]
@@ -528,8 +557,14 @@ repeat:
 			continue;
 
 		case 's':
-			str = string(str, end, va_arg(args, char *),
-				     field_width, precision, flags);
+			if (qualifier == 'l') {
+				str = string16(str, end, va_arg(args, u16 *),
+					       field_width, precision, flags);
+
+			} else {
+				str = string(str, end, va_arg(args, char *),
+					     field_width, precision, flags);
+			}
 			continue;
 
 		case 'p':
Signature · 1 line
2.13.0
#2 lore raw

PATCH 1/1 vsprintf.c: add wide string (%ls) support

Quoted 21 lines · Rob Clark

This is convenient for efi_loader which deals a lot with utf16.

---
 lib/vsprintf.c | 39 +++++++++++++++++++++++++++++++++++++--
 1 file changed, 37 insertions(+), 2 deletions(-)
lib/vsprintf.c +6 -0
index 874a2951f7..84e157ecb1 100644
@@ -270,6 +270,35 @@ static char *string(char *buf, char *end, char *s, int field_width,
 	return buf;
 }
 
+static size_t strnlen16(const u16* s, size_t count)
+{
+	const u16 *sc;
+
+	for (sc = s; count-- && *sc; ++sc)
+		/* nothing */;

lib/vsprintf.c static char *string(char *buf, char *end, char *s, int field_width, · line 288

Quoted 10 lines
lib/vsprintf.c +10 -0
+	return sc - s;
+}
+
+static char *string16(char *buf, char *end, u16 *s, int field_width,
+		int precision, int flags)
+{
+	int len, i;
+
+	if (s == NULL)
+		s = L"<NULL>";

The L notation creates a wchar_t string. The width of wchar_t depends on gcc compiler flag -fshort-wchar.

vsprintf.c is not compiled with -fshort-wchar. So change this to

const u16 null[] = { '<', 'N', 'U', 'L', 'L', '>', 0}; s = null;

Quoted 17 lines
lib/vsprintf.c +13 -0
+
+	len = strnlen16(s, precision);
+
+	if (!(flags & LEFT))
+		while (len < field_width--)
+			ADDCH(buf, ' ');
+	for (i = 0; i < len; ++i)
+		ADDCH(buf, *s++);
+	while (len < field_width--)
+		ADDCH(buf, ' ');
+	return buf;
+}
+
 #ifdef CONFIG_CMD_NET
 static const char hex_asc[] = "0123456789abcdef";
 #define hex_asc_lo(x)	hex_asc[((x) & 0x0f)]

lib/vsprintf.c repeat: · line 560

Quoted 6 lines
lib/vsprintf.c +1 -2
@@ -528,8 +557,14 @@ repeat:
 			continue;
 
 		case 's':
-			str = string(str, end, va_arg(args, char *),
-				     field_width, precision, flags);
+			if (qualifier == 'l') {

According to ISO 9899:1999 %ls is used to indicate a wchar_t string, which may be u32 * or u16 * depending on GCC flag -fshort-wchar.

Wouldn't it make sense to use some other notation, e.g. %S, to indicate that we explicitly mean u16 *?

Please, add a comment into the code indicating why we need u16 * support referring to the UEFI spec.

Best regards

Heinrich

Quoted 11 lines
lib/vsprintf.c +7 -0
+				str = string16(str, end, va_arg(args, u16 *),
+					       field_width, precision, flags);
+
+			} else {
+				str = string(str, end, va_arg(args, char *),
+					     field_width, precision, flags);
+			}
 			continue;
 
 		case 'p':
author
#3 lore raw

PATCH 1/1 vsprintf.c: add wide string (%ls) support

Quoted 36 lines · Heinrich Schuchardt
Quoted 21 lines · Rob Clark

This is convenient for efi_loader which deals a lot with utf16.

---
 lib/vsprintf.c | 39 +++++++++++++++++++++++++++++++++++++--
 1 file changed, 37 insertions(+), 2 deletions(-)
lib/vsprintf.c +6 -0
index 874a2951f7..84e157ecb1 100644
@@ -270,6 +270,35 @@ static char *string(char *buf, char *end, char *s, int field_width,
      return buf;
 }
 
+static size_t strnlen16(const u16* s, size_t count)
+{
+     const u16 *sc;
+
+     for (sc = s; count-- && *sc; ++sc)
+             /* nothing */;

lib/vsprintf.c static char *string(char *buf, char *end, char *s, int field_width, · line 288

Quoted 10 lines
lib/vsprintf.c +10 -0
+     return sc - s;
+}
+
+static char *string16(char *buf, char *end, u16 *s, int field_width,
+             int precision, int flags)
+{
+     int len, i;
+
+     if (s == NULL)
+             s = L"<NULL>";

The L notation creates a wchar_t string. The width of wchar_t depends on gcc compiler flag -fshort-wchar.

Quoted 4 lines

vsprintf.c is not compiled with -fshort-wchar. So change this to

const u16 null[] = { '<', 'N', 'U', 'L', 'L', '>', 0}; s = null;

oh, I have another patch that adds -fshort-wchar globally.. which I probably should have split out and sent with this.

The problem is we cannot mix objects using short-wchar and ones that don't without a compiler warning. Travis would complain a lot more but I guess BOOTEFI_HELLO is not normally enabled.

With addition of efi_bootmgr.c we really want to be able to use L"string" to be u16.. and I don't think u-boot has any good reason to use 32b wchar.

But maybe for this code I should use wchar_t instead of u16.

BR,
-R

Quoted 49 lines
Quoted 17 lines
lib/vsprintf.c +13 -0
+
+     len = strnlen16(s, precision);
+
+     if (!(flags & LEFT))
+             while (len < field_width--)
+                     ADDCH(buf, ' ');
+     for (i = 0; i < len; ++i)
+             ADDCH(buf, *s++);
+     while (len < field_width--)
+             ADDCH(buf, ' ');
+     return buf;
+}
+
 #ifdef CONFIG_CMD_NET
 static const char hex_asc[] = "0123456789abcdef";
 #define hex_asc_lo(x)        hex_asc[((x) & 0x0f)]

lib/vsprintf.c repeat: · line 560

Quoted 6 lines
lib/vsprintf.c +1 -2
@@ -528,8 +557,14 @@ repeat:
                      continue;
 
              case 's':
-                     str = string(str, end, va_arg(args, char *),
-                                  field_width, precision, flags);
+                     if (qualifier == 'l') {

According to ISO 9899:1999 %ls is used to indicate a wchar_t string, which may be u32 * or u16 * depending on GCC flag -fshort-wchar.

Wouldn't it make sense to use some other notation, e.g. %S, to indicate that we explicitly mean u16 *?

Please, add a comment into the code indicating why we need u16 * support referring to the UEFI spec.

Best regards

Heinrich

Quoted 11 lines
lib/vsprintf.c +7 -0
+                             str = string16(str, end, va_arg(args, u16 *),
+                                            field_width, precision, flags);
+
+                     } else {
+                             str = string(str, end, va_arg(args, char *),
+                                          field_width, precision, flags);
+                     }
                      continue;
 
              case 'p':
#4 lore raw

PATCH 1/1 vsprintf.c: add wide string (%ls) support

Quoted 49 lines · Rob Clark
Quoted 36 lines · Heinrich Schuchardt
Quoted 21 lines · Rob Clark

This is convenient for efi_loader which deals a lot with utf16.

---
 lib/vsprintf.c | 39 +++++++++++++++++++++++++++++++++++++--
 1 file changed, 37 insertions(+), 2 deletions(-)
lib/vsprintf.c +6 -0
index 874a2951f7..84e157ecb1 100644
@@ -270,6 +270,35 @@ static char *string(char *buf, char *end, char *s, int field_width,
      return buf;
 }
 
+static size_t strnlen16(const u16* s, size_t count)
+{
+     const u16 *sc;
+
+     for (sc = s; count-- && *sc; ++sc)
+             /* nothing */;

lib/vsprintf.c static char *string(char *buf, char *end, char *s, int field_width, · line 288

Quoted 10 lines
lib/vsprintf.c +10 -0
+     return sc - s;
+}
+
+static char *string16(char *buf, char *end, u16 *s, int field_width,
+             int precision, int flags)
+{
+     int len, i;
+
+     if (s == NULL)
+             s = L"<NULL>";

The L notation creates a wchar_t string. The width of wchar_t depends on gcc compiler flag -fshort-wchar.

Quoted 4 lines

vsprintf.c is not compiled with -fshort-wchar. So change this to

const u16 null[] = { '<', 'N', 'U', 'L', 'L', '>', 0}; s = null;

oh, I have another patch that adds -fshort-wchar globally.. which I probably should have split out and sent with this.

The problem is we cannot mix objects using short-wchar and ones that don't without a compiler warning. Travis would complain a lot more but I guess BOOTEFI_HELLO is not normally enabled.

Quoted 8 lines

With addition of efi_bootmgr.c we really want to be able to use L"string" to be u16.. and I don't think u-boot has any good reason to use 32b wchar.

But maybe for this code I should use wchar_t instead of u16.

BR,
-R

ext4 filenames may contain letters with Unicode values > 2**16, e.g. using Takri letters: 𑚀�𑚂

So ext4ls probably should be enabled to display these on a Unicode console.

Using -fshort-wchar globally is not necessary. Only UEFI requires 16 bit wchar_t. We should rather not enforce the UEFI standard on the rest of the code.

Quoted 9 lines
Quoted 9 lines

lib/vsprintf.c static char *string(char *buf, char *end, char *s, int field_width, · line 296

Quoted 9 lines
lib/vsprintf.c +8 -0
+
+     len = strnlen16(s, precision);
+
+     if (!(flags & LEFT))
+             while (len < field_width--)
+                     ADDCH(buf, ' ');
+     for (i = 0; i < len; ++i)
+             ADDCH(buf, *s++);

I would prefer to see a conversion to UTF-8 here.

Conversion from 32bit Unicode (Or the capped 16bit Unicode of EFI) is quite easy. This is what I used in another project:

        uint32_t u = s[i];
        char c[5];
        if (u < 0x80) {
            c[0] = u & 0x7F;
            c[1] = 0;
            str.append(c);
        } else if (u < 0x800) {
            c[1] = 0x80 | (u & 0x3F);
            u >>= 6;
            c[0] = 0xC0 | (u & 0x1F);
            c[2] = 0;
            str.append(c);
        } else if (u < 0x10000) {
            c[2] = 0x80 | (u & 0x3F);
            u >>= 6;
            c[1] = 0x80 | (u & 0x3F);
            u >>= 6;
            c[0] = 0xE0 | (u & 0x0F);
            c[3] = 0;
            str.append(c);
        } else if (u < 0x200000) {
            c[3] = 0x80 | (u & 0x3F);
            u >>= 6;
            c[2] = 0x80 | (u & 0x3F);
            u >>= 6;
            c[1] = 0x80 | (u & 0x3F);
            u >>= 6;
            c[0] = 0xF0 | (u & 0x07);
            c[4] = 0;
            str.append(c);
        } else {
            throw invalid;
        }

Best regards

Heinrich

Quoted 42 lines
Quoted 41 lines
Quoted 9 lines
lib/vsprintf.c +5 -0
+     while (len < field_width--)
+             ADDCH(buf, ' ');
+     return buf;
+}
+
 #ifdef CONFIG_CMD_NET
 static const char hex_asc[] = "0123456789abcdef";
 #define hex_asc_lo(x)        hex_asc[((x) & 0x0f)]

lib/vsprintf.c repeat: · line 560

Quoted 6 lines
lib/vsprintf.c +1 -2
@@ -528,8 +557,14 @@ repeat:
                      continue;
 
              case 's':
-                     str = string(str, end, va_arg(args, char *),
-                                  field_width, precision, flags);
+                     if (qualifier == 'l') {

According to ISO 9899:1999 %ls is used to indicate a wchar_t string, which may be u32 * or u16 * depending on GCC flag -fshort-wchar.

Wouldn't it make sense to use some other notation, e.g. %S, to indicate that we explicitly mean u16 *?

Please, add a comment into the code indicating why we need u16 * support referring to the UEFI spec.

Best regards

Heinrich

Quoted 11 lines
lib/vsprintf.c +7 -0
+                             str = string16(str, end, va_arg(args, u16 *),
+                                            field_width, precision, flags);
+
+                     } else {
+                             str = string(str, end, va_arg(args, char *),
+                                          field_width, precision, flags);
+                     }
                      continue;
 
              case 'p':
author
#5 lore raw

PATCH 1/1 vsprintf.c: add wide string (%ls) support

Quoted 59 lines · Heinrich Schuchardt
Quoted 49 lines · Rob Clark
Quoted 36 lines · Heinrich Schuchardt
Quoted 21 lines · Rob Clark

This is convenient for efi_loader which deals a lot with utf16.

---
 lib/vsprintf.c | 39 +++++++++++++++++++++++++++++++++++++--
 1 file changed, 37 insertions(+), 2 deletions(-)
lib/vsprintf.c +6 -0
index 874a2951f7..84e157ecb1 100644
@@ -270,6 +270,35 @@ static char *string(char *buf, char *end, char *s, int field_width,
      return buf;
 }
 
+static size_t strnlen16(const u16* s, size_t count)
+{
+     const u16 *sc;
+
+     for (sc = s; count-- && *sc; ++sc)
+             /* nothing */;

lib/vsprintf.c static char *string(char *buf, char *end, char *s, int field_width, · line 288

Quoted 10 lines
lib/vsprintf.c +10 -0
+     return sc - s;
+}
+
+static char *string16(char *buf, char *end, u16 *s, int field_width,
+             int precision, int flags)
+{
+     int len, i;
+
+     if (s == NULL)
+             s = L"<NULL>";

The L notation creates a wchar_t string. The width of wchar_t depends on gcc compiler flag -fshort-wchar.

Quoted 4 lines

vsprintf.c is not compiled with -fshort-wchar. So change this to

const u16 null[] = { '<', 'N', 'U', 'L', 'L', '>', 0}; s = null;

oh, I have another patch that adds -fshort-wchar globally.. which I probably should have split out and sent with this.

The problem is we cannot mix objects using short-wchar and ones that don't without a compiler warning. Travis would complain a lot more but I guess BOOTEFI_HELLO is not normally enabled.

Quoted 8 lines

With addition of efi_bootmgr.c we really want to be able to use L"string" to be u16.. and I don't think u-boot has any good reason to use 32b wchar.

But maybe for this code I should use wchar_t instead of u16.

BR,
-R

Quoted 8 lines

ext4 filenames may contain letters with Unicode values > 2**16, e.g. using Takri letters: 𑚀�𑚂

So ext4ls probably should be enabled to display these on a Unicode console.

Using -fshort-wchar globally is not necessary. Only UEFI requires 16 bit wchar_t. We should rather not enforce the UEFI standard on the rest of the code.

The alternative is disabling a gcc warning about mixing 32b and 16b wchar.. and really mixing 32b and 16b wchar seems like a bad idea.

We could use -fshort-wchar only if EFI_LOADER is enabled. Technically if we are a UEFI implementation, we do not need to have ext2/ext4 (or really anything other than fat/vfat).

Quoted 40 lines
Quoted 9 lines
Quoted 9 lines

lib/vsprintf.c static char *string(char *buf, char *end, char *s, int field_width, · line 296

Quoted 9 lines
lib/vsprintf.c +8 -0
+
+     len = strnlen16(s, precision);
+
+     if (!(flags & LEFT))
+             while (len < field_width--)
+                     ADDCH(buf, ' ');
+     for (i = 0; i < len; ++i)
+             ADDCH(buf, *s++);

I would prefer to see a conversion to UTF-8 here.

Conversion from 32bit Unicode (Or the capped 16bit Unicode of EFI) is quite easy. This is what I used in another project:

        uint32_t u = s[i];
        char c[5];
        if (u < 0x80) {
            c[0] = u & 0x7F;
            c[1] = 0;
            str.append(c);
        } else if (u < 0x800) {
            c[1] = 0x80 | (u & 0x3F);
            u >>= 6;
            c[0] = 0xC0 | (u & 0x1F);
            c[2] = 0;
            str.append(c);
        } else if (u < 0x10000) {
            c[2] = 0x80 | (u & 0x3F);
            u >>= 6;
            c[1] = 0x80 | (u & 0x3F);
            u >>= 6;
            c[0] = 0xE0 | (u & 0x0F);
            c[3] = 0;
            str.append(c);
        } else if (u < 0x200000) {
            c[3] = 0x80 | (u & 0x3F);
            u >>= 6;
            c[2] = 0x80 | (u & 0x3F);
            u >>= 6;
Quoted 8 lines
            c[1] = 0x80 | (u & 0x3F);
            u >>= 6;
            c[0] = 0xF0 | (u & 0x07);
            c[4] = 0;
            str.append(c);
        } else {
            throw invalid;
        }

I did add a utf16_to_utf8() (based on code from grub) as part of the efi-variables patch, since there we are dealing with utf16 coming from outside of grub. I guess I could use that. I think that mostly matters if we end up printing strings that originate outside of u-boot, but I guess that will be the case for filenames in a device-path.

BR,
-R

Quoted 47 lines

Best regards

Heinrich

Quoted 42 lines
Quoted 41 lines
Quoted 9 lines
lib/vsprintf.c +5 -0
+     while (len < field_width--)
+             ADDCH(buf, ' ');
+     return buf;
+}
+
 #ifdef CONFIG_CMD_NET
 static const char hex_asc[] = "0123456789abcdef";
 #define hex_asc_lo(x)        hex_asc[((x) & 0x0f)]

lib/vsprintf.c repeat: · line 560

Quoted 6 lines
lib/vsprintf.c +1 -2
@@ -528,8 +557,14 @@ repeat:
                      continue;
 
              case 's':
-                     str = string(str, end, va_arg(args, char *),
-                                  field_width, precision, flags);
+                     if (qualifier == 'l') {

According to ISO 9899:1999 %ls is used to indicate a wchar_t string, which may be u32 * or u16 * depending on GCC flag -fshort-wchar.

Wouldn't it make sense to use some other notation, e.g. %S, to indicate that we explicitly mean u16 *?

Please, add a comment into the code indicating why we need u16 * support referring to the UEFI spec.

Best regards

Heinrich

Quoted 11 lines
lib/vsprintf.c +7 -0
+                             str = string16(str, end, va_arg(args, u16 *),
+                                            field_width, precision, flags);
+
+                     } else {
+                             str = string(str, end, va_arg(args, char *),
+                                          field_width, precision, flags);
+                     }
                      continue;
 
              case 'p':
#6 lore raw

PATCH 1/1 vsprintf.c: add wide string (%ls) support

Quoted 69 lines · Rob Clark
Quoted 59 lines · Heinrich Schuchardt
Quoted 49 lines · Rob Clark
Quoted 36 lines · Heinrich Schuchardt
Quoted 21 lines · Rob Clark

This is convenient for efi_loader which deals a lot with utf16.

---
 lib/vsprintf.c | 39 +++++++++++++++++++++++++++++++++++++--
 1 file changed, 37 insertions(+), 2 deletions(-)
lib/vsprintf.c +6 -0
index 874a2951f7..84e157ecb1 100644
@@ -270,6 +270,35 @@ static char *string(char *buf, char *end, char *s, int field_width,
      return buf;
 }
 
+static size_t strnlen16(const u16* s, size_t count)
+{
+     const u16 *sc;
+
+     for (sc = s; count-- && *sc; ++sc)
+             /* nothing */;

lib/vsprintf.c static char *string(char *buf, char *end, char *s, int field_width, · line 288

Quoted 10 lines
lib/vsprintf.c +10 -0
+     return sc - s;
+}
+
+static char *string16(char *buf, char *end, u16 *s, int field_width,
+             int precision, int flags)
+{
+     int len, i;
+
+     if (s == NULL)
+             s = L"<NULL>";

The L notation creates a wchar_t string. The width of wchar_t depends on gcc compiler flag -fshort-wchar.

Quoted 4 lines

vsprintf.c is not compiled with -fshort-wchar. So change this to

const u16 null[] = { '<', 'N', 'U', 'L', 'L', '>', 0}; s = null;

oh, I have another patch that adds -fshort-wchar globally.. which I probably should have split out and sent with this.

The problem is we cannot mix objects using short-wchar and ones that don't without a compiler warning. Travis would complain a lot more but I guess BOOTEFI_HELLO is not normally enabled.

Quoted 8 lines

With addition of efi_bootmgr.c we really want to be able to use L"string" to be u16.. and I don't think u-boot has any good reason to use 32b wchar.

But maybe for this code I should use wchar_t instead of u16.

BR,
-R

Quoted 8 lines

ext4 filenames may contain letters with Unicode values > 2**16, e.g. using Takri letters: 𑚀�𑚂

So ext4ls probably should be enabled to display these on a Unicode console.

Using -fshort-wchar globally is not necessary. Only UEFI requires 16 bit wchar_t. We should rather not enforce the UEFI standard on the rest of the code.

Quoted 6 lines

The alternative is disabling a gcc warning about mixing 32b and 16b wchar.. and really mixing 32b and 16b wchar seems like a bad idea.

We could use -fshort-wchar only if EFI_LOADER is enabled. Technically if we are a UEFI implementation, we do not need to have ext2/ext4 (or really anything other than fat/vfat).

You can avoid the problem of variable width wchar by using constants starting with u (e.g. u"Hello world") which are char16_t (introduced with C11, #include <uchar.h>) and converting to utf-8 for console output.

This way we do not need -fshort-wchar at all.

Best regards

Heinrich

Quoted 108 lines
Quoted 41 lines
Quoted 10 lines
Quoted 10 lines

lib/vsprintf.c static char *string(char *buf, char *end, char *s, int field_width, · line 296

Quoted 10 lines
lib/vsprintf.c +8 -0
+
+     len = strnlen16(s, precision);
+
+     if (!(flags & LEFT))
+             while (len < field_width--)
+                     ADDCH(buf, ' ');
+     for (i = 0; i < len; ++i)
+             ADDCH(buf, *s++);

I would prefer to see a conversion to UTF-8 here.

Conversion from 32bit Unicode (Or the capped 16bit Unicode of EFI) is quite easy. This is what I used in another project:

        uint32_t u = s[i];
        char c[5];
        if (u < 0x80) {
            c[0] = u & 0x7F;
            c[1] = 0;
            str.append(c);
        } else if (u < 0x800) {
            c[1] = 0x80 | (u & 0x3F);
            u >>= 6;
            c[0] = 0xC0 | (u & 0x1F);
            c[2] = 0;
            str.append(c);
        } else if (u < 0x10000) {
            c[2] = 0x80 | (u & 0x3F);
            u >>= 6;
            c[1] = 0x80 | (u & 0x3F);
            u >>= 6;
            c[0] = 0xE0 | (u & 0x0F);
            c[3] = 0;
            str.append(c);
        } else if (u < 0x200000) {
            c[3] = 0x80 | (u & 0x3F);
            u >>= 6;
            c[2] = 0x80 | (u & 0x3F);
            u >>= 6;
Quoted 8 lines
            c[1] = 0x80 | (u & 0x3F);
            u >>= 6;
            c[0] = 0xF0 | (u & 0x07);
            c[4] = 0;
            str.append(c);
        } else {
            throw invalid;
        }

I did add a utf16_to_utf8() (based on code from grub) as part of the efi-variables patch, since there we are dealing with utf16 coming from outside of grub. I guess I could use that. I think that mostly matters if we end up printing strings that originate outside of u-boot, but I guess that will be the case for filenames in a device-path.

BR,
-R

Quoted 47 lines

Best regards

Heinrich

Quoted 42 lines
Quoted 41 lines
Quoted 9 lines
lib/vsprintf.c +5 -0
+     while (len < field_width--)
+             ADDCH(buf, ' ');
+     return buf;
+}
+
 #ifdef CONFIG_CMD_NET
 static const char hex_asc[] = "0123456789abcdef";
 #define hex_asc_lo(x)        hex_asc[((x) & 0x0f)]

lib/vsprintf.c repeat: · line 560

Quoted 6 lines
lib/vsprintf.c +1 -2
@@ -528,8 +557,14 @@ repeat:
                      continue;
 
              case 's':
-                     str = string(str, end, va_arg(args, char *),
-                                  field_width, precision, flags);
+                     if (qualifier == 'l') {

According to ISO 9899:1999 %ls is used to indicate a wchar_t string, which may be u32 * or u16 * depending on GCC flag -fshort-wchar.

Wouldn't it make sense to use some other notation, e.g. %S, to indicate that we explicitly mean u16 *?

Please, add a comment into the code indicating why we need u16 * support referring to the UEFI spec.

Best regards

Heinrich

Quoted 11 lines
lib/vsprintf.c +7 -0
+                             str = string16(str, end, va_arg(args, u16 *),
+                                            field_width, precision, flags);
+
+                     } else {
+                             str = string(str, end, va_arg(args, char *),
+                                          field_width, precision, flags);
+                     }
                      continue;
 
              case 'p':
author
#7 lore raw

PATCH 1/1 vsprintf.c: add wide string (%ls) support

Quoted 77 lines · Heinrich Schuchardt
Quoted 69 lines · Rob Clark
Quoted 59 lines · Heinrich Schuchardt
Quoted 49 lines · Rob Clark
Quoted 36 lines · Heinrich Schuchardt
Quoted 21 lines · Rob Clark

This is convenient for efi_loader which deals a lot with utf16.

---
 lib/vsprintf.c | 39 +++++++++++++++++++++++++++++++++++++--
 1 file changed, 37 insertions(+), 2 deletions(-)
lib/vsprintf.c +6 -0
index 874a2951f7..84e157ecb1 100644
@@ -270,6 +270,35 @@ static char *string(char *buf, char *end, char *s, int field_width,
      return buf;
 }
 
+static size_t strnlen16(const u16* s, size_t count)
+{
+     const u16 *sc;
+
+     for (sc = s; count-- && *sc; ++sc)
+             /* nothing */;

lib/vsprintf.c static char *string(char *buf, char *end, char *s, int field_width, · line 288

Quoted 10 lines
lib/vsprintf.c +10 -0
+     return sc - s;
+}
+
+static char *string16(char *buf, char *end, u16 *s, int field_width,
+             int precision, int flags)
+{
+     int len, i;
+
+     if (s == NULL)
+             s = L"<NULL>";

The L notation creates a wchar_t string. The width of wchar_t depends on gcc compiler flag -fshort-wchar.

Quoted 4 lines

vsprintf.c is not compiled with -fshort-wchar. So change this to

const u16 null[] = { '<', 'N', 'U', 'L', 'L', '>', 0}; s = null;

oh, I have another patch that adds -fshort-wchar globally.. which I probably should have split out and sent with this.

The problem is we cannot mix objects using short-wchar and ones that don't without a compiler warning. Travis would complain a lot more but I guess BOOTEFI_HELLO is not normally enabled.

Quoted 8 lines

With addition of efi_bootmgr.c we really want to be able to use L"string" to be u16.. and I don't think u-boot has any good reason to use 32b wchar.

But maybe for this code I should use wchar_t instead of u16.

BR,
-R

Quoted 8 lines

ext4 filenames may contain letters with Unicode values > 2**16, e.g. using Takri letters: 𑚀�𑚂

So ext4ls probably should be enabled to display these on a Unicode console.

Using -fshort-wchar globally is not necessary. Only UEFI requires 16 bit wchar_t. We should rather not enforce the UEFI standard on the rest of the code.

Quoted 6 lines

The alternative is disabling a gcc warning about mixing 32b and 16b wchar.. and really mixing 32b and 16b wchar seems like a bad idea.

We could use -fshort-wchar only if EFI_LOADER is enabled. Technically if we are a UEFI implementation, we do not need to have ext2/ext4 (or really anything other than fat/vfat).

Quoted 5 lines

You can avoid the problem of variable width wchar by using constants starting with u (e.g. u"Hello world") which are char16_t (introduced with C11, #include <uchar.h>) and converting to utf-8 for console output.

This way we do not need -fshort-wchar at all.

oh, that would simplify things a *lot*.. is there a corresponding printf() modifier?

and any reason to fear requiring c11 (I have none myself)?

If not I'll switch over my patches to using u"string" and fixup efi hello too.

BR,
-R

Quoted 113 lines

Best regards

Heinrich

Quoted 108 lines
Quoted 41 lines
Quoted 10 lines
Quoted 10 lines

lib/vsprintf.c static char *string(char *buf, char *end, char *s, int field_width, · line 296

Quoted 10 lines
lib/vsprintf.c +8 -0
+
+     len = strnlen16(s, precision);
+
+     if (!(flags & LEFT))
+             while (len < field_width--)
+                     ADDCH(buf, ' ');
+     for (i = 0; i < len; ++i)
+             ADDCH(buf, *s++);

I would prefer to see a conversion to UTF-8 here.

Conversion from 32bit Unicode (Or the capped 16bit Unicode of EFI) is quite easy. This is what I used in another project:

        uint32_t u = s[i];
        char c[5];
        if (u < 0x80) {
            c[0] = u & 0x7F;
            c[1] = 0;
            str.append(c);
        } else if (u < 0x800) {
            c[1] = 0x80 | (u & 0x3F);
            u >>= 6;
            c[0] = 0xC0 | (u & 0x1F);
            c[2] = 0;
            str.append(c);
        } else if (u < 0x10000) {
            c[2] = 0x80 | (u & 0x3F);
            u >>= 6;
            c[1] = 0x80 | (u & 0x3F);
            u >>= 6;
            c[0] = 0xE0 | (u & 0x0F);
            c[3] = 0;
            str.append(c);
        } else if (u < 0x200000) {
            c[3] = 0x80 | (u & 0x3F);
            u >>= 6;
            c[2] = 0x80 | (u & 0x3F);
            u >>= 6;
Quoted 8 lines
            c[1] = 0x80 | (u & 0x3F);
            u >>= 6;
            c[0] = 0xF0 | (u & 0x07);
            c[4] = 0;
            str.append(c);
        } else {
            throw invalid;
        }

I did add a utf16_to_utf8() (based on code from grub) as part of the efi-variables patch, since there we are dealing with utf16 coming from outside of grub. I guess I could use that. I think that mostly matters if we end up printing strings that originate outside of u-boot, but I guess that will be the case for filenames in a device-path.

BR,
-R

Quoted 47 lines

Best regards

Heinrich

Quoted 42 lines
Quoted 41 lines
Quoted 9 lines
lib/vsprintf.c +5 -0
+     while (len < field_width--)
+             ADDCH(buf, ' ');
+     return buf;
+}
+
 #ifdef CONFIG_CMD_NET
 static const char hex_asc[] = "0123456789abcdef";
 #define hex_asc_lo(x)        hex_asc[((x) & 0x0f)]

lib/vsprintf.c repeat: · line 560

Quoted 6 lines
lib/vsprintf.c +1 -2
@@ -528,8 +557,14 @@ repeat:
                      continue;
 
              case 's':
-                     str = string(str, end, va_arg(args, char *),
-                                  field_width, precision, flags);
+                     if (qualifier == 'l') {

According to ISO 9899:1999 %ls is used to indicate a wchar_t string, which may be u32 * or u16 * depending on GCC flag -fshort-wchar.

Wouldn't it make sense to use some other notation, e.g. %S, to indicate that we explicitly mean u16 *?

Please, add a comment into the code indicating why we need u16 * support referring to the UEFI spec.

Best regards

Heinrich

Quoted 11 lines
lib/vsprintf.c +7 -0
+                             str = string16(str, end, va_arg(args, u16 *),
+                                            field_width, precision, flags);
+
+                     } else {
+                             str = string(str, end, va_arg(args, char *),
+                                          field_width, precision, flags);
+                     }
                      continue;
 
              case 'p':
#8 lore raw

PATCH 1/1 env: add ENV_IS_ANYWHERE

In reply to Rob Clark
Quoted 6 lines · Rob Clark

Useful for devices which would otherwise have to use ENV_IS_NOWHERE. Tries to find and load uboot.env from any block device (which may be, for example, hot-pluggable sd-card, SATA or USB disk, so the exact location is not known at the time u-boot is compiled).

I can see where this concept is useful. What I would like to see is updating the ENV_IS_IN_FAT / ENV_IS_IN_EXT4 / ENV_IS_ANYWHERE so that we end up with:
- ENV_IS_IN_FILESYSTEM
- Configured device, part, file.
- Optional specify device, otherwise help for the option describes the logic behind how U-Boot will iterate until it finds something.

Signature · 8 lines
Tom
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: Digital signature
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20170802/b5d8b565/attachment.sig>