185 lines · 4.4 KB · C
RawDownload
// SPDX-License-Identifier: GPL-2.0-or-later/* * This file does the necessary interface mapping between the bootwrapper * device tree operations and the interface provided by shared source * files flatdevicetree.[ch]. * * Copyright 2007 David Gibson, IBM Corporation. */ #include <stddef.h>#include <stdio.h>#include <page.h>#include <libfdt.h>#include "ops.h" #define DEBUG	0#define BAD_ERROR(err)	(((err) < 0) \			 && ((err) != -FDT_ERR_NOTFOUND) \			 && ((err) != -FDT_ERR_EXISTS)) #define check_err(err) \	({ \		if (BAD_ERROR(err) || ((err < 0) && DEBUG)) \			printf("%s():%d  %s\n\r", __func__, __LINE__, \			       fdt_strerror(err)); \		if (BAD_ERROR(err)) \			exit(); \		(err < 0) ? -1 : 0; \	}) #define offset_devp(off)	\	({ \		unsigned long _offset = (off); \		check_err(_offset) ? NULL : (void *)(_offset+1); \	}) #define devp_offset_find(devp)	(((unsigned long)(devp))-1)#define devp_offset(devp)	(devp ? ((unsigned long)(devp))-1 : 0) static void *fdt;static void *buf; /* = NULL */ #define EXPAND_GRANULARITY	1024 static void expand_buf(int minexpand){	int size = fdt_totalsize(fdt);	int rc; 	size = _ALIGN(size + minexpand, EXPAND_GRANULARITY);	buf = platform_ops.realloc(buf, size);	if (!buf)		fatal("Couldn't find %d bytes to expand device tree\n\r", size);	rc = fdt_open_into(fdt, buf, size);	if (rc != 0)		fatal("Couldn't expand fdt into new buffer: %s\n\r",		      fdt_strerror(rc)); 	fdt = buf;} static void *fdt_wrapper_finddevice(const char *path){	return offset_devp(fdt_path_offset(fdt, path));} static int fdt_wrapper_getprop(const void *devp, const char *name,			       void *buf, const int buflen){	const void *p;	int len; 	p = fdt_getprop(fdt, devp_offset(devp), name, &len);	if (!p)		return check_err(len);	memcpy(buf, p, min(len, buflen));	return len;} static int fdt_wrapper_setprop(const void *devp, const char *name,			       const void *buf, const int len){	int rc; 	rc = fdt_setprop(fdt, devp_offset(devp), name, buf, len);	if (rc == -FDT_ERR_NOSPACE) {		expand_buf(len + 16);		rc = fdt_setprop(fdt, devp_offset(devp), name, buf, len);	} 	return check_err(rc);} static int fdt_wrapper_del_node(const void *devp){	return fdt_del_node(fdt, devp_offset(devp));} static void *fdt_wrapper_get_parent(const void *devp){	return offset_devp(fdt_parent_offset(fdt, devp_offset(devp)));} static void *fdt_wrapper_create_node(const void *devp, const char *name){	int offset; 	offset = fdt_add_subnode(fdt, devp_offset(devp), name);	if (offset == -FDT_ERR_NOSPACE) {		expand_buf(strlen(name) + 16);		offset = fdt_add_subnode(fdt, devp_offset(devp), name);	} 	return offset_devp(offset);} static void *fdt_wrapper_find_node_by_prop_value(const void *prev,						 const char *name,						 const char *val,						 int len){	int offset = fdt_node_offset_by_prop_value(fdt, devp_offset_find(prev),	                                           name, val, len);	return offset_devp(offset);} static void *fdt_wrapper_find_node_by_compatible(const void *prev,						 const char *val){	int offset = fdt_node_offset_by_compatible(fdt, devp_offset_find(prev),	                                           val);	return offset_devp(offset);} static char *fdt_wrapper_get_path(const void *devp, char *buf, int len){	int rc; 	rc = fdt_get_path(fdt, devp_offset(devp), buf, len);	if (check_err(rc))		return NULL;	return buf;} static unsigned long fdt_wrapper_finalize(void){	int rc; 	rc = fdt_pack(fdt);	if (rc != 0)		fatal("Couldn't pack flat tree: %s\n\r",		      fdt_strerror(rc));	return (unsigned long)fdt;} void fdt_init(void *blob){	int err;	int bufsize; 	dt_ops.finddevice = fdt_wrapper_finddevice;	dt_ops.getprop = fdt_wrapper_getprop;	dt_ops.setprop = fdt_wrapper_setprop;	dt_ops.get_parent = fdt_wrapper_get_parent;	dt_ops.create_node = fdt_wrapper_create_node;	dt_ops.find_node_by_prop_value = fdt_wrapper_find_node_by_prop_value;	dt_ops.find_node_by_compatible = fdt_wrapper_find_node_by_compatible;	dt_ops.del_node = fdt_wrapper_del_node;	dt_ops.get_path = fdt_wrapper_get_path;	dt_ops.finalize = fdt_wrapper_finalize; 	/* Make sure the dt blob is the right version and so forth */	fdt = blob;	bufsize = fdt_totalsize(fdt) + EXPAND_GRANULARITY;	buf = malloc(bufsize);	if(!buf)		fatal("malloc failed. can't relocate the device tree\n\r"); 	err = fdt_open_into(fdt, buf, bufsize); 	if (err != 0)		fatal("fdt_init(): %s\n\r", fdt_strerror(err)); 	fdt = buf;}