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

libfdt-wrapper.c (4520B)


      1// SPDX-License-Identifier: GPL-2.0-or-later
      2/*
      3 * This file does the necessary interface mapping between the bootwrapper
      4 * device tree operations and the interface provided by shared source
      5 * files flatdevicetree.[ch].
      6 *
      7 * Copyright 2007 David Gibson, IBM Corporation.
      8 */
      9
     10#include <stddef.h>
     11#include <stdio.h>
     12#include <page.h>
     13#include <libfdt.h>
     14#include "ops.h"
     15
     16#define DEBUG	0
     17#define BAD_ERROR(err)	(((err) < 0) \
     18			 && ((err) != -FDT_ERR_NOTFOUND) \
     19			 && ((err) != -FDT_ERR_EXISTS))
     20
     21#define check_err(err) \
     22	({ \
     23		if (BAD_ERROR(err) || ((err < 0) && DEBUG)) \
     24			printf("%s():%d  %s\n\r", __func__, __LINE__, \
     25			       fdt_strerror(err)); \
     26		if (BAD_ERROR(err)) \
     27			exit(); \
     28		(err < 0) ? -1 : 0; \
     29	})
     30
     31#define offset_devp(off)	\
     32	({ \
     33		unsigned long _offset = (off); \
     34		check_err(_offset) ? NULL : (void *)(_offset+1); \
     35	})
     36
     37#define devp_offset_find(devp)	(((unsigned long)(devp))-1)
     38#define devp_offset(devp)	(devp ? ((unsigned long)(devp))-1 : 0)
     39
     40static void *fdt;
     41static void *buf; /* = NULL */
     42
     43#define EXPAND_GRANULARITY	1024
     44
     45static void expand_buf(int minexpand)
     46{
     47	int size = fdt_totalsize(fdt);
     48	int rc;
     49
     50	size = _ALIGN(size + minexpand, EXPAND_GRANULARITY);
     51	buf = platform_ops.realloc(buf, size);
     52	if (!buf)
     53		fatal("Couldn't find %d bytes to expand device tree\n\r", size);
     54	rc = fdt_open_into(fdt, buf, size);
     55	if (rc != 0)
     56		fatal("Couldn't expand fdt into new buffer: %s\n\r",
     57		      fdt_strerror(rc));
     58
     59	fdt = buf;
     60}
     61
     62static void *fdt_wrapper_finddevice(const char *path)
     63{
     64	return offset_devp(fdt_path_offset(fdt, path));
     65}
     66
     67static int fdt_wrapper_getprop(const void *devp, const char *name,
     68			       void *buf, const int buflen)
     69{
     70	const void *p;
     71	int len;
     72
     73	p = fdt_getprop(fdt, devp_offset(devp), name, &len);
     74	if (!p)
     75		return check_err(len);
     76	memcpy(buf, p, min(len, buflen));
     77	return len;
     78}
     79
     80static int fdt_wrapper_setprop(const void *devp, const char *name,
     81			       const void *buf, const int len)
     82{
     83	int rc;
     84
     85	rc = fdt_setprop(fdt, devp_offset(devp), name, buf, len);
     86	if (rc == -FDT_ERR_NOSPACE) {
     87		expand_buf(len + 16);
     88		rc = fdt_setprop(fdt, devp_offset(devp), name, buf, len);
     89	}
     90
     91	return check_err(rc);
     92}
     93
     94static int fdt_wrapper_del_node(const void *devp)
     95{
     96	return fdt_del_node(fdt, devp_offset(devp));
     97}
     98
     99static void *fdt_wrapper_get_parent(const void *devp)
    100{
    101	return offset_devp(fdt_parent_offset(fdt, devp_offset(devp)));
    102}
    103
    104static void *fdt_wrapper_create_node(const void *devp, const char *name)
    105{
    106	int offset;
    107
    108	offset = fdt_add_subnode(fdt, devp_offset(devp), name);
    109	if (offset == -FDT_ERR_NOSPACE) {
    110		expand_buf(strlen(name) + 16);
    111		offset = fdt_add_subnode(fdt, devp_offset(devp), name);
    112	}
    113
    114	return offset_devp(offset);
    115}
    116
    117static void *fdt_wrapper_find_node_by_prop_value(const void *prev,
    118						 const char *name,
    119						 const char *val,
    120						 int len)
    121{
    122	int offset = fdt_node_offset_by_prop_value(fdt, devp_offset_find(prev),
    123	                                           name, val, len);
    124	return offset_devp(offset);
    125}
    126
    127static void *fdt_wrapper_find_node_by_compatible(const void *prev,
    128						 const char *val)
    129{
    130	int offset = fdt_node_offset_by_compatible(fdt, devp_offset_find(prev),
    131	                                           val);
    132	return offset_devp(offset);
    133}
    134
    135static char *fdt_wrapper_get_path(const void *devp, char *buf, int len)
    136{
    137	int rc;
    138
    139	rc = fdt_get_path(fdt, devp_offset(devp), buf, len);
    140	if (check_err(rc))
    141		return NULL;
    142	return buf;
    143}
    144
    145static unsigned long fdt_wrapper_finalize(void)
    146{
    147	int rc;
    148
    149	rc = fdt_pack(fdt);
    150	if (rc != 0)
    151		fatal("Couldn't pack flat tree: %s\n\r",
    152		      fdt_strerror(rc));
    153	return (unsigned long)fdt;
    154}
    155
    156void fdt_init(void *blob)
    157{
    158	int err;
    159	int bufsize;
    160
    161	dt_ops.finddevice = fdt_wrapper_finddevice;
    162	dt_ops.getprop = fdt_wrapper_getprop;
    163	dt_ops.setprop = fdt_wrapper_setprop;
    164	dt_ops.get_parent = fdt_wrapper_get_parent;
    165	dt_ops.create_node = fdt_wrapper_create_node;
    166	dt_ops.find_node_by_prop_value = fdt_wrapper_find_node_by_prop_value;
    167	dt_ops.find_node_by_compatible = fdt_wrapper_find_node_by_compatible;
    168	dt_ops.del_node = fdt_wrapper_del_node;
    169	dt_ops.get_path = fdt_wrapper_get_path;
    170	dt_ops.finalize = fdt_wrapper_finalize;
    171
    172	/* Make sure the dt blob is the right version and so forth */
    173	fdt = blob;
    174	bufsize = fdt_totalsize(fdt) + EXPAND_GRANULARITY;
    175	buf = malloc(bufsize);
    176	if(!buf)
    177		fatal("malloc failed. can't relocate the device tree\n\r");
    178
    179	err = fdt_open_into(fdt, buf, bufsize);
    180
    181	if (err != 0)
    182		fatal("fdt_init(): %s\n\r", fdt_strerror(err));
    183
    184	fdt = buf;
    185}