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

fdtoverlay.c (4345B)


      1// SPDX-License-Identifier: GPL-2.0-or-later
      2/*
      3 * Copyright (c) 2017 Konsulko Group Inc. All rights reserved.
      4 *
      5 * Author:
      6 *	 Pantelis Antoniou <pantelis.antoniou@konsulko.com>
      7 */
      8
      9#include <assert.h>
     10#include <ctype.h>
     11#include <getopt.h>
     12#include <stdio.h>
     13#include <stdlib.h>
     14#include <string.h>
     15#include <inttypes.h>
     16
     17#include <libfdt.h>
     18
     19#include "util.h"
     20
     21#define BUF_INCREMENT	65536
     22
     23/* Usage related data. */
     24static const char usage_synopsis[] =
     25	"apply a number of overlays to a base blob\n"
     26	"	fdtoverlay <options> [<overlay.dtbo> [<overlay.dtbo>]]\n"
     27	"\n"
     28	USAGE_TYPE_MSG;
     29static const char usage_short_opts[] = "i:o:v" USAGE_COMMON_SHORT_OPTS;
     30static struct option const usage_long_opts[] = {
     31	{"input",            required_argument, NULL, 'i'},
     32	{"output",	     required_argument, NULL, 'o'},
     33	{"verbose",	           no_argument, NULL, 'v'},
     34	USAGE_COMMON_LONG_OPTS,
     35};
     36static const char * const usage_opts_help[] = {
     37	"Input base DT blob",
     38	"Output DT blob",
     39	"Verbose messages",
     40	USAGE_COMMON_OPTS_HELP
     41};
     42
     43int verbose = 0;
     44
     45static void *apply_one(char *base, const char *overlay, size_t *buf_len,
     46		       const char *name)
     47{
     48	char *tmp = NULL;
     49	char *tmpo;
     50	int ret;
     51
     52	/*
     53	 * We take a copies first, because a a failed apply can trash
     54	 * both the base blob and the overlay
     55	 */
     56	tmpo = xmalloc(fdt_totalsize(overlay));
     57
     58	do {
     59		tmp = xrealloc(tmp, *buf_len);
     60		ret = fdt_open_into(base, tmp, *buf_len);
     61		if (ret) {
     62			fprintf(stderr,
     63				"\nFailed to make temporary copy: %s\n",
     64				fdt_strerror(ret));
     65			goto fail;
     66		}
     67
     68		memcpy(tmpo, overlay, fdt_totalsize(overlay));
     69
     70		ret = fdt_overlay_apply(tmp, tmpo);
     71		if (ret == -FDT_ERR_NOSPACE) {
     72			*buf_len += BUF_INCREMENT;
     73		}
     74	} while (ret == -FDT_ERR_NOSPACE);
     75
     76	if (ret) {
     77		fprintf(stderr, "\nFailed to apply '%s': %s\n",
     78			name, fdt_strerror(ret));
     79		goto fail;
     80	}
     81
     82	free(base);
     83	free(tmpo);
     84	return tmp;
     85
     86fail:
     87	free(tmpo);
     88	if (tmp)
     89		free(tmp);
     90
     91	return NULL;
     92}
     93static int do_fdtoverlay(const char *input_filename,
     94			 const char *output_filename,
     95			 int argc, char *argv[])
     96{
     97	char *blob = NULL;
     98	char **ovblob = NULL;
     99	size_t buf_len;
    100	int i, ret = -1;
    101
    102	blob = utilfdt_read(input_filename, &buf_len);
    103	if (!blob) {
    104		fprintf(stderr, "\nFailed to read '%s'\n", input_filename);
    105		goto out_err;
    106	}
    107	if (fdt_totalsize(blob) > buf_len) {
    108		fprintf(stderr,
    109 "\nBase blob is incomplete (%lu / %" PRIu32 " bytes read)\n",
    110			(unsigned long)buf_len, fdt_totalsize(blob));
    111		goto out_err;
    112	}
    113
    114	/* allocate blob pointer array */
    115	ovblob = xmalloc(sizeof(*ovblob) * argc);
    116	memset(ovblob, 0, sizeof(*ovblob) * argc);
    117
    118	/* read and keep track of the overlay blobs */
    119	for (i = 0; i < argc; i++) {
    120		size_t ov_len;
    121		ovblob[i] = utilfdt_read(argv[i], &ov_len);
    122		if (!ovblob[i]) {
    123			fprintf(stderr, "\nFailed to read '%s'\n", argv[i]);
    124			goto out_err;
    125		}
    126		if (fdt_totalsize(ovblob[i]) > ov_len) {
    127			fprintf(stderr,
    128"\nOverlay '%s' is incomplete (%lu / %" PRIu32 " bytes read)\n",
    129				argv[i], (unsigned long)ov_len,
    130				fdt_totalsize(ovblob[i]));
    131			goto out_err;
    132		}
    133	}
    134
    135	buf_len = fdt_totalsize(blob);
    136
    137	/* apply the overlays in sequence */
    138	for (i = 0; i < argc; i++) {
    139		blob = apply_one(blob, ovblob[i], &buf_len, argv[i]);
    140		if (!blob)
    141			goto out_err;
    142	}
    143
    144	fdt_pack(blob);
    145	ret = utilfdt_write(output_filename, blob);
    146	if (ret)
    147		fprintf(stderr, "\nFailed to write '%s'\n",
    148			output_filename);
    149
    150out_err:
    151	if (ovblob) {
    152		for (i = 0; i < argc; i++) {
    153			if (ovblob[i])
    154				free(ovblob[i]);
    155		}
    156		free(ovblob);
    157	}
    158	free(blob);
    159
    160	return ret;
    161}
    162
    163int main(int argc, char *argv[])
    164{
    165	int opt, i;
    166	char *input_filename = NULL;
    167	char *output_filename = NULL;
    168
    169	while ((opt = util_getopt_long()) != EOF) {
    170		switch (opt) {
    171		case_USAGE_COMMON_FLAGS
    172
    173		case 'i':
    174			input_filename = optarg;
    175			break;
    176		case 'o':
    177			output_filename = optarg;
    178			break;
    179		case 'v':
    180			verbose = 1;
    181			break;
    182		}
    183	}
    184
    185	if (!input_filename)
    186		usage("missing input file");
    187
    188	if (!output_filename)
    189		usage("missing output file");
    190
    191	argv += optind;
    192	argc -= optind;
    193
    194	if (argc <= 0)
    195		usage("missing overlay file(s)");
    196
    197	if (verbose) {
    198		printf("input  = %s\n", input_filename);
    199		printf("output = %s\n", output_filename);
    200		for (i = 0; i < argc; i++)
    201			printf("overlay[%d] = %s\n", i, argv[i]);
    202	}
    203
    204	if (do_fdtoverlay(input_filename, output_filename, argc, argv))
    205		return 1;
    206
    207	return 0;
    208}