X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=lib%2Fvsprintf.c;h=425f2f53f79770d53047a27893aad6b0b776216b;hb=4411652aead3509ce497e4598f533e2b7e4f4ba0;hp=24167a135c020b9629181bb01c369e762d293d80;hpb=9cddb4fe0266484aab9babdd2ebe650021644ea9;p=oweals%2Fu-boot.git diff --git a/lib/vsprintf.c b/lib/vsprintf.c index 24167a135c..425f2f53f7 100644 --- a/lib/vsprintf.c +++ b/lib/vsprintf.c @@ -11,14 +11,17 @@ * from hush: simple_itoa() was lifted from boa-0.93.15 */ +#include +#include +#include +#include +#include #include +#include +#include #include #include -#include -#include - -#include #define noinline __attribute__((noinline)) /* we use this so that we can do without the ctype library */ @@ -141,7 +144,6 @@ static noinline char *put_dec(char *buf, uint64_t num) #define SMALL 32 /* Must be 32 == 0x20 */ #define SPECIAL 64 /* 0x */ -#ifdef CONFIG_SYS_VSNPRINTF /* * Macro to add a new character to our output string, but only if it will * fit. The macro moves to the next character position in the output string. @@ -151,9 +153,6 @@ static noinline char *put_dec(char *buf, uint64_t num) *(str) = (ch); \ ++str; \ } while (0) -#else -#define ADDCH(str, ch) (*(str)++ = (ch)) -#endif static char *number(char *buf, char *end, u64 num, int base, int size, int precision, int type) @@ -274,18 +273,51 @@ static char *string(char *buf, char *end, char *s, int field_width, return buf; } -#ifdef CONFIG_CMD_NET -static const char hex_asc[] = "0123456789abcdef"; -#define hex_asc_lo(x) hex_asc[((x) & 0x0f)] -#define hex_asc_hi(x) hex_asc[((x) & 0xf0) >> 4] +/* 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) +{ + const u16 *str = s ? s : L""; + ssize_t i, len = utf16_strnlen(str, precision); + + if (!(flags & LEFT)) + for (; len < field_width; --field_width) + ADDCH(buf, ' '); + for (i = 0; i < len && buf + utf16_utf8_strnlen(str, 1) <= end; ++i) { + s32 s = utf16_get(&str); -static inline char *pack_hex_byte(char *buf, u8 byte) + if (s < 0) + s = '?'; + utf8_put(s, &buf); + } + for (; len < field_width; --field_width) + ADDCH(buf, ' '); + 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) { - *buf++ = hex_asc_hi(byte); - *buf++ = hex_asc_lo(byte); + u16 *str; + + /* If dp == NULL output the string '' */ + if (!dp) + return string16(buf, end, dp, field_width, precision, flags); + + str = efi_dp_str((struct efi_device_path *)dp); + if (!str) + return ERR_PTR(-ENOMEM); + + buf = string16(buf, end, str, field_width, precision, flags); + efi_free_pool(str); return buf; } +#endif +#endif +#ifdef CONFIG_CMD_NET static char *mac_address_string(char *buf, char *end, u8 *addr, int field_width, int precision, int flags) { @@ -295,7 +327,7 @@ static char *mac_address_string(char *buf, char *end, u8 *addr, int field_width, int i; for (i = 0; i < 6; i++) { - p = pack_hex_byte(p, addr[i]); + p = hex_byte_pack(p, addr[i]); if (!(flags & SPECIAL) && i != 5) *p++ = ':'; } @@ -314,8 +346,8 @@ static char *ip6_addr_string(char *buf, char *end, u8 *addr, int field_width, int i; for (i = 0; i < 8; i++) { - p = pack_hex_byte(p, addr[2 * i]); - p = pack_hex_byte(p, addr[2 * i + 1]); + p = hex_byte_pack(p, addr[2 * i]); + p = hex_byte_pack(p, addr[2 * i + 1]); if (!(flags & SPECIAL) && i != 7) *p++ = ':'; } @@ -349,6 +381,45 @@ static char *ip4_addr_string(char *buf, char *end, u8 *addr, int field_width, } #endif +#ifdef CONFIG_LIB_UUID +/* + * 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 + */ +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; + + 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': + str_format = UUID_STR_FORMAT_STD | UUID_STR_UPPER_CASE; + break; + default: + str_format = UUID_STR_FORMAT_STD; + break; + } + + if (addr) + uuid_bin_to_str(addr, uuid, str_format); + else + strcpy(uuid, ""); + + return string(buf, end, uuid, field_width, precision, flags); +} +#endif + /* * Show a '%p' thing. A kernel extension is that the '%p' is followed * by an extra set of alphanumeric characters that are extended format @@ -382,8 +453,13 @@ static char *pointer(const char *fmt, char *buf, char *end, void *ptr, flags); #endif -#ifdef CONFIG_CMD_NET switch (*fmt) { +/* Device paths only exist in the EFI context. */ +#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 case 'a': flags |= SPECIAL | ZEROPAD; @@ -395,6 +471,7 @@ static char *pointer(const char *fmt, char *buf, char *end, void *ptr, break; } break; +#ifdef CONFIG_CMD_NET case 'm': flags |= SPECIAL; /* Fallthrough */ @@ -413,8 +490,15 @@ 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, + flags, fmt); +#endif + default: + break; + } flags |= SMALL; if (field_width == -1) { field_width = 2*sizeof(void *); @@ -441,13 +525,11 @@ static int vsnprintf_internal(char *buf, size_t size, const char *fmt, /* 't' added for ptrdiff_t */ char *end = buf + size; -#ifdef CONFIG_SYS_VSNPRINTF /* Make sure end is always >= buf - do we want this in U-Boot? */ if (end < buf) { end = ((void *)-1); size = end - buf; } -#endif str = buf; for (; *fmt ; ++fmt) { @@ -534,14 +616,25 @@ repeat: continue; case 's': - str = string(str, end, va_arg(args, char *), - field_width, precision, flags); +/* U-Boot uses UTF-16 strings in the EFI context only. */ +#if CONFIG_IS_ENABLED(EFI_LOADER) && !defined(API_BUILD) + if (qualifier == 'l') { + str = string16(str, end, va_arg(args, u16 *), + field_width, precision, flags); + } else +#endif + { + str = string(str, end, va_arg(args, char *), + field_width, precision, flags); + } continue; case 'p': str = pointer(fmt + 1, str, end, va_arg(args, void *), field_width, precision, flags); + if (IS_ERR(str)) + return PTR_ERR(str); /* Skip all alphanumeric pointer suffixes */ while (isalnum(fmt[1])) fmt++; @@ -609,21 +702,16 @@ repeat: flags); } -#ifdef CONFIG_SYS_VSNPRINTF if (size > 0) { ADDCH(str, '\0'); if (str > end) end[-1] = '\0'; --str; } -#else - *str = '\0'; -#endif /* the trailing null byte doesn't count towards the total */ return str - buf; } -#ifdef CONFIG_SYS_VSNPRINTF int vsnprintf(char *buf, size_t size, const char *fmt, va_list args) { @@ -666,7 +754,6 @@ int scnprintf(char *buf, size_t size, const char *fmt, ...) return i; } -#endif /* CONFIG_SYS_VSNPRINT */ /** * Format a string and place it in a buffer (va_list version) @@ -697,6 +784,7 @@ int sprintf(char *buf, const char *fmt, ...) return i; } +#if CONFIG_IS_ENABLED(PRINTF) int printf(const char *fmt, ...) { va_list args; @@ -712,6 +800,9 @@ int printf(const char *fmt, ...) i = vscnprintf(printbuffer, sizeof(printbuffer), fmt, args); va_end(args); + /* Handle error */ + if (i <= 0) + return i; /* Print the string */ puts(printbuffer); return i; @@ -728,19 +819,14 @@ int vprintf(const char *fmt, va_list args) */ i = vscnprintf(printbuffer, sizeof(printbuffer), fmt, args); + /* Handle error */ + if (i <= 0) + return i; /* Print the string */ puts(printbuffer); return i; } - - -void __assert_fail(const char *assertion, const char *file, unsigned line, - const char *function) -{ - /* This will not return */ - panic("%s:%u: %s: Assertion `%s' failed.", file, line, function, - assertion); -} +#endif char *simple_itoa(ulong i) {