blob: ea06d5bd9b31cc2762ac177cc7e74cbd3b6838d9 [file] [log] [blame]
Achin Guptad0ae6922019-10-11 14:54:48 +01001/*
2 * Copyright (c) 2019, Arm Limited. All rights reserved.
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7#include <assert.h>
8#include <string.h>
9
10#include <libfdt.h>
11
12#include <platform_def.h>
13
14#include <common/debug.h>
15#include <common/fdt_wrappers.h>
16#include <errno.h>
17#include <services/spm_core_manifest.h>
18
19/*******************************************************************************
20 * Attribute section handler
21 ******************************************************************************/
22static int manifest_parse_attribute(spmc_manifest_sect_attribute_t *attr,
23 const void *fdt,
24 int node)
25{
26 int rc = 0;
27
28 assert(attr && fdt);
29
30 rc = fdtw_read_cells(fdt, node, "maj_ver", 1, &attr->major_version);
31 if (rc) {
32 ERROR("Missing SPCI major version in SPM core manifest.\n");
33 return -ENOENT;
34 }
35
36 rc = fdtw_read_cells(fdt, node, "min_ver", 1, &attr->minor_version);
37 if (rc) {
38 ERROR("Missing SPCI minor version in SPM core manifest.\n");
39 return -ENOENT;
40 }
41
42 rc = fdtw_read_cells(fdt, node, "runtime_el", 1, &attr->runtime_el);
43 if (rc) {
44 ERROR("Missing SPM core runtime EL in manifest.\n");
45 return -ENOENT;
46 }
47
48 rc = fdtw_read_cells(fdt, node, "exec_state", 1, &attr->exec_state);
49 if (rc)
50 NOTICE("Execution state not specified in SPM core manifest.\n");
51
52 rc = fdtw_read_cells(fdt, node, "binary_size", 1, &attr->binary_size);
53 if (rc)
54 NOTICE("Binary size not specified in SPM core manifest.\n");
55
56 rc = fdtw_read_cells(fdt, node, "load_address", 2, &attr->load_address);
57 if (rc)
58 NOTICE("Load address not specified in SPM core manifest.\n");
59
60 rc = fdtw_read_cells(fdt, node, "entrypoint", 2, &attr->entrypoint);
61 if (rc)
62 NOTICE("Entrypoint not specified in SPM core manifest.\n");
63
64 VERBOSE("SPM core manifest attribute section:\n");
65 VERBOSE(" version: %x.%x\n", attr->major_version, attr->minor_version);
66 VERBOSE(" runtime_el: 0x%x\n", attr->runtime_el);
67 VERBOSE(" binary_size: 0x%x\n", attr->binary_size);
68 VERBOSE(" load_address: 0x%llx\n", attr->load_address);
69 VERBOSE(" entrypoint: 0x%llx\n", attr->entrypoint);
70
71 return 0;
72}
73
74/*******************************************************************************
75 * Root node handler
76 ******************************************************************************/
77static int manifest_parse_root(spmc_manifest_sect_attribute_t *manifest,
78 const void *fdt,
79 int root)
80{
81 int node;
82 char *str;
83
84 str = "attribute";
85 node = fdt_subnode_offset_namelen(fdt, root, str, strlen(str));
86 if (node < 0) {
87 ERROR("Root node doesn't contain subnode '%s'\n", str);
88 return -ENOENT;
89 }
90
91 return manifest_parse_attribute(manifest, fdt, node);
92}
93
94/*******************************************************************************
95 * Platform handler to parse a SPM core manifest.
96 ******************************************************************************/
97int plat_spm_core_manifest_load(spmc_manifest_sect_attribute_t *manifest,
98 const void *ptr,
99 size_t size)
100{
101 int rc;
102 int root_node;
103
104 assert(manifest != NULL);
105 assert(ptr != NULL);
106
107 INFO("Reading SPM core manifest at address %p\n", ptr);
108
109 rc = fdt_check_header(ptr);
110 if (rc != 0) {
111 ERROR("Wrong format for SPM core manifest (%d).\n", rc);
112 return -EINVAL;
113 }
114
115 INFO("Reading SPM core manifest at address %p\n", ptr);
116
117 root_node = fdt_node_offset_by_compatible(ptr, -1, "arm,spmc_rd");
118 if (root_node < 0) {
119 ERROR("Unrecognized SPM core manifest\n");
120 return -ENOENT;
121 }
122
123 INFO("Reading SPM core manifest at address %p\n", ptr);
124 return manifest_parse_root(manifest, ptr, root_node);
125}