diff options
Diffstat (limited to 'scripts/dtc/treesource.c')
| -rw-r--r-- | scripts/dtc/treesource.c | 225 | 
1 files changed, 135 insertions, 90 deletions
| diff --git a/scripts/dtc/treesource.c b/scripts/dtc/treesource.c index 2461a3d068a0..f2874f1d1465 100644 --- a/scripts/dtc/treesource.c +++ b/scripts/dtc/treesource.c @@ -61,24 +61,14 @@ static bool isstring(char c)  		|| strchr("\a\b\t\n\v\f\r", c));  } -static void write_propval_string(FILE *f, struct data val) +static void write_propval_string(FILE *f, const char *s, size_t len)  { -	const char *str = val.val; -	int i; -	struct marker *m = val.markers; - -	assert(str[val.len-1] == '\0'); +	const char *end = s + len - 1; +	assert(*end == '\0'); -	while (m && (m->offset == 0)) { -		if (m->type == LABEL) -			fprintf(f, "%s: ", m->ref); -		m = m->next; -	}  	fprintf(f, "\""); - -	for (i = 0; i < (val.len-1); i++) { -		char c = str[i]; - +	while (s < end) { +		char c = *s++;  		switch (c) {  		case '\a':  			fprintf(f, "\\a"); @@ -108,91 +98,78 @@ static void write_propval_string(FILE *f, struct data val)  			fprintf(f, "\\\"");  			break;  		case '\0': -			fprintf(f, "\", "); -			while (m && (m->offset <= (i + 1))) { -				if (m->type == LABEL) { -					assert(m->offset == (i+1)); -					fprintf(f, "%s: ", m->ref); -				} -				m = m->next; -			} -			fprintf(f, "\""); +			fprintf(f, "\\0");  			break;  		default:  			if (isprint((unsigned char)c))  				fprintf(f, "%c", c);  			else -				fprintf(f, "\\x%02hhx", c); +				fprintf(f, "\\x%02"PRIx8, c);  		}  	}  	fprintf(f, "\""); - -	/* Wrap up any labels at the end of the value */ -	for_each_marker_of_type(m, LABEL) { -		assert (m->offset == val.len); -		fprintf(f, " %s:", m->ref); -	}  } -static void write_propval_cells(FILE *f, struct data val) +static void write_propval_int(FILE *f, const char *p, size_t len, size_t width)  { -	void *propend = val.val + val.len; -	fdt32_t *cp = (fdt32_t *)val.val; -	struct marker *m = val.markers; - -	fprintf(f, "<"); -	for (;;) { -		while (m && (m->offset <= ((char *)cp - val.val))) { -			if (m->type == LABEL) { -				assert(m->offset == ((char *)cp - val.val)); -				fprintf(f, "%s: ", m->ref); -			} -			m = m->next; -		} +	const char *end = p + len; +	assert(len % width == 0); -		fprintf(f, "0x%x", fdt32_to_cpu(*cp++)); -		if ((void *)cp >= propend) +	for (; p < end; p += width) { +		switch (width) { +		case 1: +			fprintf(f, " %02"PRIx8, *(const uint8_t*)p); +			break; +		case 2: +			fprintf(f, " 0x%02"PRIx16, fdt16_to_cpu(*(const fdt16_t*)p)); +			break; +		case 4: +			fprintf(f, " 0x%02"PRIx32, fdt32_to_cpu(*(const fdt32_t*)p)); +			break; +		case 8: +			fprintf(f, " 0x%02"PRIx64, fdt64_to_cpu(*(const fdt64_t*)p));  			break; -		fprintf(f, " "); +		}  	} +} -	/* Wrap up any labels at the end of the value */ -	for_each_marker_of_type(m, LABEL) { -		assert (m->offset == val.len); -		fprintf(f, " %s:", m->ref); -	} -	fprintf(f, ">"); +static bool has_data_type_information(struct marker *m) +{ +	return m->type >= TYPE_UINT8;  } -static void write_propval_bytes(FILE *f, struct data val) +static struct marker *next_type_marker(struct marker *m)  { -	void *propend = val.val + val.len; -	const char *bp = val.val; -	struct marker *m = val.markers; - -	fprintf(f, "["); -	for (;;) { -		while (m && (m->offset == (bp-val.val))) { -			if (m->type == LABEL) -				fprintf(f, "%s: ", m->ref); -			m = m->next; -		} +	while (m && !has_data_type_information(m)) +		m = m->next; +	return m; +} -		fprintf(f, "%02hhx", (unsigned char)(*bp++)); -		if ((const void *)bp >= propend) -			break; -		fprintf(f, " "); -	} +size_t type_marker_length(struct marker *m) +{ +	struct marker *next = next_type_marker(m->next); -	/* Wrap up any labels at the end of the value */ -	for_each_marker_of_type(m, LABEL) { -		assert (m->offset == val.len); -		fprintf(f, " %s:", m->ref); -	} -	fprintf(f, "]"); +	if (next) +		return next->offset - m->offset; +	return 0;  } -static void write_propval(FILE *f, struct property *prop) +static const char *delim_start[] = { +	[TYPE_UINT8] = "[", +	[TYPE_UINT16] = "/bits/ 16 <", +	[TYPE_UINT32] = "<", +	[TYPE_UINT64] = "/bits/ 64 <", +	[TYPE_STRING] = "", +}; +static const char *delim_end[] = { +	[TYPE_UINT8] = " ]", +	[TYPE_UINT16] = " >", +	[TYPE_UINT32] = " >", +	[TYPE_UINT64] = " >", +	[TYPE_STRING] = "", +}; + +static enum markertype guess_value_type(struct property *prop)  {  	int len = prop->val.len;  	const char *p = prop->val.val; @@ -201,11 +178,6 @@ static void write_propval(FILE *f, struct property *prop)  	int nnotstringlbl = 0, nnotcelllbl = 0;  	int i; -	if (len == 0) { -		fprintf(f, ";\n"); -		return; -	} -  	for (i = 0; i < len; i++) {  		if (! isstring(p[i]))  			nnotstring++; @@ -220,17 +192,91 @@ static void write_propval(FILE *f, struct property *prop)  			nnotcelllbl++;  	} -	fprintf(f, " = ");  	if ((p[len-1] == '\0') && (nnotstring == 0) && (nnul < (len-nnul))  	    && (nnotstringlbl == 0)) { -		write_propval_string(f, prop->val); +		return TYPE_STRING;  	} else if (((len % sizeof(cell_t)) == 0) && (nnotcelllbl == 0)) { -		write_propval_cells(f, prop->val); -	} else { -		write_propval_bytes(f, prop->val); +		return TYPE_UINT32;  	} -	fprintf(f, ";\n"); +	return TYPE_UINT8; +} + +static void write_propval(FILE *f, struct property *prop) +{ +	size_t len = prop->val.len; +	struct marker *m = prop->val.markers; +	struct marker dummy_marker; +	enum markertype emit_type = TYPE_NONE; + +	if (len == 0) { +		fprintf(f, ";\n"); +		return; +	} + +	fprintf(f, " = "); + +	if (!next_type_marker(m)) { +		/* data type information missing, need to guess */ +		dummy_marker.type = guess_value_type(prop); +		dummy_marker.next = prop->val.markers; +		dummy_marker.offset = 0; +		dummy_marker.ref = NULL; +		m = &dummy_marker; +	} + +	struct marker *m_label = prop->val.markers; +	for_each_marker(m) { +		size_t chunk_len; +		const char *p = &prop->val.val[m->offset]; + +		if (!has_data_type_information(m)) +			continue; + +		chunk_len = type_marker_length(m); +		if (!chunk_len) +			chunk_len = len - m->offset; + +		if (emit_type != TYPE_NONE) +			fprintf(f, "%s, ", delim_end[emit_type]); +		emit_type = m->type; + +		for_each_marker_of_type(m_label, LABEL) { +			if (m_label->offset > m->offset) +				break; +			fprintf(f, "%s: ", m_label->ref); +		} + +		fprintf(f, "%s", delim_start[emit_type]); + +		if (chunk_len <= 0) +			continue; + +		switch(emit_type) { +		case TYPE_UINT16: +			write_propval_int(f, p, chunk_len, 2); +			break; +		case TYPE_UINT32: +			write_propval_int(f, p, chunk_len, 4); +			break; +		case TYPE_UINT64: +			write_propval_int(f, p, chunk_len, 8); +			break; +		case TYPE_STRING: +			write_propval_string(f, p, chunk_len); +			break; +		default: +			write_propval_int(f, p, chunk_len, 1); +		} +	} + +	/* Wrap up any labels at the end of the value */ +	for_each_marker_of_type(m_label, LABEL) { +		assert (m_label->offset == len); +		fprintf(f, " %s:", m_label->ref); +	} + +	fprintf(f, "%s;\n", delim_end[emit_type] ? : "");  }  static void write_tree_source_node(FILE *f, struct node *tree, int level) @@ -281,4 +327,3 @@ void dt_to_source(FILE *f, struct dt_info *dti)  	write_tree_source_node(f, dti->dt, 0);  } - | 
