1 /*
2 * Arm SCP/MCP Software
3 * Copyright (c) 2018-2022, Arm Limited and Contributors. All rights reserved.
4 *
5 * SPDX-License-Identifier: BSD-3-Clause
6 */
7
8 #include "synquacer_mmap.h"
9
10 #include <ddr_init.h>
11
12 #include <mod_nor.h>
13 #include <mod_synquacer_system.h>
14
15 #include <fwk_assert.h>
16 #include <fwk_attributes.h>
17 #include <fwk_log.h>
18 #include <fwk_macros.h>
19
20 #include <inttypes.h>
21 #include <stdint.h>
22 #include <string.h>
23
24 static fwk_id_t nor_id = FWK_ID_ELEMENT(FWK_MODULE_IDX_NOR, 0);
25
26 struct FWK_PACKED fip_toc_header_s {
27 uint32_t name;
28 uint32_t serial_num;
29 uint64_t flags;
30 };
31
32 typedef struct fip_toc_header_s fip_toc_header_t;
33 /* fip toc header 16 byte*/
34
35 struct FWK_PACKED fip_toc_entry_s {
36 uint8_t uuid[16];
37 uint64_t offset_addr;
38 uint64_t size;
39 uint64_t flags;
40 };
41
42 typedef struct fip_toc_entry_s fip_toc_entry_t;
43 /* fip toc entry 40 byte*/
44
45 struct FWK_PACKED fip_package_s {
46 fip_toc_header_t fip_toc_header;
47 fip_toc_entry_t fip_toc_entry[5];
48 uint32_t data[1];
49 };
50
51 typedef struct fip_package_s fip_package_t;
52
53 struct FWK_PACKED arm_tf_fip_package_s {
54 fip_toc_header_t fip_toc_header;
55 fip_toc_entry_t fip_toc_entry[4];
56 };
57
58 typedef struct arm_tf_fip_package_s arm_tf_fip_package_t;
59
60 #define ADDR_TRANS_EN (0x1 /* ADDR_TRANS_EN */ << 20)
61 #define REG_ASH_SCP_POW_CTL UINT32_C(0x50000000)
62 #define ADDR_TRANS_OFFSET UINT32_C(0x34)
63 #define OPTEE_OS_BINARY_SIZE UINT32_C(0x80000)
64 #define SCP_ADDR_TRANS_AREA UINT32_C(0xCB000000)
65 #define BL32_TOC_ENTRY_INDEX (3)
66
67 #define FIP_TOC_HEADER_NAME UINT32_C(0xAA640001)
68
69 #define UUID_NULL \
70 { \
71 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, \
72 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 \
73 }
74
75 #define FIP_UUID_TFA_BL2 \
76 { \
77 0x5f, 0xf9, 0xec, 0x0b, 0x4d, 0x22, 0x3e, 0x4d, \
78 0xa5, 0x44, 0xc3, 0x9d, 0x81, 0xc7, 0x3f, 0x0a, \
79 }
80
81 #define UUID_SECURE_PAYLOAD_BL32 \
82 { \
83 0x05, 0xd0, 0xe1, 0x89, 0x53, 0xdc, 0x13, 0x47, 0x8d, 0x2b, 0x50, \
84 0x0a, 0x4b, 0x7a, 0x3e, 0x38 \
85 }
86
87 /*
88 * New FIP loader for TBBR supported BL2
89 */
fw_fip_load_bl2(uint32_t boot_index)90 void fw_fip_load_bl2(uint32_t boot_index)
91 {
92 fip_toc_entry_t *toc_entry;
93 unsigned long offset;
94 uint8_t uuid_null[] = UUID_NULL;
95 uint8_t uuid_bl2[] = FIP_UUID_TFA_BL2;
96
97 arm_tf_fip_package_t fip_package;
98
99 offset = CONFIG_SCB_ARM_BL2_OFFSET + boot_index * CONFIG_SCB_FWU_BANK_SIZE;
100
101 synquacer_system_ctx.nor_api->read(
102 nor_id,
103 0,
104 MOD_NOR_READ_FAST_1_4_4_4BYTE,
105 offset,
106 &fip_package,
107 sizeof(fip_package));
108
109 if (fip_package.fip_toc_header.name != FIP_TOC_HEADER_NAME) {
110 FWK_LOG_ERR("No FIP Image found @%lx !", offset);
111 return;
112 }
113
114 toc_entry = fip_package.fip_toc_entry;
115
116 do {
117 if (memcmp((void *) uuid_null, (void *)toc_entry->uuid, 16) == 0) {
118 FWK_LOG_ERR("[FIP] BL2 not found!");
119 return;
120 }
121 if (memcmp((void *)uuid_bl2, (void *)toc_entry->uuid, 16) == 0) {
122 offset += (uint32_t)toc_entry->offset_addr;
123 FWK_LOG_INFO("[FIP] BL2 found %ubytes @%lx ",
124 (unsigned int)toc_entry->size, offset);
125 synquacer_system_ctx.nor_api->read(
126 nor_id,
127 0,
128 MOD_NOR_READ_FAST_1_4_4_4BYTE,
129 offset,
130 (void *)CONFIG_SCB_ARM_TB_BL1_BASE_ADDR,
131 toc_entry->size);
132 return;
133 }
134 toc_entry++;
135 } while (1);
136 }
137
138 /*
139 * Legacy implementation expects bl32 is located as 4th binary
140 * in the arm-tf fip package.
141 */
fw_fip_load_bl32(arm_tf_fip_package_t * fip_package_p)142 static void fw_fip_load_bl32(arm_tf_fip_package_t *fip_package_p)
143 {
144 uint32_t trans_addr_39_20;
145 uint32_t src;
146 void *dst;
147
148 /* enable DRAM access by configuring address trans register */
149 trans_addr_39_20 =
150 ((CONFIG_SCB_ARM_TB_BL32_BASE_ADDR >> 20) | ADDR_TRANS_EN);
151 *((volatile uint32_t *)(REG_ASH_SCP_POW_CTL + ADDR_TRANS_OFFSET)) =
152 trans_addr_39_20;
153
154 src = CONFIG_SCB_ARM_TF_OFFSET +
155 (uint32_t)fip_package_p->fip_toc_entry[BL32_TOC_ENTRY_INDEX].offset_addr;
156 dst = (void *)SCP_ADDR_TRANS_AREA;
157
158 FWK_LOG_INFO(
159 "[FIP] load BL32 src 0x%" PRIx32 ", dst %" PRIx32 ", size %" PRIu32,
160 HSSPI_MEM_BASE + src,
161 (uint32_t)CONFIG_SCB_ARM_TB_BL32_BASE_ADDR,
162 (uint32_t)fip_package_p->fip_toc_entry[BL32_TOC_ENTRY_INDEX].size);
163
164 synquacer_system_ctx.nor_api->read(
165 nor_id,
166 0,
167 MOD_NOR_READ_FAST_1_4_4_4BYTE,
168 src,
169 dst,
170 (uint32_t)fip_package_p->fip_toc_entry[BL32_TOC_ENTRY_INDEX].size);
171
172 /* disable DRAM access */
173 trans_addr_39_20 =
174 ((CONFIG_SCB_ARM_TB_BL32_BASE_ADDR >> 20) & ~ADDR_TRANS_EN);
175 *((volatile uint32_t *)(REG_ASH_SCP_POW_CTL + ADDR_TRANS_OFFSET)) =
176 trans_addr_39_20;
177
178 FWK_LOG_INFO("[FIP] BL32 is loaded");
179 }
180
fw_fip_load_arm_tf(void)181 void fw_fip_load_arm_tf(void)
182 {
183 uint32_t i;
184 uint32_t src;
185 uint8_t bl32_uuid[] = UUID_SECURE_PAYLOAD_BL32;
186 const uint32_t arm_tf_dst_addr[] = { CONFIG_SCB_ARM_TB_BL1_BASE_ADDR,
187 CONFIG_SCB_ARM_TB_BL2_BASE_ADDR,
188 CONFIG_SCB_ARM_TB_BL3_BASE_ADDR };
189 arm_tf_fip_package_t fip_package;
190
191 static_assert(
192 sizeof(fip_toc_header_t) == 16, "sizeof(fip_toc_header_t) is wrong");
193 static_assert(
194 sizeof(fip_toc_entry_t) == 40, "sizeof(fip_toc_entry_t) is wrong");
195 static_assert(
196 sizeof(arm_tf_fip_package_t) == 176,
197 "sizeof(arm_tf_fip_package_t) is wrong");
198
199 synquacer_system_ctx.nor_api->read(
200 nor_id,
201 0,
202 MOD_NOR_READ_FAST_1_4_4_4BYTE,
203 CONFIG_SCB_ARM_TF_OFFSET,
204 &fip_package,
205 sizeof(fip_package));
206
207 for (i = 0; i < FWK_ARRAY_SIZE(arm_tf_dst_addr); i++) {
208 FWK_LOG_INFO(
209 "[FIP] fip_toc_entry[%" PRIu32 "] offset_addr %" PRIx32,
210 i,
211 (uint32_t)fip_package.fip_toc_entry[i].offset_addr);
212
213 FWK_LOG_INFO(
214 "[FIP] fip_toc_entry[%" PRIu32 "] size %" PRIu32,
215 i,
216 (uint32_t)fip_package.fip_toc_entry[i].size);
217
218 FWK_LOG_INFO(
219 "[FIP] dst addr[%" PRIu32 "] %" PRIx32,
220 i,
221 arm_tf_dst_addr[i]);
222
223 src = CONFIG_SCB_ARM_TF_OFFSET +
224 (uint32_t)fip_package.fip_toc_entry[i].offset_addr;
225
226 FWK_LOG_INFO(
227 "[FIP] src addr[%" PRIu32 "] %" PRIx32,
228 i,
229 HSSPI_MEM_BASE + src);
230
231 synquacer_system_ctx.nor_api->read(
232 nor_id,
233 0,
234 MOD_NOR_READ_FAST_1_4_4_4BYTE,
235 src,
236 (void *)arm_tf_dst_addr[i],
237 (uint32_t)fip_package.fip_toc_entry[i].size);
238 }
239
240 if (ddr_is_secure_dram_enabled()) {
241 if (memcmp(
242 (void *)bl32_uuid,
243 (void *)fip_package.fip_toc_entry[BL32_TOC_ENTRY_INDEX].uuid,
244 sizeof(bl32_uuid)) == 0) {
245 fw_fip_load_bl32(&fip_package);
246 } else {
247 FWK_LOG_WARN("[FIP] no BL32 payload in fip image");
248 }
249 }
250 }
251