1*d18719a4STom Rini /* 2*d18719a4STom Rini * Copyright 2011 The Chromium Authors, All Rights Reserved. 3*d18719a4STom Rini * Copyright 2008 Jon Loeliger, Freescale Semiconductor, Inc. 4*d18719a4STom Rini * 5*d18719a4STom Rini * util_is_printable_string contributed by 6*d18719a4STom Rini * Pantelis Antoniou <pantelis.antoniou AT gmail.com> 7*d18719a4STom Rini * 8*d18719a4STom Rini * This program is free software; you can redistribute it and/or 9*d18719a4STom Rini * modify it under the terms of the GNU General Public License as 10*d18719a4STom Rini * published by the Free Software Foundation; either version 2 of the 11*d18719a4STom Rini * License, or (at your option) any later version. 12*d18719a4STom Rini * 13*d18719a4STom Rini * This program is distributed in the hope that it will be useful, 14*d18719a4STom Rini * but WITHOUT ANY WARRANTY; without even the implied warranty of 15*d18719a4STom Rini * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16*d18719a4STom Rini * General Public License for more details. 17*d18719a4STom Rini * 18*d18719a4STom Rini * You should have received a copy of the GNU General Public License 19*d18719a4STom Rini * along with this program; if not, write to the Free Software 20*d18719a4STom Rini * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 21*d18719a4STom Rini * USA 22*d18719a4STom Rini */ 23*d18719a4STom Rini 24*d18719a4STom Rini #include <ctype.h> 25*d18719a4STom Rini #include <stdio.h> 26*d18719a4STom Rini #include <stdlib.h> 27*d18719a4STom Rini #include <stdarg.h> 28*d18719a4STom Rini #include <string.h> 29*d18719a4STom Rini #include <assert.h> 30*d18719a4STom Rini 31*d18719a4STom Rini #include <errno.h> 32*d18719a4STom Rini #include <fcntl.h> 33*d18719a4STom Rini #include <unistd.h> 34*d18719a4STom Rini 35*d18719a4STom Rini #include "libfdt.h" 36*d18719a4STom Rini #include "util.h" 37*d18719a4STom Rini #include "version_gen.h" 38*d18719a4STom Rini 39*d18719a4STom Rini char *xstrdup(const char *s) 40*d18719a4STom Rini { 41*d18719a4STom Rini int len = strlen(s) + 1; 42*d18719a4STom Rini char *d = xmalloc(len); 43*d18719a4STom Rini 44*d18719a4STom Rini memcpy(d, s, len); 45*d18719a4STom Rini 46*d18719a4STom Rini return d; 47*d18719a4STom Rini } 48*d18719a4STom Rini 49*d18719a4STom Rini /* based in part from (3) vsnprintf */ 50*d18719a4STom Rini int xasprintf(char **strp, const char *fmt, ...) 51*d18719a4STom Rini { 52*d18719a4STom Rini int n, size = 128; /* start with 128 bytes */ 53*d18719a4STom Rini char *p; 54*d18719a4STom Rini va_list ap; 55*d18719a4STom Rini 56*d18719a4STom Rini /* initial pointer is NULL making the fist realloc to be malloc */ 57*d18719a4STom Rini p = NULL; 58*d18719a4STom Rini while (1) { 59*d18719a4STom Rini p = xrealloc(p, size); 60*d18719a4STom Rini 61*d18719a4STom Rini /* Try to print in the allocated space. */ 62*d18719a4STom Rini va_start(ap, fmt); 63*d18719a4STom Rini n = vsnprintf(p, size, fmt, ap); 64*d18719a4STom Rini va_end(ap); 65*d18719a4STom Rini 66*d18719a4STom Rini /* If that worked, return the string. */ 67*d18719a4STom Rini if (n > -1 && n < size) 68*d18719a4STom Rini break; 69*d18719a4STom Rini /* Else try again with more space. */ 70*d18719a4STom Rini if (n > -1) /* glibc 2.1 */ 71*d18719a4STom Rini size = n + 1; /* precisely what is needed */ 72*d18719a4STom Rini else /* glibc 2.0 */ 73*d18719a4STom Rini size *= 2; /* twice the old size */ 74*d18719a4STom Rini } 75*d18719a4STom Rini *strp = p; 76*d18719a4STom Rini return strlen(p); 77*d18719a4STom Rini } 78*d18719a4STom Rini 79*d18719a4STom Rini char *join_path(const char *path, const char *name) 80*d18719a4STom Rini { 81*d18719a4STom Rini int lenp = strlen(path); 82*d18719a4STom Rini int lenn = strlen(name); 83*d18719a4STom Rini int len; 84*d18719a4STom Rini int needslash = 1; 85*d18719a4STom Rini char *str; 86*d18719a4STom Rini 87*d18719a4STom Rini len = lenp + lenn + 2; 88*d18719a4STom Rini if ((lenp > 0) && (path[lenp-1] == '/')) { 89*d18719a4STom Rini needslash = 0; 90*d18719a4STom Rini len--; 91*d18719a4STom Rini } 92*d18719a4STom Rini 93*d18719a4STom Rini str = xmalloc(len); 94*d18719a4STom Rini memcpy(str, path, lenp); 95*d18719a4STom Rini if (needslash) { 96*d18719a4STom Rini str[lenp] = '/'; 97*d18719a4STom Rini lenp++; 98*d18719a4STom Rini } 99*d18719a4STom Rini memcpy(str+lenp, name, lenn+1); 100*d18719a4STom Rini return str; 101*d18719a4STom Rini } 102*d18719a4STom Rini 103*d18719a4STom Rini bool util_is_printable_string(const void *data, int len) 104*d18719a4STom Rini { 105*d18719a4STom Rini const char *s = data; 106*d18719a4STom Rini const char *ss, *se; 107*d18719a4STom Rini 108*d18719a4STom Rini /* zero length is not */ 109*d18719a4STom Rini if (len == 0) 110*d18719a4STom Rini return 0; 111*d18719a4STom Rini 112*d18719a4STom Rini /* must terminate with zero */ 113*d18719a4STom Rini if (s[len - 1] != '\0') 114*d18719a4STom Rini return 0; 115*d18719a4STom Rini 116*d18719a4STom Rini se = s + len; 117*d18719a4STom Rini 118*d18719a4STom Rini while (s < se) { 119*d18719a4STom Rini ss = s; 120*d18719a4STom Rini while (s < se && *s && isprint((unsigned char)*s)) 121*d18719a4STom Rini s++; 122*d18719a4STom Rini 123*d18719a4STom Rini /* not zero, or not done yet */ 124*d18719a4STom Rini if (*s != '\0' || s == ss) 125*d18719a4STom Rini return 0; 126*d18719a4STom Rini 127*d18719a4STom Rini s++; 128*d18719a4STom Rini } 129*d18719a4STom Rini 130*d18719a4STom Rini return 1; 131*d18719a4STom Rini } 132*d18719a4STom Rini 133*d18719a4STom Rini /* 134*d18719a4STom Rini * Parse a octal encoded character starting at index i in string s. The 135*d18719a4STom Rini * resulting character will be returned and the index i will be updated to 136*d18719a4STom Rini * point at the character directly after the end of the encoding, this may be 137*d18719a4STom Rini * the '\0' terminator of the string. 138*d18719a4STom Rini */ 139*d18719a4STom Rini static char get_oct_char(const char *s, int *i) 140*d18719a4STom Rini { 141*d18719a4STom Rini char x[4]; 142*d18719a4STom Rini char *endx; 143*d18719a4STom Rini long val; 144*d18719a4STom Rini 145*d18719a4STom Rini x[3] = '\0'; 146*d18719a4STom Rini strncpy(x, s + *i, 3); 147*d18719a4STom Rini 148*d18719a4STom Rini val = strtol(x, &endx, 8); 149*d18719a4STom Rini 150*d18719a4STom Rini assert(endx > x); 151*d18719a4STom Rini 152*d18719a4STom Rini (*i) += endx - x; 153*d18719a4STom Rini return val; 154*d18719a4STom Rini } 155*d18719a4STom Rini 156*d18719a4STom Rini /* 157*d18719a4STom Rini * Parse a hexadecimal encoded character starting at index i in string s. The 158*d18719a4STom Rini * resulting character will be returned and the index i will be updated to 159*d18719a4STom Rini * point at the character directly after the end of the encoding, this may be 160*d18719a4STom Rini * the '\0' terminator of the string. 161*d18719a4STom Rini */ 162*d18719a4STom Rini static char get_hex_char(const char *s, int *i) 163*d18719a4STom Rini { 164*d18719a4STom Rini char x[3]; 165*d18719a4STom Rini char *endx; 166*d18719a4STom Rini long val; 167*d18719a4STom Rini 168*d18719a4STom Rini x[2] = '\0'; 169*d18719a4STom Rini strncpy(x, s + *i, 2); 170*d18719a4STom Rini 171*d18719a4STom Rini val = strtol(x, &endx, 16); 172*d18719a4STom Rini if (!(endx > x)) 173*d18719a4STom Rini die("\\x used with no following hex digits\n"); 174*d18719a4STom Rini 175*d18719a4STom Rini (*i) += endx - x; 176*d18719a4STom Rini return val; 177*d18719a4STom Rini } 178*d18719a4STom Rini 179*d18719a4STom Rini char get_escape_char(const char *s, int *i) 180*d18719a4STom Rini { 181*d18719a4STom Rini char c = s[*i]; 182*d18719a4STom Rini int j = *i + 1; 183*d18719a4STom Rini char val; 184*d18719a4STom Rini 185*d18719a4STom Rini switch (c) { 186*d18719a4STom Rini case 'a': 187*d18719a4STom Rini val = '\a'; 188*d18719a4STom Rini break; 189*d18719a4STom Rini case 'b': 190*d18719a4STom Rini val = '\b'; 191*d18719a4STom Rini break; 192*d18719a4STom Rini case 't': 193*d18719a4STom Rini val = '\t'; 194*d18719a4STom Rini break; 195*d18719a4STom Rini case 'n': 196*d18719a4STom Rini val = '\n'; 197*d18719a4STom Rini break; 198*d18719a4STom Rini case 'v': 199*d18719a4STom Rini val = '\v'; 200*d18719a4STom Rini break; 201*d18719a4STom Rini case 'f': 202*d18719a4STom Rini val = '\f'; 203*d18719a4STom Rini break; 204*d18719a4STom Rini case 'r': 205*d18719a4STom Rini val = '\r'; 206*d18719a4STom Rini break; 207*d18719a4STom Rini case '0': 208*d18719a4STom Rini case '1': 209*d18719a4STom Rini case '2': 210*d18719a4STom Rini case '3': 211*d18719a4STom Rini case '4': 212*d18719a4STom Rini case '5': 213*d18719a4STom Rini case '6': 214*d18719a4STom Rini case '7': 215*d18719a4STom Rini j--; /* need to re-read the first digit as 216*d18719a4STom Rini * part of the octal value */ 217*d18719a4STom Rini val = get_oct_char(s, &j); 218*d18719a4STom Rini break; 219*d18719a4STom Rini case 'x': 220*d18719a4STom Rini val = get_hex_char(s, &j); 221*d18719a4STom Rini break; 222*d18719a4STom Rini default: 223*d18719a4STom Rini val = c; 224*d18719a4STom Rini } 225*d18719a4STom Rini 226*d18719a4STom Rini (*i) = j; 227*d18719a4STom Rini return val; 228*d18719a4STom Rini } 229*d18719a4STom Rini 230*d18719a4STom Rini int utilfdt_read_err_len(const char *filename, char **buffp, off_t *len) 231*d18719a4STom Rini { 232*d18719a4STom Rini int fd = 0; /* assume stdin */ 233*d18719a4STom Rini char *buf = NULL; 234*d18719a4STom Rini off_t bufsize = 1024, offset = 0; 235*d18719a4STom Rini int ret = 0; 236*d18719a4STom Rini 237*d18719a4STom Rini *buffp = NULL; 238*d18719a4STom Rini if (strcmp(filename, "-") != 0) { 239*d18719a4STom Rini fd = open(filename, O_RDONLY); 240*d18719a4STom Rini if (fd < 0) 241*d18719a4STom Rini return errno; 242*d18719a4STom Rini } 243*d18719a4STom Rini 244*d18719a4STom Rini /* Loop until we have read everything */ 245*d18719a4STom Rini buf = xmalloc(bufsize); 246*d18719a4STom Rini do { 247*d18719a4STom Rini /* Expand the buffer to hold the next chunk */ 248*d18719a4STom Rini if (offset == bufsize) { 249*d18719a4STom Rini bufsize *= 2; 250*d18719a4STom Rini buf = xrealloc(buf, bufsize); 251*d18719a4STom Rini } 252*d18719a4STom Rini 253*d18719a4STom Rini ret = read(fd, &buf[offset], bufsize - offset); 254*d18719a4STom Rini if (ret < 0) { 255*d18719a4STom Rini ret = errno; 256*d18719a4STom Rini break; 257*d18719a4STom Rini } 258*d18719a4STom Rini offset += ret; 259*d18719a4STom Rini } while (ret != 0); 260*d18719a4STom Rini 261*d18719a4STom Rini /* Clean up, including closing stdin; return errno on error */ 262*d18719a4STom Rini close(fd); 263*d18719a4STom Rini if (ret) 264*d18719a4STom Rini free(buf); 265*d18719a4STom Rini else 266*d18719a4STom Rini *buffp = buf; 267*d18719a4STom Rini *len = bufsize; 268*d18719a4STom Rini return ret; 269*d18719a4STom Rini } 270*d18719a4STom Rini 271*d18719a4STom Rini int utilfdt_read_err(const char *filename, char **buffp) 272*d18719a4STom Rini { 273*d18719a4STom Rini off_t len; 274*d18719a4STom Rini return utilfdt_read_err_len(filename, buffp, &len); 275*d18719a4STom Rini } 276*d18719a4STom Rini 277*d18719a4STom Rini char *utilfdt_read_len(const char *filename, off_t *len) 278*d18719a4STom Rini { 279*d18719a4STom Rini char *buff; 280*d18719a4STom Rini int ret = utilfdt_read_err_len(filename, &buff, len); 281*d18719a4STom Rini 282*d18719a4STom Rini if (ret) { 283*d18719a4STom Rini fprintf(stderr, "Couldn't open blob from '%s': %s\n", filename, 284*d18719a4STom Rini strerror(ret)); 285*d18719a4STom Rini return NULL; 286*d18719a4STom Rini } 287*d18719a4STom Rini /* Successful read */ 288*d18719a4STom Rini return buff; 289*d18719a4STom Rini } 290*d18719a4STom Rini 291*d18719a4STom Rini char *utilfdt_read(const char *filename) 292*d18719a4STom Rini { 293*d18719a4STom Rini off_t len; 294*d18719a4STom Rini return utilfdt_read_len(filename, &len); 295*d18719a4STom Rini } 296*d18719a4STom Rini 297*d18719a4STom Rini int utilfdt_write_err(const char *filename, const void *blob) 298*d18719a4STom Rini { 299*d18719a4STom Rini int fd = 1; /* assume stdout */ 300*d18719a4STom Rini int totalsize; 301*d18719a4STom Rini int offset; 302*d18719a4STom Rini int ret = 0; 303*d18719a4STom Rini const char *ptr = blob; 304*d18719a4STom Rini 305*d18719a4STom Rini if (strcmp(filename, "-") != 0) { 306*d18719a4STom Rini fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0666); 307*d18719a4STom Rini if (fd < 0) 308*d18719a4STom Rini return errno; 309*d18719a4STom Rini } 310*d18719a4STom Rini 311*d18719a4STom Rini totalsize = fdt_totalsize(blob); 312*d18719a4STom Rini offset = 0; 313*d18719a4STom Rini 314*d18719a4STom Rini while (offset < totalsize) { 315*d18719a4STom Rini ret = write(fd, ptr + offset, totalsize - offset); 316*d18719a4STom Rini if (ret < 0) { 317*d18719a4STom Rini ret = -errno; 318*d18719a4STom Rini break; 319*d18719a4STom Rini } 320*d18719a4STom Rini offset += ret; 321*d18719a4STom Rini } 322*d18719a4STom Rini /* Close the file/stdin; return errno on error */ 323*d18719a4STom Rini if (fd != 1) 324*d18719a4STom Rini close(fd); 325*d18719a4STom Rini return ret < 0 ? -ret : 0; 326*d18719a4STom Rini } 327*d18719a4STom Rini 328*d18719a4STom Rini 329*d18719a4STom Rini int utilfdt_write(const char *filename, const void *blob) 330*d18719a4STom Rini { 331*d18719a4STom Rini int ret = utilfdt_write_err(filename, blob); 332*d18719a4STom Rini 333*d18719a4STom Rini if (ret) { 334*d18719a4STom Rini fprintf(stderr, "Couldn't write blob to '%s': %s\n", filename, 335*d18719a4STom Rini strerror(ret)); 336*d18719a4STom Rini } 337*d18719a4STom Rini return ret ? -1 : 0; 338*d18719a4STom Rini } 339*d18719a4STom Rini 340*d18719a4STom Rini int utilfdt_decode_type(const char *fmt, int *type, int *size) 341*d18719a4STom Rini { 342*d18719a4STom Rini int qualifier = 0; 343*d18719a4STom Rini 344*d18719a4STom Rini if (!*fmt) 345*d18719a4STom Rini return -1; 346*d18719a4STom Rini 347*d18719a4STom Rini /* get the conversion qualifier */ 348*d18719a4STom Rini *size = -1; 349*d18719a4STom Rini if (strchr("hlLb", *fmt)) { 350*d18719a4STom Rini qualifier = *fmt++; 351*d18719a4STom Rini if (qualifier == *fmt) { 352*d18719a4STom Rini switch (*fmt++) { 353*d18719a4STom Rini /* TODO: case 'l': qualifier = 'L'; break;*/ 354*d18719a4STom Rini case 'h': 355*d18719a4STom Rini qualifier = 'b'; 356*d18719a4STom Rini break; 357*d18719a4STom Rini } 358*d18719a4STom Rini } 359*d18719a4STom Rini } 360*d18719a4STom Rini 361*d18719a4STom Rini /* we should now have a type */ 362*d18719a4STom Rini if ((*fmt == '\0') || !strchr("iuxs", *fmt)) 363*d18719a4STom Rini return -1; 364*d18719a4STom Rini 365*d18719a4STom Rini /* convert qualifier (bhL) to byte size */ 366*d18719a4STom Rini if (*fmt != 's') 367*d18719a4STom Rini *size = qualifier == 'b' ? 1 : 368*d18719a4STom Rini qualifier == 'h' ? 2 : 369*d18719a4STom Rini qualifier == 'l' ? 4 : -1; 370*d18719a4STom Rini *type = *fmt++; 371*d18719a4STom Rini 372*d18719a4STom Rini /* that should be it! */ 373*d18719a4STom Rini if (*fmt) 374*d18719a4STom Rini return -1; 375*d18719a4STom Rini return 0; 376*d18719a4STom Rini } 377*d18719a4STom Rini 378*d18719a4STom Rini void utilfdt_print_data(const char *data, int len) 379*d18719a4STom Rini { 380*d18719a4STom Rini int i; 381*d18719a4STom Rini const char *s; 382*d18719a4STom Rini 383*d18719a4STom Rini /* no data, don't print */ 384*d18719a4STom Rini if (len == 0) 385*d18719a4STom Rini return; 386*d18719a4STom Rini 387*d18719a4STom Rini if (util_is_printable_string(data, len)) { 388*d18719a4STom Rini printf(" = "); 389*d18719a4STom Rini 390*d18719a4STom Rini s = data; 391*d18719a4STom Rini do { 392*d18719a4STom Rini printf("\"%s\"", s); 393*d18719a4STom Rini s += strlen(s) + 1; 394*d18719a4STom Rini if (s < data + len) 395*d18719a4STom Rini printf(", "); 396*d18719a4STom Rini } while (s < data + len); 397*d18719a4STom Rini 398*d18719a4STom Rini } else if ((len % 4) == 0) { 399*d18719a4STom Rini const uint32_t *cell = (const uint32_t *)data; 400*d18719a4STom Rini 401*d18719a4STom Rini printf(" = <"); 402*d18719a4STom Rini for (i = 0, len /= 4; i < len; i++) 403*d18719a4STom Rini printf("0x%08x%s", fdt32_to_cpu(cell[i]), 404*d18719a4STom Rini i < (len - 1) ? " " : ""); 405*d18719a4STom Rini printf(">"); 406*d18719a4STom Rini } else { 407*d18719a4STom Rini const unsigned char *p = (const unsigned char *)data; 408*d18719a4STom Rini printf(" = ["); 409*d18719a4STom Rini for (i = 0; i < len; i++) 410*d18719a4STom Rini printf("%02x%s", *p++, i < len - 1 ? " " : ""); 411*d18719a4STom Rini printf("]"); 412*d18719a4STom Rini } 413*d18719a4STom Rini } 414*d18719a4STom Rini 415*d18719a4STom Rini void util_version(void) 416*d18719a4STom Rini { 417*d18719a4STom Rini printf("Version: %s\n", DTC_VERSION); 418*d18719a4STom Rini exit(0); 419*d18719a4STom Rini } 420*d18719a4STom Rini 421*d18719a4STom Rini void util_usage(const char *errmsg, const char *synopsis, 422*d18719a4STom Rini const char *short_opts, struct option const long_opts[], 423*d18719a4STom Rini const char * const opts_help[]) 424*d18719a4STom Rini { 425*d18719a4STom Rini FILE *fp = errmsg ? stderr : stdout; 426*d18719a4STom Rini const char a_arg[] = "<arg>"; 427*d18719a4STom Rini size_t a_arg_len = strlen(a_arg) + 1; 428*d18719a4STom Rini size_t i; 429*d18719a4STom Rini int optlen; 430*d18719a4STom Rini 431*d18719a4STom Rini fprintf(fp, 432*d18719a4STom Rini "Usage: %s\n" 433*d18719a4STom Rini "\n" 434*d18719a4STom Rini "Options: -[%s]\n", synopsis, short_opts); 435*d18719a4STom Rini 436*d18719a4STom Rini /* prescan the --long opt length to auto-align */ 437*d18719a4STom Rini optlen = 0; 438*d18719a4STom Rini for (i = 0; long_opts[i].name; ++i) { 439*d18719a4STom Rini /* +1 is for space between --opt and help text */ 440*d18719a4STom Rini int l = strlen(long_opts[i].name) + 1; 441*d18719a4STom Rini if (long_opts[i].has_arg == a_argument) 442*d18719a4STom Rini l += a_arg_len; 443*d18719a4STom Rini if (optlen < l) 444*d18719a4STom Rini optlen = l; 445*d18719a4STom Rini } 446*d18719a4STom Rini 447*d18719a4STom Rini for (i = 0; long_opts[i].name; ++i) { 448*d18719a4STom Rini /* helps when adding new applets or options */ 449*d18719a4STom Rini assert(opts_help[i] != NULL); 450*d18719a4STom Rini 451*d18719a4STom Rini /* first output the short flag if it has one */ 452*d18719a4STom Rini if (long_opts[i].val > '~') 453*d18719a4STom Rini fprintf(fp, " "); 454*d18719a4STom Rini else 455*d18719a4STom Rini fprintf(fp, " -%c, ", long_opts[i].val); 456*d18719a4STom Rini 457*d18719a4STom Rini /* then the long flag */ 458*d18719a4STom Rini if (long_opts[i].has_arg == no_argument) 459*d18719a4STom Rini fprintf(fp, "--%-*s", optlen, long_opts[i].name); 460*d18719a4STom Rini else 461*d18719a4STom Rini fprintf(fp, "--%s %s%*s", long_opts[i].name, a_arg, 462*d18719a4STom Rini (int)(optlen - strlen(long_opts[i].name) - a_arg_len), ""); 463*d18719a4STom Rini 464*d18719a4STom Rini /* finally the help text */ 465*d18719a4STom Rini fprintf(fp, "%s\n", opts_help[i]); 466*d18719a4STom Rini } 467*d18719a4STom Rini 468*d18719a4STom Rini if (errmsg) { 469*d18719a4STom Rini fprintf(fp, "\nError: %s\n", errmsg); 470*d18719a4STom Rini exit(EXIT_FAILURE); 471*d18719a4STom Rini } else 472*d18719a4STom Rini exit(EXIT_SUCCESS); 473*d18719a4STom Rini } 474