blob: 66662c111f41841f4f177f3eb61f5579416dbef9 [file] [log] [blame]
Jorge Ramirez-Ortizeaa63b42018-09-23 09:40:45 +02001/*
Tobias Rist2a5aa522023-03-16 21:31:15 +09002 * Copyright (c) 2015-2023, Renesas Electronics Corporation. All rights reserved.
Jorge Ramirez-Ortizeaa63b42018-09-23 09:40:45 +02003 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
Jorge Ramirez-Ortizeaa63b42018-09-23 09:40:45 +02007#include <errno.h>
Jorge Ramirez-Ortizeaa63b42018-09-23 09:40:45 +02008#include <stdint.h>
9#include <string.h>
Antonio Nino Diaze0f90632018-12-14 00:18:21 +000010
Jorge Ramirez-Ortizeaa63b42018-09-23 09:40:45 +020011#include <arch_helpers.h>
Antonio Nino Diaze0f90632018-12-14 00:18:21 +000012#include <common/bl_common.h>
13#include <common/debug.h>
14#include <drivers/auth/auth_mod.h>
15#include <drivers/io/io_driver.h>
16#include <drivers/io/io_storage.h>
17#include <lib/mmio.h>
18#include <plat/common/platform.h>
19#include <tools_share/firmware_image_package.h>
20#include <tools_share/uuid.h>
21
Jorge Ramirez-Ortizeaa63b42018-09-23 09:40:45 +020022#include "io_rcar.h"
23#include "io_common.h"
24#include "io_private.h"
Biju Das50bfdc42020-12-13 20:28:45 +000025#include <platform_def.h>
Antonio Nino Diaze0f90632018-12-14 00:18:21 +000026
Jorge Ramirez-Ortizeaa63b42018-09-23 09:40:45 +020027extern int32_t plat_get_drv_source(uint32_t id, uintptr_t *dev,
28 uintptr_t *image_spec);
29
Jorge Ramirez-Ortizeaa63b42018-09-23 09:40:45 +020030static int32_t rcar_dev_open(const uintptr_t dev_spec __attribute__ ((unused)),
31 io_dev_info_t **dev_info);
32static int32_t rcar_dev_close(io_dev_info_t *dev_info);
33
34typedef struct {
35 const int32_t name;
36 const uint32_t offset;
37 const uint32_t attr;
38} plat_rcar_name_offset_t;
39
40typedef struct {
Biju Das50bfdc42020-12-13 20:28:45 +000041 /*
42 * Put position above the struct to allow {0} on static init.
Jorge Ramirez-Ortizeaa63b42018-09-23 09:40:45 +020043 * It is a workaround for a known bug in GCC
44 * http://gcc.gnu.org/bugzilla/show_bug.cgi?id=53119
45 */
46 uint32_t position;
47 uint32_t no_load;
48 uintptr_t offset;
49 uint32_t size;
50 uintptr_t dst;
51 uintptr_t partition; /* for eMMC */
52 /* RCAR_EMMC_PARTITION_BOOT_0 */
53 /* RCAR_EMMC_PARTITION_BOOT_1 */
54 /* RCAR_EMMC_PARTITION_USER */
55} file_state_t;
56
57#define RCAR_GET_FLASH_ADR(a, b) ((uint32_t)((0x40000U * (a)) + (b)))
58#define RCAR_ATTR_SET_CALCADDR(a) ((a) & 0xF)
59#define RCAR_ATTR_SET_ISNOLOAD(a) (((a) & 0x1) << 16U)
60#define RCAR_ATTR_SET_CERTOFF(a) (((a) & 0xF) << 8U)
61#define RCAR_ATTR_SET_ALL(a, b, c) ((uint32_t)(RCAR_ATTR_SET_CALCADDR(a) |\
Biju Das50bfdc42020-12-13 20:28:45 +000062 RCAR_ATTR_SET_ISNOLOAD(b) |\
Jorge Ramirez-Ortizeaa63b42018-09-23 09:40:45 +020063 RCAR_ATTR_SET_CERTOFF(c)))
64
65#define RCAR_ATTR_GET_CALCADDR(a) ((a) & 0xFU)
66#define RCAR_ATTR_GET_ISNOLOAD(a) (((a) >> 16) & 0x1U)
67#define RCAR_ATTR_GET_CERTOFF(a) ((uint32_t)(((a) >> 8) & 0xFU))
68
69#define RCAR_MAX_BL3X_IMAGE (8U)
70#define RCAR_SECTOR6_CERT_OFFSET (0x400U)
71#define RCAR_SDRAM_certESS (0x43F00000U)
72#define RCAR_CERT_SIZE (0x800U)
73#define RCAR_CERT_INFO_SIZE_OFFSET (0x264U)
74#define RCAR_CERT_INFO_DST_OFFSET (0x154U)
75#define RCAR_CERT_INFO_SIZE_OFFSET1 (0x364U)
76#define RCAR_CERT_INFO_DST_OFFSET1 (0x1D4U)
77#define RCAR_CERT_INFO_SIZE_OFFSET2 (0x464U)
78#define RCAR_CERT_INFO_DST_OFFSET2 (0x254U)
79#define RCAR_CERT_LOAD (1U)
80
81#define RCAR_FLASH_CERT_HEADER RCAR_GET_FLASH_ADR(6U, 0U)
82#define RCAR_EMMC_CERT_HEADER (0x00030000U)
83
84#define RCAR_COUNT_LOAD_BL33 (2U)
85#define RCAR_COUNT_LOAD_BL33X (3U)
86
Tobias Rist2a5aa522023-03-16 21:31:15 +090087#define CHECK_IMAGE_AREA_CNT (7U)
88#define BOOT_BL2_ADDR (0xE6304000U)
89#define BOOT_BL2_LENGTH (0x19000U)
90
91typedef struct {
92 uintptr_t dest;
93 uintptr_t length;
94} addr_loaded_t;
95
96static addr_loaded_t addr_loaded[CHECK_IMAGE_AREA_CNT] = {
97 [0] = {BOOT_BL2_ADDR, BOOT_BL2_LENGTH},
98 [1] = {BL31_BASE, RCAR_TRUSTED_SRAM_SIZE},
99#ifndef SPD_NONE
100 [2] = {BL32_BASE, BL32_SIZE}
101#endif
102};
103
104#ifndef SPD_NONE
105static uint32_t addr_loaded_cnt = 3;
106#else
107static uint32_t addr_loaded_cnt = 2;
108#endif
109
Jorge Ramirez-Ortizeaa63b42018-09-23 09:40:45 +0200110static const plat_rcar_name_offset_t name_offset[] = {
111 {BL31_IMAGE_ID, 0U, RCAR_ATTR_SET_ALL(0, 0, 0)},
112
113 /* BL3-2 is optional in the platform */
114 {BL32_IMAGE_ID, 0U, RCAR_ATTR_SET_ALL(1, 0, 1)},
115 {BL33_IMAGE_ID, 0U, RCAR_ATTR_SET_ALL(2, 0, 2)},
116 {BL332_IMAGE_ID, 0U, RCAR_ATTR_SET_ALL(3, 0, 3)},
117 {BL333_IMAGE_ID, 0U, RCAR_ATTR_SET_ALL(4, 0, 4)},
118 {BL334_IMAGE_ID, 0U, RCAR_ATTR_SET_ALL(5, 0, 5)},
119 {BL335_IMAGE_ID, 0U, RCAR_ATTR_SET_ALL(6, 0, 6)},
120 {BL336_IMAGE_ID, 0U, RCAR_ATTR_SET_ALL(7, 0, 7)},
121 {BL337_IMAGE_ID, 0U, RCAR_ATTR_SET_ALL(8, 0, 8)},
122 {BL338_IMAGE_ID, 0U, RCAR_ATTR_SET_ALL(9, 0, 9)},
123};
124
125#if TRUSTED_BOARD_BOOT
126static const plat_rcar_name_offset_t cert_offset[] = {
127 /* Certificates */
128 {TRUSTED_KEY_CERT_ID, 0U, RCAR_ATTR_SET_ALL(0, 1, 0)},
129 {SOC_FW_KEY_CERT_ID, 0U, RCAR_ATTR_SET_ALL(0, 1, 0)},
130 {TRUSTED_OS_FW_KEY_CERT_ID, 0U, RCAR_ATTR_SET_ALL(0, 1, 0)},
131 {NON_TRUSTED_FW_KEY_CERT_ID, 0U, RCAR_ATTR_SET_ALL(0, 1, 0)},
132 {SOC_FW_CONTENT_CERT_ID, 0U, RCAR_ATTR_SET_ALL(0, 1, 0)},
133 {TRUSTED_OS_FW_CONTENT_CERT_ID, 0U, RCAR_ATTR_SET_ALL(0, 1, 1)},
134 {NON_TRUSTED_FW_CONTENT_CERT_ID, 0U, RCAR_ATTR_SET_ALL(0, 1, 2)},
135 {BL332_CERT_ID, 0U, RCAR_ATTR_SET_ALL(0, 1, 3)},
136 {BL333_CERT_ID, 0U, RCAR_ATTR_SET_ALL(0, 1, 4)},
137 {BL334_CERT_ID, 0U, RCAR_ATTR_SET_ALL(0, 1, 5)},
138 {BL335_CERT_ID, 0U, RCAR_ATTR_SET_ALL(0, 1, 6)},
139 {BL336_CERT_ID, 0U, RCAR_ATTR_SET_ALL(0, 1, 7)},
140 {BL337_CERT_ID, 0U, RCAR_ATTR_SET_ALL(0, 1, 8)},
141 {BL338_CERT_ID, 0U, RCAR_ATTR_SET_ALL(0, 1, 9)},
142};
143#endif /* TRUSTED_BOARD_BOOT */
144
145static file_state_t current_file = { 0 };
146
147static uintptr_t rcar_handle, rcar_spec;
148static uint64_t rcar_image_header[RCAR_MAX_BL3X_IMAGE + 2U] = { 0U };
149static uint64_t rcar_image_header_prttn[RCAR_MAX_BL3X_IMAGE + 2U] = { 0U };
150static uint64_t rcar_image_number = { 0U };
151static uint32_t rcar_cert_load = { 0U };
152
153static io_type_t device_type_rcar(void)
154{
155 return IO_TYPE_FIRMWARE_IMAGE_PACKAGE;
156}
157
158int32_t rcar_get_certificate(const int32_t name, uint32_t *cert)
159{
160#if TRUSTED_BOARD_BOOT
161 int32_t i;
Biju Das50bfdc42020-12-13 20:28:45 +0000162
Jorge Ramirez-Ortizeaa63b42018-09-23 09:40:45 +0200163 for (i = 0; i < ARRAY_SIZE(cert_offset); i++) {
Biju Das50bfdc42020-12-13 20:28:45 +0000164 if (name != cert_offset[i].name) {
Jorge Ramirez-Ortizeaa63b42018-09-23 09:40:45 +0200165 continue;
Biju Das50bfdc42020-12-13 20:28:45 +0000166 }
Jorge Ramirez-Ortizeaa63b42018-09-23 09:40:45 +0200167
168 *cert = RCAR_CERT_SIZE;
169 *cert *= RCAR_ATTR_GET_CERTOFF(cert_offset[i].attr);
170 *cert += RCAR_SDRAM_certESS;
171 return 0;
172 }
173#endif
174 return -EINVAL;
175}
176
Marek Vasut62ae5422021-03-21 00:55:48 +0100177#define MFISBTSTSR (0xE6260604U)
178#define MFISBTSTSR_BOOT_PARTITION (0x00000010U)
179
Jorge Ramirez-Ortizeaa63b42018-09-23 09:40:45 +0200180static int32_t file_to_offset(const int32_t name, uintptr_t *offset,
181 uint32_t *cert, uint32_t *no_load,
182 uintptr_t *partition)
183{
184 uint32_t addr;
185 int32_t i;
186
187 for (i = 0; i < ARRAY_SIZE(name_offset); i++) {
Biju Das50bfdc42020-12-13 20:28:45 +0000188 if (name != name_offset[i].name) {
Jorge Ramirez-Ortizeaa63b42018-09-23 09:40:45 +0200189 continue;
Biju Das50bfdc42020-12-13 20:28:45 +0000190 }
Jorge Ramirez-Ortizeaa63b42018-09-23 09:40:45 +0200191
192 addr = RCAR_ATTR_GET_CALCADDR(name_offset[i].attr);
Biju Das50bfdc42020-12-13 20:28:45 +0000193 if (rcar_image_number + 2U < addr) {
Jorge Ramirez-Ortizeaa63b42018-09-23 09:40:45 +0200194 continue;
Biju Das50bfdc42020-12-13 20:28:45 +0000195 }
Jorge Ramirez-Ortizeaa63b42018-09-23 09:40:45 +0200196
197 *offset = rcar_image_header[addr];
Marek Vasut62ae5422021-03-21 00:55:48 +0100198
199 if (mmio_read_32(MFISBTSTSR) & MFISBTSTSR_BOOT_PARTITION)
200 *offset += 0x800000;
Jorge Ramirez-Ortizeaa63b42018-09-23 09:40:45 +0200201 *cert = RCAR_CERT_SIZE;
202 *cert *= RCAR_ATTR_GET_CERTOFF(name_offset[i].attr);
203 *cert += RCAR_SDRAM_certESS;
204 *no_load = RCAR_ATTR_GET_ISNOLOAD(name_offset[i].attr);
205 *partition = rcar_image_header_prttn[addr];
206 return IO_SUCCESS;
207 }
208
209#if TRUSTED_BOARD_BOOT
210 for (i = 0; i < ARRAY_SIZE(cert_offset); i++) {
Biju Das50bfdc42020-12-13 20:28:45 +0000211 if (name != cert_offset[i].name) {
Jorge Ramirez-Ortizeaa63b42018-09-23 09:40:45 +0200212 continue;
Biju Das50bfdc42020-12-13 20:28:45 +0000213 }
Jorge Ramirez-Ortizeaa63b42018-09-23 09:40:45 +0200214
215 *no_load = RCAR_ATTR_GET_ISNOLOAD(cert_offset[i].attr);
216 *partition = 0U;
217 *offset = 0U;
218 *cert = 0U;
219 return IO_SUCCESS;
220 }
221#endif
222 return -EINVAL;
223}
224
225#define RCAR_BOOT_KEY_CERT_NEW (0xE6300F00U)
226#define RCAR_CERT_MAGIC_NUM (0xE291F358U)
227
228void rcar_read_certificate(uint64_t cert, uint32_t *len, uintptr_t *dst)
229{
230 uint32_t seed, val, info_1, info_2;
231 uintptr_t size, dsth, dstl;
232
233 cert &= 0xFFFFFFFFU;
234
235 seed = mmio_read_32(RCAR_BOOT_KEY_CERT_NEW);
236 val = mmio_read_32(RCAR_BOOT_KEY_CERT_NEW + 0xC);
237 info_1 = (val >> 18) & 0x3U;
238 val = mmio_read_32(cert + 0xC);
239 info_2 = (val >> 21) & 0x3;
240
241 if (seed == RCAR_CERT_MAGIC_NUM) {
242 if (info_1 != 1) {
243 ERROR("BL2: Cert is invalid.\n");
244 *dst = 0;
245 *len = 0;
246 return;
247 }
248
249 if (info_2 > 2) {
250 ERROR("BL2: Cert is invalid.\n");
251 *dst = 0;
252 *len = 0;
253 return;
254 }
255
256 switch (info_2) {
257 case 2:
258 size = cert + RCAR_CERT_INFO_SIZE_OFFSET2;
259 dstl = cert + RCAR_CERT_INFO_DST_OFFSET2;
260 break;
261 case 1:
262 size = cert + RCAR_CERT_INFO_SIZE_OFFSET1;
263 dstl = cert + RCAR_CERT_INFO_DST_OFFSET1;
264 break;
265 case 0:
266 size = cert + RCAR_CERT_INFO_SIZE_OFFSET;
267 dstl = cert + RCAR_CERT_INFO_DST_OFFSET;
268 break;
269 }
Tobias Rist55351b92023-03-07 09:00:09 +0100270 val = mmio_read_32(size);
271 if (val > (UINT32_MAX / 4)) {
272 ERROR("BL2: %s[%d] uint32 overflow!\n",
273 __func__, __LINE__);
274 *dst = 0;
275 *len = 0;
276 return;
277 }
Jorge Ramirez-Ortizeaa63b42018-09-23 09:40:45 +0200278
Tobias Rist55351b92023-03-07 09:00:09 +0100279 *len = val * 4U;
Jorge Ramirez-Ortizeaa63b42018-09-23 09:40:45 +0200280 dsth = dstl + 4U;
281 *dst = ((uintptr_t) mmio_read_32(dsth) << 32) +
282 ((uintptr_t) mmio_read_32(dstl));
283 return;
284 }
285
286 size = cert + RCAR_CERT_INFO_SIZE_OFFSET;
Yoshifumi Hosoya12d1e632023-04-23 19:14:51 +0900287 val = mmio_read_32(size);
288 if (val > (UINT32_MAX / 4)) {
289 ERROR("BL2: %s[%d] uint32 overflow!\n", __func__, __LINE__);
290 *dst = 0;
291 *len = 0;
292 return;
293 }
294 *len = val * 4U;
Jorge Ramirez-Ortizeaa63b42018-09-23 09:40:45 +0200295 dstl = cert + RCAR_CERT_INFO_DST_OFFSET;
296 dsth = dstl + 4U;
297 *dst = ((uintptr_t) mmio_read_32(dsth) << 32) +
298 ((uintptr_t) mmio_read_32(dstl));
299}
300
301static int32_t check_load_area(uintptr_t dst, uintptr_t len)
302{
303 uint32_t legacy = dst + len <= UINT32_MAX - 1 ? 1 : 0;
304 uintptr_t dram_start, dram_end;
305 uintptr_t prot_start, prot_end;
306 int32_t result = IO_SUCCESS;
Tobias Rist2a5aa522023-03-16 21:31:15 +0900307 int n;
Jorge Ramirez-Ortizeaa63b42018-09-23 09:40:45 +0200308
Tobias Rist2a5aa522023-03-16 21:31:15 +0900309 dram_start = legacy ? DRAM1_NS_BASE : DRAM_40BIT_BASE;
Jorge Ramirez-Ortizeaa63b42018-09-23 09:40:45 +0200310
Tobias Rist2a5aa522023-03-16 21:31:15 +0900311 dram_end = legacy ? DRAM1_NS_BASE + DRAM1_NS_SIZE :
Jorge Ramirez-Ortizeaa63b42018-09-23 09:40:45 +0200312 DRAM_40BIT_BASE + DRAM_40BIT_SIZE;
313
314 prot_start = legacy ? DRAM_PROTECTED_BASE : DRAM_40BIT_PROTECTED_BASE;
315
316 prot_end = prot_start + DRAM_PROTECTED_SIZE;
317
Tobias Ristae508be2023-03-07 09:40:37 +0100318 if (dst < dram_start || len > dram_end || dst > dram_end - len) {
Jorge Ramirez-Ortizeaa63b42018-09-23 09:40:45 +0200319 ERROR("BL2: dst address is on the protected area.\n");
320 result = IO_FAIL;
321 goto done;
322 }
323
324 /* load image is within SDRAM protected area */
325 if (dst >= prot_start && dst < prot_end) {
326 ERROR("BL2: dst address is on the protected area.\n");
327 result = IO_FAIL;
Tobias Rist2a5aa522023-03-16 21:31:15 +0900328 goto done;
Jorge Ramirez-Ortizeaa63b42018-09-23 09:40:45 +0200329 }
330
Tobias Ristae508be2023-03-07 09:40:37 +0100331 if (len > prot_start || (dst < prot_start && dst > prot_start - len)) {
332 ERROR("BL2: %s[%d] loaded data is on the protected area.\n",
333 __func__, __LINE__);
Jorge Ramirez-Ortizeaa63b42018-09-23 09:40:45 +0200334 result = IO_FAIL;
Tobias Rist2a5aa522023-03-16 21:31:15 +0900335 goto done;
336 }
337
338 if (addr_loaded_cnt >= CHECK_IMAGE_AREA_CNT) {
339 ERROR("BL2: max loadable non secure images reached\n");
340 result = IO_FAIL;
341 goto done;
Jorge Ramirez-Ortizeaa63b42018-09-23 09:40:45 +0200342 }
Tobias Rist2a5aa522023-03-16 21:31:15 +0900343
344 addr_loaded[addr_loaded_cnt].dest = dst;
345 addr_loaded[addr_loaded_cnt].length = len;
346 for (n = 0; n < addr_loaded_cnt; n++) {
347 /*
348 * Check if next image invades a previous loaded image
349 *
350 * IMAGE n: area from previous image: dest| IMAGE n |length
351 * IMAGE n+1: area from next image: dst | IMAGE n |len
352 *
353 * 1. check:
354 * | IMAGE n |
355 * | IMAGE n+1 |
356 * 2. check:
357 * | IMAGE n |
358 * | IMAGE n+1 |
359 * 3. check:
360 * | IMAGE n |
361 * | IMAGE n+1 |
362 */
363 if (((dst >= addr_loaded[n].dest) &&
364 (dst <= addr_loaded[n].dest + addr_loaded[n].length)) ||
365 ((dst + len >= addr_loaded[n].dest) &&
366 (dst + len <= addr_loaded[n].dest + addr_loaded[n].length)) ||
367 ((dst <= addr_loaded[n].dest) &&
368 (dst + len >= addr_loaded[n].dest + addr_loaded[n].length))) {
369 ERROR("BL2: next image overlap a previous image area.\n");
370 result = IO_FAIL;
371 goto done;
372 }
373 }
374 addr_loaded_cnt++;
375
Jorge Ramirez-Ortizeaa63b42018-09-23 09:40:45 +0200376done:
Biju Das50bfdc42020-12-13 20:28:45 +0000377 if (result == IO_FAIL) {
Jorge Ramirez-Ortizeaa63b42018-09-23 09:40:45 +0200378 ERROR("BL2: Out of range : dst=0x%lx len=0x%lx\n", dst, len);
Biju Das50bfdc42020-12-13 20:28:45 +0000379 }
Jorge Ramirez-Ortizeaa63b42018-09-23 09:40:45 +0200380
381 return result;
382}
383
384static int32_t load_bl33x(void)
385{
386 static int32_t loaded = IO_NOT_SUPPORTED;
387 uintptr_t dst, partition, handle;
388 uint32_t noload, cert, len, i;
389 uintptr_t offset;
390 int32_t rc;
391 size_t cnt;
392 const int32_t img[] = {
393 BL33_IMAGE_ID,
394 BL332_IMAGE_ID,
395 BL333_IMAGE_ID,
396 BL334_IMAGE_ID,
397 BL335_IMAGE_ID,
398 BL336_IMAGE_ID,
399 BL337_IMAGE_ID,
400 BL338_IMAGE_ID
401 };
402
Biju Das50bfdc42020-12-13 20:28:45 +0000403 if (loaded != IO_NOT_SUPPORTED) {
Jorge Ramirez-Ortizeaa63b42018-09-23 09:40:45 +0200404 return loaded;
Biju Das50bfdc42020-12-13 20:28:45 +0000405 }
Jorge Ramirez-Ortizeaa63b42018-09-23 09:40:45 +0200406
407 for (i = 1; i < rcar_image_number; i++) {
408 rc = file_to_offset(img[i], &offset, &cert, &noload,
409 &partition);
410 if (rc != IO_SUCCESS) {
Biju Das50bfdc42020-12-13 20:28:45 +0000411 WARN("%s: failed to get offset\n", __func__);
Jorge Ramirez-Ortizeaa63b42018-09-23 09:40:45 +0200412 loaded = IO_FAIL;
413 return loaded;
414 }
415
416 rcar_read_certificate((uint64_t) cert, &len, &dst);
417 ((io_drv_spec_t *) rcar_spec)->partition = partition;
418
419 rc = io_open(rcar_handle, rcar_spec, &handle);
420 if (rc != IO_SUCCESS) {
Biju Das50bfdc42020-12-13 20:28:45 +0000421 WARN("%s: Failed to open FIP (%i)\n", __func__, rc);
Jorge Ramirez-Ortizeaa63b42018-09-23 09:40:45 +0200422 loaded = IO_FAIL;
423 return loaded;
424 }
425
426 rc = io_seek(handle, IO_SEEK_SET, offset);
427 if (rc != IO_SUCCESS) {
Biju Das50bfdc42020-12-13 20:28:45 +0000428 WARN("%s: failed to seek\n", __func__);
Jorge Ramirez-Ortizeaa63b42018-09-23 09:40:45 +0200429 loaded = IO_FAIL;
430 return loaded;
431 }
432
433 rc = check_load_area(dst, len);
434 if (rc != IO_SUCCESS) {
Biju Das50bfdc42020-12-13 20:28:45 +0000435 WARN("%s: check load area\n", __func__);
Jorge Ramirez-Ortizeaa63b42018-09-23 09:40:45 +0200436 loaded = IO_FAIL;
437 return loaded;
438 }
439
440 rc = io_read(handle, dst, len, &cnt);
441 if (rc != IO_SUCCESS) {
Biju Das50bfdc42020-12-13 20:28:45 +0000442 WARN("%s: failed to read\n", __func__);
Jorge Ramirez-Ortizeaa63b42018-09-23 09:40:45 +0200443 loaded = IO_FAIL;
444 return loaded;
445 }
446#if TRUSTED_BOARD_BOOT
447 rc = auth_mod_verify_img(img[i], (void *)dst, len);
Biju Das50bfdc42020-12-13 20:28:45 +0000448 if (rc != 0) {
Jorge Ramirez-Ortizeaa63b42018-09-23 09:40:45 +0200449 memset((void *)dst, 0x00, len);
450 loaded = IO_FAIL;
451 return loaded;
452 }
453#endif
454 io_close(handle);
455 }
456
457 loaded = IO_SUCCESS;
458
459 return loaded;
460}
461
462static int32_t rcar_dev_init(io_dev_info_t *dev_info, const uintptr_t name)
463{
Toshiyuki Ogasaharafe9bad82021-07-12 19:34:34 +0900464 static uint64_t header[64] __aligned(FLASH_TRANS_SIZE_UNIT) = {0UL};
Jorge Ramirez-Ortizeaa63b42018-09-23 09:40:45 +0200465 uintptr_t handle;
466 ssize_t offset;
467 uint32_t i;
468 int32_t rc;
469 size_t cnt;
470
471 /* Obtain a reference to the image by querying the platform layer */
472 rc = plat_get_drv_source(name, &rcar_handle, &rcar_spec);
473 if (rc != IO_SUCCESS) {
474 WARN("Failed to obtain reference to img %ld (%i)\n", name, rc);
475 return IO_FAIL;
476 }
477
Biju Das50bfdc42020-12-13 20:28:45 +0000478 if (rcar_cert_load == RCAR_CERT_LOAD) {
Jorge Ramirez-Ortizeaa63b42018-09-23 09:40:45 +0200479 return IO_SUCCESS;
Biju Das50bfdc42020-12-13 20:28:45 +0000480 }
Jorge Ramirez-Ortizeaa63b42018-09-23 09:40:45 +0200481
482 rc = io_open(rcar_handle, rcar_spec, &handle);
483 if (rc != IO_SUCCESS) {
484 WARN("Failed to access img %ld (%i)\n", name, rc);
485 return IO_FAIL;
486 }
487
Biju Das50bfdc42020-12-13 20:28:45 +0000488 /*
489 * get start address list
490 * [0] address num
491 * [1] BL33-1 image address
492 * [2] BL33-2 image address
493 * [3] BL33-3 image address
494 * [4] BL33-4 image address
495 * [5] BL33-5 image address
496 * [6] BL33-6 image address
497 * [7] BL33-7 image address
498 * [8] BL33-8 image address
499 */
Jorge Ramirez-Ortizeaa63b42018-09-23 09:40:45 +0200500 offset = name == EMMC_DEV_ID ? RCAR_EMMC_CERT_HEADER :
501 RCAR_FLASH_CERT_HEADER;
502 rc = io_seek(handle, IO_SEEK_SET, offset);
503 if (rc != IO_SUCCESS) {
504 WARN("Firmware Image Package header failed to seek\n");
505 goto error;
506 }
Toshiyuki Ogasahara67116a82021-07-13 14:20:57 +0900507
Jorge Ramirez-Ortizeaa63b42018-09-23 09:40:45 +0200508 rc = io_read(handle, (uintptr_t) &header, sizeof(header), &cnt);
509 if (rc != IO_SUCCESS) {
510 WARN("Firmware Image Package header failed to read\n");
511 goto error;
512 }
513
Toshiyuki Ogasahara67116a82021-07-13 14:20:57 +0900514#if RCAR_BL2_DCACHE == 1
515 inv_dcache_range((uint64_t) header, sizeof(header));
516#endif
517
Jorge Ramirez-Ortizeaa63b42018-09-23 09:40:45 +0200518 rcar_image_number = header[0];
Jorge Ramirez-Ortizeaa63b42018-09-23 09:40:45 +0200519 if (rcar_image_number == 0 || rcar_image_number > RCAR_MAX_BL3X_IMAGE) {
520 WARN("Firmware Image Package header check failed.\n");
Toshiyuki Ogasaharafe9bad82021-07-12 19:34:34 +0900521 rc = IO_FAIL;
Jorge Ramirez-Ortizeaa63b42018-09-23 09:40:45 +0200522 goto error;
523 }
524
Yoshifumi Hosoya473cfc82023-07-03 16:58:11 +0900525 for (i = 0; i < rcar_image_number + 2; i++) {
526 rcar_image_header[i] = header[i * 2 + 1];
527 rcar_image_header_prttn[i] = header[i * 2 + 2];
528 }
529
Jorge Ramirez-Ortizeaa63b42018-09-23 09:40:45 +0200530 rc = io_seek(handle, IO_SEEK_SET, offset + RCAR_SECTOR6_CERT_OFFSET);
531 if (rc != IO_SUCCESS) {
532 WARN("Firmware Image Package header failed to seek cert\n");
533 goto error;
534 }
Toshiyuki Ogasahara67116a82021-07-13 14:20:57 +0900535
Jorge Ramirez-Ortizeaa63b42018-09-23 09:40:45 +0200536 rc = io_read(handle, RCAR_SDRAM_certESS,
537 RCAR_CERT_SIZE * (2 + rcar_image_number), &cnt);
538 if (rc != IO_SUCCESS) {
539 WARN("cert file read error.\n");
540 goto error;
541 }
542
Toshiyuki Ogasahara67116a82021-07-13 14:20:57 +0900543#if RCAR_BL2_DCACHE == 1
544 inv_dcache_range(RCAR_SDRAM_certESS,
545 RCAR_CERT_SIZE * (2 + rcar_image_number));
546#endif
547
Jorge Ramirez-Ortizeaa63b42018-09-23 09:40:45 +0200548 rcar_cert_load = RCAR_CERT_LOAD;
549error:
550
Biju Das50bfdc42020-12-13 20:28:45 +0000551 if (rc != IO_SUCCESS) {
Jorge Ramirez-Ortizeaa63b42018-09-23 09:40:45 +0200552 rc = IO_FAIL;
Biju Das50bfdc42020-12-13 20:28:45 +0000553 }
Jorge Ramirez-Ortizeaa63b42018-09-23 09:40:45 +0200554
555 io_close(handle);
556
557 return rc;
558
559}
560
561static int32_t rcar_file_open(io_dev_info_t *info, const uintptr_t file_spec,
562 io_entity_t *entity)
563{
564 const io_drv_spec_t *spec = (io_drv_spec_t *) file_spec;
565 uintptr_t partition, offset, dst;
566 uint32_t noload, cert, len;
567 int32_t rc;
568
Biju Das50bfdc42020-12-13 20:28:45 +0000569 /*
570 * Only one file open at a time. We need to track state (ie, file
571 * cursor position). Since the header lives at offset zero, this entry
Jorge Ramirez-Ortizeaa63b42018-09-23 09:40:45 +0200572 * should never be zero in an active file.
573 * Once the system supports dynamic memory allocation we will allow more
Biju Das50bfdc42020-12-13 20:28:45 +0000574 * than one open file at a time.
575 */
Jorge Ramirez-Ortizeaa63b42018-09-23 09:40:45 +0200576 if (current_file.offset != 0U) {
Biju Das50bfdc42020-12-13 20:28:45 +0000577 WARN("%s: Only one open file at a time.\n", __func__);
Jorge Ramirez-Ortizeaa63b42018-09-23 09:40:45 +0200578 return IO_RESOURCES_EXHAUSTED;
579 }
580
581 rc = file_to_offset(spec->offset, &offset, &cert, &noload, &partition);
582 if (rc != IO_SUCCESS) {
583 WARN("Failed to open file name %ld (%i)\n", spec->offset, rc);
584 return IO_FAIL;
585 }
586
Biju Das50bfdc42020-12-13 20:28:45 +0000587 if (noload != 0U) {
Jorge Ramirez-Ortizeaa63b42018-09-23 09:40:45 +0200588 current_file.offset = 1;
589 current_file.dst = 0;
590 current_file.size = 1;
591 current_file.position = 0;
592 current_file.no_load = noload;
593 current_file.partition = 0;
594 entity->info = (uintptr_t) &current_file;
595
596 return IO_SUCCESS;
597 }
598
599 rcar_read_certificate((uint64_t) cert, &len, &dst);
600
Jorge Ramirez-Ortizeaa63b42018-09-23 09:40:45 +0200601 current_file.partition = partition;
602 current_file.no_load = noload;
603 current_file.offset = offset;
604 current_file.position = 0;
605 current_file.size = len;
606 current_file.dst = dst;
607 entity->info = (uintptr_t) &current_file;
608
609 return IO_SUCCESS;
610}
611
612static int32_t rcar_file_len(io_entity_t *entity, size_t *length)
613{
614 *length = ((file_state_t *) entity->info)->size;
615
616 NOTICE("%s: len: 0x%08lx\n", __func__, *length);
617
618 return IO_SUCCESS;
619}
620
621static int32_t rcar_file_read(io_entity_t *entity, uintptr_t buffer,
622 size_t length, size_t *cnt)
623{
624 file_state_t *fp = (file_state_t *) entity->info;
625 ssize_t offset = fp->offset + fp->position;
626 uintptr_t handle;
627 int32_t rc;
628
629#ifdef SPD_NONE
630 static uint32_t load_bl33x_counter = 1;
631#else
632 static uint32_t load_bl33x_counter;
633#endif
Biju Das50bfdc42020-12-13 20:28:45 +0000634 if (current_file.no_load != 0U) {
Jorge Ramirez-Ortizeaa63b42018-09-23 09:40:45 +0200635 *cnt = length;
636 return IO_SUCCESS;
637 }
638
639 ((io_drv_spec_t *) rcar_spec)->partition = fp->partition;
640
641 rc = io_open(rcar_handle, rcar_spec, &handle);
642 if (rc != IO_SUCCESS) {
643 WARN("Failed to open FIP (%i)\n", rc);
644 return IO_FAIL;
645 }
646
647 rc = io_seek(handle, IO_SEEK_SET, offset);
648 if (rc != IO_SUCCESS) {
Biju Das50bfdc42020-12-13 20:28:45 +0000649 WARN("%s: failed to seek\n", __func__);
Jorge Ramirez-Ortizeaa63b42018-09-23 09:40:45 +0200650 goto error;
651 }
652
653 if (load_bl33x_counter == RCAR_COUNT_LOAD_BL33) {
654 rc = check_load_area(buffer, length);
655 if (rc != IO_SUCCESS) {
Biju Das50bfdc42020-12-13 20:28:45 +0000656 WARN("%s: load area err\n", __func__);
Jorge Ramirez-Ortizeaa63b42018-09-23 09:40:45 +0200657 goto error;
658 }
659 }
660
661 rc = io_read(handle, buffer, length, cnt);
662 if (rc != IO_SUCCESS) {
663 WARN("Failed to read payload (%i)\n", rc);
664 goto error;
665 }
666
667 fp->position += *cnt;
668 io_close(handle);
669
670 load_bl33x_counter += 1;
Biju Das50bfdc42020-12-13 20:28:45 +0000671 if (load_bl33x_counter == RCAR_COUNT_LOAD_BL33X) {
Jorge Ramirez-Ortizeaa63b42018-09-23 09:40:45 +0200672 return load_bl33x();
Biju Das50bfdc42020-12-13 20:28:45 +0000673 }
Jorge Ramirez-Ortizeaa63b42018-09-23 09:40:45 +0200674
675 return IO_SUCCESS;
676error:
677 io_close(handle);
678 return IO_FAIL;
679}
680
681static int32_t rcar_file_close(io_entity_t *entity)
682{
Biju Das50bfdc42020-12-13 20:28:45 +0000683 if (current_file.offset != 0U) {
Jorge Ramirez-Ortizeaa63b42018-09-23 09:40:45 +0200684 memset(&current_file, 0, sizeof(current_file));
Biju Das50bfdc42020-12-13 20:28:45 +0000685 }
Jorge Ramirez-Ortizeaa63b42018-09-23 09:40:45 +0200686
687 entity->info = 0U;
688
689 return IO_SUCCESS;
690}
691
692static const io_dev_funcs_t rcar_dev_funcs = {
693 .type = &device_type_rcar,
694 .open = &rcar_file_open,
695 .seek = NULL,
696 .size = &rcar_file_len,
697 .read = &rcar_file_read,
698 .write = NULL,
699 .close = &rcar_file_close,
700 .dev_init = &rcar_dev_init,
701 .dev_close = &rcar_dev_close,
702};
703
704static const io_dev_info_t rcar_dev_info = {
705 .funcs = &rcar_dev_funcs,
706 .info = (uintptr_t) 0
707};
708
709static const io_dev_connector_t rcar_dev_connector = {
710 .dev_open = &rcar_dev_open
711};
712
713static int32_t rcar_dev_open(const uintptr_t dev_spec __attribute__ ((unused)),
714 io_dev_info_t **dev_info)
715{
716 *dev_info = (io_dev_info_t *) &rcar_dev_info;
717
718 return IO_SUCCESS;
719}
720
721static int32_t rcar_dev_close(io_dev_info_t *dev_info)
722{
723 rcar_handle = 0;
724 rcar_spec = 0;
725
726 return IO_SUCCESS;
727}
728
729int32_t rcar_register_io_dev(const io_dev_connector_t **dev_con)
730{
731 int32_t result;
732
733 result = io_register_device(&rcar_dev_info);
Biju Das50bfdc42020-12-13 20:28:45 +0000734 if (result == IO_SUCCESS) {
Jorge Ramirez-Ortizeaa63b42018-09-23 09:40:45 +0200735 *dev_con = &rcar_dev_connector;
Biju Das50bfdc42020-12-13 20:28:45 +0000736 }
Jorge Ramirez-Ortizeaa63b42018-09-23 09:40:45 +0200737
738 return result;
739}