cmd_fdt.c

来自「uboot详细解读可用启动引导LINUX2.6内核」· C语言 代码 · 共 805 行 · 第 1/2 页

C
805
字号
/* * (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 **newval, int count, char *data, int *len);static int fdt_print(const char *pathp, char *prop, int depth);/* * The working_fdt points to our working flattened device tree. */struct fdt_header *working_fdt;/* * 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.		 */		working_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(working_fdt)) {				printf ("New length %d < existing length %d, "					"ignoring.\n",					len, fdt_totalsize(working_fdt));			} else {				/*				 * Open in place with a new length.				 */				err = fdt_open_into(working_fdt, working_fdt, len);				if (err != 0) {					printf ("libfdt fdt_open_into(): %s\n",						fdt_strerror(err));				}			}		}	/********************************************************************	 * Move the working_fdt	 ********************************************************************/	} else if (strncmp(argv[1], "mo", 2) == 0) {		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.		 */		working_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(working_fdt);		} else {			len = simple_strtoul(argv[4], NULL, 16);			if (len < fdt_totalsize(working_fdt)) {				printf ("New length 0x%X < existing length "					"0x%X, aborting.\n",					len, fdt_totalsize(working_fdt));				return 1;			}		}		/*		 * Copy to the new location.		 */		err = fdt_open_into(working_fdt, newaddr, len);		if (err != 0) {			printf ("libfdt fdt_open_into(): %s\n",				fdt_strerror(err));			return 1;		}		working_fdt = newaddr;	/********************************************************************	 * Make a new node	 ********************************************************************/	} else if (strncmp(argv[1], "mk", 2) == 0) {		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 (working_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(working_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 working_fdt.	 ********************************************************************/	} else if (argv[1][0] == 's') {		char *pathp;		/* path */		char *prop;		/* property */		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, optional value.		 */		if (argc < 4) {			printf ("Usage:\n%s\n", cmdtp->usage);			return 1;		}		pathp  = argv[2];		prop   = argv[3];		if (argc == 4) {			len = 0;		} else {			ret = fdt_parse_prop(&argv[4], argc - 4, data, &len);			if (ret != 0)				return ret;		}		nodeoffset = fdt_path_offset (working_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_setprop(working_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 (strncmp(argv[1], "rm", 2) == 0) {		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 (working_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(working_fdt, nodeoffset, argv[3]);			if (err < 0) {				printf("libfdt fdt_delprop():  %s\n",					fdt_strerror(err));				return err;			}		} else {			err = fdt_del_node(working_fdt, nodeoffset);			if (err < 0) {				printf("libfdt fdt_del_node():  %s\n",					fdt_strerror(err));				return err;			}		}	/********************************************************************	 * Display header info	 ********************************************************************/	} else if (argv[1][0] == 'h') {		u32 version = fdt_version(working_fdt);		printf("magic:\t\t\t0x%x\n", fdt_magic(working_fdt));		printf("totalsize:\t\t0x%x (%d)\n", fdt_totalsize(working_fdt),		       fdt_totalsize(working_fdt));		printf("off_dt_struct:\t\t0x%x\n",		       fdt_off_dt_struct(working_fdt));		printf("off_dt_strings:\t\t0x%x\n",		       fdt_off_dt_strings(working_fdt));		printf("off_mem_rsvmap:\t\t0x%x\n",		       fdt_off_mem_rsvmap(working_fdt));		printf("version:\t\t%d\n", version);		printf("last_comp_version:\t%d\n",		       fdt_last_comp_version(working_fdt));		if (version >= 2)			printf("boot_cpuid_phys:\t0x%x\n",				fdt_boot_cpuid_phys(working_fdt));		if (version >= 3)			printf("size_dt_strings:\t0x%x\n",				fdt_size_dt_strings(working_fdt));		if (version >= 17)			printf("size_dt_struct:\t\t0x%x\n",				fdt_size_dt_struct(working_fdt));		printf("number mem_rsv:\t\t0x%x\n",		       fdt_num_mem_rsv(working_fdt));		printf("\n");	/********************************************************************	 * Set boot cpu id	 ********************************************************************/	} else if (strncmp(argv[1], "boo", 3) == 0) {		unsigned long tmp = simple_strtoul(argv[2], NULL, 16);		fdt_set_boot_cpuid_phys(working_fdt, tmp);	/********************************************************************	 * memory command	 ********************************************************************/	} else if (strncmp(argv[1], "me", 2) == 0) {		uint64_t addr, size;		int err;#ifdef CFG_64BIT_STRTOUL			addr = simple_strtoull(argv[2], NULL, 16);			size = simple_strtoull(argv[3], NULL, 16);#else			addr = simple_strtoul(argv[2], NULL, 16);			size = simple_strtoul(argv[3], NULL, 16);#endif		err = fdt_fixup_memory(working_fdt, addr, size);		if (err < 0)			return err;	/********************************************************************	 * mem reserve commands	 ********************************************************************/	} else if (strncmp(argv[1], "rs", 2) == 0) {		if (argv[2][0] == 'p') {			uint64_t addr, size;			int total = fdt_num_mem_rsv(working_fdt);			int j, err;			printf("index\t\t   start\t\t    size\n");			printf("-------------------------------"				"-----------------\n");			for (j = 0; j < total; j++) {				err = fdt_get_mem_rsv(working_fdt, j, &addr, &size);				if (err < 0) {					printf("libfdt fdt_get_mem_rsv():  %s\n",							fdt_strerror(err));					return err;				}				printf("    %x\t%08x%08x\t%08x%08x\n", j,					(u32)(addr >> 32),					(u32)(addr & 0xffffffff),					(u32)(size >> 32),					(u32)(size & 0xffffffff));			}		} else if (argv[2][0] == 'a') {			uint64_t addr, size;			int err;#ifdef CFG_64BIT_STRTOUL			addr = simple_strtoull(argv[3], NULL, 16);			size = simple_strtoull(argv[4], NULL, 16);#else			addr = simple_strtoul(argv[3], NULL, 16);			size = simple_strtoul(argv[4], NULL, 16);#endif			err = fdt_add_mem_rsv(working_fdt, addr, size);			if (err < 0) {				printf("libfdt fdt_add_mem_rsv():  %s\n",					fdt_strerror(err));				return err;			}		} else if (argv[2][0] == 'd') {			unsigned long idx = simple_strtoul(argv[3], NULL, 16);			int err = fdt_del_mem_rsv(working_fdt, idx);			if (err < 0) {

⌨️ 快捷键说明

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