1 // Copyright 2016 The Fuchsia Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "util.h"
6
7 #pragma GCC visibility push(hidden)
8
9 #include <assert.h>
10 #include <zircon/syscalls.h>
11 #include <zircon/syscalls/log.h>
12 #include <stdarg.h>
13 #include <string.h>
14
15 #pragma GCC visibility pop
16
17 #define LOG_PREFIX "userboot: "
18 #define LOG_WRITE_FAIL \
19 (LOG_PREFIX "Error printing error message. No error message printed.\n")
20
hexstring(char * s,size_t len,uint64_t n)21 static char* hexstring(char* s, size_t len, uint64_t n) {
22 char tmp[16];
23 char* hex = tmp;
24 do {
25 *hex++ = "0123456789abcdef"[n & 15];
26 n >>= 4;
27 } while (n);
28
29 if (len > 2) {
30 *s++ = '0';
31 *s++ = 'x';
32 len -= 2;
33 }
34
35 while ((hex > tmp) && (len > 0)) {
36 *s++ = *--hex;
37 len--;
38 }
39 return s;
40 }
41
u64string(char * s,size_t len,uint64_t n)42 static char* u64string(char* s, size_t len, uint64_t n) {
43 char tmp[21]; // strlen(maxint64) + 1
44 char* dec = tmp;
45 do {
46 *dec++ = "0123456789"[n % 10];
47 n /= 10;
48 } while (n > 0);
49
50 while ((dec > tmp) && (len > 0)) {
51 *s++ = *--dec;
52 len--;
53 }
54 return s;
55 }
56
i64string(char * s,size_t len,int64_t n)57 static char* i64string(char* s, size_t len, int64_t n) {
58 if (n < 0) {
59 // this will never be called with len < 1 so we
60 // don't need to check for len
61 n = -n;
62 *s++ = '-';
63 len--;
64 }
65 return u64string(s, len, n);
66 }
67
vprintl(zx_handle_t log,const char * fmt,va_list ap)68 void vprintl(zx_handle_t log, const char* fmt, va_list ap) {
69 char buffer[ZX_LOG_RECORD_MAX - sizeof(zx_log_record_t)];
70 static_assert(sizeof(LOG_PREFIX) < sizeof(buffer), "buffer too small");
71
72 memcpy(buffer, LOG_PREFIX, sizeof(LOG_PREFIX) - 1);
73 char* p = &buffer[sizeof(LOG_PREFIX) - 1];
74
75 size_t avail;
76 const char* s;
77 uint64_t n;
78 int64_t i;
79
80 while (*fmt && (avail = (size_t)(&buffer[sizeof(buffer)] - p))) {
81 if (*fmt != '%') {
82 *p++ = *fmt++;
83 continue;
84 }
85 switch (*++fmt) {
86 case 's':
87 s = va_arg(ap, const char*);
88 while (avail && *s) {
89 *p++ = *s++;
90 avail--;
91 }
92 break;
93 case '.':
94 fmt++;
95 if (*fmt != '*')
96 goto bad_format;
97 fmt++;
98 if (*fmt != 's')
99 goto bad_format;
100 i = va_arg(ap, int);
101 s = va_arg(ap, const char*);
102 while (avail && *s && i != 0) {
103 *p++ = *s++;
104 avail--;
105 if (i > 0)
106 --i;
107 }
108 break;
109 case 'z':
110 fmt++;
111 switch (*fmt) {
112 case 'u':
113 n = va_arg(ap, uint64_t);
114 goto u64print;
115 case 'd':
116 i = va_arg(ap, int64_t);
117 goto i64print;
118 case 'x':
119 n = va_arg(ap, uint64_t);
120 goto x64print;
121 default:
122 goto bad_format;
123 }
124 break;
125 case 'p':
126 n = va_arg(ap, uint64_t);
127 goto x64print;
128 case 'u':
129 n = va_arg(ap, uint32_t);
130 u64print:
131 p = u64string(p, avail, n);
132 break;
133 case 'd':
134 i = va_arg(ap, int32_t);
135 i64print:
136 p = i64string(p, avail, i);
137 break;
138 case 'x':
139 n = va_arg(ap, uint32_t);
140 x64print:
141 p = hexstring(p, avail, n);
142 break;
143 default:
144 bad_format:
145 printl(log, "printl: invalid fmt char 0x%x", *fmt);
146 zx_process_exit(-1);
147 }
148 fmt++;
149 }
150
151 if ((log == ZX_HANDLE_INVALID) ||
152 (zx_debuglog_write(log, 0, buffer, p - buffer) != ZX_OK)) {
153 zx_debug_write(buffer, p - buffer);
154 zx_debug_write("\n", 1);
155 }
156 }
157
printl(zx_handle_t log,const char * fmt,...)158 void printl(zx_handle_t log, const char* fmt, ...) {
159 va_list ap;
160 va_start(ap, fmt);
161 vprintl(log, fmt, ap);
162 va_end(ap);
163 }
164
fail(zx_handle_t log,const char * fmt,...)165 void fail(zx_handle_t log, const char* fmt, ...) {
166 va_list ap;
167 va_start(ap, fmt);
168 vprintl(log, fmt, ap);
169 va_end(ap);
170 zx_process_exit(-1);
171 }
172