Merge tag 'efi-2022-04-rc1-2' of https://source.denx.de/u-boot/custodians/u-boot-efi
[platform/kernel/u-boot.git] / lib / vsprintf.c
index 1b6c154..2c84649 100644 (file)
@@ -2,6 +2,8 @@
  *  linux/lib/vsprintf.c
  *
  *  Copyright (C) 1991, 1992  Linus Torvalds
+ * (C) Copyright 2000-2009
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
  */
 
 /* vsprintf.c -- Lars Wirzenius & Linus Torvalds. */
 #include <efi_loader.h>
 #include <div64.h>
 #include <hexdump.h>
-#include <uuid.h>
 #include <stdarg.h>
+#include <uuid.h>
+#include <vsprintf.h>
 #include <linux/ctype.h>
 #include <linux/err.h>
 #include <linux/types.h>
 #include <linux/string.h>
 
-#define noinline __attribute__((noinline))
-
 /* we use this so that we can do without the ctype library */
 #define is_digit(c)    ((c) >= '0' && (c) <= '9')
 
@@ -254,7 +255,7 @@ static char *number(char *buf, char *end, u64 num,
        return buf;
 }
 
-static char *string(char *buf, char *end, char *s, int field_width,
+static char *string(char *buf, char *end, const char *s, int field_width,
                int precision, int flags)
 {
        int len, i;
@@ -275,9 +276,8 @@ static char *string(char *buf, char *end, char *s, int field_width,
 }
 
 /* U-Boot uses UTF-16 strings in the EFI context only. */
-#if CONFIG_IS_ENABLED(EFI_LOADER) && !defined(API_BUILD)
-static char *string16(char *buf, char *end, u16 *s, int field_width,
-               int precision, int flags)
+static __maybe_unused char *string16(char *buf, char *end, u16 *s,
+                                    int field_width, int precision, int flags)
 {
        const u16 *str = s ? s : L"<NULL>";
        ssize_t i, len = utf16_strnlen(str, precision);
@@ -297,6 +297,7 @@ static char *string16(char *buf, char *end, u16 *s, int field_width,
        return buf;
 }
 
+#if CONFIG_IS_ENABLED(EFI_DEVICE_PATH_TO_TEXT)
 static char *device_path_string(char *buf, char *end, void *dp, int field_width,
                                int precision, int flags)
 {
@@ -316,7 +317,6 @@ static char *device_path_string(char *buf, char *end, void *dp, int field_width,
 }
 #endif
 
-#ifdef CONFIG_CMD_NET
 static char *mac_address_string(char *buf, char *end, u8 *addr, int field_width,
                                int precision, int flags)
 {
@@ -378,33 +378,43 @@ static char *ip4_addr_string(char *buf, char *end, u8 *addr, int field_width,
        return string(buf, end, ip4_addr, field_width, precision,
                      flags & ~SPECIAL);
 }
-#endif
 
 #ifdef CONFIG_LIB_UUID
 /*
- * This works (roughly) the same way as linux's, but we currently always
- * print lower-case (ie. we just keep %pUB and %pUL for compat with linux),
- * mostly just because that is what uuid_bin_to_str() supports.
+ * This works (roughly) the same way as Linux's.
  *
  *   %pUb:   01020304-0506-0708-090a-0b0c0d0e0f10
+ *   %pUB:   01020304-0506-0708-090A-0B0C0D0E0F10
  *   %pUl:   04030201-0605-0807-090a-0b0c0d0e0f10
+ *   %pUL:   04030201-0605-0807-090A-0B0C0D0E0F10
+ *   %pUs:   GUID text representation if known or fallback to %pUl
  */
 static char *uuid_string(char *buf, char *end, u8 *addr, int field_width,
                         int precision, int flags, const char *fmt)
 {
        char uuid[UUID_STR_LEN + 1];
-       int str_format = UUID_STR_FORMAT_STD;
+       int str_format;
+       const char *str;
 
        switch (*(++fmt)) {
        case 'L':
+               str_format = UUID_STR_FORMAT_GUID | UUID_STR_UPPER_CASE;
+               break;
        case 'l':
                str_format = UUID_STR_FORMAT_GUID;
                break;
        case 'B':
-       case 'b':
-               /* this is the default */
+               str_format = UUID_STR_FORMAT_STD | UUID_STR_UPPER_CASE;
+               break;
+       case 's':
+               str = uuid_guid_get_str(addr);
+               if (str)
+                       return string(buf, end, str,
+                                     field_width, precision, flags);
+               str_format = UUID_STR_FORMAT_GUID;
                break;
        default:
+               str_format = UUID_STR_FORMAT_STD;
                break;
        }
 
@@ -431,9 +441,9 @@ static char *uuid_string(char *buf, char *end, u8 *addr, int field_width,
  * - 'i' [46] for 'raw' IPv4/IPv6 addresses, IPv6 omits the colons, IPv4 is
  *       currently the same
  *
- * Note: The difference between 'S' and 'F' is that on ia64 and ppc64
- * function pointers are really function descriptors, which contain a
- * pointer to the real address.
+ * Note: IPv6 support is currently if(0)'ed out. If you ever need
+ * %pI6, please add an IPV6 Kconfig knob, make your code select or
+ * depend on that, and change the 0 below to CONFIG_IS_ENABLED(IPV6).
  */
 static char *pointer(const char *fmt, char *buf, char *end, void *ptr,
                int field_width, int precision, int flags)
@@ -452,12 +462,11 @@ static char *pointer(const char *fmt, char *buf, char *end, void *ptr,
 
        switch (*fmt) {
 /* Device paths only exist in the EFI context. */
-#if CONFIG_IS_ENABLED(EFI_LOADER) && !defined(API_BUILD)
+#if CONFIG_IS_ENABLED(EFI_DEVICE_PATH_TO_TEXT) && !defined(API_BUILD)
        case 'D':
                return device_path_string(buf, end, ptr, field_width,
                                          precision, flags);
 #endif
-#ifdef CONFIG_CMD_NET
        case 'a':
                flags |= SPECIAL | ZEROPAD;
 
@@ -479,7 +488,8 @@ static char *pointer(const char *fmt, char *buf, char *end, void *ptr,
                flags |= SPECIAL;
                /* Fallthrough */
        case 'I':
-               if (fmt[1] == '6')
+               /* %pI6 currently unused */
+               if (0 && fmt[1] == '6')
                        return ip6_addr_string(buf, end, ptr, field_width,
                                               precision, flags);
                if (fmt[1] == '4')
@@ -487,7 +497,6 @@ static char *pointer(const char *fmt, char *buf, char *end, void *ptr,
                                               precision, flags);
                flags &= ~SPECIAL;
                break;
-#endif
 #ifdef CONFIG_LIB_UUID
        case 'U':
                return uuid_string(buf, end, ptr, field_width, precision,
@@ -614,7 +623,8 @@ repeat:
 
                case 's':
 /* U-Boot uses UTF-16 strings in the EFI context only. */
-#if CONFIG_IS_ENABLED(EFI_LOADER) && !defined(API_BUILD)
+#if (CONFIG_IS_ENABLED(EFI_LOADER) || CONFIG_IS_ENABLED(EFI_APP)) && \
+       !defined(API_BUILD)
                        if (qualifier == 'l') {
                                str = string16(str, end, va_arg(args, u16 *),
                                               field_width, precision, flags);
@@ -786,22 +796,11 @@ int printf(const char *fmt, ...)
 {
        va_list args;
        uint i;
-       char printbuffer[CONFIG_SYS_PBSIZE];
 
        va_start(args, fmt);
-
-       /*
-        * For this to work, printbuffer must be larger than
-        * anything we ever want to print.
-        */
-       i = vscnprintf(printbuffer, sizeof(printbuffer), fmt, args);
+       i = vprintf(fmt, args);
        va_end(args);
 
-       /* Handle error */
-       if (i <= 0)
-               return i;
-       /* Print the string */
-       puts(printbuffer);
        return i;
 }
 
@@ -825,11 +824,12 @@ int vprintf(const char *fmt, va_list args)
 }
 #endif
 
+static char local_toa[22];
+
 char *simple_itoa(ulong i)
 {
        /* 21 digits plus null terminator, good for 64-bit or smaller ints */
-       static char local[22];
-       char *p = &local[21];
+       char *p = &local_toa[21];
 
        *p-- = '\0';
        do {
@@ -839,6 +839,21 @@ char *simple_itoa(ulong i)
        return p + 1;
 }
 
+char *simple_xtoa(ulong num)
+{
+       /* 16 digits plus nul terminator, good for 64-bit or smaller ints */
+       char *p = &local_toa[17];
+
+       *--p = '\0';
+       do {
+               p -= 2;
+               hex_byte_pack(p, num & 0xff);
+               num >>= 8;
+       } while (num > 0);
+
+       return p;
+}
+
 /* We don't seem to have %'d in U-Boot */
 void print_grouped_ull(unsigned long long int_val, int digits)
 {
@@ -867,6 +882,22 @@ bool str2long(const char *p, ulong *num)
 {
        char *endptr;
 
-       *num = simple_strtoul(p, &endptr, 16);
+       *num = hextoul(p, &endptr);
        return *p != '\0' && *endptr == '\0';
 }
+
+char *strmhz(char *buf, unsigned long hz)
+{
+       long l, n;
+       long m;
+
+       n = DIV_ROUND_CLOSEST(hz, 1000) / 1000L;
+       l = sprintf(buf, "%ld", n);
+
+       hz -= n * 1000000L;
+       m = DIV_ROUND_CLOSEST(hz, 1000L);
+       if (m != 0)
+               sprintf(buf + l, ".%03ld", m);
+
+       return buf;
+}