cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

yamltree.c (6461B)


      1// SPDX-License-Identifier: GPL-2.0-or-later
      2/*
      3 * (C) Copyright Linaro, Ltd. 2018
      4 * (C) Copyright Arm Holdings.  2017
      5 * (C) Copyright David Gibson <dwg@au1.ibm.com>, IBM Corporation.  2005.
      6 */
      7
      8#include <stdlib.h>
      9#include <yaml.h>
     10#include "dtc.h"
     11#include "srcpos.h"
     12
     13char *yaml_error_name[] = {
     14	[YAML_NO_ERROR] = "no error",
     15	[YAML_MEMORY_ERROR] = "memory error",
     16	[YAML_READER_ERROR] = "reader error",
     17	[YAML_SCANNER_ERROR] = "scanner error",
     18	[YAML_PARSER_ERROR] = "parser error",
     19	[YAML_COMPOSER_ERROR] = "composer error",
     20	[YAML_WRITER_ERROR] = "writer error",
     21	[YAML_EMITTER_ERROR] = "emitter error",
     22};
     23
     24#define yaml_emitter_emit_or_die(emitter, event) (			\
     25{									\
     26	if (!yaml_emitter_emit(emitter, event))				\
     27		die("yaml '%s': %s in %s, line %i\n",			\
     28		    yaml_error_name[(emitter)->error], 			\
     29		    (emitter)->problem, __func__, __LINE__);		\
     30})
     31
     32static void yaml_propval_int(yaml_emitter_t *emitter, struct marker *markers,
     33	char *data, unsigned int seq_offset, unsigned int len, int width)
     34{
     35	yaml_event_t event;
     36	void *tag;
     37	unsigned int off;
     38
     39	switch(width) {
     40		case 1: tag = "!u8"; break;
     41		case 2: tag = "!u16"; break;
     42		case 4: tag = "!u32"; break;
     43		case 8: tag = "!u64"; break;
     44		default:
     45			die("Invalid width %i", width);
     46	}
     47	assert(len % width == 0);
     48
     49	yaml_sequence_start_event_initialize(&event, NULL,
     50		(yaml_char_t *)tag, width == 4, YAML_FLOW_SEQUENCE_STYLE);
     51	yaml_emitter_emit_or_die(emitter, &event);
     52
     53	for (off = 0; off < len; off += width) {
     54		char buf[32];
     55		struct marker *m;
     56		bool is_phandle = false;
     57
     58		switch(width) {
     59		case 1:
     60			sprintf(buf, "0x%"PRIx8, *(uint8_t*)(data + off));
     61			break;
     62		case 2:
     63			sprintf(buf, "0x%"PRIx16, dtb_ld16(data + off));
     64			break;
     65		case 4:
     66			sprintf(buf, "0x%"PRIx32, dtb_ld32(data + off));
     67			m = markers;
     68			is_phandle = false;
     69			for_each_marker_of_type(m, REF_PHANDLE) {
     70				if (m->offset == (seq_offset + off)) {
     71					is_phandle = true;
     72					break;
     73				}
     74			}
     75			break;
     76		case 8:
     77			sprintf(buf, "0x%"PRIx64, dtb_ld64(data + off));
     78			break;
     79		}
     80
     81		if (is_phandle)
     82			yaml_scalar_event_initialize(&event, NULL,
     83				(yaml_char_t*)"!phandle", (yaml_char_t *)buf,
     84				strlen(buf), 0, 0, YAML_PLAIN_SCALAR_STYLE);
     85		else
     86			yaml_scalar_event_initialize(&event, NULL,
     87				(yaml_char_t*)YAML_INT_TAG, (yaml_char_t *)buf,
     88				strlen(buf), 1, 1, YAML_PLAIN_SCALAR_STYLE);
     89		yaml_emitter_emit_or_die(emitter, &event);
     90	}
     91
     92	yaml_sequence_end_event_initialize(&event);
     93	yaml_emitter_emit_or_die(emitter, &event);
     94}
     95
     96static void yaml_propval_string(yaml_emitter_t *emitter, char *str, int len)
     97{
     98	yaml_event_t event;
     99	int i;
    100
    101	assert(str[len-1] == '\0');
    102
    103	/* Make sure the entire string is in the lower 7-bit ascii range */
    104	for (i = 0; i < len; i++)
    105		assert(isascii(str[i]));
    106
    107	yaml_scalar_event_initialize(&event, NULL,
    108		(yaml_char_t *)YAML_STR_TAG, (yaml_char_t*)str,
    109		len-1, 0, 1, YAML_DOUBLE_QUOTED_SCALAR_STYLE);
    110	yaml_emitter_emit_or_die(emitter, &event);
    111}
    112
    113static void yaml_propval(yaml_emitter_t *emitter, struct property *prop)
    114{
    115	yaml_event_t event;
    116	unsigned int len = prop->val.len;
    117	struct marker *m = prop->val.markers;
    118	struct marker *markers = prop->val.markers;
    119
    120	/* Emit the property name */
    121	yaml_scalar_event_initialize(&event, NULL,
    122		(yaml_char_t *)YAML_STR_TAG, (yaml_char_t*)prop->name,
    123		strlen(prop->name), 1, 1, YAML_PLAIN_SCALAR_STYLE);
    124	yaml_emitter_emit_or_die(emitter, &event);
    125
    126	/* Boolean properties are easiest to deal with. Length is zero, so just emit 'true' */
    127	if (len == 0) {
    128		yaml_scalar_event_initialize(&event, NULL,
    129			(yaml_char_t *)YAML_BOOL_TAG,
    130			(yaml_char_t*)"true",
    131			strlen("true"), 1, 0, YAML_PLAIN_SCALAR_STYLE);
    132		yaml_emitter_emit_or_die(emitter, &event);
    133		return;
    134	}
    135
    136	if (!m)
    137		die("No markers present in property '%s' value\n", prop->name);
    138
    139	yaml_sequence_start_event_initialize(&event, NULL,
    140		(yaml_char_t *)YAML_SEQ_TAG, 1, YAML_FLOW_SEQUENCE_STYLE);
    141	yaml_emitter_emit_or_die(emitter, &event);
    142
    143	for_each_marker(m) {
    144		int chunk_len;
    145		char *data = &prop->val.val[m->offset];
    146
    147		if (m->type < TYPE_UINT8)
    148			continue;
    149
    150		chunk_len = type_marker_length(m) ? : len;
    151		assert(chunk_len > 0);
    152		len -= chunk_len;
    153
    154		switch(m->type) {
    155		case TYPE_UINT16:
    156			yaml_propval_int(emitter, markers, data, m->offset, chunk_len, 2);
    157			break;
    158		case TYPE_UINT32:
    159			yaml_propval_int(emitter, markers, data, m->offset, chunk_len, 4);
    160			break;
    161		case TYPE_UINT64:
    162			yaml_propval_int(emitter, markers, data, m->offset, chunk_len, 8);
    163			break;
    164		case TYPE_STRING:
    165			yaml_propval_string(emitter, data, chunk_len);
    166			break;
    167		default:
    168			yaml_propval_int(emitter, markers, data, m->offset, chunk_len, 1);
    169			break;
    170		}
    171	}
    172
    173	yaml_sequence_end_event_initialize(&event);
    174	yaml_emitter_emit_or_die(emitter, &event);
    175}
    176
    177
    178static void yaml_tree(struct node *tree, yaml_emitter_t *emitter)
    179{
    180	struct property *prop;
    181	struct node *child;
    182	yaml_event_t event;
    183
    184	if (tree->deleted)
    185		return;
    186
    187	yaml_mapping_start_event_initialize(&event, NULL,
    188		(yaml_char_t *)YAML_MAP_TAG, 1, YAML_ANY_MAPPING_STYLE);
    189	yaml_emitter_emit_or_die(emitter, &event);
    190
    191	for_each_property(tree, prop)
    192		yaml_propval(emitter, prop);
    193
    194	/* Loop over all the children, emitting them into the map */
    195	for_each_child(tree, child) {
    196		yaml_scalar_event_initialize(&event, NULL,
    197			(yaml_char_t *)YAML_STR_TAG, (yaml_char_t*)child->name,
    198			strlen(child->name), 1, 0, YAML_PLAIN_SCALAR_STYLE);
    199		yaml_emitter_emit_or_die(emitter, &event);
    200		yaml_tree(child, emitter);
    201	}
    202
    203	yaml_mapping_end_event_initialize(&event);
    204	yaml_emitter_emit_or_die(emitter, &event);
    205}
    206
    207void dt_to_yaml(FILE *f, struct dt_info *dti)
    208{
    209	yaml_emitter_t emitter;
    210	yaml_event_t event;
    211
    212	yaml_emitter_initialize(&emitter);
    213	yaml_emitter_set_output_file(&emitter, f);
    214	yaml_stream_start_event_initialize(&event, YAML_UTF8_ENCODING);
    215	yaml_emitter_emit_or_die(&emitter, &event);
    216
    217	yaml_document_start_event_initialize(&event, NULL, NULL, NULL, 0);
    218	yaml_emitter_emit_or_die(&emitter, &event);
    219
    220	yaml_sequence_start_event_initialize(&event, NULL, (yaml_char_t *)YAML_SEQ_TAG, 1, YAML_ANY_SEQUENCE_STYLE);
    221	yaml_emitter_emit_or_die(&emitter, &event);
    222
    223	yaml_tree(dti->dt, &emitter);
    224
    225	yaml_sequence_end_event_initialize(&event);
    226	yaml_emitter_emit_or_die(&emitter, &event);
    227
    228	yaml_document_end_event_initialize(&event, 0);
    229	yaml_emitter_emit_or_die(&emitter, &event);
    230
    231	yaml_stream_end_event_initialize(&event);
    232	yaml_emitter_emit_or_die(&emitter, &event);
    233
    234	yaml_emitter_delete(&emitter);
    235}