ia64/xen-unstable

changeset 11506:a22a7797e0ba

[LIBXC][POWERPC] Update to latest flatdevtree snapshot.

Signed-off-by: Hollis Blanchard <hollisb@us.ibm.com>
author Hollis Blanchard <hollisb@us.ibm.com>
date Thu Sep 07 17:25:52 2006 -0500 (2006-09-07)
parents 2ebf55e419c9
children 38d6cf70e8f2
files tools/libxc/powerpc64/Makefile tools/libxc/powerpc64/flatdevtree.c tools/libxc/powerpc64/flatdevtree.h tools/libxc/powerpc64/flatdevtree_env.h tools/libxc/powerpc64/xc_linux_build.c
line diff
     1.1 --- a/tools/libxc/powerpc64/Makefile	Thu Sep 07 21:46:33 2006 -0400
     1.2 +++ b/tools/libxc/powerpc64/Makefile	Thu Sep 07 17:25:52 2006 -0500
     1.3 @@ -1,4 +1,4 @@
     1.4  GUEST_SRCS-y += powerpc64/xc_linux_build.c
     1.5 -GUEST_SRCS-y += powerpc64/ft_build.c
     1.6 +GUEST_SRCS-y += powerpc64/flatdevtree.c
     1.7  
     1.8  CTRL_SRCS-y += powerpc64/xc_memory.c
     2.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     2.2 +++ b/tools/libxc/powerpc64/flatdevtree.c	Thu Sep 07 17:25:52 2006 -0500
     2.3 @@ -0,0 +1,636 @@
     2.4 +/*
     2.5 + * This program is free software; you can redistribute it and/or modify
     2.6 + * it under the terms of the GNU General Public License as published by
     2.7 + * the Free Software Foundation; either version 2 of the License, or
     2.8 + * (at your option) any later version.
     2.9 + *
    2.10 + * This program is distributed in the hope that it will be useful,
    2.11 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
    2.12 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    2.13 + * GNU General Public License for more details.
    2.14 + *
    2.15 + * You should have received a copy of the GNU General Public License
    2.16 + * along with this program; if not, write to the Free Software
    2.17 + * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
    2.18 + *
    2.19 + * Copyright Pantelis Antoniou 2006
    2.20 + * Copyright (C) IBM Corporation 2006
    2.21 + * 2006 (c) MontaVista, Software, Inc.
    2.22 + *
    2.23 + * Authors: Pantelis Antoniou <pantelis@embeddedalley.com>
    2.24 + *          Hollis Blanchard <hollisb@us.ibm.com>
    2.25 + *          Mark A. Greer <mgreer@mvista.com>
    2.26 + */
    2.27 +
    2.28 +#include "flatdevtree.h"
    2.29 +
    2.30 +/* Set ptrs to current one's info; return addr of next one */
    2.31 +static u32 *ft_next(u32 *p, const u32 *p_strings, const u32 version,
    2.32 +		u32 **tagpp, char **namepp, char **datapp, u32 **sizepp)
    2.33 +{
    2.34 +	u32 sz;
    2.35 +
    2.36 +	*namepp = NULL;
    2.37 +	*datapp = NULL;
    2.38 +	*sizepp = NULL;
    2.39 +	*tagpp = p;
    2.40 +
    2.41 +	switch (be32_to_cpu(*p++)) { /* Tag */
    2.42 +	case OF_DT_BEGIN_NODE:
    2.43 +		*namepp = (char *)p;
    2.44 +		p = (u32 *)_ALIGN((unsigned long)p + strlen((char *)p) + 1, 4);
    2.45 +		break;
    2.46 +	case OF_DT_PROP:
    2.47 +		sz = be32_to_cpu(*p);
    2.48 +		*sizepp = p++;
    2.49 +		*namepp = (char *)p_strings + be32_to_cpu(*p++);
    2.50 +		if ((version < 0x10) && (sz >= 8))
    2.51 +			p = (u32 *)_ALIGN((unsigned long)p, 8);
    2.52 +		*datapp = (char *)p;
    2.53 +		p = (u32 *)_ALIGN((unsigned long)p + sz, 4);
    2.54 +		break;
    2.55 +	case OF_DT_END_NODE:
    2.56 +	case OF_DT_NOP:
    2.57 +		break;
    2.58 +	case OF_DT_END:
    2.59 +	default:
    2.60 +		p = NULL;
    2.61 +		break;
    2.62 +	}
    2.63 +
    2.64 +	return p;
    2.65 +}
    2.66 +
    2.67 +static void ft_put_word(struct ft_cxt *cxt, u32 v)
    2.68 +{
    2.69 +	if (cxt->overflow)	/* do nothing */
    2.70 +		return;
    2.71 +
    2.72 +	/* check for overflow */
    2.73 +	if (cxt->p + 4 > cxt->pstr) {
    2.74 +		cxt->overflow = 1;
    2.75 +		return;
    2.76 +	}
    2.77 +
    2.78 +	*(u32 *) cxt->p = cpu_to_be32(v);
    2.79 +	cxt->p += 4;
    2.80 +}
    2.81 +
    2.82 +static inline void ft_put_bin(struct ft_cxt *cxt, const void *data, int sz)
    2.83 +{
    2.84 +	char *p;
    2.85 +
    2.86 +	if (cxt->overflow)	/* do nothing */
    2.87 +		return;
    2.88 +
    2.89 +	/* next pointer pos */
    2.90 +	p = (char *) _ALIGN((unsigned long)cxt->p + sz, 4);
    2.91 +
    2.92 +	/* check for overflow */
    2.93 +	if (p > cxt->pstr) {
    2.94 +		cxt->overflow = 1;
    2.95 +		return;
    2.96 +	}
    2.97 +
    2.98 +	memcpy(cxt->p, data, sz);
    2.99 +	if ((sz & 3) != 0)
   2.100 +		memset(cxt->p + sz, 0, 4 - (sz & 3));
   2.101 +	cxt->p = p;
   2.102 +}
   2.103 +
   2.104 +void ft_begin_node(struct ft_cxt *cxt, const char *name)
   2.105 +{
   2.106 +	ft_put_word(cxt, OF_DT_BEGIN_NODE);
   2.107 +	ft_put_bin(cxt, name, strlen(name) + 1);
   2.108 +}
   2.109 +
   2.110 +void ft_end_node(struct ft_cxt *cxt)
   2.111 +{
   2.112 +	ft_put_word(cxt, OF_DT_END_NODE);
   2.113 +}
   2.114 +
   2.115 +void ft_nop(struct ft_cxt *cxt)
   2.116 +{
   2.117 +	ft_put_word(cxt, OF_DT_NOP);
   2.118 +}
   2.119 +
   2.120 +static int lookup_string(struct ft_cxt *cxt, const char *name)
   2.121 +{
   2.122 +	char *p;
   2.123 +
   2.124 +	p = cxt->pstr;
   2.125 +	while (p < cxt->pstr_begin) {
   2.126 +		if (strcmp(p, (char *)name) == 0)
   2.127 +			return p - cxt->p_begin;
   2.128 +		p += strlen(p) + 1;
   2.129 +	}
   2.130 +
   2.131 +	return -1;
   2.132 +}
   2.133 +
   2.134 +void ft_prop(struct ft_cxt *cxt, const char *name,
   2.135 +		const void *data, unsigned int sz)
   2.136 +{
   2.137 +	int len, off;
   2.138 +
   2.139 +	if (cxt->overflow)
   2.140 +		return;
   2.141 +
   2.142 +	len = strlen(name) + 1;
   2.143 +
   2.144 +	off = lookup_string(cxt, name);
   2.145 +	if (off == -1) {
   2.146 +		/* check if we have space */
   2.147 +		if (cxt->p + 12 + sz + len > cxt->pstr) {
   2.148 +			cxt->overflow = 1;
   2.149 +			return;
   2.150 +		}
   2.151 +
   2.152 +		cxt->pstr -= len;
   2.153 +		memcpy(cxt->pstr, name, len);
   2.154 +		off = cxt->pstr - cxt->p_begin;
   2.155 +	}
   2.156 +
   2.157 +	/* now put offset from beginning of *STRUCTURE* */
   2.158 +	/* will be fixed up at the end */
   2.159 +	ft_put_word(cxt, OF_DT_PROP);
   2.160 +	ft_put_word(cxt, sz);
   2.161 +	ft_put_word(cxt, off);
   2.162 +	ft_put_bin(cxt, data, sz);
   2.163 +}
   2.164 +
   2.165 +void ft_prop_str(struct ft_cxt *cxt, const char *name, const char *str)
   2.166 +{
   2.167 +	ft_prop(cxt, name, str, strlen(str) + 1);
   2.168 +}
   2.169 +
   2.170 +void ft_prop_int(struct ft_cxt *cxt, const char *name, unsigned int val)
   2.171 +{
   2.172 +	u32 v = cpu_to_be32((u32) val);
   2.173 +
   2.174 +	ft_prop(cxt, name, &v, 4);
   2.175 +}
   2.176 +
   2.177 +/* start construction of the flat OF tree */
   2.178 +void ft_begin(struct ft_cxt *cxt, void *blob, unsigned int max_size)
   2.179 +{
   2.180 +	struct boot_param_header *bph = blob;
   2.181 +	u32 off;
   2.182 +
   2.183 +	/* clear the cxt */
   2.184 +	memset(cxt, 0, sizeof(*cxt));
   2.185 +
   2.186 +	cxt->bph = bph;
   2.187 +	cxt->max_size = max_size;
   2.188 +
   2.189 +	/* zero everything in the header area */
   2.190 +	memset(bph, 0, sizeof(*bph));
   2.191 +
   2.192 +	bph->magic = cpu_to_be32(OF_DT_HEADER);
   2.193 +	bph->version = cpu_to_be32(0x10);
   2.194 +	bph->last_comp_version = cpu_to_be32(0x10);
   2.195 +
   2.196 +	/* start pointers */
   2.197 +	cxt->pres_begin = (char *) _ALIGN((unsigned long)(bph + 1), 8);
   2.198 +	cxt->pres = cxt->pres_begin;
   2.199 +
   2.200 +	off = (unsigned long)cxt->pres_begin - (unsigned long)bph;
   2.201 +	bph->off_mem_rsvmap = cpu_to_be32(off);
   2.202 +
   2.203 +	((u64 *) cxt->pres)[0] = 0;	/* phys = 0, size = 0, terminate */
   2.204 +	((u64 *) cxt->pres)[1] = 0;
   2.205 +
   2.206 +	cxt->p_anchor = cxt->pres + 16;	/* over the terminator */
   2.207 +}
   2.208 +
   2.209 +/* add a reserver physical area to the rsvmap */
   2.210 +void ft_add_rsvmap(struct ft_cxt *cxt, u64 physaddr, u64 size)
   2.211 +{
   2.212 +	((u64 *) cxt->pres)[0] = cpu_to_be64(physaddr);	/* phys = 0, size = 0, terminate */
   2.213 +	((u64 *) cxt->pres)[1] = cpu_to_be64(size);
   2.214 +
   2.215 +	cxt->pres += 18;	/* advance */
   2.216 +
   2.217 +	((u64 *) cxt->pres)[0] = 0;	/* phys = 0, size = 0, terminate */
   2.218 +	((u64 *) cxt->pres)[1] = 0;
   2.219 +
   2.220 +	/* keep track of size */
   2.221 +	cxt->res_size = cxt->pres + 16 - cxt->pres_begin;
   2.222 +
   2.223 +	cxt->p_anchor = cxt->pres + 16;	/* over the terminator */
   2.224 +}
   2.225 +
   2.226 +void ft_begin_tree(struct ft_cxt *cxt)
   2.227 +{
   2.228 +	cxt->p_begin = cxt->p_anchor;
   2.229 +	cxt->pstr_begin = (char *)cxt->bph + cxt->max_size;	/* point at the end */
   2.230 +
   2.231 +	cxt->p = cxt->p_begin;
   2.232 +	cxt->pstr = cxt->pstr_begin;
   2.233 +}
   2.234 +
   2.235 +int ft_end_tree(struct ft_cxt *cxt)
   2.236 +{
   2.237 +	struct boot_param_header *bph = cxt->bph;
   2.238 +	int off, sz, sz1;
   2.239 +	u32 tag, v;
   2.240 +	char *p;
   2.241 +
   2.242 +	ft_put_word(cxt, OF_DT_END);
   2.243 +
   2.244 +	if (cxt->overflow)
   2.245 +		return -ENOMEM;
   2.246 +
   2.247 +	/* size of the areas */
   2.248 +	cxt->struct_size = cxt->p - cxt->p_begin;
   2.249 +	cxt->strings_size = cxt->pstr_begin - cxt->pstr;
   2.250 +
   2.251 +	/* the offset we must move */
   2.252 +	off = (cxt->pstr_begin - cxt->p_begin) - cxt->strings_size;
   2.253 +
   2.254 +	/* the new strings start */
   2.255 +	cxt->pstr_begin = cxt->p_begin + cxt->struct_size;
   2.256 +
   2.257 +	/* move the whole string area */
   2.258 +	memmove(cxt->pstr_begin, cxt->pstr, cxt->strings_size);
   2.259 +
   2.260 +	/* now perform the fixup of the strings */
   2.261 +	p = cxt->p_begin;
   2.262 +	while ((tag = be32_to_cpu(*(u32 *) p)) != OF_DT_END) {
   2.263 +		p += 4;
   2.264 +
   2.265 +		if (tag == OF_DT_BEGIN_NODE) {
   2.266 +			p = (char *) _ALIGN((unsigned long)p + strlen(p) + 1, 4);
   2.267 +			continue;
   2.268 +		}
   2.269 +
   2.270 +		if (tag == OF_DT_END_NODE || tag == OF_DT_NOP)
   2.271 +			continue;
   2.272 +
   2.273 +		if (tag != OF_DT_PROP)
   2.274 +			return -EINVAL;
   2.275 +
   2.276 +		sz = be32_to_cpu(*(u32 *) p);
   2.277 +		p += 4;
   2.278 +
   2.279 +		v = be32_to_cpu(*(u32 *) p);
   2.280 +		v -= off;
   2.281 +		*(u32 *) p = cpu_to_be32(v);	/* move down */
   2.282 +		p += 4;
   2.283 +
   2.284 +		p = (char *) _ALIGN((unsigned long)p + sz, 4);
   2.285 +	}
   2.286 +
   2.287 +	/* fix sizes */
   2.288 +	p = (char *)cxt->bph;
   2.289 +	sz = (cxt->pstr_begin + cxt->strings_size) - p;
   2.290 +	sz1 = _ALIGN(sz, 16);	/* align at 16 bytes */
   2.291 +	if (sz != sz1)
   2.292 +		memset(p + sz, 0, sz1 - sz);
   2.293 +	bph->totalsize = cpu_to_be32(sz1);
   2.294 +	bph->off_dt_struct = cpu_to_be32(cxt->p_begin - p);
   2.295 +	bph->off_dt_strings = cpu_to_be32(cxt->pstr_begin - p);
   2.296 +
   2.297 +	/* the new strings start */
   2.298 +	cxt->pstr_begin = cxt->p_begin + cxt->struct_size;
   2.299 +	cxt->pstr = cxt->pstr_begin + cxt->strings_size;
   2.300 +
   2.301 +	return 0;
   2.302 +}
   2.303 +
   2.304 +/**********************************************************************/
   2.305 +
   2.306 +static inline int isprint(int c)
   2.307 +{
   2.308 +	return c >= 0x20 && c <= 0x7e;
   2.309 +}
   2.310 +
   2.311 +static int is_printable_string(const void *data, int len)
   2.312 +{
   2.313 +	const char *s = data;
   2.314 +	const char *ss;
   2.315 +
   2.316 +	/* zero length is not */
   2.317 +	if (len == 0)
   2.318 +		return 0;
   2.319 +
   2.320 +	/* must terminate with zero */
   2.321 +	if (s[len - 1] != '\0')
   2.322 +		return 0;
   2.323 +
   2.324 +	ss = s;
   2.325 +	while (*s && isprint(*s))
   2.326 +		s++;
   2.327 +
   2.328 +	/* not zero, or not done yet */
   2.329 +	if (*s != '\0' || (s + 1 - ss) < len)
   2.330 +		return 0;
   2.331 +
   2.332 +	return 1;
   2.333 +}
   2.334 +
   2.335 +static void print_data(const void *data, int len)
   2.336 +{
   2.337 +	int i;
   2.338 +	const char *s;
   2.339 +
   2.340 +	/* no data, don't print */
   2.341 +	if (len == 0)
   2.342 +		return;
   2.343 +
   2.344 +	if (is_printable_string(data, len)) {
   2.345 +		printf(" = \"%s\"", (char *)data);
   2.346 +		return;
   2.347 +	}
   2.348 +
   2.349 +	switch (len) {
   2.350 +	case 1:		/* byte */
   2.351 +		printf(" = <0x%02x>", (*(char *) data) & 0xff);
   2.352 +		break;
   2.353 +	case 2:		/* half-word */
   2.354 +		printf(" = <0x%04x>", be16_to_cpu(*(u16 *) data) & 0xffff);
   2.355 +		break;
   2.356 +	case 4:		/* word */
   2.357 +		printf(" = <0x%08x>", be32_to_cpu(*(u32 *) data) & 0xffffffffU);
   2.358 +		break;
   2.359 +	case 8:		/* double-word */
   2.360 +		printf(" = <0x%16llx>", be64_to_cpu(*(u64 *) data));
   2.361 +		break;
   2.362 +	default:		/* anything else... hexdump */
   2.363 +		printf(" = [");
   2.364 +		for (i = 0, s = data; i < len; i++)
   2.365 +			printf("%02x%s", s[i], i < len - 1 ? " " : "");
   2.366 +		printf("]");
   2.367 +
   2.368 +		break;
   2.369 +	}
   2.370 +}
   2.371 +
   2.372 +void ft_dump_blob(const void *bphp)
   2.373 +{
   2.374 +	const struct boot_param_header *bph = bphp;
   2.375 +	const u64 *p_rsvmap = (const u64 *)
   2.376 +		((const char *)bph + be32_to_cpu(bph->off_mem_rsvmap));
   2.377 +	const u32 *p_struct = (const u32 *)
   2.378 +		((const char *)bph + be32_to_cpu(bph->off_dt_struct));
   2.379 +	const u32 *p_strings = (const u32 *)
   2.380 +		((const char *)bph + be32_to_cpu(bph->off_dt_strings));
   2.381 +	const u32 version = be32_to_cpu(bph->version);
   2.382 +	u32 i, *p, *tagp, *sizep;
   2.383 +	char *namep, *datap;
   2.384 +	int depth, shift;
   2.385 +	u64 addr, size;
   2.386 +
   2.387 +
   2.388 +	if (be32_to_cpu(bph->magic) != OF_DT_HEADER) {
   2.389 +		/* not valid tree */
   2.390 +		return;
   2.391 +	}
   2.392 +
   2.393 +	depth = 0;
   2.394 +	shift = 4;
   2.395 +
   2.396 +	for (i = 0;; i++) {
   2.397 +		addr = be64_to_cpu(p_rsvmap[i * 2]);
   2.398 +		size = be64_to_cpu(p_rsvmap[i * 2 + 1]);
   2.399 +		if (addr == 0 && size == 0)
   2.400 +			break;
   2.401 +
   2.402 +		printf("/memreserve/ 0x%llx 0x%llx;\n", addr, size);
   2.403 +	}
   2.404 +
   2.405 +	p = (u32 *)p_struct;
   2.406 +	while ((p = ft_next(p, p_strings, version, &tagp, &namep, &datap,
   2.407 +					&sizep)) != NULL)
   2.408 +		switch (be32_to_cpu(*tagp)) {
   2.409 +		case OF_DT_BEGIN_NODE:
   2.410 +			printf("%*s%s {\n", depth * shift, "", namep);
   2.411 +			depth++;
   2.412 +			break;
   2.413 +		case OF_DT_END_NODE:
   2.414 +			depth--;
   2.415 +			printf("%*s};\n", depth * shift, "");
   2.416 +			break;
   2.417 +		case OF_DT_NOP:
   2.418 +			printf("%*s[NOP]\n", depth * shift, "");
   2.419 +			break;
   2.420 +		case OF_DT_END:
   2.421 +			break;
   2.422 +		case OF_DT_PROP:
   2.423 +			printf("%*s%s", depth * shift, "", namep);
   2.424 +			print_data(datap, *sizep);
   2.425 +			printf(";\n");
   2.426 +			break;
   2.427 +		default:
   2.428 +			fprintf(stderr, "%*s ** Unknown tag 0x%08x\n",
   2.429 +				depth * shift, "", *tagp);
   2.430 +			return;
   2.431 +		}
   2.432 +}
   2.433 +
   2.434 +void ft_backtrack_node(struct ft_cxt *cxt)
   2.435 +{
   2.436 +	if (be32_to_cpu(*(u32 *) (cxt->p - 4)) != OF_DT_END_NODE)
   2.437 +		return;		/* XXX only for node */
   2.438 +
   2.439 +	cxt->p -= 4;
   2.440 +}
   2.441 +
   2.442 +/* note that the root node of the blob is "peeled" off */
   2.443 +void ft_merge_blob(struct ft_cxt *cxt, void *blob)
   2.444 +{
   2.445 +	struct boot_param_header *bph = (struct boot_param_header *)blob;
   2.446 +	u32 *p_struct = (u32 *) ((char *)bph + be32_to_cpu(bph->off_dt_struct));
   2.447 +	u32 *p_strings =
   2.448 +		(u32 *) ((char *)bph + be32_to_cpu(bph->off_dt_strings));
   2.449 +	const u32 version = be32_to_cpu(bph->version);
   2.450 +	u32 *p, *tagp, *sizep;
   2.451 +	char *namep, *datap;
   2.452 +	int depth;
   2.453 +
   2.454 +	if (be32_to_cpu(*(u32 *) (cxt->p - 4)) != OF_DT_END_NODE)
   2.455 +		return;		/* XXX only for node */
   2.456 +
   2.457 +	cxt->p -= 4;
   2.458 +
   2.459 +	depth = 0;
   2.460 +	p = p_struct;
   2.461 +	while ((p = ft_next(p, p_strings, version, &tagp, &namep, &datap,
   2.462 +					&sizep)) != NULL)
   2.463 +		switch (be32_to_cpu(*tagp)) {
   2.464 +		case OF_DT_BEGIN_NODE:
   2.465 +			if (depth++ > 0)
   2.466 +				ft_begin_node(cxt, namep);
   2.467 +			break;
   2.468 +		case OF_DT_END_NODE:
   2.469 +			ft_end_node(cxt);
   2.470 +			if (--depth == 0)
   2.471 +				return;
   2.472 +			break;
   2.473 +		case OF_DT_PROP:
   2.474 +			ft_prop(cxt, namep, datap, *sizep);
   2.475 +			break;
   2.476 +		}
   2.477 +}
   2.478 +
   2.479 +/**********************************************************************/
   2.480 +
   2.481 +void *ft_find_node(const void *bphp, const char *srch_path)
   2.482 +{
   2.483 +	const struct boot_param_header *bph = bphp;
   2.484 +	u32 *p_struct = (u32 *)((char *)bph + be32_to_cpu(bph->off_dt_struct));
   2.485 +	u32 *p_strings= (u32 *)((char *)bph + be32_to_cpu(bph->off_dt_strings));
   2.486 +	u32 version = be32_to_cpu(bph->version);
   2.487 +	u32 *p, *tagp, *sizep;
   2.488 +	char *namep, *datap;
   2.489 +	static char path[MAX_PATH_LEN];
   2.490 +
   2.491 +	path[0] = '\0';
   2.492 +	p = p_struct;
   2.493 +
   2.494 +	while ((p = ft_next(p, p_strings, version, &tagp, &namep, &datap,
   2.495 +					&sizep)) != NULL)
   2.496 +		switch (be32_to_cpu(*tagp)) {
   2.497 +		case OF_DT_BEGIN_NODE:
   2.498 +			strcat(path, namep);
   2.499 +			if (!strcmp(path, srch_path))
   2.500 +				return tagp;
   2.501 +			strcat(path, "/");
   2.502 +			break;
   2.503 +		case OF_DT_END_NODE:
   2.504 +			ft_parentize(path, 1);
   2.505 +			break;
   2.506 +		}
   2.507 +	return NULL;
   2.508 +}
   2.509 +
   2.510 +int ft_get_prop(const void *bphp, const void *node, const char *propname,
   2.511 +		void *buf, const unsigned int buflen)
   2.512 +{
   2.513 +	const struct boot_param_header *bph = bphp;
   2.514 +	u32 *p_strings= (u32 *)((char *)bph + be32_to_cpu(bph->off_dt_strings));
   2.515 +	u32 version = be32_to_cpu(bph->version);
   2.516 +	u32 *p, *tagp, *sizep, size;
   2.517 +	char *namep, *datap;
   2.518 +	int depth;
   2.519 +
   2.520 +	depth = 0;
   2.521 +	p = (u32 *)node;
   2.522 +
   2.523 +	while ((p = ft_next(p, p_strings, version, &tagp, &namep, &datap,
   2.524 +					&sizep)) != NULL)
   2.525 +		switch (be32_to_cpu(*tagp)) {
   2.526 +		case OF_DT_BEGIN_NODE:
   2.527 +			depth++;
   2.528 +			break;
   2.529 +		case OF_DT_PROP:
   2.530 +			if ((depth == 1) && !strcmp(namep, propname)) {
   2.531 +				size = min(be32_to_cpu(*sizep), (u32)buflen);
   2.532 +				memcpy(buf, datap, size);
   2.533 +				return size;
   2.534 +			}
   2.535 +			break;
   2.536 +		case OF_DT_END_NODE:
   2.537 +			if (--depth <= 0)
   2.538 +				return -1;
   2.539 +			break;
   2.540 +		}
   2.541 +	return -1;
   2.542 +}
   2.543 +
   2.544 +static void ft_modify_prop(void **bphpp, char *datap, u32 *old_prop_sizep,
   2.545 +		const char *buf, const unsigned int buflen)
   2.546 +{
   2.547 +	u32 old_prop_data_len, new_prop_data_len;
   2.548 +
   2.549 +	old_prop_data_len = _ALIGN(be32_to_cpu(*old_prop_sizep), 4);
   2.550 +	new_prop_data_len = _ALIGN(buflen, 4);
   2.551 +
   2.552 +	/* Check if new prop data fits in old prop data area */
   2.553 +	if (new_prop_data_len == old_prop_data_len) {
   2.554 +		memcpy(datap, buf, buflen);
   2.555 +		*old_prop_sizep = cpu_to_be32(buflen);
   2.556 +	} else {
   2.557 +		/* Need to alloc new area to put larger or smaller ft */
   2.558 +		struct boot_param_header *old_bph = *bphpp, *new_bph;
   2.559 +		u32 *old_tailp, *new_tailp, *new_datap;
   2.560 +		u32 old_total_size, new_total_size, head_len, tail_len, diff, v;
   2.561 +
   2.562 +		old_total_size = be32_to_cpu(old_bph->totalsize);
   2.563 +		head_len = (u32)(datap - (char *)old_bph);
   2.564 +		tail_len = old_total_size - (head_len + old_prop_data_len);
   2.565 +		old_tailp = (u32 *)(datap + old_prop_data_len);
   2.566 +		new_total_size = head_len + new_prop_data_len + tail_len;
   2.567 +
   2.568 +		if (!(new_bph = malloc(new_total_size))) {
   2.569 +			printf("Can't alloc space for new ft\n");
   2.570 +			ft_exit(-ENOSPC);
   2.571 +		}
   2.572 +
   2.573 +		new_datap = (u32 *)((char *)new_bph + head_len);
   2.574 +		new_tailp = (u32 *)((char *)new_datap + new_prop_data_len);
   2.575 +
   2.576 +		memcpy(new_bph, *bphpp, head_len);
   2.577 +		memcpy(new_datap, buf, buflen);
   2.578 +		memcpy(new_tailp, old_tailp, tail_len);
   2.579 +
   2.580 +		*(new_datap - 2) = cpu_to_be32(buflen); /* Set prop size */
   2.581 +
   2.582 +		new_bph->totalsize = cpu_to_be32(new_total_size);
   2.583 +		diff = new_prop_data_len - old_prop_data_len;
   2.584 +
   2.585 +		if (be32_to_cpu(old_bph->off_dt_strings)
   2.586 +				> be32_to_cpu(old_bph->off_dt_struct)) {
   2.587 +			v = be32_to_cpu(new_bph->off_dt_strings);
   2.588 +			new_bph->off_dt_strings = cpu_to_be32(v + diff);
   2.589 +		}
   2.590 +
   2.591 +		if (be32_to_cpu(old_bph->off_mem_rsvmap)
   2.592 +				> be32_to_cpu(old_bph->off_dt_struct)) {
   2.593 +			v = be32_to_cpu(new_bph->off_mem_rsvmap);
   2.594 +			new_bph->off_mem_rsvmap = cpu_to_be32(v + diff);
   2.595 +		}
   2.596 +
   2.597 +		ft_free(*bphpp, old_total_size);
   2.598 +		*bphpp = new_bph;
   2.599 +	}
   2.600 +}
   2.601 +
   2.602 +/*
   2.603 + * - Only modifies existing properties.
   2.604 + * - The dev tree passed in may be freed and a new one allocated
   2.605 + *   (and *bphpp set to location of new dev tree).
   2.606 + */
   2.607 +int ft_set_prop(void **bphpp, const void *node, const char *propname,
   2.608 +		const void *buf, const unsigned int buflen)
   2.609 +{
   2.610 +	struct boot_param_header *bph = *bphpp;
   2.611 +	u32 *p_strings= (u32 *)((char *)bph + be32_to_cpu(bph->off_dt_strings));
   2.612 +	u32 version = be32_to_cpu(bph->version);
   2.613 +	u32 *p, *tagp, *sizep;
   2.614 +	char *namep, *datap;
   2.615 +	int depth;
   2.616 +
   2.617 +	depth = 0;
   2.618 +	p = (u32 *)node;
   2.619 +
   2.620 +	while ((p = ft_next(p, p_strings, version, &tagp, &namep, &datap,
   2.621 +					&sizep)) != NULL)
   2.622 +		switch (be32_to_cpu(*tagp)) {
   2.623 +		case OF_DT_BEGIN_NODE:
   2.624 +			depth++;
   2.625 +			break;
   2.626 +		case OF_DT_PROP:
   2.627 +			if ((depth == 1) && !strcmp(namep, propname)) {
   2.628 +				ft_modify_prop(bphpp, datap, sizep, buf,
   2.629 +						buflen);
   2.630 +				return be32_to_cpu(*sizep);
   2.631 +			}
   2.632 +			break;
   2.633 +		case OF_DT_END_NODE:
   2.634 +			if (--depth <= 0)
   2.635 +				return -1;
   2.636 +			break;
   2.637 +		}
   2.638 +	return -1;
   2.639 +}
     3.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     3.2 +++ b/tools/libxc/powerpc64/flatdevtree.h	Thu Sep 07 17:25:52 2006 -0500
     3.3 @@ -0,0 +1,106 @@
     3.4 +/*
     3.5 + * This program is free software; you can redistribute it and/or modify
     3.6 + * it under the terms of the GNU General Public License as published by
     3.7 + * the Free Software Foundation; either version 2 of the License, or
     3.8 + * (at your option) any later version.
     3.9 + *
    3.10 + * This program is distributed in the hope that it will be useful,
    3.11 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
    3.12 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    3.13 + * GNU General Public License for more details.
    3.14 + *
    3.15 + * You should have received a copy of the GNU General Public License
    3.16 + * along with this program; if not, write to the Free Software
    3.17 + * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
    3.18 + */
    3.19 +
    3.20 +#ifndef _FLATDEVTREE_H_
    3.21 +#define _FLATDEVTREE_H_
    3.22 +
    3.23 +#include "flatdevtree_env.h"
    3.24 +
    3.25 +/* Definitions used by the flattened device tree */
    3.26 +#define OF_DT_HEADER            0xd00dfeed      /* marker */
    3.27 +#define OF_DT_BEGIN_NODE        0x1     /* Start of node, full name */
    3.28 +#define OF_DT_END_NODE          0x2     /* End node */
    3.29 +#define OF_DT_PROP              0x3     /* Property: name off, size, content */
    3.30 +#define OF_DT_NOP               0x4     /* nop */
    3.31 +#define OF_DT_END               0x9
    3.32 +
    3.33 +#define OF_DT_VERSION           0x10
    3.34 +
    3.35 +struct boot_param_header {
    3.36 +	u32 magic;              /* magic word OF_DT_HEADER */
    3.37 +	u32 totalsize;          /* total size of DT block */
    3.38 +	u32 off_dt_struct;      /* offset to structure */
    3.39 +	u32 off_dt_strings;     /* offset to strings */
    3.40 +	u32 off_mem_rsvmap;     /* offset to memory reserve map */
    3.41 +	u32 version;            /* format version */
    3.42 +	u32 last_comp_version;  /* last compatible version */
    3.43 +	/* version 2 fields below */
    3.44 +	u32 boot_cpuid_phys;    /* Physical CPU id we're booting on */
    3.45 +	/* version 3 fields below */
    3.46 +	u32 dt_strings_size;    /* size of the DT strings block */
    3.47 +};
    3.48 +
    3.49 +struct ft_cxt {
    3.50 +	struct boot_param_header *bph;
    3.51 +	int max_size;           /* maximum size of tree */
    3.52 +	int overflow;           /* set when this happens */
    3.53 +	char *p, *pstr, *pres;  /* running pointers */
    3.54 +	char *p_begin, *pstr_begin, *pres_begin;        /* starting pointers */
    3.55 +	char *p_anchor;         /* start of constructed area */
    3.56 +	int struct_size, strings_size, res_size;
    3.57 +};
    3.58 +
    3.59 +void ft_begin_node(struct ft_cxt *cxt, const char *name);
    3.60 +void ft_end_node(struct ft_cxt *cxt);
    3.61 +
    3.62 +void ft_begin_tree(struct ft_cxt *cxt);
    3.63 +int ft_end_tree(struct ft_cxt *cxt);
    3.64 +
    3.65 +void ft_nop(struct ft_cxt *cxt);
    3.66 +void ft_prop(struct ft_cxt *cxt, const char *name,
    3.67 +             const void *data, unsigned int sz);
    3.68 +void ft_prop_str(struct ft_cxt *cxt, const char *name, const char *str);
    3.69 +void ft_prop_int(struct ft_cxt *cxt, const char *name, unsigned int val);
    3.70 +void ft_begin(struct ft_cxt *cxt, void *blob, unsigned int max_size);
    3.71 +void ft_add_rsvmap(struct ft_cxt *cxt, u64 physaddr, u64 size);
    3.72 +
    3.73 +void ft_dump_blob(const void *bphp);
    3.74 +void ft_merge_blob(struct ft_cxt *cxt, void *blob);
    3.75 +
    3.76 +void *ft_find_node(const void *bphp, const char *srch_path);
    3.77 +int ft_get_prop(const void *bphp, const void *node, const char *propname,
    3.78 +		void *buf, const unsigned int buflen);
    3.79 +int ft_set_prop(void **bphp, const void *node, const char *propname,
    3.80 +		const void *buf, const unsigned int buflen);
    3.81 +
    3.82 +static inline char *ft_strrchr(const char *s, int c)
    3.83 +{
    3.84 +	const char *p = s + strlen(s);
    3.85 +
    3.86 +	do {
    3.87 +		if (*p == (char)c)
    3.88 +			return (char *)p;
    3.89 +	} while (--p >= s);
    3.90 +	return NULL;
    3.91 +}
    3.92 +
    3.93 +/* 'path' is modified */
    3.94 +static inline void ft_parentize(char *path, int leave_slash)
    3.95 +{
    3.96 +	char *s = &path[strlen(path) - 1];
    3.97 +
    3.98 +	if (*s == '/')
    3.99 +		*s = '\0';
   3.100 +	s = ft_strrchr(path, '/');
   3.101 +	if (s != NULL) {
   3.102 +		if (leave_slash)
   3.103 +			s[1] = '\0';
   3.104 +		else if (s[0] == '/')
   3.105 +			s[0] = '\0';
   3.106 +	}
   3.107 +}
   3.108 +
   3.109 +#endif /* FLATDEVTREE_H */
     4.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     4.2 +++ b/tools/libxc/powerpc64/flatdevtree_env.h	Thu Sep 07 17:25:52 2006 -0500
     4.3 @@ -0,0 +1,94 @@
     4.4 +/*
     4.5 + * This program is free software; you can redistribute it and/or modify
     4.6 + * it under the terms of the GNU General Public License as published by
     4.7 + * the Free Software Foundation; either version 2 of the License, or
     4.8 + * (at your option) any later version.
     4.9 + *
    4.10 + * This program is distributed in the hope that it will be useful,
    4.11 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
    4.12 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    4.13 + * GNU General Public License for more details.
    4.14 + *
    4.15 + * You should have received a copy of the GNU General Public License
    4.16 + * along with this program; if not, write to the Free Software
    4.17 + * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
    4.18 + */
    4.19 +
    4.20 +#ifndef _FLATDEVTREE_ENV_H_
    4.21 +#define _FLATDEVTREE_ENV_H_
    4.22 +
    4.23 +#include <stdarg.h>
    4.24 +#include <stdio.h>
    4.25 +#include <stdlib.h>
    4.26 +#include <string.h>
    4.27 +#include <endian.h>
    4.28 +#include <errno.h>
    4.29 +
    4.30 +#define MAX_PATH_LEN 1024
    4.31 +
    4.32 +#define _ALIGN(addr,size)       (((addr)+(size)-1)&(~((size)-1)))
    4.33 +
    4.34 +typedef unsigned short u16;
    4.35 +typedef unsigned int u32;
    4.36 +typedef unsigned long long u64;
    4.37 +
    4.38 +static inline u16 swab16(u16 x)
    4.39 +{
    4.40 +	return  (((u16)(x) & (u16)0x00ffU) << 8) |
    4.41 +			(((u16)(x) & (u16)0xff00U) >> 8);
    4.42 +}
    4.43 +
    4.44 +static inline u32 swab32(u32 x)
    4.45 +{
    4.46 +	return  (((u32)(x) & (u32)0x000000ffUL) << 24) |
    4.47 +			(((u32)(x) & (u32)0x0000ff00UL) <<  8) |
    4.48 +			(((u32)(x) & (u32)0x00ff0000UL) >>  8) |
    4.49 +			(((u32)(x) & (u32)0xff000000UL) >> 24);
    4.50 +}
    4.51 +
    4.52 +static inline u64 swab64(u64 x)
    4.53 +{
    4.54 +	return  (u64)(((u64)(x) & (u64)0x00000000000000ffULL) << 56) |
    4.55 +			(u64)(((u64)(x) & (u64)0x000000000000ff00ULL) << 40) |
    4.56 +			(u64)(((u64)(x) & (u64)0x0000000000ff0000ULL) << 24) |
    4.57 +			(u64)(((u64)(x) & (u64)0x00000000ff000000ULL) <<  8) |
    4.58 +			(u64)(((u64)(x) & (u64)0x000000ff00000000ULL) >>  8) |
    4.59 +			(u64)(((u64)(x) & (u64)0x0000ff0000000000ULL) >> 24) |
    4.60 +			(u64)(((u64)(x) & (u64)0x00ff000000000000ULL) >> 40) |
    4.61 +			(u64)(((u64)(x) & (u64)0xff00000000000000ULL) >> 56);
    4.62 +}
    4.63 +
    4.64 +#if __BYTE_ORDER == __LITTLE_ENDIAN
    4.65 +#define cpu_to_be16(x) swab16(x)
    4.66 +#define be16_to_cpu(x) swab16(x)
    4.67 +#define cpu_to_be32(x) swab32(x)
    4.68 +#define be32_to_cpu(x) swab32(x)
    4.69 +#define cpu_to_be64(x) swab64(x)
    4.70 +#define be64_to_cpu(x) swab64(x)
    4.71 +#else
    4.72 +#define cpu_to_be16(x) (x)
    4.73 +#define be16_to_cpu(x) (x)
    4.74 +#define cpu_to_be32(x) (x)
    4.75 +#define be32_to_cpu(x) (x)
    4.76 +#define cpu_to_be64(x) (x)
    4.77 +#define be64_to_cpu(x) (x)
    4.78 +#endif
    4.79 +
    4.80 +static inline void ft_exit(int code)
    4.81 +{
    4.82 +	exit(code);
    4.83 +}
    4.84 +
    4.85 +static inline void ft_free(void *ptr, int len)
    4.86 +{
    4.87 +	free(ptr);
    4.88 +}
    4.89 +
    4.90 +static inline u32 min(u32 a, u32 b)
    4.91 +{
    4.92 +	if (a < b)
    4.93 +		return a;
    4.94 +	return b;
    4.95 +}
    4.96 +
    4.97 +#endif /* _FLATDEVTREE_ENV_H_ */
     5.1 --- a/tools/libxc/powerpc64/xc_linux_build.c	Thu Sep 07 21:46:33 2006 -0400
     5.2 +++ b/tools/libxc/powerpc64/xc_linux_build.c	Thu Sep 07 17:25:52 2006 -0500
     5.3 @@ -33,7 +33,8 @@
     5.4  #include <xg_private.h>
     5.5  #include <xenctrl.h>
     5.6  
     5.7 -#include "ft_build.h"
     5.8 +#include "flatdevtree_env.h"
     5.9 +#include "flatdevtree.h"
    5.10  
    5.11  #define INITRD_ADDR (24UL << 20)
    5.12  #define DEVTREE_ADDR (16UL << 20)
    5.13 @@ -164,64 +165,63 @@ static int load_devtree(
    5.14      xen_pfn_t *page_array,
    5.15      void *devtree,
    5.16      unsigned long devtree_addr,
    5.17 -    unsigned long initrd_base,
    5.18 +    uint64_t initrd_base,
    5.19      unsigned long initrd_len,
    5.20      start_info_t *si,
    5.21      unsigned long si_addr)
    5.22  {
    5.23      uint32_t start_info[4] = {0, si_addr, 0, 0x1000};
    5.24      struct boot_param_header *header;
    5.25 -    uint64_t *prop;
    5.26 +    void *chosen;
    5.27 +    void *xen;
    5.28 +    uint64_t initrd_end = initrd_base + initrd_len;
    5.29      unsigned int devtree_size;
    5.30 -    unsigned int proplen;
    5.31      int rc = 0;
    5.32  
    5.33 +    DPRINTF("adding initrd props\n");
    5.34 +
    5.35 +    chosen = ft_find_node(devtree, "/chosen");
    5.36 +    if (chosen == NULL) {
    5.37 +        DPRINTF("couldn't find /chosen\n");
    5.38 +        return -1;
    5.39 +    }
    5.40 +
    5.41 +    xen = ft_find_node(devtree, "/xen");
    5.42 +    if (xen == NULL) {
    5.43 +        DPRINTF("couldn't find /xen\n");
    5.44 +        return -1;
    5.45 +    }
    5.46 +
    5.47 +    /* initrd-start */
    5.48 +    rc = ft_set_prop(&devtree, chosen, "linux,initrd-start",
    5.49 +            &initrd_base, sizeof(initrd_base));
    5.50 +    if (rc < 0) {
    5.51 +        DPRINTF("couldn't set /chosen/linux,initrd-start\n");
    5.52 +        return rc;
    5.53 +    }
    5.54 +
    5.55 +    /* initrd-end */
    5.56 +    rc = ft_set_prop(&devtree, chosen, "linux,initrd-end",
    5.57 +            &initrd_end, sizeof(initrd_end));
    5.58 +    if (rc < 0) {
    5.59 +        DPRINTF("couldn't set /chosen/linux,initrd-end\n");
    5.60 +        return rc;
    5.61 +    }
    5.62 +
    5.63 +    /* start-info (XXX being removed soon) */
    5.64 +    rc = ft_set_prop(&devtree, xen, "start-info",
    5.65 +            start_info, sizeof(start_info));
    5.66 +    if (rc < 0) {
    5.67 +        DPRINTF("couldn't set /xen/start-info\n");
    5.68 +        return rc;
    5.69 +    }
    5.70 +
    5.71      header = devtree;
    5.72      devtree_size = header->totalsize;
    5.73  
    5.74 -    DPRINTF("adding initrd props\n");
    5.75 -
    5.76 -	/* initrd-start */
    5.77 -    prop = ft_get_prop(devtree, "/chosen/linux,initrd-start", &proplen);
    5.78 -    if (prop == NULL) {
    5.79 -        DPRINTF("couldn't find linux,initrd-start\n");
    5.80 -        return -1;
    5.81 -    }
    5.82 -    if (proplen != sizeof(*prop)) {
    5.83 -        DPRINTF("couldn't set linux,initrd-start (size %d)\n", proplen);
    5.84 -        return -1;
    5.85 -    }
    5.86 -    *prop = initrd_base;
    5.87 -
    5.88 -	/* initrd-end */
    5.89 -    prop = ft_get_prop(devtree, "/chosen/linux,initrd-end", &proplen);
    5.90 -    if (prop == NULL) {
    5.91 -        DPRINTF("couldn't find linux,initrd-end\n");
    5.92 -        return -1;
    5.93 -    }
    5.94 -    if (proplen != sizeof(*prop)) {
    5.95 -        DPRINTF("couldn't set linux,initrd-end (size %d)\n", proplen);
    5.96 -        return -1;
    5.97 -    }
    5.98 -    *prop = initrd_base + initrd_len;
    5.99 -
   5.100 -	/* start-info (XXX being removed soon) */
   5.101 -    prop = ft_get_prop(devtree, "/xen/start-info", &proplen);
   5.102 -    if (prop == NULL) {
   5.103 -        DPRINTF("couldn't find /xen/start-info\n");
   5.104 -        return -1;
   5.105 -    }
   5.106 -    if (proplen != sizeof(start_info)) {
   5.107 -        DPRINTF("couldn't set /xen/start-info (size %d)\n", proplen);
   5.108 -        return -1;
   5.109 -    }
   5.110 -    memcpy(prop, start_info, proplen);
   5.111 -
   5.112      DPRINTF("copying device tree to 0x%lx[0x%x]\n", DEVTREE_ADDR, devtree_size);
   5.113 -    rc = install_image(xc_handle, domid, page_array, devtree, DEVTREE_ADDR,
   5.114 +    return install_image(xc_handle, domid, page_array, devtree, DEVTREE_ADDR,
   5.115                         devtree_size);
   5.116 -
   5.117 -    return rc;
   5.118  }
   5.119  
   5.120  unsigned long spin_list[] = {