blob: 7d9f0138d8bf22c62341878a7f052f9262ec7863 [file] [log] [blame]
J-Alves35315782022-01-25 17:58:32 +00001/*
2 * Copyright 2022 The Hafnium Authors.
3 *
4 * Use of this source code is governed by a BSD-style
5 * license that can be found in the LICENSE file or at
6 * https://opensource.org/licenses/BSD-3-Clause.
7 */
8
9#include "hf/boot_info.h"
10
11#include "hf/assert.h"
12#include "hf/dlog.h"
J-Alves7e67d102022-04-13 13:22:39 +010013#include "hf/ffa.h"
J-Alves35315782022-01-25 17:58:32 +000014#include "hf/memiter.h"
15#include "hf/std.h"
16
17#include "vmapi/hf/ffa.h"
18
19/**
J-Alves7e67d102022-04-13 13:22:39 +010020 * Initializes the ffa_boot_info_header in accordance to the specification.
21 */
22static void ffa_boot_info_header_init(struct ffa_boot_info_header *header,
Kathleen Capella8393ea92025-01-09 17:22:21 -050023 size_t blob_size,
24 enum ffa_version vm_ffa_version)
J-Alves7e67d102022-04-13 13:22:39 +010025{
26 assert(header != NULL);
27 assert(blob_size != 0U);
28
29 header->signature = FFA_BOOT_INFO_SIG;
Kathleen Capella8393ea92025-01-09 17:22:21 -050030 header->version = vm_ffa_version;
J-Alves7e67d102022-04-13 13:22:39 +010031 header->info_blob_size = blob_size;
32 header->desc_size = sizeof(struct ffa_boot_info_desc);
33 header->desc_count = 0;
34 header->desc_offset =
35 (uint32_t)offsetof(struct ffa_boot_info_header, boot_info);
36 header->reserved = 0U;
37}
38
39static void ffa_boot_info_desc_init(struct ffa_boot_info_desc *info_desc,
40 uint8_t content_format, bool std_type,
41 uint8_t type_id, uint32_t size,
42 uint64_t content)
43{
44 assert(info_desc != NULL);
45
46 /*
47 * Init name size with 0s, as it is currently unused. Data can be
48 * identified checking the type field.
49 */
50 memset_s(info_desc, FFA_BOOT_INFO_NAME_LEN, 0, FFA_BOOT_INFO_NAME_LEN);
51
52 info_desc->type = std_type == true ? FFA_BOOT_INFO_TYPE_STD
53 : FFA_BOOT_INFO_TYPE_IMPDEF;
54 info_desc->type <<= FFA_BOOT_INFO_TYPE_SHIFT;
55 info_desc->type |= (type_id & FFA_BOOT_INFO_TYPE_ID_MASK);
56
57 info_desc->reserved = 0U;
58 info_desc->flags =
59 ((content_format << FFA_BOOT_INFO_FLAG_CONTENT_FORMAT_SHIFT) &
60 FFA_BOOT_INFO_FLAG_CONTENT_FORMAT_MASK);
61 info_desc->size = size;
62 info_desc->content = content;
63}
64
65/*
66 * Write initialization parameter to the boot info descriptor array.
67 */
68static void boot_info_write_desc(struct ffa_boot_info_header *header,
69 uint8_t content_format, bool std_type,
70 uint8_t type_id, uint32_t size,
71 uint64_t content,
72 const size_t max_info_desc_count)
73{
74 assert(header != NULL);
75
76 /* Check that writing the data won't surpass the blob memory limit. */
77 if (header->desc_count >= max_info_desc_count) {
78 dlog_error(
79 "Boot info memory is full. No space for a "
80 "descriptor.\n");
81 return;
82 }
83
84 ffa_boot_info_desc_init(&header->boot_info[header->desc_count],
85 content_format, std_type, type_id, size,
86 content);
87
88 header->desc_count++;
89}
90
91/**
J-Alves35315782022-01-25 17:58:32 +000092 * Looks for the FF-A manifest boot information node, and writes the
93 * requested information into the boot info memory.
94 */
J-Alves6e0abc42024-12-30 16:51:16 +000095bool ffa_boot_info_node(struct fdt_node *boot_info_node,
Kathleen Capella8393ea92025-01-09 17:22:21 -050096 struct partition_pkg *pkg,
97 enum ffa_version vm_ffa_version)
J-Alves35315782022-01-25 17:58:32 +000098{
99 struct memiter data;
J-Alves6e0abc42024-12-30 16:51:16 +0000100 struct ffa_boot_info_header *boot_info_header;
101 const size_t boot_info_size =
102 pa_difference(pkg->boot_info.begin, pkg->boot_info.end);
J-Alves7e67d102022-04-13 13:22:39 +0100103 const size_t max_boot_info_desc_count =
Madhukar Pappireddy00d3b632024-06-03 18:32:44 -0500104 (boot_info_size -
105 offsetof(struct ffa_boot_info_header, boot_info)) /
106 sizeof(struct ffa_boot_info_desc);
Kathleen Capellaf38bfff2024-10-16 18:12:59 -0400107 bool ret = false;
J-Alves35315782022-01-25 17:58:32 +0000108
109 assert(boot_info_node != NULL);
J-Alves6e0abc42024-12-30 16:51:16 +0000110 assert(pkg != NULL);
111
112 boot_info_header = (struct ffa_boot_info_header *)ptr_from_va(
113 va_from_pa(pkg->boot_info.begin));
114
J-Alves7e67d102022-04-13 13:22:39 +0100115 assert(boot_info_header != NULL);
J-Alves35315782022-01-25 17:58:32 +0000116
J-Alves7e67d102022-04-13 13:22:39 +0100117 /*
118 * FF-A v1.1 EAC0 specification states the region for the boot info
119 * descriptors, and the contents of the boot info shall be contiguous.
120 * Together they constitute the boot info blob. The are for the boot
121 * info blob is allocated in the SP's respective package.
122 * Retrieve from the SP package the size of the region for the boot info
123 * descriptors. The size of boot info contents to be incremented,
124 * depending on the info specified in the partition's FF-A manifest.
125 */
Kathleen Capella8393ea92025-01-09 17:22:21 -0500126 ffa_boot_info_header_init(boot_info_header, boot_info_size,
127 vm_ffa_version);
J-Alves35315782022-01-25 17:58:32 +0000128
129 if (!fdt_is_compatible(boot_info_node, "arm,ffa-manifest-boot-info")) {
130 dlog_verbose("The node 'boot-info' is not compatible.\n");
131 return false;
132 }
133
Kathleen Capellaf38bfff2024-10-16 18:12:59 -0400134 dlog_verbose(" FF-A Boot Info: base %lx\n",
135 (uintptr_t)ptr_from_va(va_from_pa(pkg->boot_info.begin)));
J-Alves35315782022-01-25 17:58:32 +0000136
137 if (fdt_read_property(boot_info_node, "ffa_manifest", &data) &&
138 memiter_size(&data) == 0U) {
J-Alves6e0abc42024-12-30 16:51:16 +0000139 ipaddr_t manifest_address = ipa_from_pa(pkg->pm.begin);
140 const uint32_t pm_size =
141 pa_difference(pkg->pm.begin, pkg->pm.end);
J-Alves7e67d102022-04-13 13:22:39 +0100142
Kathleen Capellaf38bfff2024-10-16 18:12:59 -0400143 dlog_verbose(" FF-A Manifest: %lx\n",
144 ipa_addr(manifest_address));
J-Alves6e0abc42024-12-30 16:51:16 +0000145 boot_info_write_desc(boot_info_header,
146 FFA_BOOT_INFO_FLAG_CONTENT_FORMAT_ADDR,
147 true, FFA_BOOT_INFO_TYPE_ID_FDT, pm_size,
148 ipa_addr(manifest_address),
149 max_boot_info_desc_count);
J-Alves7e67d102022-04-13 13:22:39 +0100150
151 /*
152 * Incrementing the size of the boot information blob with the
153 * size of the partition's manifest.
154 */
J-Alves6e0abc42024-12-30 16:51:16 +0000155 boot_info_header->info_blob_size += pm_size;
J-Alves7e67d102022-04-13 13:22:39 +0100156
Kathleen Capellaf38bfff2024-10-16 18:12:59 -0400157 ret = true;
158 }
159
160 if (fdt_read_property(boot_info_node, "hob_list", &data) &&
161 memiter_size(&data) == 0U) {
162 ipaddr_t hob_address = ipa_from_pa(pkg->hob.begin);
163 const uint32_t hob_size =
164 pa_difference(pkg->hob.begin, pkg->hob.end);
165
166 dlog_verbose(" Hob List: %lx, size: %x\n",
167 ipa_addr(hob_address), hob_size);
168 boot_info_write_desc(boot_info_header,
169 FFA_BOOT_INFO_FLAG_CONTENT_FORMAT_ADDR,
170 true, FFA_BOOT_INFO_TYPE_ID_HOB, hob_size,
171 ipa_addr(hob_address),
172 max_boot_info_desc_count);
173
174 /*
175 * Incrementing the size of the boot information blob with the
176 * size of the partition's manifest.
177 */
178 boot_info_header->info_blob_size += hob_size;
179
180 ret = true;
181 }
182
183 if (ret == true) {
J-Alves7e67d102022-04-13 13:22:39 +0100184 /*
185 * Flush the data cache in case partition initializes with
186 * caches disabled.
187 */
188 arch_mm_flush_dcache((void *)boot_info_header,
189 boot_info_header->info_blob_size);
J-Alves35315782022-01-25 17:58:32 +0000190 }
191
Kathleen Capellaf38bfff2024-10-16 18:12:59 -0400192 return ret;
J-Alves35315782022-01-25 17:58:32 +0000193}