cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

util.c (8701B)


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