plat_spmd_manifest.c 3.5 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
/*
 * Copyright (c) 2020, Arm Limited. All rights reserved.
 *
 * SPDX-License-Identifier: BSD-3-Clause
 */

#include <assert.h>
#include <string.h>
#include <libfdt.h>

#include <common/debug.h>
#include <common/fdt_wrappers.h>
#include <errno.h>
#include <platform_def.h>
#include <services/spm_core_manifest.h>

/*******************************************************************************
 * Attribute section handler
 ******************************************************************************/
static int manifest_parse_attribute(spmc_manifest_sect_attribute_t *attr,
				    const void *fdt,
				    int node)
{
	int rc = 0;

	assert(attr && fdt);

	rc = fdtw_read_cells(fdt, node, "maj_ver", 1, &attr->major_version);
	if (rc) {
		ERROR("Missing SPCI major version in SPM core manifest.\n");
		return -ENOENT;
	}

	rc = fdtw_read_cells(fdt, node, "min_ver", 1, &attr->minor_version);
	if (rc) {
		ERROR("Missing SPCI minor version in SPM core manifest.\n");
		return -ENOENT;
	}

	rc = fdtw_read_cells(fdt, node, "runtime_el", 1, &attr->runtime_el);
	if (rc) {
		ERROR("Missing SPM core runtime EL in manifest.\n");
		return -ENOENT;
	}

	rc = fdtw_read_cells(fdt, node, "exec_state", 1, &attr->exec_state);
	if (rc)
		NOTICE("Execution state not specified in SPM core manifest.\n");

	rc = fdtw_read_cells(fdt, node, "binary_size", 1, &attr->binary_size);
	if (rc)
		NOTICE("Binary size not specified in SPM core manifest.\n");

	rc = fdtw_read_cells(fdt, node, "load_address", 2, &attr->load_address);
	if (rc)
		NOTICE("Load address not specified in SPM core manifest.\n");

	rc = fdtw_read_cells(fdt, node, "entrypoint", 2, &attr->entrypoint);
	if (rc)
		NOTICE("Entrypoint not specified in SPM core manifest.\n");

	VERBOSE("SPM core manifest attribute section:\n");
	VERBOSE("  version: %x.%x\n", attr->major_version, attr->minor_version);
	VERBOSE("  runtime_el: 0x%x\n", attr->runtime_el);
	VERBOSE("  binary_size: 0x%x\n", attr->binary_size);
	VERBOSE("  load_address: 0x%llx\n", attr->load_address);
	VERBOSE("  entrypoint: 0x%llx\n", attr->entrypoint);

	return 0;
}

/*******************************************************************************
 * Root node handler
 ******************************************************************************/
static int manifest_parse_root(spmc_manifest_sect_attribute_t *manifest,
				const void *fdt,
				int root)
{
	int node;
	char *str;

	str = "attribute";
	node = fdt_subnode_offset_namelen(fdt, root, str, strlen(str));
	if (node < 0) {
		ERROR("Root node doesn't contain subnode '%s'\n", str);
		return -ENOENT;
	}

	return manifest_parse_attribute(manifest, fdt, node);
}

/*******************************************************************************
 * Platform handler to parse a SPM core manifest.
 ******************************************************************************/
int plat_spm_core_manifest_load(spmc_manifest_sect_attribute_t *manifest,
				const void *ptr,
				size_t size)
{
	int rc;
	int root_node;

	assert(manifest != NULL);
	assert(ptr != NULL);

	INFO("Reading SPM core manifest at address %p\n", ptr);

	rc = fdt_check_header(ptr);
	if (rc != 0) {
		ERROR("Wrong format for SPM core manifest (%d).\n", rc);
		return -EINVAL;
	}

	INFO("Reading SPM core manifest at address %p\n", ptr);

	root_node = fdt_node_offset_by_compatible(ptr, -1,
				"arm,spci-core-manifest-1.0");
	if (root_node < 0) {
		ERROR("Unrecognized SPM core manifest\n");
		return -ENOENT;
	}

	INFO("Reading SPM core manifest at address %p\n", ptr);
	return manifest_parse_root(manifest, ptr, root_node);
}