cmd_fdt.c

来自「U-boot源码 ARM7启动代码」· C语言 代码 · 共 704 行 · 第 1/2 页

C
704
字号
/* * (C) Copyright 2007 * Gerald Van Baren, Custom IDEAS, vanbaren@cideas.com * Based on code written by: *   Pantelis Antoniou <pantelis.antoniou@gmail.com> and *   Matthew McClintock <msm@freescale.com> * * See file CREDITS for list of people who contributed to this * project. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, * MA 02111-1307 USA */#include <common.h>#include <command.h>#include <linux/ctype.h>#include <linux/types.h>#include <asm/global_data.h>#include <fdt.h>#include <libfdt.h>#include <fdt_support.h>#define MAX_LEVEL	32		/* how deeply nested we will go */#define SCRATCHPAD	1024		/* bytes of scratchpad memory *//* * Global data (for the gd->bd) */DECLARE_GLOBAL_DATA_PTR;static int fdt_valid(void);static int fdt_parse_prop(char *pathp, char *prop, char *newval,	char *data, int *len);static int fdt_print(const char *pathp, char *prop, int depth);/* * Flattened Device Tree command, see the help for parameter definitions. */int do_fdt (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]){	if (argc < 2) {		printf ("Usage:\n%s\n", cmdtp->usage);		return 1;	}	/********************************************************************	 * Set the address of the fdt	 ********************************************************************/	if (argv[1][0] == 'a') {		/*		 * Set the address [and length] of the fdt.		 */		fdt = (struct fdt_header *)simple_strtoul(argv[2], NULL, 16);		if (!fdt_valid()) {			return 1;		}		if (argc >= 4) {			int  len;			int  err;			/*			 * Optional new length			 */			len = simple_strtoul(argv[3], NULL, 16);			if (len < fdt_totalsize(fdt)) {				printf ("New length %d < existing length %d, "					"ignoring.\n",					len, fdt_totalsize(fdt));			} else {				/*				 * Open in place with a new length.				 */				err = fdt_open_into(fdt, fdt, len);				if (err != 0) {					printf ("libfdt fdt_open_into(): %s\n",						fdt_strerror(err));				}			}		}	/********************************************************************	 * Move the fdt	 ********************************************************************/	} else if ((argv[1][0] == 'm') && (argv[1][1] == 'o')) {		struct fdt_header *newaddr;		int  len;		int  err;		if (argc < 4) {			printf ("Usage:\n%s\n", cmdtp->usage);			return 1;		}		/*		 * Set the address and length of the fdt.		 */		fdt = (struct fdt_header *)simple_strtoul(argv[2], NULL, 16);		if (!fdt_valid()) {			return 1;		}		newaddr = (struct fdt_header *)simple_strtoul(argv[3],NULL,16);		/*		 * If the user specifies a length, use that.  Otherwise use the		 * current length.		 */		if (argc <= 4) {			len = fdt_totalsize(fdt);		} else {			len = simple_strtoul(argv[4], NULL, 16);			if (len < fdt_totalsize(fdt)) {				printf ("New length 0x%X < existing length "					"0x%X, aborting.\n",					len, fdt_totalsize(fdt));				return 1;			}		}		/*		 * Copy to the new location.		 */		err = fdt_open_into(fdt, newaddr, len);		if (err != 0) {			printf ("libfdt fdt_open_into(): %s\n",				fdt_strerror(err));			return 1;		}		fdt = newaddr;	/********************************************************************	 * Make a new node	 ********************************************************************/	} else if ((argv[1][0] == 'm') && (argv[1][1] == 'k')) {		char *pathp;		/* path */		char *nodep;		/* new node to add */		int  nodeoffset;	/* node offset from libfdt */		int  err;		/*		 * Parameters: Node path, new node to be appended to the path.		 */		if (argc < 4) {			printf ("Usage:\n%s\n", cmdtp->usage);			return 1;		}		pathp = argv[2];		nodep = argv[3];		nodeoffset = fdt_path_offset (fdt, pathp);		if (nodeoffset < 0) {			/*			 * Not found or something else bad happened.			 */			printf ("libfdt fdt_path_offset() returned %s\n",				fdt_strerror(nodeoffset));			return 1;		}		err = fdt_add_subnode(fdt, nodeoffset, nodep);		if (err < 0) {			printf ("libfdt fdt_add_subnode(): %s\n",				fdt_strerror(err));			return 1;		}	/********************************************************************	 * Set the value of a property in the fdt.	 ********************************************************************/	} else if (argv[1][0] == 's') {		char *pathp;		/* path */		char *prop;		/* property */		char *newval;		/* value from the user (as a string) */		int  nodeoffset;	/* node offset from libfdt */		static char data[SCRATCHPAD];	/* storage for the property */		int  len;		/* new length of the property */		int  ret;		/* return value */		/*		 * Parameters: Node path, property, value.		 */		if (argc < 5) {			printf ("Usage:\n%s\n", cmdtp->usage);			return 1;		}		pathp  = argv[2];		prop   = argv[3];		newval = argv[4];		nodeoffset = fdt_path_offset (fdt, pathp);		if (nodeoffset < 0) {			/*			 * Not found or something else bad happened.			 */			printf ("libfdt fdt_path_offset() returned %s\n",				fdt_strerror(nodeoffset));			return 1;		}		ret = fdt_parse_prop(pathp, prop, newval, data, &len);		if (ret != 0)			return ret;		ret = fdt_setprop(fdt, nodeoffset, prop, data, len);		if (ret < 0) {			printf ("libfdt fdt_setprop(): %s\n", fdt_strerror(ret));			return 1;		}	/********************************************************************	 * Print (recursive) / List (single level)	 ********************************************************************/	} else if ((argv[1][0] == 'p') || (argv[1][0] == 'l')) {		int depth = MAX_LEVEL;	/* how deep to print */		char *pathp;		/* path */		char *prop;		/* property */		int  ret;		/* return value */		static char root[2] = "/";		/*		 * list is an alias for print, but limited to 1 level		 */		if (argv[1][0] == 'l') {			depth = 1;		}		/*		 * Get the starting path.  The root node is an oddball,		 * the offset is zero and has no name.		 */		if (argc == 2)			pathp = root;		else			pathp = argv[2];		if (argc > 3)			prop = argv[3];		else			prop = NULL;		ret = fdt_print(pathp, prop, depth);		if (ret != 0)			return ret;	/********************************************************************	 * Remove a property/node	 ********************************************************************/	} else if (argv[1][0] == 'r') {		int  nodeoffset;	/* node offset from libfdt */		int  err;		/*		 * Get the path.  The root node is an oddball, the offset		 * is zero and has no name.		 */		nodeoffset = fdt_path_offset (fdt, argv[2]);		if (nodeoffset < 0) {			/*			 * Not found or something else bad happened.			 */			printf ("libfdt fdt_path_offset() returned %s\n",				fdt_strerror(nodeoffset));			return 1;		}		/*		 * Do the delete.  A fourth parameter means delete a property,		 * otherwise delete the node.		 */		if (argc > 3) {			err = fdt_delprop(fdt, nodeoffset, argv[3]);			if (err < 0) {				printf("libfdt fdt_delprop():  %s\n",					fdt_strerror(err));				return err;			}		} else {			err = fdt_del_node(fdt, nodeoffset);			if (err < 0) {				printf("libfdt fdt_del_node():  %s\n",					fdt_strerror(err));				return err;			}		}	}#ifdef CONFIG_OF_BOARD_SETUP	/* Call the board-specific fixup routine */	else if (argv[1][0] == 'b')		ft_board_setup(fdt, gd->bd);#endif	/* Create a chosen node */	else if (argv[1][0] == 'c')		fdt_chosen(fdt, 0, 0, 1);#ifdef CONFIG_OF_HAS_UBOOT_ENV	/* Create a u-boot-env node */	else if (argv[1][0] == 'e')		fdt_env(fdt);#endif#ifdef CONFIG_OF_HAS_BD_T	/* Create a bd_t node */	else if (argv[1][0] == 'b')		fdt_bd_t(fdt);#endif	else {		/* Unrecognized command */		printf ("Usage:\n%s\n", cmdtp->usage);		return 1;	}	return 0;}/****************************************************************************/static int fdt_valid(void){	int  err;	if (fdt == NULL) {		printf ("The address of the fdt is invalid (NULL).\n");		return 0;	}	err = fdt_check_header(fdt);	if (err == 0)		return 1;	/* valid */	if (err < 0) {		printf("libfdt fdt_check_header(): %s", fdt_strerror(err));		/*		 * Be more informative on bad version.		 */		if (err == -FDT_ERR_BADVERSION) {			if (fdt_version(fdt) < FDT_FIRST_SUPPORTED_VERSION) {				printf (" - too old, fdt $d < %d",					fdt_version(fdt),					FDT_FIRST_SUPPORTED_VERSION);				fdt = NULL;			}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?