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