/*
 * Recursively print (a portion of) the fdt.  The depth parameter
 * determines how deeply nested the fdt is printed.
 */
static int fdt_print(const char *pathp, char *prop, int depth)
{
	static char tabs[MAX_LEVEL+1] =
		"\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t"
		"\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t";
	const void *nodep;	/* property node pointer */
	int  nodeoffset;	/* node offset from libfdt */
	int  nextoffset;	/* next node offset from libfdt */
	uint32_t tag;		/* tag */
	int  len;		/* length of the property */
	int  level = 0;		/* keep track of nesting level */
	const struct fdt_property *fdt_prop;

	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;
	}
	/*
	 * The user passed in a property as well as node path.
	 * Print only the given property and then return.
	 */
	if (prop) {
		nodep = fdt_getprop (fdt, nodeoffset, prop, &len);
		if (len == 0) {
			/* no property value */
			printf("%s %s\n", pathp, prop);
			return 0;
		} else if (len > 0) {
			printf("%s=", prop);
			print_data (nodep, len);
			printf("\n");
			return 0;
		} else {
			printf ("libfdt fdt_getprop(): %s\n",
				fdt_strerror(len));
			return 1;
		}
	}

	/*
	 * The user passed in a node path and no property,
	 * print the node and all subnodes.
	 */
	while(level >= 0) {
		tag = fdt_next_tag(fdt, nodeoffset, &nextoffset);
		switch(tag) {
		case FDT_BEGIN_NODE:
			pathp = fdt_get_name(fdt, nodeoffset, NULL);
			if (level <= depth) {
				if (pathp == NULL)
					pathp = "/* NULL pointer error */";
				if (*pathp == '\0')
					pathp = "/";	/* root is nameless */
				printf("%s%s {\n",
					&tabs[MAX_LEVEL - level], pathp);
			}
			level++;
			if (level >= MAX_LEVEL) {
				printf("Nested too deep, aborting.\n");
				return 1;
			}
			break;
		case FDT_END_NODE:
			level--;
			if (level <= depth)
				printf("%s};\n", &tabs[MAX_LEVEL - level]);
			if (level == 0) {
				level = -1;		/* exit the loop */
			}
			break;
		case FDT_PROP:
			fdt_prop = fdt_offset_ptr(fdt, nodeoffset,
					sizeof(*fdt_prop));
			pathp    = fdt_string(fdt,
					fdt32_to_cpu(fdt_prop->nameoff));
			len      = fdt32_to_cpu(fdt_prop->len);
			nodep    = fdt_prop->data;
			if (len < 0) {
				printf ("libfdt fdt_getprop(): %s\n",
					fdt_strerror(len));
				return 1;
			} else if (len == 0) {
				/* the property has no value */
				if (level <= depth)
					printf("%s%s;\n",
						&tabs[MAX_LEVEL - level],
						pathp);
			} else {
				if (level <= depth) {
					printf("%s%s=",
						&tabs[MAX_LEVEL - level],
						pathp);
					print_data (nodep, len);
					printf(";\n");
				}
			}
			break;
		case FDT_NOP:
			printf("/* NOP */\n", &tabs[MAX_LEVEL - level]);
			break;
		case FDT_END:
			return 1;
		default:
			if (level <= depth)
				printf("Unknown tag 0x%08X\n", tag);
			return 1;
		}
		nodeoffset = nextoffset;
	}
	return 0;
}
Beispiel #2
0
void ft_board_setup_ex(void *blob, bd_t *bd)
{
	int lpae;
	u64 size;
	char *env;
	u64 *reserve_start;
	int unitrd_fixup = 0;

	env = env_get("mem_lpae");
	lpae = env && simple_strtol(env, NULL, 0);
	env = env_get("uinitrd_fixup");
	unitrd_fixup = env && simple_strtol(env, NULL, 0);

	/* Fix up the initrd */
	if (lpae && unitrd_fixup) {
		int nodeoffset;
		int err;
		u64 *prop1, *prop2;
		u64 initrd_start, initrd_end;

		nodeoffset = fdt_path_offset(blob, "/chosen");
		if (nodeoffset >= 0) {
			prop1 = (u64 *)fdt_getprop(blob, nodeoffset,
					    "linux,initrd-start", NULL);
			prop2 = (u64 *)fdt_getprop(blob, nodeoffset,
					    "linux,initrd-end", NULL);
			if (prop1 && prop2) {
				initrd_start = __be64_to_cpu(*prop1);
				initrd_start -= CONFIG_SYS_SDRAM_BASE;
				initrd_start += CONFIG_SYS_LPAE_SDRAM_BASE;
				initrd_start = __cpu_to_be64(initrd_start);
				initrd_end = __be64_to_cpu(*prop2);
				initrd_end -= CONFIG_SYS_SDRAM_BASE;
				initrd_end += CONFIG_SYS_LPAE_SDRAM_BASE;
				initrd_end = __cpu_to_be64(initrd_end);

				err = fdt_delprop(blob, nodeoffset,
						  "linux,initrd-start");
				if (err < 0)
					puts("error deleting initrd-start\n");

				err = fdt_delprop(blob, nodeoffset,
						  "linux,initrd-end");
				if (err < 0)
					puts("error deleting initrd-end\n");

				err = fdt_setprop(blob, nodeoffset,
						  "linux,initrd-start",
						  &initrd_start,
						  sizeof(initrd_start));
				if (err < 0)
					puts("error adding initrd-start\n");

				err = fdt_setprop(blob, nodeoffset,
						  "linux,initrd-end",
						  &initrd_end,
						  sizeof(initrd_end));
				if (err < 0)
					puts("error adding linux,initrd-end\n");
			}
		}
	}

	if (lpae) {
		/*
		 * the initrd and other reserved memory areas are
		 * embedded in in the DTB itslef. fix up these addresses
		 * to 36 bit format
		 */
		reserve_start = (u64 *)((char *)blob +
				       fdt_off_mem_rsvmap(blob));
		while (1) {
			*reserve_start = __cpu_to_be64(*reserve_start);
			size = __cpu_to_be64(*(reserve_start + 1));
			if (size) {
				*reserve_start -= CONFIG_SYS_SDRAM_BASE;
				*reserve_start +=
					CONFIG_SYS_LPAE_SDRAM_BASE;
				*reserve_start =
					__cpu_to_be64(*reserve_start);
			} else {
				break;
			}
			reserve_start += 2;
		}
	}

	ddr3_check_ecc_int(KS2_DDR3A_EMIF_CTRL_BASE);
}
Beispiel #3
0
/**
 * fit_print_contents - prints out the contents of the FIT format image
 * @fit: pointer to the FIT format image header
 * @p: pointer to prefix string
 *
 * fit_print_contents() formats a multi line FIT image contents description.
 * The routine prints out FIT image properties (root node level) followed by
 * the details of each component image.
 *
 * returns:
 *     no returned results
 */
void fit_print_contents(const void *fit)
{
	char *desc;
	char *uname;
	int images_noffset;
	int confs_noffset;
	int noffset;
	int ndepth;
	int count = 0;
	int ret;
	const char *p;
	time_t timestamp;

	/* Indent string is defined in header image.h */
	p = IMAGE_INDENT_STRING;

	/* Root node properties */
	ret = fit_get_desc(fit, 0, &desc);
	printf("%sFIT description: ", p);
	if (ret)
		printf("unavailable\n");
	else
		printf("%s\n", desc);

	if (IMAGE_ENABLE_TIMESTAMP) {
		ret = fit_get_timestamp(fit, 0, &timestamp);
		printf("%sCreated:         ", p);
		if (ret)
			printf("unavailable\n");
		else
			genimg_print_time(timestamp);
	}

	/* Find images parent node offset */
	images_noffset = fdt_path_offset(fit, FIT_IMAGES_PATH);
	if (images_noffset < 0) {
		printf("Can't find images parent node '%s' (%s)\n",
		       FIT_IMAGES_PATH, fdt_strerror(images_noffset));
		return;
	}

	/* Process its subnodes, print out component images details */
	for (ndepth = 0, count = 0,
		noffset = fdt_next_node(fit, images_noffset, &ndepth);
	     (noffset >= 0) && (ndepth > 0);
	     noffset = fdt_next_node(fit, noffset, &ndepth)) {
		if (ndepth == 1) {
			/*
			 * Direct child node of the images parent node,
			 * i.e. component image node.
			 */
			printf("%s Image %u (%s)\n", p, count++,
			       fit_get_name(fit, noffset, NULL));

			fit_image_print(fit, noffset, p);
		}
	}

	/* Find configurations parent node offset */
	confs_noffset = fdt_path_offset(fit, FIT_CONFS_PATH);
	if (confs_noffset < 0) {
		debug("Can't get configurations parent node '%s' (%s)\n",
		      FIT_CONFS_PATH, fdt_strerror(confs_noffset));
		return;
	}

	/* get default configuration unit name from default property */
	uname = (char *)fdt_getprop(fit, noffset, FIT_DEFAULT_PROP, NULL);
	if (uname)
		printf("%s Default Configuration: '%s'\n", p, uname);

	/* Process its subnodes, print out configurations details */
	for (ndepth = 0, count = 0,
		noffset = fdt_next_node(fit, confs_noffset, &ndepth);
	     (noffset >= 0) && (ndepth > 0);
	     noffset = fdt_next_node(fit, noffset, &ndepth)) {
		if (ndepth == 1) {
			/*
			 * Direct child node of the configurations parent node,
			 * i.e. configuration node.
			 */
			printf("%s Configuration %u (%s)\n", p, count++,
			       fit_get_name(fit, noffset, NULL));

			fit_conf_print(fit, noffset, p);
		}
	}
}
static int nlm_fdt_read_ucore(char *page, char **start, off_t off,
				int count, int *eof, void * data)
{
	char path[128];
	int node, src;
	uint32_t blen, wlen;
	uint8_t * buf;
	int plen = 0, windex, _windex;
	off_t begin = 0;
	int srccount = 0;

	working_fdt = (struct fdt_header *)fdt;

	for(node = 0; node < 4; node++) {
		for(src = 0; src < 32; src++) {
			sprintf(path, "/soc/nae@node-%d/ucore/src@%d", node, src);
			if ( fdt_path_offset (working_fdt, path) < 0 ) 
				continue;

			if ( copy_fdt_prop(working_fdt, path, "src-data-bytes", 
				PROP_CELL, &blen, sizeof(uint32_t)) <= 0 )
				continue;

#ifndef __MIPSEL__
			blen = fdt32_to_cpu(blen);
#endif			
			wlen = ((blen+4)/4)*4;
			buf = (uint8_t *)kmalloc(sizeof(uint8_t)*wlen, GFP_KERNEL);
			if ( !buf ) {
				plen += sprintf(page + plen, "Unable to kmalloc 0x%x bytes for node-%d/src-%d\n",
					wlen, node, src);
				continue;
			}
			if ( copy_fdt_prop(working_fdt, path, "src-data",
				PROP_CELL, buf, wlen) <= 0 ) {
				plen += sprintf(page + plen, "Failed to copy source data for node-%d/src-%d\n",
					node, src);
				continue;
			}

			srccount++;

			/* FIXME - do we need to handle little endian - wrap buf[windex] below with call to fdt32_to_cpu? */
			plen += sprintf(page + plen, "/** -- BEGIN uCore src for %s -- **/\n", path);
			for(windex = 0; windex < blen; windex++) {
#ifndef __MIPSEL__
				_windex = windex;
#else
				_windex = (windex & ~(0x3) ) | (3 - (windex & 0x3) );
#endif
				plen += sprintf(page + plen, "%c", buf[_windex]);
			}
			if (!proc_pos_check(&begin, &plen, off, count)) goto out;
			plen += sprintf(page + plen, "/** -- END uCore src for %s -- **/\n", path);
			
		}
	}

	plen += sprintf(page + plen, "/** Total source files: %d **/\n", srccount);

	*eof = 1;

	out:
	*start = page + (off - begin);
	plen -= (off - begin);
	if (plen > count)
		plen = count;
	if (plen < 0)
		plen = 0;

	return plen;
}
Beispiel #5
0
int zImage_arm_load(int argc, char **argv, const char *buf, off_t len,
	struct kexec_info *info)
{
	unsigned long base;
	unsigned int atag_offset = 0x1000; /* 4k offset from memory start */
	unsigned int offset = 0x8000;      /* 32k offset from memory start */
	unsigned int opt_ramdisk_addr;
	unsigned int opt_atags_addr;
	const char *command_line;
	char *modified_cmdline = NULL;
	off_t command_line_len;
	const char *ramdisk;
	char *ramdisk_buf;
	int opt;
	char *endptr;
	int use_dtb;
	const char *dtb_file;
	char *dtb_buf;
	off_t dtb_length;
	off_t dtb_offset;
	struct arm_mach *mach;

	/* See options.h -- add any more there, too. */
	static const struct option options[] = {
		KEXEC_ARCH_OPTIONS
		{ "command-line",	1, 0, OPT_APPEND },
		{ "append",		1, 0, OPT_APPEND },
		{ "initrd",		1, 0, OPT_RAMDISK },
		{ "ramdisk",		1, 0, OPT_RAMDISK },
		{ "dtb",		2, 0, OPT_DTB },
		{ "rd-addr",		1, 0, OPT_RD_ADDR },
		{ "atags-addr",		1, 0, OPT_ATAGS_ADDR },
		{ "boardname",  1, 0, OPT_BOARDNAME },
		{ 0, 			0, 0, 0 },
	};
	static const char short_options[] = KEXEC_ARCH_OPT_STR "a:r:d::i:g:b:";

	/*
	 * Parse the command line arguments
	 */
	command_line = 0;
	command_line_len = 0;
	ramdisk = 0;
	ramdisk_buf = 0;
	use_dtb = 0;
	dtb_file = NULL;
	opt_ramdisk_addr = 0;
	opt_atags_addr = 0;
	mach = NULL;
	while((opt = getopt_long(argc, argv, short_options, options, 0)) != -1) {
		switch(opt) {
		default:
			/* Ignore core options */
			if (opt < OPT_ARCH_MAX) {
				break;
			}
		case '?':
			usage();
			return -1;
		case OPT_APPEND:
			command_line = optarg;
			break;
		case OPT_RAMDISK:
			ramdisk = optarg;
			break;
		case OPT_DTB:
			use_dtb = 1;
			if(optarg)
				dtb_file = optarg;
			break;
		case OPT_RD_ADDR:
			opt_ramdisk_addr = strtoul(optarg, &endptr, 0);
			if (*endptr) {
				fprintf(stderr,
					"Bad option value in --rd-addr=%s\n",
					optarg);
				usage();
				return -1;
			}
			break;
		case OPT_ATAGS_ADDR:
			opt_atags_addr = strtoul(optarg, &endptr, 0);
			if (*endptr) {
				fprintf(stderr,
					"Bad option value in --atag-addr=%s\n",
					optarg);
				usage();
				return -1;
			}
			break;
		case OPT_BOARDNAME:
			mach = arm_mach_choose(optarg);
			if(!mach)
			{
				fprintf(stderr, "Unknown boardname '%s'!\n", optarg);
				return -1;
			}
			break;
		}
	}
	if (command_line) {
		command_line_len = strlen(command_line) + 1;
		if (command_line_len > COMMAND_LINE_SIZE)
			command_line_len = COMMAND_LINE_SIZE;
	}
	if (ramdisk) {
		ramdisk_buf = slurp_file(ramdisk, &initrd_size);
	}

	/*
	 * If we are loading a dump capture kernel, we need to update kernel
	 * command line and also add some additional segments.
	 */
	if (info->kexec_flags & KEXEC_ON_CRASH) {
		uint64_t start, end;

		modified_cmdline = xmalloc(COMMAND_LINE_SIZE);
		if (!modified_cmdline)
			return -1;

		if (command_line) {
			(void) strncpy(modified_cmdline, command_line,
				       COMMAND_LINE_SIZE);
			modified_cmdline[COMMAND_LINE_SIZE - 1] = '\0';
		}

		if (load_crashdump_segments(info, modified_cmdline) < 0) {
			free(modified_cmdline);
			return -1;
		}

		command_line = modified_cmdline;
		command_line_len = strlen(command_line) + 1;

		/*
		 * We put the dump capture kernel at the start of crashkernel
		 * reserved memory.
		 */
		if (parse_iomem_single("Crash kernel\n", &start, &end)) {
			/*
			 * No crash kernel memory reserved. We cannot do more
			 * but just bail out.
			 */
			return -1;
		}
		base = start;
	} else {
		base = locate_hole(info,len+offset,0,0,ULONG_MAX,INT_MAX);
	}

	if (base == ULONG_MAX)
		return -1;

	/* assume the maximum kernel compression ratio is 4,
	 * and just to be safe, place ramdisk after that
	 */
	if(opt_ramdisk_addr == 0)
		initrd_base = _ALIGN(base + len * 4, getpagesize());
	else
		initrd_base = opt_ramdisk_addr;

	if(!use_dtb)
	{
		if (atag_arm_load(info, base + atag_offset,
				command_line, command_line_len,
				ramdisk_buf, initrd_size, initrd_base) == -1)
			return -1;
	}
	else
	{
		char *dtb_img = NULL;
		off_t dtb_img_len = 0;
		int free_dtb_img = 0;
		int choose_res = 0;
		int ret, off;

		if(!mach)
		{
			fprintf(stderr, "DTB: --boardname was not specified.\n");
			return -1;
		}

		if(dtb_file)
		{
			if(!load_dtb_image(dtb_file, &dtb_img, &dtb_img_len))
				return -1;

			printf("DTB: Using DTB from file %s\n", dtb_file);
			free_dtb_img = 1;
		}
		else
		{
			if(!get_appended_dtb(buf, len, &dtb_img, &dtb_img_len))
				return -1;

			printf("DTB: Using DTB appended to zImage\n");
		}

		choose_res = (mach->choose_dtb)(dtb_img, dtb_img_len, &dtb_buf, &dtb_length);

		if(free_dtb_img)
			free(dtb_img);

		if(!choose_res)
		{
			fprintf(stderr, "Failed to load DTB!\n");
			return -1;
		}

		dtb_length = fdt_totalsize(dtb_buf) + DTB_PAD_SIZE;
		dtb_buf = xrealloc(dtb_buf, dtb_length);
		ret = fdt_open_into(dtb_buf, dtb_buf, dtb_length);
		if(ret)
			die("DTB: fdt_open_into failed");

		ret = (mach->add_extra_regs)(dtb_buf);
		if (ret < 0)
		{
			fprintf(stderr, "DTB: error while adding mach-specific extra regs\n");
			return -1;
		}

		if (command_line) {
			const char *node_name = "/chosen";
			const char *prop_name = "bootargs";

			/* check if a /choosen subnode already exists */
			off = fdt_path_offset(dtb_buf, node_name);

			if (off == -FDT_ERR_NOTFOUND)
				off = fdt_add_subnode(dtb_buf, off, node_name);

			if (off < 0) {
				fprintf(stderr, "DTB: Error adding %s node.\n", node_name);
				return -1;
			}

			if (fdt_setprop(dtb_buf, off, prop_name,
					command_line, strlen(command_line) + 1) != 0) {
				fprintf(stderr, "DTB: Error setting %s/%s property.\n",
					node_name, prop_name);
				return -1;
			}
		}

		if(ramdisk)
		{
			const char *node_name = "/chosen";
			uint32_t initrd_start, initrd_end;

			/* check if a /choosen subnode already exists */
			off = fdt_path_offset(dtb_buf, node_name);

			if (off == -FDT_ERR_NOTFOUND)
				off = fdt_add_subnode(dtb_buf, off, node_name);

			if (off < 0) {
				fprintf(stderr, "DTB: Error adding %s node.\n", node_name);
				return -1;
			}

			initrd_start = cpu_to_fdt32(initrd_base);
			initrd_end = cpu_to_fdt32(initrd_base + initrd_size);

			ret = fdt_setprop(dtb_buf, off, "linux,initrd-start", &initrd_start, sizeof(initrd_start));
			if (ret)
				die("DTB: Error setting %s/linux,initrd-start property.\n", node_name);

			ret = fdt_setprop(dtb_buf, off, "linux,initrd-end", &initrd_end, sizeof(initrd_end));
			if (ret)
				die("DTB: Error setting %s/linux,initrd-end property.\n", node_name);
		}

		fdt_pack(dtb_buf);

		if(ramdisk)
		{
			add_segment(info, ramdisk_buf, initrd_size, initrd_base,
				initrd_size);
		}

		if(opt_atags_addr != 0)
			dtb_offset = opt_atags_addr;
		else
		{
			dtb_offset = initrd_base + initrd_size + getpagesize();
			dtb_offset = _ALIGN_DOWN(dtb_offset, getpagesize());
		}

		printf("DTB: add dtb segment 0x%x\n", (unsigned int)dtb_offset);
		add_segment(info, dtb_buf, dtb_length,
		            dtb_offset, dtb_length);
	}

	add_segment(info, buf, len, base + offset, len);

	info->entry = (void*)base + offset;

	return 0;
}
/* VbExLegacy calls a payload (e.g. SeaBIOS) from an alternate CBFS
 * that lives in the RW section if CTRL-L is pressed at the dev screen.
 * FIXME: Right now no verification is done what so ever!
 */
int VbExLegacy(void)
{
	CbfsFile payload;
	int legacy_node, flash_node;
	u32 flash_base, legacy_offset, legacy_length;
	u32 reg[2];

	flash_node = fdt_path_offset(gd->fdt_blob, "/flash");
	if (flash_node < 0) {
		printf("Could not find /flash in FDT\n");
		return 1;
	}

	legacy_node = fdt_path_offset(gd->fdt_blob, "/flash/rw-legacy");
	if (!legacy_node) {
		printf("Could not find /flash/rw-legacy in FDT\n");
		return 1;
	}

	if (fdtdec_get_int_array(gd->fdt_blob, flash_node, "reg", reg, 2)) {
		printf("Error decoding reg property of /flash\n");
		return 1;
	}
	flash_base = reg[0];

	if (fdtdec_get_int_array(gd->fdt_blob, legacy_node, "reg", reg, 2)) {
		printf("Error decoding reg property of /flash/rw-legacy\n");
		return 1;
	}
	legacy_offset = reg[0];
	legacy_length = reg[1];

	/* Point to alternate CBFS */
	file_cbfs_init(flash_base + legacy_offset + legacy_length - 1);

	/* For debugging, show the contents of our CBFS */
	do_cbfs_ls(NULL, 0, 0, NULL);

	/* Look for a payload named "payload" */
	payload = file_cbfs_find("payload");
	if (!payload) {
		printf("No file \"payload\" found in CBFS.\n");
		return 1;
	}

	/* This is a minimalistic SELF parser.  */
	CbfsPayloadSegment *seg = payload->data;
	while (1) {
		void (*payload_entry)(void);
		void *src = payload->data + be32_to_cpu(seg->offset);
		void *dst = (void *)(unsigned long)be64_to_cpu(seg->load_addr);
		u32 src_len = be32_to_cpu(seg->len);
		u32 dst_len = be32_to_cpu(seg->mem_len);

		switch (seg->type) {
		case PAYLOAD_SEGMENT_CODE:
		case PAYLOAD_SEGMENT_DATA:
			printf("CODE/DATA: dst=%p dst_len=%d src=%p "
				"src_len=%d\n", dst, dst_len, src, src_len);
			if (be32_to_cpu(seg->compression) ==
						CBFS_COMPRESS_NONE) {
				memcpy(dst, src, src_len);
			} else
#ifdef CONFIG_LZMA
			if (be32_to_cpu(seg->compression) ==
						CBFS_COMPRESS_LZMA) {
				int ret;
				SizeT lzma_len = dst_len;
				ret = lzmaBuffToBuffDecompress(
					(unsigned char *)dst, &lzma_len,
					(unsigned char *)src, src_len);
				if (ret != SZ_OK) {
					printf("LZMA: Decompression failed. "
						"ret=%d.\n", ret);
					return 1;
				}
			} else
#endif
			{
				printf("Compression type %x not supported\n",
					be32_to_cpu(seg->compression));
				return 1;
			}
			break;
		case PAYLOAD_SEGMENT_BSS:
			printf("BSS: dst=%p len=%d\n", dst, dst_len);
			memset(dst, 0, dst_len);
			break;
		case PAYLOAD_SEGMENT_PARAMS:
			printf("PARAMS: skipped\n");
			break;
		case PAYLOAD_SEGMENT_ENTRY:
			board_final_cleanup();
			TlclSaveState();
			payload_entry = dst;
			payload_entry();
			return 0;
		default:
			printf("segment type %x not implemented. Exiting\n",
				seg->type);
			return 1;
		}
		seg++;
	}

	/* Make GCC happy. This point is never reached. */
	return 0;
}
/*
 * 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') {
		unsigned long addr;
		/*
		 * Set the address [and length] of the fdt.
		 */
		if (argc == 2) {
			if (!fdt_valid()) {
				return 1;
			}
			printf("The address of the fdt is %p\n", working_fdt);
			return 0;
		}

		addr = simple_strtoul(argv[2], NULL, 16);
		set_working_fdt_addr((void *)addr);

		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 CONFIG_SYS_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') {
Beispiel #8
0
int spl_load_simple_fit(struct spl_load_info *info, ulong sector, void *fit)
{
	int sectors;
	ulong size, load;
	unsigned long count;
	int node, images;
	void *load_ptr;
	int fdt_offset, fdt_len;
	int data_offset, data_size;
	int base_offset, align_len = ARCH_DMA_MINALIGN - 1;
	int src_sector;
	void *dst, *src;

	/*
	 * Figure out where the external images start. This is the base for the
	 * data-offset properties in each image.
	 */
	size = fdt_totalsize(fit);
	size = (size + 3) & ~3;
	base_offset = (size + 3) & ~3;

	/*
	 * So far we only have one block of data from the FIT. Read the entire
	 * thing, including that first block, placing it so it finishes before
	 * where we will load the image.
	 *
	 * Note that we will load the image such that its first byte will be
	 * at the load address. Since that byte may be part-way through a
	 * block, we may load the image up to one block before the load
	 * address. So take account of that here by subtracting an addition
	 * block length from the FIT start position.
	 *
	 * In fact the FIT has its own load address, but we assume it cannot
	 * be before CONFIG_SYS_TEXT_BASE.
	 */
	fit = (void *)((CONFIG_SYS_TEXT_BASE - size - info->bl_len -
			align_len) & ~align_len);
	sectors = get_aligned_image_size(info, size, 0);
	count = info->read(info, sector, sectors, fit);
	debug("fit read sector %lx, sectors=%d, dst=%p, count=%lu\n",
	      sector, sectors, fit, count);
	if (count == 0)
		return -EIO;

	/* find the firmware image to load */
	images = fdt_path_offset(fit, FIT_IMAGES_PATH);
	if (images < 0) {
		debug("%s: Cannot find /images node: %d\n", __func__, images);
		return -1;
	}
	node = fdt_first_subnode(fit, images);
	if (node < 0) {
		debug("%s: Cannot find first image node: %d\n", __func__, node);
		return -1;
	}

	/* Get its information and set up the spl_image structure */
	data_offset = fdt_getprop_u32(fit, node, "data-offset");
	data_size = fdt_getprop_u32(fit, node, "data-size");
	load = fdt_getprop_u32(fit, node, "load");
	debug("data_offset=%x, data_size=%x\n", data_offset, data_size);
	spl_image.load_addr = load;
	spl_image.entry_point = load;
	spl_image.os = IH_OS_U_BOOT;

	/*
	 * Work out where to place the image. We read it so that the first
	 * byte will be at 'load'. This may mean we need to load it starting
	 * before then, since we can only read whole blocks.
	 */
	data_offset += base_offset;
	sectors = get_aligned_image_size(info, data_size, data_offset);
	load_ptr = (void *)load;
	debug("U-Boot size %x, data %p\n", data_size, load_ptr);
	dst = load_ptr;

	/* Read the image */
	src_sector = sector + get_aligned_image_offset(info, data_offset);
	debug("Aligned image read: dst=%p, src_sector=%x, sectors=%x\n",
	      dst, src_sector, sectors);
	count = info->read(info, src_sector, sectors, dst);
	if (count != sectors)
		return -EIO;
	debug("image: dst=%p, data_offset=%x, size=%x\n", dst, data_offset,
	      data_size);
	src = dst + get_aligned_image_overhead(info, data_offset);

#ifdef CONFIG_SPL_FIT_IMAGE_POST_PROCESS
	board_fit_image_post_process((void **)&src, (size_t *)&data_size);
#endif

	memcpy(dst, src, data_size);

	/* Figure out which device tree the board wants to use */
	fdt_len = spl_fit_select_fdt(fit, images, &fdt_offset);
	if (fdt_len < 0)
		return fdt_len;

	/*
	 * Read the device tree and place it after the image. There may be
	 * some extra data before it since we can only read entire blocks.
	 * And also align the destination address to ARCH_DMA_MINALIGN.
	 */
	dst = (void *)((load + data_size + align_len) & ~align_len);
	fdt_offset += base_offset;
	sectors = get_aligned_image_size(info, fdt_len, fdt_offset);
	src_sector = sector + get_aligned_image_offset(info, fdt_offset);
	count = info->read(info, src_sector, sectors, dst);
	debug("Aligned fdt read: dst %p, src_sector = %x, sectors %x\n",
	      dst, src_sector, sectors);
	if (count != sectors)
		return -EIO;

	/*
	 * Copy the device tree so that it starts immediately after the image.
	 * After this we will have the U-Boot image and its device tree ready
	 * for us to start.
	 */
	debug("fdt: dst=%p, data_offset=%x, size=%x\n", dst, fdt_offset,
	      fdt_len);
	src = dst + get_aligned_image_overhead(info, fdt_offset);
	dst = load_ptr + data_size;

#ifdef CONFIG_SPL_FIT_IMAGE_POST_PROCESS
	board_fit_image_post_process((void **)&src, (size_t *)&fdt_len);
#endif

	memcpy(dst, src, fdt_len);

	return 0;
}
Beispiel #9
0
static int spl_fit_select_fdt(const void *fdt, int images, int *fdt_offsetp)
{
	const char *name, *fdt_name;
	int conf, node, fdt_node;
	int len;

	*fdt_offsetp = 0;
	conf = fdt_path_offset(fdt, FIT_CONFS_PATH);
	if (conf < 0) {
		debug("%s: Cannot find /configurations node: %d\n", __func__,
		      conf);
		return -EINVAL;
	}
	for (node = fdt_first_subnode(fdt, conf);
	     node >= 0;
	     node = fdt_next_subnode(fdt, node)) {
		name = fdt_getprop(fdt, node, "description", &len);
		if (!name) {
#ifdef CONFIG_SPL_LIBCOMMON_SUPPORT
			printf("%s: Missing FDT description in DTB\n",
			       __func__);
#endif
			return -EINVAL;
		}
		if (board_fit_config_name_match(name))
			continue;

		debug("Selecting config '%s'", name);
		fdt_name = fdt_getprop(fdt, node, FIT_FDT_PROP, &len);
		if (!fdt_name) {
			debug("%s: Cannot find fdt name property: %d\n",
			      __func__, len);
			return -EINVAL;
		}

		debug(", fdt '%s'\n", fdt_name);
		fdt_node = fdt_subnode_offset(fdt, images, fdt_name);
		if (fdt_node < 0) {
			debug("%s: Cannot find fdt node '%s': %d\n",
			      __func__, fdt_name, fdt_node);
			return -EINVAL;
		}

		*fdt_offsetp = fdt_getprop_u32(fdt, fdt_node, "data-offset");
		len = fdt_getprop_u32(fdt, fdt_node, "data-size");
		debug("FIT: Selected '%s'\n", name);

		return len;
	}

#ifdef CONFIG_SPL_LIBCOMMON_SUPPORT
	printf("No matching DT out of these options:\n");
	for (node = fdt_first_subnode(fdt, conf);
	     node >= 0;
	     node = fdt_next_subnode(fdt, node)) {
		name = fdt_getprop(fdt, node, "description", &len);
		printf("   %s\n", name);
	}
#endif

	return -ENOENT;
}
Beispiel #10
0
//__attribute__((no_sanitize("all")))
void kernel_start(uintptr_t magic, uintptr_t addrin)
{
  kprintf("Magic %zx addrin %zx\n",magic,addrin);

  __init_sanity_checks();

  cpu_print_current_el();
  //its a "RAM address 0"
  const struct fdt_property *prop;
  int addr_cells = 0, size_cells = 0;
  int proplen;

  //TODO find this somewhere ?.. although it is at memory 0x00
  uint64_t fdt_addr=0x40000000;
  char *fdt=(char*)fdt_addr;


  //OK so these get overidden in the for loop which should return a map of memory and not just a single one
  uint64_t addr = 0;
  uint64_t size = 0;

  //checks both magic and version
  if ( fdt_check_header(fdt) != 0 )
  {
    kprint("FDT Header check failed\r\n");
    return;
  }

  size_cells = fdt_size_cells(fdt,0);
  print_le_named32("size_cells :",(char *)&size_cells);
  addr_cells = fdt_address_cells(fdt, 0);//fdt32_ld((const fdt32_t *)prop->data);
  print_le_named32("addr_cells :",(char *)&addr_cells);

  const int mem_offset = fdt_path_offset(fdt, "/memory");
  if (mem_offset < 0)
    return;

  print_le_named32("mem_offset :",(char *)&mem_offset);

  prop = fdt_get_property(fdt, mem_offset, "reg", &proplen);
  int cellslen = (int)sizeof(uint32_t) * (addr_cells + size_cells);

  for (int i = 0; i < proplen / cellslen; ++i) {

  	for (int j = 0; j < addr_cells; ++j) {
  		int offset = (cellslen * i) + (sizeof(uint32_t) * j);

  		addr |= (uint64_t)fdt32_ld((const fdt32_t *)((char *)prop->data + offset)) <<
  			((addr_cells - j - 1) * 32);
  	}
  	for (int j = 0; j < size_cells; ++j) {
  		int offset = (cellslen * i) +
  			(sizeof(uint32_t) * (j + addr_cells));

  		size |= (uint64_t)fdt32_ld((const fdt32_t *)((char *)prop->data + offset)) <<
  			((size_cells - j - 1) * 32);
  	}
	}

  print_le_named64("RAM BASE :",(char *)&addr);
  print_le_named64("RAM SIZE :",(char *)&size);

  uint64_t mem_end=addr+size;

  extern char _end;
  uintptr_t free_mem_begin = reinterpret_cast<uintptr_t>(&_end);

    //ok now its sane
  free_mem_begin += _move_symbols(free_mem_begin);

  // Initialize .bss
  _init_bss();

  // Instantiate machine
  size_t memsize = mem_end - free_mem_begin;
  __machine = os::Machine::create((void*)free_mem_begin, memsize);

  _init_elf_parser();
  // Begin portable HAL initialization
  __machine->init();

  // Initialize system calls
  _init_syscalls();

  //probably not very sane!
  cpu_debug_enable();
  cpu_fiq_enable();
  cpu_irq_enable();
  cpu_serror_enable();

  aarch64::init_libc((uintptr_t)fdt_addr);

}
Beispiel #11
0
int load_fit(const struct fit_loader *ldr, const char *filename, void *opaque)
{
    const struct fit_loader_match *match;
    const void *itb, *match_data = NULL;
    const char *def_cfg_name;
    char path[FIT_LOADER_MAX_PATH];
    int itb_size, configs, cfg_off, off, err;
    hwaddr kernel_end;
    int ret;

    itb = load_device_tree(filename, &itb_size);
    if (!itb) {
        return -EINVAL;
    }

    configs = fdt_path_offset(itb, "/configurations");
    if (configs < 0) {
        ret = configs;
        goto out;
    }

    cfg_off = -FDT_ERR_NOTFOUND;

    if (ldr->matches) {
        for (match = ldr->matches; match->compatible; match++) {
            off = fdt_first_subnode(itb, configs);
            while (off >= 0) {
                if (fit_cfg_compatible(itb, off, match->compatible)) {
                    cfg_off = off;
                    match_data = match->data;
                    break;
                }

                off = fdt_next_subnode(itb, off);
            }

            if (cfg_off >= 0) {
                break;
            }
        }
    }

    if (cfg_off < 0) {
        def_cfg_name = fdt_getprop(itb, configs, "default", NULL);
        if (def_cfg_name) {
            snprintf(path, sizeof(path), "/configurations/%s", def_cfg_name);
            cfg_off = fdt_path_offset(itb, path);
        }
    }

    if (cfg_off < 0) {
        /* couldn't find a configuration to use */
        ret = cfg_off;
        goto out;
    }

    err = fit_load_kernel(ldr, itb, cfg_off, opaque, &kernel_end);
    if (err) {
        ret = err;
        goto out;
    }

    err = fit_load_fdt(ldr, itb, cfg_off, opaque, match_data, kernel_end);
    if (err) {
        ret = err;
        goto out;
    }

    ret = 0;
out:
    g_free((void *) itb);
    return ret;
}
static void *fdt_wrapper_finddevice(const char *path)
{
	return offset_devp(fdt_path_offset(fdt, path));
}
Beispiel #13
0
static int dev_tree_compatible(void *dtb, uint32_t dtb_size, struct dt_entry_node *dtb_list)
{
	int root_offset;
	const void *prop = NULL;
	const char *plat_prop = NULL;
	const char *board_prop = NULL;
	const char *pmic_prop = NULL;
	char *model = NULL;
	struct dt_entry *cur_dt_entry;
	struct dt_entry *dt_entry_array = NULL;
	struct board_id *board_data = NULL;
	struct plat_id *platform_data = NULL;
	struct pmic_id *pmic_data = NULL;
	int len;
	int len_board_id;
	int len_plat_id;
	int min_plat_id_len = 0;
	int len_pmic_id;
	uint32_t dtb_ver;
	uint32_t num_entries = 0;
	uint32_t i, j, k, n;
	uint32_t msm_data_count;
	uint32_t board_data_count;
	uint32_t pmic_data_count;

	root_offset = fdt_path_offset(dtb, "/");
	if (root_offset < 0)
		return false;

	prop = fdt_getprop(dtb, root_offset, "model", &len);
	if (prop && len > 0) {
		model = (char *) malloc(sizeof(char) * len);
		ASSERT(model);
		strlcpy(model, prop, len);
	} else {
		dprintf(INFO, "model does not exist in device tree\n");
	}
	/* Find the pmic-id prop from DTB , if pmic-id is present then
	* the DTB is version 3, otherwise find the board-id prop from DTB ,
	* if board-id is present then the DTB is version 2 */
	pmic_prop = (const char *)fdt_getprop(dtb, root_offset, "qcom,pmic-id", &len_pmic_id);
	board_prop = (const char *)fdt_getprop(dtb, root_offset, "qcom,board-id", &len_board_id);
	if (pmic_prop && (len_pmic_id > 0) && board_prop && (len_board_id > 0)) {
		if ((len_pmic_id % PMIC_ID_SIZE) || (len_board_id % BOARD_ID_SIZE))
		{
			dprintf(CRITICAL, "qcom,pmic-id(%d) or qcom,board-id(%d) in device tree is not a multiple of (%d %d)\n",
				len_pmic_id, len_board_id, PMIC_ID_SIZE, BOARD_ID_SIZE);
			return false;
		}
		dtb_ver = DEV_TREE_VERSION_V3;
		min_plat_id_len = PLAT_ID_SIZE;
	} else if (board_prop && len_board_id > 0) {
		if (len_board_id % BOARD_ID_SIZE)
		{
			dprintf(CRITICAL, "qcom,board-id in device tree is (%d) not a multiple of (%d)\n",
				len_board_id, BOARD_ID_SIZE);
			return false;
		}
		dtb_ver = DEV_TREE_VERSION_V2;
		min_plat_id_len = PLAT_ID_SIZE;
	} else {
		dtb_ver = DEV_TREE_VERSION_V1;
		min_plat_id_len = DT_ENTRY_V1_SIZE;
	}

	/* Get the msm-id prop from DTB */
	plat_prop = (const char *)fdt_getprop(dtb, root_offset, "qcom,msm-id", &len_plat_id);
	if (!plat_prop || len_plat_id <= 0) {
		dprintf(INFO, "qcom,msm-id entry not found\n");
		return false;
	} else if (len_plat_id % min_plat_id_len) {
		dprintf(INFO, "qcom,msm-id in device tree is (%d) not a multiple of (%d)\n",
			len_plat_id, min_plat_id_len);
		return false;
	}

	/*
	 * If DTB version is '1' look for <x y z> pair in the DTB
	 * x: platform_id
	 * y: variant_id
	 * z: SOC rev
	 */
	if (dtb_ver == DEV_TREE_VERSION_V1) {
		cur_dt_entry = (struct dt_entry *)
				malloc(sizeof(struct dt_entry));

		if (!cur_dt_entry) {
			dprintf(CRITICAL, "Out of memory\n");
			return false;
		}
		memset(cur_dt_entry, 0, sizeof(struct dt_entry));

		while (len_plat_id) {
			cur_dt_entry->platform_id = fdt32_to_cpu(((const struct dt_entry_v1 *)plat_prop)->platform_id);
			cur_dt_entry->variant_id = fdt32_to_cpu(((const struct dt_entry_v1 *)plat_prop)->variant_id);
			cur_dt_entry->soc_rev = fdt32_to_cpu(((const struct dt_entry_v1 *)plat_prop)->soc_rev);
			cur_dt_entry->board_hw_subtype =
				fdt32_to_cpu(((const struct dt_entry_v1 *)plat_prop)->variant_id) >> 0x18;
			cur_dt_entry->pmic_rev[0] = board_pmic_target(0);
			cur_dt_entry->pmic_rev[1] = board_pmic_target(1);
			cur_dt_entry->pmic_rev[2] = board_pmic_target(2);
			cur_dt_entry->pmic_rev[3] = board_pmic_target(3);
			cur_dt_entry->offset = (uint32_t)dtb;
			cur_dt_entry->size = dtb_size;

			dprintf(SPEW, "Found an appended flattened device tree (%s - %u %u 0x%x)\n",
				*model ? model : "unknown",
				cur_dt_entry->platform_id, cur_dt_entry->variant_id, cur_dt_entry->soc_rev);

			if (platform_dt_absolute_match(cur_dt_entry, dtb_list)) {
				dprintf(SPEW, "Device tree exact match the board: <%u %u 0x%x> != <%u %u 0x%x>\n",
					cur_dt_entry->platform_id,
					cur_dt_entry->variant_id,
					cur_dt_entry->soc_rev,
					board_platform_id(),
					board_hardware_id(),
					board_soc_version());

			} else {
				dprintf(SPEW, "Device tree's msm_id doesn't match the board: <%u %u 0x%x> != <%u %u 0x%x>\n",
					cur_dt_entry->platform_id,
					cur_dt_entry->variant_id,
					cur_dt_entry->soc_rev,
					board_platform_id(),
					board_hardware_id(),
					board_soc_version());
				plat_prop += DT_ENTRY_V1_SIZE;
				len_plat_id -= DT_ENTRY_V1_SIZE;
				continue;
			}
		}
		free(cur_dt_entry);

	}
Beispiel #14
0
void update_partial_goods_dtb_nodes(void *fdt)
{
	int i;
	int tbl_sz = sizeof(table) / sizeof(struct partial_goods);
	int parent_offset = 0;
	int subnode_offset = 0;
	int ret = 0;
	int prop_len = 0;
	uint32_t reg = readl(QFPROM_PTE_PART_ADDR);
	uint32_t prop_type = 0;
	struct subnode_list *subnode_lst = NULL;
	const struct fdt_property *prop = NULL;
	const char *replace_str = NULL;

	/*
	 * The PTE register bits 23 to 27 have the partial goods
	 * info, extract the partial goods value before using
	 */
	reg = (reg & 0x0f800000) >> 23;

	/* If none of the DTB needs update */
	if (!reg)
		return;

	ret = fdt_open_into(fdt, fdt, fdt_totalsize(fdt));
	if (ret != 0)
	{
		dprintf(CRITICAL, "Failed to move/resize dtb buffer: %d\n", ret);
		ASSERT(0);
	}

	for (i = 0; i < tbl_sz; i++)
	{
		if (reg == table[i].val)
		{
			/* Find the Parent node */
			ret = fdt_path_offset(fdt, table[i].parent_node);
			if (ret < 0)
			{
				dprintf(CRITICAL, "Failed to get parent node: %s\terrno:%d\n", table[i].parent_node, ret);
				ASSERT(0);
			}
			parent_offset = ret;

			/* Find the subnode */
			subnode_lst = table[i].subnode;

			while (subnode_lst->subnode)
			{
				ret = fdt_subnode_offset(fdt, parent_offset, subnode_lst->subnode);
				if (ret < 0)
				{
					dprintf(CRITICAL, "Failed to get subnode: %s\terrno:%d\n", subnode_lst->subnode, ret);
					ASSERT(0);
				}
				subnode_offset = ret;

				/* Find the property node and its length */
				prop = fdt_get_property(fdt, subnode_offset, subnode_lst->property, &prop_len);
				if (!prop)
				{
					dprintf(CRITICAL, "Failed to get property: %s\terrno: %d\n", subnode_lst->property, prop_len);
					ASSERT(0);
				}

				/*
				 * Replace the property value based on the property
				 * length and type
				 */
				if (!(strncmp(subnode_lst->property, "device_type", sizeof(subnode_lst->property))))
					prop_type = DEVICE_TYPE;
				else if ((!strncmp(subnode_lst->property, "status", sizeof(subnode_lst->property))))
					prop_type = STATUS_TYPE;
				else
				{
					dprintf(CRITICAL, "%s: Property type is not supported\n", subnode_lst->property);
					ASSERT(0);
				}

				switch (prop_type)
				{
					case DEVICE_TYPE:
						replace_str = "nak";
						break;
					case STATUS_TYPE:
						if (prop_len == sizeof("ok"))
							replace_str = "no";
						else if (prop_len == sizeof("okay"))
							replace_str = "dsbl";
						else
						{
							dprintf(CRITICAL, "Property value length: %u is invalid for property: %s\n", prop_len, subnode_lst->property);
							ASSERT(0);
						}
						break;
					default:
						/* Control would not come here, as this gets taken care while setting property type */
						break;
				};

				/* Replace the property with new value */
				ret = fdt_setprop_inplace(fdt, subnode_offset, subnode_lst->property, (const void *)replace_str, prop_len);
				if (!ret)
					dprintf(INFO, "Updated device tree property: %s @ %s node\n", subnode_lst->property, subnode_lst->subnode);
				else
				{
					dprintf(CRITICAL, "Failed to update property: %s: error no: %d\n", subnode_lst->property, ret);
					ASSERT(0);
				}

				subnode_lst++;
			}
		}
	}

	fdt_pack(fdt);
}
Beispiel #15
0
int fdt_chosen(void *fdt, int force)
{
	int   nodeoffset;
	int   err;
	char  *str;		/* used to set string properties */
	const char *path;

	err = fdt_check_header(fdt);
	if (err < 0) {
		printf("fdt_chosen: %s\n", fdt_strerror(err));
		return err;
	}

	/*
	 * Find the "chosen" node.
	 */
	nodeoffset = fdt_path_offset (fdt, "/chosen");

	/*
	 * If there is no "chosen" node in the blob, create it.
	 */
	if (nodeoffset < 0) {
		/*
		 * Create a new node "/chosen" (offset 0 is root level)
		 */
		nodeoffset = fdt_add_subnode(fdt, 0, "chosen");
		if (nodeoffset < 0) {
			printf("WARNING: could not create /chosen %s.\n",
				fdt_strerror(nodeoffset));
			return nodeoffset;
		}
	}

	/*
	 * Create /chosen properites that don't exist in the fdt.
	 * If the property exists, update it only if the "force" parameter
	 * is true.
	 */
	str = getenv("bootargs");
	if (str != NULL) {
		path = fdt_getprop(fdt, nodeoffset, "bootargs", NULL);
		if ((path == NULL) || force) {
			err = fdt_setprop(fdt, nodeoffset,
				"bootargs", str, strlen(str)+1);
			if (err < 0)
				printf("WARNING: could not set bootargs %s.\n",
					fdt_strerror(err));
		}
	}

#ifdef CONFIG_OF_STDOUT_VIA_ALIAS
	path = fdt_getprop(fdt, nodeoffset, "linux,stdout-path", NULL);
	if ((path == NULL) || force)
		err = fdt_fixup_stdout(fdt, nodeoffset);
#endif

#ifdef OF_STDOUT_PATH
	path = fdt_getprop(fdt, nodeoffset, "linux,stdout-path", NULL);
	if ((path == NULL) || force) {
		err = fdt_setprop(fdt, nodeoffset,
			"linux,stdout-path", OF_STDOUT_PATH, strlen(OF_STDOUT_PATH)+1);
		if (err < 0)
			printf("WARNING: could not set linux,stdout-path %s.\n",
				fdt_strerror(err));
	}
#endif

	return err;
}
Beispiel #16
0
int spl_load_simple_fit(struct spl_image_info *spl_image,
			struct spl_load_info *info, ulong sector, void *fit)
{
	int sectors;
	ulong size;
	unsigned long count;
	struct spl_image_info image_info;
	int node = -1;
	int images, ret;
	int base_offset, hsize, align_len = ARCH_DMA_MINALIGN - 1;
	int index = 0;

	/*
	 * For FIT with external data, figure out where the external images
	 * start. This is the base for the data-offset properties in each
	 * image.
	 */
	size = fdt_totalsize(fit);
	size = (size + 3) & ~3;
	size = board_spl_fit_size_align(size);
	base_offset = (size + 3) & ~3;

	/*
	 * So far we only have one block of data from the FIT. Read the entire
	 * thing, including that first block, placing it so it finishes before
	 * where we will load the image.
	 *
	 * Note that we will load the image such that its first byte will be
	 * at the load address. Since that byte may be part-way through a
	 * block, we may load the image up to one block before the load
	 * address. So take account of that here by subtracting an addition
	 * block length from the FIT start position.
	 *
	 * In fact the FIT has its own load address, but we assume it cannot
	 * be before CONFIG_SYS_TEXT_BASE.
	 *
	 * For FIT with data embedded, data is loaded as part of FIT image.
	 * For FIT with external data, data is not loaded in this step.
	 */
	hsize = (size + info->bl_len + align_len) & ~align_len;
	fit = spl_get_load_buffer(-hsize, hsize);
	sectors = get_aligned_image_size(info, size, 0);
	count = info->read(info, sector, sectors, fit);
	debug("fit read sector %lx, sectors=%d, dst=%p, count=%lu, size=0x%lx\n",
	      sector, sectors, fit, count, size);

	if (count == 0)
		return -EIO;

	/* find the node holding the images information */
	images = fdt_path_offset(fit, FIT_IMAGES_PATH);
	if (images < 0) {
		debug("%s: Cannot find /images node: %d\n", __func__, images);
		return -1;
	}

#ifdef CONFIG_SPL_FPGA_SUPPORT
	node = spl_fit_get_image_node(fit, images, "fpga", 0);
	if (node >= 0) {
		/* Load the image and set up the spl_image structure */
		ret = spl_load_fit_image(info, sector, fit, base_offset, node,
					 spl_image);
		if (ret) {
			printf("%s: Cannot load the FPGA: %i\n", __func__, ret);
			return ret;
		}

		debug("FPGA bitstream at: %x, size: %x\n",
		      (u32)spl_image->load_addr, spl_image->size);

		ret = fpga_load(0, (const void *)spl_image->load_addr,
				spl_image->size, BIT_FULL);
		if (ret) {
			printf("%s: Cannot load the image to the FPGA\n",
			       __func__);
			return ret;
		}

		puts("FPGA image loaded from FIT\n");
		node = -1;
	}
#endif

	/*
	 * Find the U-Boot image using the following search order:
	 *   - start at 'firmware' (e.g. an ARM Trusted Firmware)
	 *   - fall back 'kernel' (e.g. a Falcon-mode OS boot
	 *   - fall back to using the first 'loadables' entry
	 */
	if (node < 0)
		node = spl_fit_get_image_node(fit, images, FIT_FIRMWARE_PROP,
					      0);
#ifdef CONFIG_SPL_OS_BOOT
	if (node < 0)
		node = spl_fit_get_image_node(fit, images, FIT_KERNEL_PROP, 0);
#endif
	if (node < 0) {
		debug("could not find firmware image, trying loadables...\n");
		node = spl_fit_get_image_node(fit, images, "loadables", 0);
		/*
		 * If we pick the U-Boot image from "loadables", start at
		 * the second image when later loading additional images.
		 */
		index = 1;
	}
	if (node < 0) {
		debug("%s: Cannot find u-boot image node: %d\n",
		      __func__, node);
		return -1;
	}

	/* Load the image and set up the spl_image structure */
	ret = spl_load_fit_image(info, sector, fit, base_offset, node,
				 spl_image);
	if (ret)
		return ret;

	/*
	 * For backward compatibility, we treat the first node that is
	 * as a U-Boot image, if no OS-type has been declared.
	 */
	if (!spl_fit_image_get_os(fit, node, &spl_image->os))
		debug("Image OS is %s\n", genimg_get_os_name(spl_image->os));
#if !defined(CONFIG_SPL_OS_BOOT)
	else
		spl_image->os = IH_OS_U_BOOT;
#endif

	/*
	 * Booting a next-stage U-Boot may require us to append the FDT.
	 * We allow this to fail, as the U-Boot image might embed its FDT.
	 */
	if (spl_image->os == IH_OS_U_BOOT)
		spl_fit_append_fdt(spl_image, info, sector, fit,
				   images, base_offset);

	/* Now check if there are more images for us to load */
	for (; ; index++) {
		uint8_t os_type = IH_OS_INVALID;

		node = spl_fit_get_image_node(fit, images, "loadables", index);
		if (node < 0)
			break;

		ret = spl_load_fit_image(info, sector, fit, base_offset, node,
					 &image_info);
		if (ret < 0)
			continue;

		if (!spl_fit_image_get_os(fit, node, &os_type))
			debug("Loadable is %s\n", genimg_get_os_name(os_type));

		if (os_type == IH_OS_U_BOOT) {
			spl_fit_append_fdt(&image_info, info, sector,
					   fit, images, base_offset);
			spl_image->fdt_addr = image_info.fdt_addr;
		}

		/*
		 * If the "firmware" image did not provide an entry point,
		 * use the first valid entry point from the loadables.
		 */
		if (spl_image->entry_point == FDT_ERROR &&
		    image_info.entry_point != FDT_ERROR)
			spl_image->entry_point = image_info.entry_point;

		/* Record our loadables into the FDT */
		if (spl_image->fdt_addr)
			spl_fit_record_loadable(fit, images, index,
						spl_image->fdt_addr,
						&image_info);
	}

	/*
	 * If a platform does not provide CONFIG_SYS_UBOOT_START, U-Boot's
	 * Makefile will set it to 0 and it will end up as the entry point
	 * here. What it actually means is: use the load address.
	 */
	if (spl_image->entry_point == FDT_ERROR || spl_image->entry_point == 0)
		spl_image->entry_point = spl_image->load_addr;

	spl_image->flags |= SPL_FIT_FOUND;

#ifdef CONFIG_SECURE_BOOT
	board_spl_fit_post_load((ulong)fit, size);
#endif

	return 0;
}
Beispiel #17
0
static int ft_hs_fixup_crossbar(void *fdt, bd_t *bd)
{
	const char *path;
	int offs;
	int ret;
	int len, i, old_cnt, new_cnt;
	u32 *temp;
	const u32 *p_data;

	/*
	 * Increase the size of the fdt
	 * so we have some breathing room
	 */
	ret = fdt_increase_size(fdt, 512);
	if (ret < 0) {
		printf("Could not increase size of device tree: %s\n",
		       fdt_strerror(ret));
		return ret;
	}

	/* Reserve IRQs that are used/needed by secure world */
	path = "/ocp/crossbar";
	offs = fdt_path_offset(fdt, path);
	if (offs < 0) {
		debug("Node %s not found.\n", path);
		return 0;
	}

	/* Get current entries */
	p_data = fdt_getprop(fdt, offs, "ti,irqs-skip", &len);
	if (p_data)
		old_cnt = len / sizeof(u32);
	else
		old_cnt = 0;

	new_cnt = sizeof(hs_irq_skip) /
				sizeof(hs_irq_skip[0]);

	/* Create new/updated skip list for HS parts */
	temp = malloc(sizeof(u32) * (old_cnt + new_cnt));
	for (i = 0; i < new_cnt; i++)
		temp[i] = cpu_to_fdt32(hs_irq_skip[i]);
	for (i = 0; i < old_cnt; i++)
		temp[i + new_cnt] = p_data[i];

	/* Blow away old data and set new data */
	fdt_delprop(fdt, offs, "ti,irqs-skip");
	ret = fdt_setprop(fdt, offs, "ti,irqs-skip",
			  temp,
			  (old_cnt + new_cnt) * sizeof(u32));
	free(temp);

	/* Check if the update worked */
	if (ret < 0) {
		printf("Could not add ti,irqs-skip property to node %s: %s\n",
		       path, fdt_strerror(ret));
		return ret;
	}

	return 0;
}
Beispiel #18
0
int update_tftp(ulong addr)
{
	char *filename, *env_addr;
	int images_noffset, ndepth, noffset;
	ulong update_addr, update_fladdr, update_size;
	void *fit;
	int ret = 0;

	/* use already present image */
	if (addr)
		goto got_update_file;

	printf("Auto-update from TFTP: ");

	/* get the file name of the update file */
	filename = getenv(UPDATE_FILE_ENV);
	if (filename == NULL) {
		printf("failed, env. variable '%s' not found\n",
							UPDATE_FILE_ENV);
		return 1;
	}

	printf("trying update file '%s'\n", filename);

	/* get load address of downloaded update file */
	if ((env_addr = getenv("loadaddr")) != NULL)
		addr = simple_strtoul(env_addr, NULL, 16);
	else
		addr = CONFIG_UPDATE_LOAD_ADDR;


	if (update_load(filename, CONFIG_UPDATE_TFTP_MSEC_MAX,
					CONFIG_UPDATE_TFTP_CNT_MAX, addr)) {
		printf("Can't load update file, aborting auto-update\n");
		return 1;
	}

got_update_file:
	fit = (void *)addr;

	if (!fit_check_format((void *)fit)) {
		printf("Bad FIT format of the update file, aborting "
							"auto-update\n");
		return 1;
	}

	/* process updates */
	images_noffset = fdt_path_offset(fit, FIT_IMAGES_PATH);

	ndepth = 0;
	noffset = fdt_next_node(fit, images_noffset, &ndepth);
	while (noffset >= 0 && ndepth > 0) {
		if (ndepth != 1)
			goto next_node;

		printf("Processing update '%s' :",
			fit_get_name(fit, noffset, NULL));

		if (!fit_image_verify(fit, noffset)) {
			printf("Error: invalid update hash, aborting\n");
			ret = 1;
			goto next_node;
		}

		printf("\n");
		if (update_fit_getparams(fit, noffset, &update_addr,
					&update_fladdr, &update_size)) {
			printf("Error: can't get update parameteres, "
								"aborting\n");
			ret = 1;
			goto next_node;
		}
		if (update_flash(update_addr, update_fladdr, update_size)) {
			printf("Error: can't flash update, aborting\n");
			ret = 1;
			goto next_node;
		}
next_node:
		noffset = fdt_next_node(fit, noffset, &ndepth);
	}

	return ret;
}
static int fdt_init_qdev(char *node_path, FDTMachineInfo *fdti, char *compat)
{
    int err;
    qemu_irq irq;
    hwaddr base;
    int offset;
    DeviceState *dev;
    char *dev_type = NULL;
    int is_intc;
    Error *errp = NULL;
    int i;

    dev = fdt_create_qdev_from_compat(compat, &dev_type);
    if (!dev) {
        DB_PRINT("no match found for %s\n", compat);
        return 1;
    }
    /* FIXME: attach to the sysbus instead */
    object_property_add_child(container_get(qdev_get_machine(), "/unattached"),
                              qemu_devtree_get_node_name(fdti->fdt, node_path),
                              OBJECT(dev), NULL);

    fdt_init_set_opaque(fdti, node_path, dev);

    /* connect nic if appropriate */
    static int nics;
    if (object_property_find(OBJECT(dev), "mac", NULL)) {
        qdev_set_nic_properties(dev, &nd_table[nics]);
        if (nd_table[nics].instantiated) {
            DB_PRINT("NIC instantiated: %s\n", dev_type);
            nics++;
        }
    }

    offset = fdt_path_offset(fdti->fdt, node_path);
    for (offset = fdt_first_property_offset(fdti->fdt, offset);
            offset != -FDT_ERR_NOTFOUND;
            offset = fdt_next_property_offset(fdti->fdt, offset)) {
        const char *propname;
        int len;
        const void *val = fdt_getprop_by_offset(fdti->fdt, offset,
                                                    &propname, &len);

        propname = trim_vendor(propname);
        ObjectProperty *p = object_property_find(OBJECT(dev), propname, NULL);
        if (p) {
            DB_PRINT("matched property: %s of type %s, len %d\n",
                                            propname, p->type, len);
        }
        if (!p) {
            continue;
        }

        /* FIXME: handle generically using accessors and stuff */
        if (!strcmp(p->type, "uint8") || !strcmp(p->type, "uint16") ||
                !strcmp(p->type, "uint32") || !strcmp(p->type, "uint64")) {
            uint64_t offset = (!strcmp(propname, "reg")) ?
                              fdt_get_parent_base(node_path, fdti) : 0;
            object_property_set_int(OBJECT(dev), get_int_be(val, len) + offset,
                                    propname, &errp);
            assert_no_error(errp);
            DB_PRINT("set property %s to %#llx\n", propname,
                                            (long long unsigned int)get_int_be(val, len));
        } else if (!strcmp(p->type, "bool")) {
            object_property_set_bool(OBJECT(dev), !!get_int_be(val, len),
                        propname, &errp);
            assert_no_error(errp);
            DB_PRINT("set property %s to %#llx\n", propname,
                                            (long long unsigned int)get_int_be(val, len));
        } else if (!strncmp(p->type, "link", 4)) {
            char target_node_path[DT_PATH_LENGTH];
            DeviceState *linked_dev;

            if (qemu_devtree_get_node_by_phandle(fdti->fdt, target_node_path,
                                                get_int_be(val, len))) {
                abort();
            }
            while (!fdt_init_has_opaque(fdti, target_node_path)) {
                fdt_init_yield(fdti);
            }
            linked_dev = fdt_init_get_opaque(fdti, target_node_path);
            object_property_set_link(OBJECT(dev), OBJECT(linked_dev), propname,
                                        &errp);
            assert_no_error(errp);
        } else if (!strcmp(p->type, "string")) {
            object_property_set_str(OBJECT(dev), strndup(val, len), propname, &errp);
	}
    }

    qdev_init_nofail(dev);
    /* map slave attachment */
    base = qemu_devtree_getprop_cell(fdti->fdt, node_path, "reg", 0, false,
                                                                    &errp);
    assert_no_error(errp);

    base += fdt_get_parent_base(node_path, fdti);
    sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, base);

    {
        int len;
        fdt_get_property(fdti->fdt, fdt_path_offset(fdti->fdt, node_path),
                                "interrupt-controller", &len);
        is_intc = len >= 0;
        DB_PRINT("is interrupt controller: %c\n", is_intc ? 'y' : 'n');
    }
    /* connect irq */
    for (i = 0; ; ++i) {
        char irq_info[1024];
        irq = fdt_get_irq_info(fdti, node_path, i, &err, irq_info);
        /* INTCs inferr their top level, if no IRQ connection specified */
        if (err && is_intc) {
            irq = fdti->irq_base[0];
            sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, irq);
            fprintf(stderr, "FDT: (%s) connected top level irq %s\n", dev_type,
                        irq_info);
            break;
        }
        if (!err) {
            sysbus_connect_irq(SYS_BUS_DEVICE(dev), i, irq);
            fprintf(stderr, "FDT: (%s) connected irq %s\n", dev_type, irq_info);
        } else {
            break;
        }
    }

    if (dev_type) {
        g_free(dev_type);
    }

    return 0;
}
Beispiel #20
0
/*
 * Flattened Device Tree command, see the help for parameter definitions.
 */
static int do_fdt(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
{
	if (argc < 2)
		return CMD_RET_USAGE;

	/*
	 * Set the address of the fdt
	 */
	if (strncmp(argv[1], "ad", 2) == 0) {
		unsigned long addr;
		int control = 0;
		struct fdt_header *blob;
		/*
		 * Set the address [and length] of the fdt.
		 */
		argc -= 2;
		argv += 2;
/* Temporary #ifdef - some archs don't have fdt_blob yet */
#ifdef CONFIG_OF_CONTROL
		if (argc && !strcmp(*argv, "-c")) {
			control = 1;
			argc--;
			argv++;
		}
#endif
		if (argc == 0) {
			if (control)
				blob = (struct fdt_header *)gd->fdt_blob;
			else
				blob = working_fdt;
			if (!blob || !fdt_valid(&blob))
				return 1;
			printf("The address of the fdt is %#08lx\n",
			       control ? (ulong)map_to_sysmem(blob) :
					getenv_hex("fdtaddr", 0));
			return 0;
		}

		addr = simple_strtoul(argv[0], NULL, 16);
		blob = map_sysmem(addr, 0);
		if (!fdt_valid(&blob))
			return 1;
		if (control)
			gd->fdt_blob = blob;
		else
			set_working_fdt_addr(addr);

		if (argc >= 2) {
			int  len;
			int  err;
			/*
			 * Optional new length
			 */
			len = simple_strtoul(argv[1], NULL, 16);
			if (len < fdt_totalsize(blob)) {
				printf ("New length %d < existing length %d, "
					"ignoring.\n",
					len, fdt_totalsize(blob));
			} else {
				/*
				 * Open in place with a new length.
				 */
				err = fdt_open_into(blob, blob, len);
				if (err != 0) {
					printf ("libfdt fdt_open_into(): %s\n",
						fdt_strerror(err));
				}
			}
		}

		return CMD_RET_SUCCESS;
	}

	if (!working_fdt) {
		puts(
			"No FDT memory address configured. Please configure\n"
			"the FDT address via \"fdt addr <address>\" command.\n"
			"Aborting!\n");
		return CMD_RET_FAILURE;
	}

	/*
	 * Move the working_fdt
	 */
	if (strncmp(argv[1], "mo", 2) == 0) {
		struct fdt_header *newaddr;
		int  len;
		int  err;

		if (argc < 4)
			return CMD_RET_USAGE;

		/*
		 * Set the address and length of the fdt.
		 */
		working_fdt = (struct fdt_header *)simple_strtoul(argv[2], NULL, 16);
		if (!fdt_valid(&working_fdt))
			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)
			return CMD_RET_USAGE;

		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)
			return CMD_RET_USAGE;

		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;
		}

	/********************************************************************
	 * Get the value of a property in the working_fdt.
	 ********************************************************************/
	} else if (argv[1][0] == 'g') {
		char *subcmd;		/* sub-command */
		char *pathp;		/* path */
		char *prop;		/* property */
		char *var;		/* variable to store result */
		int  nodeoffset;	/* node offset from libfdt */
		const void *nodep;	/* property node pointer */
		int  len = 0;		/* new length of the property */

		/*
		 * Parameters: Node path, property, optional value.
		 */
		if (argc < 5)
			return CMD_RET_USAGE;

		subcmd = argv[2];

		if (argc < 6 && subcmd[0] != 's')
			return CMD_RET_USAGE;

		var    = argv[3];
		pathp  = argv[4];
		prop   = argv[5];

		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;
		}

		if (subcmd[0] == 'n' || (subcmd[0] == 's' && argc == 5)) {
			int reqIndex = -1;
			int startDepth = fdt_node_depth(
				working_fdt, nodeoffset);
			int curDepth = startDepth;
			int curIndex = -1;
			int nextNodeOffset = fdt_next_node(
				working_fdt, nodeoffset, &curDepth);

			if (subcmd[0] == 'n')
				reqIndex = simple_strtoul(argv[5], NULL, 16);

			while (curDepth > startDepth) {
				if (curDepth == startDepth + 1)
					curIndex++;
				if (subcmd[0] == 'n' && curIndex == reqIndex) {
					const char *nodeName = fdt_get_name(
					    working_fdt, nextNodeOffset, NULL);

					setenv(var, (char *)nodeName);
					return 0;
				}
				nextNodeOffset = fdt_next_node(
					working_fdt, nextNodeOffset, &curDepth);
				if (nextNodeOffset < 0)
					break;
			}
			if (subcmd[0] == 's') {
				/* get the num nodes at this level */
				setenv_ulong(var, curIndex + 1);
			} else {
				/* node index not found */
				printf("libfdt node not found\n");
				return 1;
			}
		} else {
			nodep = fdt_getprop(
				working_fdt, nodeoffset, prop, &len);
			if (len == 0) {
				/* no property value */
				setenv(var, "");
				return 0;
			} else if (len > 0) {
				if (subcmd[0] == 'v') {
					int ret;

					ret = fdt_value_setenv(nodep, len, var);
					if (ret != 0)
						return ret;
				} else if (subcmd[0] == 'a') {
					/* Get address */
					char buf[11];

					sprintf(buf, "0x%p", nodep);
					setenv(var, buf);
				} else if (subcmd[0] == 's') {
					/* Get size */
					char buf[11];

					sprintf(buf, "0x%08X", len);
					setenv(var, buf);
				} else
					return CMD_RET_USAGE;
				return 0;
			} else {
				printf("libfdt fdt_getprop(): %s\n",
					fdt_strerror(len));
				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;
		addr = simple_strtoull(argv[2], NULL, 16);
		size = simple_strtoull(argv[3], NULL, 16);
		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') {
Beispiel #21
0
/*
 * chosen {
 * bootargs = "console=ttyS0,115200 ubi.mtd=4 root=ubi0:rootfs rootfstype=ubifs";
 * };

 * 호출: int offset = fdt_path_offset(fdt, "/chosen");
*/
int fdt_path_offset(const void *fdt, const char *path)
{
	/*
	 * p : "chosen"의 시작 주소
	 * end : "chosen"의 끝 주소
	*/
	const char *end = path + strlen(path);
	const char *p = path;
	int offset = 0;

	FDT_CHECK_HEADER(fdt);

	/* see if we have an alias */
	if (*path != '/') {
		// path가 '/'로 시작하지 않으면 path내에서 '/' 위치 찾음
		const char *q = strchr(path, '/');

		// path내에 '/'가 없으면 끝 주소로 지정
		if (!q)
			q = end;

		/*
		 * '/'로 시작하지 않았다면 alias라고 가정하고 원래 node명 탐색
		 * p: alias명
		 * q-p: alias 길이
		*/ 
		p = fdt_get_alias_namelen(fdt, p, q - p);
		// alias도 아닌경우 에러 리턴
		if (!p)
			return -FDT_ERR_BADPATH;
		offset = fdt_path_offset(fdt, p);

		p = q;
	}

	/*
	 * "chosen"의 alias가 없으면 여기서 탐색
	 * 여기서는 node의 이름이 "chosen"인지 아닌지 탐색
	*/
	while (*p) {
		const char *q;

		// path내에서 '/'가 아닌곳까지 이동
		while (*p == '/')
			p++;
		// path 끝까지 이동한 경우
		if (! *p)
			return offset;
		// p를 기준으로 다음 '/' 위치까지 찾아서
		q = strchr(p, '/');
		// 다음 '/'가 없다면 path의 끝으로 지정
		if (! q)
			q = end;
	
		// path에서 '/'로 split 해보면서
		// 하위 node들중 해당 이름의 node가 있는지 탐색
		offset = fdt_subnode_offset_namelen(fdt, offset, p, q-p);
		if (offset < 0)
			return offset;

		p = q;
	}

	return offset;
}
Beispiel #22
0
static struct obj *mpu6000_gyro_ctor(const char *name) {
    const void *blob = fdtparse_get_blob();
    int offset, parent_offset;
    char *parent;
    struct obj *gyro_obj;
    struct gyro *gyro;
    struct mpu6000_gyro *mpu_gyro;

    offset = fdt_path_offset(blob, name);
    if (offset < 0) {
        return NULL;
    }

    if (fdt_node_check_compatible(blob, offset, MPU6000_GYRO_COMPAT)) {
        return NULL;
    }

    parent_offset = fdt_parent_offset(blob, offset);
    if (parent_offset < 0) {
        return NULL;
    }

    parent = fdtparse_get_path(blob, parent_offset);
    if (!parent) {
        return NULL;
    }

    gyro_obj = instantiate(name, &gyro_class, &mpu6000_gyro_ops,
                           struct gyro);
    if (!gyro_obj) {
        goto err_free_parent;
    }

    /* Connect to parent MPU6000 */
    gyro = to_gyro(gyro_obj);
    gyro->device.parent = device_get(parent);
    if (!gyro->device.parent) {
        goto err_free_obj;
    }

    /* Set up private data */
    gyro->priv = kmalloc(sizeof(struct mpu6000_gyro));
    if (!gyro->priv) {
        goto err_free_obj;
    }

    mpu_gyro = (struct mpu6000_gyro *) gyro->priv;
    mpu_gyro->ready = 0;

    /* Export to the OS */
    class_export_member(gyro_obj);

    free(parent);

    return gyro_obj;

err_free_obj:
    class_deinstantiate(gyro_obj);
err_free_parent:
    free(parent);
    return NULL;
}
static int nlm_fdt_read(char *page, char **start, off_t off,
			     int count, int *eof, void *data)
{
	static char tabs[MAX_LEVEL+1] =
		"\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t"
		"\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t";
	const void *nodep;	/* property node pointer */
	int  nodeoffset;	/* node offset from libfdt */
	int  nextoffset;	/* next node offset from libfdt */
	uint32_t tag;		/* tag */
	int  len;		/* length of the property */
	int  level = 0;		/* keep track of nesting level */
	const struct fdt_property *fdt_prop;
	int plen = 0;
	const char *pathp = "/";
	int depth = MAX_LEVEL;
	off_t begin = 0;

	working_fdt = (struct fdt_header *)fdt;

	nodeoffset = fdt_path_offset (working_fdt, pathp);
	if (nodeoffset < 0) {
		/*
		 * Not found or something else bad happened.
		 */
		plen += sprintf(page + plen, 
			"libfdt fdt_path_offset() returned %s\n",
			fdt_strerror(nodeoffset));
		goto out;
	}

	/*
	 * The user passed in a node path and no property,
	 * print the node and all subnodes.
	 */
	while(level >= 0) {
		if (!proc_pos_check(&begin, &plen, off, count)) goto out;
		tag = fdt_next_tag(working_fdt, nodeoffset, &nextoffset);
		switch(tag) {
		case FDT_BEGIN_NODE:
			pathp = fdt_get_name(working_fdt, nodeoffset, NULL);
			if (level <= depth) {
				if (pathp == NULL)
					pathp = "/* NULL pointer error */";
				if (*pathp == '\0')
					pathp = "/";	/* root is nameless */
				plen += sprintf(page + plen, "%s%s {\n",
					&tabs[MAX_LEVEL - level], pathp);
			}
			level++;
			if (level >= MAX_LEVEL) {
				plen += sprintf(page + plen, "Nested too deep, aborting.\n");
				goto out;
			}
			break;
		case FDT_END_NODE:
			level--;
			if (level <= depth)
				plen += sprintf(page + plen, "%s};\n", &tabs[MAX_LEVEL - level]);
			if (level == 0) {
				level = -1;		/* exit the loop */
			}
			break;
		case FDT_PROP:
			fdt_prop = fdt_offset_ptr(working_fdt, nodeoffset,
					sizeof(*fdt_prop));
			pathp    = fdt_string(working_fdt,
					fdt32_to_cpu(fdt_prop->nameoff));
			len      = fdt32_to_cpu(fdt_prop->len);
			nodep    = fdt_prop->data;
			if (len < 0) {
				plen += sprintf (page + plen, "libfdt fdt_getprop(): %s\n",
					fdt_strerror(len));
				goto out;
			} else if (len == 0) {
				/* the property has no value */
				if (level <= depth)
					plen += sprintf(page + plen, "%s%s;\n",
						&tabs[MAX_LEVEL - level],
						pathp);
			} else {
				if (level <= depth) {
					plen += sprintf(page + plen, "%s%s = ",
						&tabs[MAX_LEVEL - level],
						pathp);
					plen += print_data (page + plen, nodep, len);
					plen += sprintf(page + plen, ";\n");
				}
			}
			break;
		case FDT_NOP:
			plen += sprintf(page + plen, "%s/* NOP */\n", &tabs[MAX_LEVEL - level]);
			break;
		case FDT_END:
			goto good_out;
		default:
			if (level <= depth)
				plen += sprintf(page + plen, "Unknown tag 0x%08X\n", tag);
			goto out;
		}
		nodeoffset = nextoffset;
	}

	good_out:
	*eof = 1;

	out:
	*start = page + (off - begin);
	plen -= (off - begin);
	if (plen > count)
		plen = count;
	if (plen < 0)
		plen = 0;

	return plen;
}
void platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
		   unsigned long r6, unsigned long r7)
{
	const u32 *na, *ns, *reg, *timebase;
	u64 memsize64;
	int node, size, i;

	/*                            */
	if (fdt_check_header(_dtb_start) != 0)
		fatal("Invalid device tree blob\n");

	/*                                                    */
	node = fdt_path_offset(_dtb_start, "/");
	if (node < 0)
		fatal("Cannot find root node\n");
	na = fdt_getprop(_dtb_start, node, "#address-cells", &size);
	if (!na || (size != 4))
		fatal("Cannot find #address-cells property");
	ns = fdt_getprop(_dtb_start, node, "#size-cells", &size);
	if (!ns || (size != 4))
		fatal("Cannot find #size-cells property");

	/*                       */
	node = fdt_node_offset_by_prop_value(_dtb_start, -1, "device_type",
					     "memory", sizeof("memory"));
	if (node < 0)
		fatal("Cannot find memory node\n");
	reg = fdt_getprop(_dtb_start, node, "reg", &size);
	if (size < (*na+*ns) * sizeof(u32))
		fatal("cannot get memory range\n");

	/*                                      */
	for (i = 0; i < *na; i++)
		if (*reg++ != 0)
			fatal("Memory range is not based at address 0\n");

	/*                                                               */
	memsize64 = 0;
	for (i = 0; i < *ns; i++)
		memsize64 = (memsize64 << 32) | *reg++;
	if (sizeof(void *) == 4 && memsize64 >= 0x100000000ULL)
		memsize64 = 0xffffffff;

	/*                             */
	node = fdt_node_offset_by_prop_value(_dtb_start, -1, "device_type",
					     "cpu", sizeof("cpu"));
	if (!node)
		fatal("Cannot find cpu node\n");
	timebase = fdt_getprop(_dtb_start, node, "timebase-frequency", &size);
	if (timebase && (size == 4))
		timebase_period_ns = 1000000000 / *timebase;

	/*                                                  */
	simple_alloc_init(_end, memsize64 - (unsigned long)_end, 32, 64);

	/*                                              */
	fdt_init(_dtb_start);

	if (platform_specific_init)
		platform_specific_init();

	serial_console_init();
}
Beispiel #25
0
void ft_cpu_setup(void *blob, bd_t *bd)
{
	immap_t *immr = (immap_t *)CONFIG_SYS_IMMR;
	int spridr = immr->sysconf.spridr;

	/*
	 * delete crypto node if not on an E-processor
	 * initial revisions of the MPC834xE/6xE have the original SEC 2.0.
	 * EA revisions got the SEC uprevved to 2.4 but since the default device
	 * tree contains SEC 2.0 properties we uprev them here.
	 */
	if (!IS_E_PROCESSOR(spridr))
		fdt_fixup_crypto_node(blob, 0);
	else if (IS_E_PROCESSOR(spridr) &&
		 (SPR_FAMILY(spridr) == SPR_834X_FAMILY ||
		  SPR_FAMILY(spridr) == SPR_836X_FAMILY) &&
		 REVID_MAJOR(spridr) >= 2)
		fdt_fixup_crypto_node(blob, 0x0204);

#if defined(CONFIG_HAS_ETH0) || defined(CONFIG_HAS_ETH1) ||\
    defined(CONFIG_HAS_ETH2) || defined(CONFIG_HAS_ETH3) ||\
    defined(CONFIG_HAS_ETH4) || defined(CONFIG_HAS_ETH5)
	fdt_fixup_ethernet(blob);
#ifdef CONFIG_MPC8313
	/*
	* mpc8313e erratum IPIC1 swapped TSEC interrupt ID numbers on rev. 1
	* h/w (see AN3545).  The base device tree in use has rev. 1 ID numbers,
	* so if on Rev. 2 (and higher) h/w, we fix them up here
	*/
	if (REVID_MAJOR(immr->sysconf.spridr) >= 2) {
		int nodeoffset, path;
		const char *prop;

		nodeoffset = fdt_path_offset(blob, "/aliases");
		if (nodeoffset >= 0) {
#if defined(CONFIG_HAS_ETH0)
			prop = fdt_getprop(blob, nodeoffset, "ethernet0", NULL);
			if (prop) {
				u32 tmp[] = { 32, 0x8, 33, 0x8, 34, 0x8 };

				path = fdt_path_offset(blob, prop);
				prop = fdt_getprop(blob, path, "interrupts",
						   NULL);
				if (prop)
					fdt_setprop(blob, path, "interrupts",
						    &tmp, sizeof(tmp));
			}
#endif
#if defined(CONFIG_HAS_ETH1)
			prop = fdt_getprop(blob, nodeoffset, "ethernet1", NULL);
			if (prop) {
				u32 tmp[] = { 35, 0x8, 36, 0x8, 37, 0x8 };

				path = fdt_path_offset(blob, prop);
				prop = fdt_getprop(blob, path, "interrupts",
						   NULL);
				if (prop)
					fdt_setprop(blob, path, "interrupts",
						    &tmp, sizeof(tmp));
			}
#endif
		}
	}
#endif
#endif

	do_fixup_by_prop_u32(blob, "device_type", "cpu", 4,
		"timebase-frequency", (bd->bi_busfreq / 4), 1);
	do_fixup_by_prop_u32(blob, "device_type", "cpu", 4,
		"bus-frequency", bd->bi_busfreq, 1);
	do_fixup_by_prop_u32(blob, "device_type", "cpu", 4,
		"clock-frequency", gd->core_clk, 1);
	do_fixup_by_prop_u32(blob, "device_type", "soc", 4,
		"bus-frequency", bd->bi_busfreq, 1);
	do_fixup_by_compat_u32(blob, "fsl,soc",
		"bus-frequency", bd->bi_busfreq, 1);
	do_fixup_by_compat_u32(blob, "fsl,soc",
		"clock-frequency", bd->bi_busfreq, 1);
	do_fixup_by_compat_u32(blob, "fsl,immr",
		"bus-frequency", bd->bi_busfreq, 1);
	do_fixup_by_compat_u32(blob, "fsl,immr",
		"clock-frequency", bd->bi_busfreq, 1);
#ifdef CONFIG_QE
	ft_qe_setup(blob);
#endif

#ifdef CONFIG_SYS_NS16550
	do_fixup_by_compat_u32(blob, "ns16550",
		"clock-frequency", CONFIG_SYS_NS16550_CLK, 1);
#endif

	fdt_fixup_memory(blob, (u64)bd->bi_memstart, (u64)bd->bi_memsize);

#if defined(CONFIG_BOOTCOUNT_LIMIT)
	fdt_fixup_muram (blob);
#endif
}
Beispiel #26
0
/* TODO: Can we tighten this code up a little? */
int fdtdec_add_aliases_for_id(const void *blob, const char *name,
			enum fdt_compat_id id, int *node_list, int maxcount)
{
	int name_len = strlen(name);
	int nodes[maxcount];
	int num_found = 0;
	int offset, node;
	int alias_node;
	int count;
	int i, j;

	/* find the alias node if present */
	alias_node = fdt_path_offset(blob, "/aliases");

	/*
	 * start with nothing, and we can assume that the root node can't
	 * match
	 */
	memset(nodes, '\0', sizeof(nodes));

	/* First find all the compatible nodes */
	for (node = count = 0; node >= 0 && count < maxcount;) {
		node = fdtdec_next_compatible(blob, node, id);
		if (node >= 0)
			nodes[count++] = node;
	}
	if (node >= 0)
		debug("%s: warning: maxcount exceeded with alias '%s'\n",
		       __func__, name);

	/* Now find all the aliases */
	for (offset = fdt_first_property_offset(blob, alias_node);
			offset > 0;
			offset = fdt_next_property_offset(blob, offset)) {
		const struct fdt_property *prop;
		const char *path;
		int number;
		int found;

		node = 0;
		prop = fdt_get_property_by_offset(blob, offset, NULL);
		path = fdt_string(blob, fdt32_to_cpu(prop->nameoff));
		if (prop->len && 0 == strncmp(path, name, name_len))
			node = fdt_path_offset(blob, prop->data);
		if (node <= 0)
			continue;

		/* Get the alias number */
		number = simple_strtoul(path + name_len, NULL, 10);
		if (number < 0 || number >= maxcount) {
			debug("%s: warning: alias '%s' is out of range\n",
			       __func__, path);
			continue;
		}

		/* Make sure the node we found is actually in our list! */
		found = -1;
		for (j = 0; j < count; j++)
			if (nodes[j] == node) {
				found = j;
				break;
			}

		if (found == -1) {
			debug("%s: warning: alias '%s' points to a node "
				"'%s' that is missing or is not compatible "
				" with '%s'\n", __func__, path,
				fdt_get_name(blob, node, NULL),
			       compat_names[id]);
			continue;
		}

		/*
		 * Add this node to our list in the right place, and mark
		 * it as done.
		 */
		if (fdtdec_get_is_enabled(blob, node)) {
			if (node_list[number]) {
				debug("%s: warning: alias '%s' requires that "
				      "a node be placed in the list in a "
				      "position which is already filled by "
				      "node '%s'\n", __func__, path,
				      fdt_get_name(blob, node, NULL));
				continue;
			}
			node_list[number] = node;
			if (number >= num_found)
				num_found = number + 1;
		}
		nodes[found] = 0;
	}

	/* Add any nodes not mentioned by an alias */
	for (i = j = 0; i < maxcount; i++) {
		if (!node_list[i]) {
			for (; j < maxcount; j++)
				if (nodes[j] &&
					fdtdec_get_is_enabled(blob, nodes[j]))
					break;

			/* Have we run out of nodes to add? */
			if (j == maxcount)
				break;

			assert(!node_list[i]);
			node_list[i] = nodes[j++];
			if (i >= num_found)
				num_found = i + 1;
		}
	}

	return num_found;
}
Beispiel #27
0
static int ait_menu_check_image(void)
{
	char *s;
	unsigned long fit_addr;
	void *addr;
	int format;
	char *desc;
	char *subtype;
	int images_noffset;
	int noffset;
	int ndepth;
	int count = 0;
	int ret;
	int i;
	int found_uboot = -1;
	int found_ramdisk = -1;

	memset(imgs, 0, sizeof(imgs));
	s = getenv("fit_addr_r");
	fit_addr = s ? (unsigned long)simple_strtol(s, NULL, 16) : \
			CONFIG_BOARD_IMG_ADDR_R;

	addr = (void *)fit_addr;
	/* check if it is a FIT image */
	format = genimg_get_format(addr);
	if (format != IMAGE_FORMAT_FIT)
		return -EINVAL;

	if (!fit_check_format(addr))
		return -EINVAL;

	/* print the FIT description */
	ret = fit_get_desc(addr, 0, &desc);
	printf("FIT description: ");
	if (ret)
		printf("unavailable\n");
	else
		printf("%s\n", desc);

	/* find images */
	images_noffset = fdt_path_offset(addr, FIT_IMAGES_PATH);
	if (images_noffset < 0) {
		printf("Can't find images parent node '%s' (%s)\n",
			FIT_IMAGES_PATH, fdt_strerror(images_noffset));
		return -EINVAL;
	}

	/* Process its subnodes, print out component images details */
	for (ndepth = 0, count = 0,
		noffset = fdt_next_node(addr, images_noffset, &ndepth);
		(noffset >= 0) && (ndepth > 0);
		noffset = fdt_next_node(addr, noffset, &ndepth)) {
		if (ndepth == 1) {
			/*
			 * Direct child node of the images parent node,
			 * i.e. component image node.
			 */
			printf("Image %u (%s)\n", count,
					fit_get_name(addr, noffset, NULL));

			fit_image_print(addr, noffset, "");

			fit_image_get_type(addr, noffset,
				&imgs[count].type);
			/* Mandatory properties */
			ret = fit_get_desc(addr, noffset, &desc);
			printf("Description:  ");
			if (ret)
				printf("unavailable\n");
			else
				printf("%s\n", desc);

			ret = fit_get_subtype(addr, noffset, &subtype);
			printf("Subtype:  ");
			if (ret) {
				printf("unavailable\n");
			} else {
				imgs[count].subtype = ait_subtype_nr(subtype);
				printf("%s %d\n", subtype,
					imgs[count].subtype);
			}

			sprintf(imgs[count].desc, "%s", desc);

			ret = fit_image_get_data(addr, noffset,
				&imgs[count].data,
				&imgs[count].size);

			printf("Data Size:    ");
			if (ret)
				printf("unavailable\n");
			else
				genimg_print_size(imgs[count].size);
			printf("Data @ %p\n", imgs[count].data);
			count++;
		}
	}

	for (i = 0; i < count; i++) {
		if (imgs[i].subtype == FIT_SUBTYPE_UBOOT_IMAGE)
			found_uboot = i;
		if (imgs[i].type == IH_TYPE_RAMDISK) {
			found_ramdisk = i;
			imgs[i].subtype = FIT_SUBTYPE_RAMDISK_IMAGE;
		}
	}

	/* dvn_* env var update, if the FIT descriptors are different */
	if (found_uboot >= 0) {
		s = getenv("dvn_boot_vers");
		if (s) {
			ret = strcmp(s, imgs[found_uboot].desc);
			if (ret != 0) {
				setenv("x_dvn_boot_vers",
					imgs[found_uboot].desc);
			} else {
				found_uboot = -1;
				printf("no new uboot version\n");
			}
		} else {
			setenv("dvn_boot_vers", imgs[found_uboot].desc);
		}
	}
	if (found_ramdisk >= 0) {
		s = getenv("dvn_app_vers");
		if (s) {
			ret = strcmp(s, imgs[found_ramdisk].desc);
			if (ret != 0) {
				setenv("x_dvn_app_vers",
					imgs[found_ramdisk].desc);
			} else {
				found_ramdisk = -1;
				printf("no new ramdisk version\n");
			}
		} else {
			setenv("dvn_app_vers", imgs[found_ramdisk].desc);
		}
	}
	if ((found_uboot == -1) && (found_ramdisk == -1))
		return -EINVAL;

	return 0;
}
Beispiel #28
0
int fdt_initrd(void *fdt, ulong initrd_start, ulong initrd_end, int force)
{
	int   nodeoffset;
	int   err, j, total;
	u32   tmp;
	const char *path;
	uint64_t addr, size;

	/* Find the "chosen" node.  */
	nodeoffset = fdt_path_offset (fdt, "/chosen");

	/* If there is no "chosen" node in the blob return */
	if (nodeoffset < 0) {
		printf("fdt_initrd: %s\n", fdt_strerror(nodeoffset));
		return nodeoffset;
	}

	/* just return if initrd_start/end aren't valid */
	if ((initrd_start == 0) || (initrd_end == 0))
		return 0;

	total = fdt_num_mem_rsv(fdt);

	/*
	 * Look for an existing entry and update it.  If we don't find
	 * the entry, we will j be the next available slot.
	 */
	for (j = 0; j < total; j++) {
		err = fdt_get_mem_rsv(fdt, j, &addr, &size);
		if (addr == initrd_start) {
			fdt_del_mem_rsv(fdt, j);
			break;
		}
	}

	err = fdt_add_mem_rsv(fdt, initrd_start, initrd_end - initrd_start);
	if (err < 0) {
		printf("fdt_initrd: %s\n", fdt_strerror(err));
		return err;
	}

	path = fdt_getprop(fdt, nodeoffset, "linux,initrd-start", NULL);
	if ((path == NULL) || force) {
		tmp = __cpu_to_be32(initrd_start);
		err = fdt_setprop(fdt, nodeoffset,
			"linux,initrd-start", &tmp, sizeof(tmp));
		if (err < 0) {
			printf("WARNING: "
				"could not set linux,initrd-start %s.\n",
				fdt_strerror(err));
			return err;
		}
		tmp = __cpu_to_be32(initrd_end);
		err = fdt_setprop(fdt, nodeoffset,
			"linux,initrd-end", &tmp, sizeof(tmp));
		if (err < 0) {
			printf("WARNING: could not set linux,initrd-end %s.\n",
				fdt_strerror(err));

			return err;
		}
	}

	return 0;
}
Beispiel #29
0
/**
 * fit_conf_find_compat
 * @fit: pointer to the FIT format image header
 * @fdt: pointer to the device tree to compare against
 *
 * fit_conf_find_compat() attempts to find the configuration whose fdt is the
 * most compatible with the passed in device tree.
 *
 * Example:
 *
 * / o image-tree
 *   |-o images
 *   | |-o fdt@1
 *   | |-o fdt@2
 *   |
 *   |-o configurations
 *     |-o config@1
 *     | |-fdt = fdt@1
 *     |
 *     |-o config@2
 *       |-fdt = fdt@2
 *
 * / o U-Boot fdt
 *   |-compatible = "foo,bar", "bim,bam"
 *
 * / o kernel fdt1
 *   |-compatible = "foo,bar",
 *
 * / o kernel fdt2
 *   |-compatible = "bim,bam", "baz,biz"
 *
 * Configuration 1 would be picked because the first string in U-Boot's
 * compatible list, "foo,bar", matches a compatible string in the root of fdt1.
 * "bim,bam" in fdt2 matches the second string which isn't as good as fdt1.
 *
 * returns:
 *     offset to the configuration to use if one was found
 *     -1 otherwise
 */
int fit_conf_find_compat(const void *fit, const void *fdt)
{
	int ndepth = 0;
	int noffset, confs_noffset, images_noffset;
	const void *fdt_compat;
	int fdt_compat_len;
	int best_match_offset = 0;
	int best_match_pos = 0;

	confs_noffset = fdt_path_offset(fit, FIT_CONFS_PATH);
	images_noffset = fdt_path_offset(fit, FIT_IMAGES_PATH);
	if (confs_noffset < 0 || images_noffset < 0) {
		debug("Can't find configurations or images nodes.\n");
		return -1;
	}

	fdt_compat = fdt_getprop(fdt, 0, "compatible", &fdt_compat_len);
	if (!fdt_compat) {
		debug("Fdt for comparison has no \"compatible\" property.\n");
		return -1;
	}

	/*
	 * Loop over the configurations in the FIT image.
	 */
	for (noffset = fdt_next_node(fit, confs_noffset, &ndepth);
			(noffset >= 0) && (ndepth > 0);
			noffset = fdt_next_node(fit, noffset, &ndepth)) {
		const void *kfdt;
		const char *kfdt_name;
		int kfdt_noffset;
		const char *cur_fdt_compat;
		int len;
		size_t size;
		int i;

		if (ndepth > 1)
			continue;

		kfdt_name = fdt_getprop(fit, noffset, "fdt", &len);
		if (!kfdt_name) {
			debug("No fdt property found.\n");
			continue;
		}
		kfdt_noffset = fdt_subnode_offset(fit, images_noffset,
						  kfdt_name);
		if (kfdt_noffset < 0) {
			debug("No image node named \"%s\" found.\n",
			      kfdt_name);
			continue;
		}
		/*
		 * Get a pointer to this configuration's fdt.
		 */
		if (fit_image_get_data(fit, kfdt_noffset, &kfdt, &size)) {
			debug("Failed to get fdt \"%s\".\n", kfdt_name);
			continue;
		}

		len = fdt_compat_len;
		cur_fdt_compat = fdt_compat;
		/*
		 * Look for a match for each U-Boot compatibility string in
		 * turn in this configuration's fdt.
		 */
		for (i = 0; len > 0 &&
		     (!best_match_offset || best_match_pos > i); i++) {
			int cur_len = strlen(cur_fdt_compat) + 1;

			if (!fdt_node_check_compatible(kfdt, 0,
						       cur_fdt_compat)) {
				best_match_offset = noffset;
				best_match_pos = i;
				break;
			}
			len -= cur_len;
			cur_fdt_compat += cur_len;
		}
	}
	if (!best_match_offset) {
		debug("No match found.\n");
		return -1;
	}

	return best_match_offset;
}
/*
 * 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;
}