blob: 650931bb4517a6269c1b77b916568386477029bb [file] [log] [blame]
Jorge Ramirez-Ortizeaa63b42018-09-23 09:40:45 +02001/*
2 * Copyright (c) 2015-2018, Renesas Electronics Corporation. All rights reserved.
3 *
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
11#include <platform_def.h>
12
Jorge Ramirez-Ortizeaa63b42018-09-23 09:40:45 +020013#include <arch_helpers.h>
Antonio Nino Diaze0f90632018-12-14 00:18:21 +000014#include <common/bl_common.h>
15#include <common/debug.h>
16#include <drivers/auth/auth_mod.h>
17#include <drivers/io/io_driver.h>
18#include <drivers/io/io_storage.h>
19#include <lib/mmio.h>
20#include <plat/common/platform.h>
21#include <tools_share/firmware_image_package.h>
22#include <tools_share/uuid.h>
23
Jorge Ramirez-Ortizeaa63b42018-09-23 09:40:45 +020024#include "io_rcar.h"
25#include "io_common.h"
26#include "io_private.h"
Antonio Nino Diaze0f90632018-12-14 00:18:21 +000027
Jorge Ramirez-Ortizeaa63b42018-09-23 09:40:45 +020028extern int32_t plat_get_drv_source(uint32_t id, uintptr_t *dev,
29 uintptr_t *image_spec);
30
31extern int auth_mod_verify_img(unsigned int img_id, void *ptr,
32 unsigned int len);
33
34static int32_t rcar_dev_open(const uintptr_t dev_spec __attribute__ ((unused)),
35 io_dev_info_t **dev_info);
36static int32_t rcar_dev_close(io_dev_info_t *dev_info);
37
38typedef struct {
39 const int32_t name;
40 const uint32_t offset;
41 const uint32_t attr;
42} plat_rcar_name_offset_t;
43
44typedef struct {
45 /* Put position above the struct to allow {0} on static init.
46 * It is a workaround for a known bug in GCC
47 * http://gcc.gnu.org/bugzilla/show_bug.cgi?id=53119
48 */
49 uint32_t position;
50 uint32_t no_load;
51 uintptr_t offset;
52 uint32_t size;
53 uintptr_t dst;
54 uintptr_t partition; /* for eMMC */
55 /* RCAR_EMMC_PARTITION_BOOT_0 */
56 /* RCAR_EMMC_PARTITION_BOOT_1 */
57 /* RCAR_EMMC_PARTITION_USER */
58} file_state_t;
59
60#define RCAR_GET_FLASH_ADR(a, b) ((uint32_t)((0x40000U * (a)) + (b)))
61#define RCAR_ATTR_SET_CALCADDR(a) ((a) & 0xF)
62#define RCAR_ATTR_SET_ISNOLOAD(a) (((a) & 0x1) << 16U)
63#define RCAR_ATTR_SET_CERTOFF(a) (((a) & 0xF) << 8U)
64#define RCAR_ATTR_SET_ALL(a, b, c) ((uint32_t)(RCAR_ATTR_SET_CALCADDR(a) |\
65 RCAR_ATTR_SET_ISNOLOAD(b) | \
66 RCAR_ATTR_SET_CERTOFF(c)))
67
68#define RCAR_ATTR_GET_CALCADDR(a) ((a) & 0xFU)
69#define RCAR_ATTR_GET_ISNOLOAD(a) (((a) >> 16) & 0x1U)
70#define RCAR_ATTR_GET_CERTOFF(a) ((uint32_t)(((a) >> 8) & 0xFU))
71
72#define RCAR_MAX_BL3X_IMAGE (8U)
73#define RCAR_SECTOR6_CERT_OFFSET (0x400U)
74#define RCAR_SDRAM_certESS (0x43F00000U)
75#define RCAR_CERT_SIZE (0x800U)
76#define RCAR_CERT_INFO_SIZE_OFFSET (0x264U)
77#define RCAR_CERT_INFO_DST_OFFSET (0x154U)
78#define RCAR_CERT_INFO_SIZE_OFFSET1 (0x364U)
79#define RCAR_CERT_INFO_DST_OFFSET1 (0x1D4U)
80#define RCAR_CERT_INFO_SIZE_OFFSET2 (0x464U)
81#define RCAR_CERT_INFO_DST_OFFSET2 (0x254U)
82#define RCAR_CERT_LOAD (1U)
83
84#define RCAR_FLASH_CERT_HEADER RCAR_GET_FLASH_ADR(6U, 0U)
85#define RCAR_EMMC_CERT_HEADER (0x00030000U)
86
87#define RCAR_COUNT_LOAD_BL33 (2U)
88#define RCAR_COUNT_LOAD_BL33X (3U)
89
90static const plat_rcar_name_offset_t name_offset[] = {
91 {BL31_IMAGE_ID, 0U, RCAR_ATTR_SET_ALL(0, 0, 0)},
92
93 /* BL3-2 is optional in the platform */
94 {BL32_IMAGE_ID, 0U, RCAR_ATTR_SET_ALL(1, 0, 1)},
95 {BL33_IMAGE_ID, 0U, RCAR_ATTR_SET_ALL(2, 0, 2)},
96 {BL332_IMAGE_ID, 0U, RCAR_ATTR_SET_ALL(3, 0, 3)},
97 {BL333_IMAGE_ID, 0U, RCAR_ATTR_SET_ALL(4, 0, 4)},
98 {BL334_IMAGE_ID, 0U, RCAR_ATTR_SET_ALL(5, 0, 5)},
99 {BL335_IMAGE_ID, 0U, RCAR_ATTR_SET_ALL(6, 0, 6)},
100 {BL336_IMAGE_ID, 0U, RCAR_ATTR_SET_ALL(7, 0, 7)},
101 {BL337_IMAGE_ID, 0U, RCAR_ATTR_SET_ALL(8, 0, 8)},
102 {BL338_IMAGE_ID, 0U, RCAR_ATTR_SET_ALL(9, 0, 9)},
103};
104
105#if TRUSTED_BOARD_BOOT
106static const plat_rcar_name_offset_t cert_offset[] = {
107 /* Certificates */
108 {TRUSTED_KEY_CERT_ID, 0U, RCAR_ATTR_SET_ALL(0, 1, 0)},
109 {SOC_FW_KEY_CERT_ID, 0U, RCAR_ATTR_SET_ALL(0, 1, 0)},
110 {TRUSTED_OS_FW_KEY_CERT_ID, 0U, RCAR_ATTR_SET_ALL(0, 1, 0)},
111 {NON_TRUSTED_FW_KEY_CERT_ID, 0U, RCAR_ATTR_SET_ALL(0, 1, 0)},
112 {SOC_FW_CONTENT_CERT_ID, 0U, RCAR_ATTR_SET_ALL(0, 1, 0)},
113 {TRUSTED_OS_FW_CONTENT_CERT_ID, 0U, RCAR_ATTR_SET_ALL(0, 1, 1)},
114 {NON_TRUSTED_FW_CONTENT_CERT_ID, 0U, RCAR_ATTR_SET_ALL(0, 1, 2)},
115 {BL332_CERT_ID, 0U, RCAR_ATTR_SET_ALL(0, 1, 3)},
116 {BL333_CERT_ID, 0U, RCAR_ATTR_SET_ALL(0, 1, 4)},
117 {BL334_CERT_ID, 0U, RCAR_ATTR_SET_ALL(0, 1, 5)},
118 {BL335_CERT_ID, 0U, RCAR_ATTR_SET_ALL(0, 1, 6)},
119 {BL336_CERT_ID, 0U, RCAR_ATTR_SET_ALL(0, 1, 7)},
120 {BL337_CERT_ID, 0U, RCAR_ATTR_SET_ALL(0, 1, 8)},
121 {BL338_CERT_ID, 0U, RCAR_ATTR_SET_ALL(0, 1, 9)},
122};
123#endif /* TRUSTED_BOARD_BOOT */
124
125static file_state_t current_file = { 0 };
126
127static uintptr_t rcar_handle, rcar_spec;
128static uint64_t rcar_image_header[RCAR_MAX_BL3X_IMAGE + 2U] = { 0U };
129static uint64_t rcar_image_header_prttn[RCAR_MAX_BL3X_IMAGE + 2U] = { 0U };
130static uint64_t rcar_image_number = { 0U };
131static uint32_t rcar_cert_load = { 0U };
132
133static io_type_t device_type_rcar(void)
134{
135 return IO_TYPE_FIRMWARE_IMAGE_PACKAGE;
136}
137
138int32_t rcar_get_certificate(const int32_t name, uint32_t *cert)
139{
140#if TRUSTED_BOARD_BOOT
141 int32_t i;
142 for (i = 0; i < ARRAY_SIZE(cert_offset); i++) {
143 if (name != cert_offset[i].name)
144 continue;
145
146 *cert = RCAR_CERT_SIZE;
147 *cert *= RCAR_ATTR_GET_CERTOFF(cert_offset[i].attr);
148 *cert += RCAR_SDRAM_certESS;
149 return 0;
150 }
151#endif
152 return -EINVAL;
153}
154
155static int32_t file_to_offset(const int32_t name, uintptr_t *offset,
156 uint32_t *cert, uint32_t *no_load,
157 uintptr_t *partition)
158{
159 uint32_t addr;
160 int32_t i;
161
162 for (i = 0; i < ARRAY_SIZE(name_offset); i++) {
163 if (name != name_offset[i].name)
164 continue;
165
166 addr = RCAR_ATTR_GET_CALCADDR(name_offset[i].attr);
167 if (rcar_image_number + 2 < addr)
168 continue;
169
170 *offset = rcar_image_header[addr];
171 *cert = RCAR_CERT_SIZE;
172 *cert *= RCAR_ATTR_GET_CERTOFF(name_offset[i].attr);
173 *cert += RCAR_SDRAM_certESS;
174 *no_load = RCAR_ATTR_GET_ISNOLOAD(name_offset[i].attr);
175 *partition = rcar_image_header_prttn[addr];
176 return IO_SUCCESS;
177 }
178
179#if TRUSTED_BOARD_BOOT
180 for (i = 0; i < ARRAY_SIZE(cert_offset); i++) {
181 if (name != cert_offset[i].name)
182 continue;
183
184 *no_load = RCAR_ATTR_GET_ISNOLOAD(cert_offset[i].attr);
185 *partition = 0U;
186 *offset = 0U;
187 *cert = 0U;
188 return IO_SUCCESS;
189 }
190#endif
191 return -EINVAL;
192}
193
194#define RCAR_BOOT_KEY_CERT_NEW (0xE6300F00U)
195#define RCAR_CERT_MAGIC_NUM (0xE291F358U)
196
197void rcar_read_certificate(uint64_t cert, uint32_t *len, uintptr_t *dst)
198{
199 uint32_t seed, val, info_1, info_2;
200 uintptr_t size, dsth, dstl;
201
202 cert &= 0xFFFFFFFFU;
203
204 seed = mmio_read_32(RCAR_BOOT_KEY_CERT_NEW);
205 val = mmio_read_32(RCAR_BOOT_KEY_CERT_NEW + 0xC);
206 info_1 = (val >> 18) & 0x3U;
207 val = mmio_read_32(cert + 0xC);
208 info_2 = (val >> 21) & 0x3;
209
210 if (seed == RCAR_CERT_MAGIC_NUM) {
211 if (info_1 != 1) {
212 ERROR("BL2: Cert is invalid.\n");
213 *dst = 0;
214 *len = 0;
215 return;
216 }
217
218 if (info_2 > 2) {
219 ERROR("BL2: Cert is invalid.\n");
220 *dst = 0;
221 *len = 0;
222 return;
223 }
224
225 switch (info_2) {
226 case 2:
227 size = cert + RCAR_CERT_INFO_SIZE_OFFSET2;
228 dstl = cert + RCAR_CERT_INFO_DST_OFFSET2;
229 break;
230 case 1:
231 size = cert + RCAR_CERT_INFO_SIZE_OFFSET1;
232 dstl = cert + RCAR_CERT_INFO_DST_OFFSET1;
233 break;
234 case 0:
235 size = cert + RCAR_CERT_INFO_SIZE_OFFSET;
236 dstl = cert + RCAR_CERT_INFO_DST_OFFSET;
237 break;
238 }
239
240 *len = mmio_read_32(size) * 4U;
241 dsth = dstl + 4U;
242 *dst = ((uintptr_t) mmio_read_32(dsth) << 32) +
243 ((uintptr_t) mmio_read_32(dstl));
244 return;
245 }
246
247 size = cert + RCAR_CERT_INFO_SIZE_OFFSET;
248 *len = mmio_read_32(size) * 4U;
249 dstl = cert + RCAR_CERT_INFO_DST_OFFSET;
250 dsth = dstl + 4U;
251 *dst = ((uintptr_t) mmio_read_32(dsth) << 32) +
252 ((uintptr_t) mmio_read_32(dstl));
253}
254
255static int32_t check_load_area(uintptr_t dst, uintptr_t len)
256{
257 uint32_t legacy = dst + len <= UINT32_MAX - 1 ? 1 : 0;
258 uintptr_t dram_start, dram_end;
259 uintptr_t prot_start, prot_end;
260 int32_t result = IO_SUCCESS;
261
262 dram_start = legacy ? DRAM1_BASE : DRAM_40BIT_BASE;
263
264 dram_end = legacy ? DRAM1_BASE + DRAM1_SIZE :
265 DRAM_40BIT_BASE + DRAM_40BIT_SIZE;
266
267 prot_start = legacy ? DRAM_PROTECTED_BASE : DRAM_40BIT_PROTECTED_BASE;
268
269 prot_end = prot_start + DRAM_PROTECTED_SIZE;
270
271 if (dst < dram_start || dst > dram_end - len) {
272 ERROR("BL2: dst address is on the protected area.\n");
273 result = IO_FAIL;
274 goto done;
275 }
276
277 /* load image is within SDRAM protected area */
278 if (dst >= prot_start && dst < prot_end) {
279 ERROR("BL2: dst address is on the protected area.\n");
280 result = IO_FAIL;
281 }
282
283 if (dst < prot_start && dst > prot_start - len) {
284 ERROR("BL2: loaded data is on the protected area.\n");
285 result = IO_FAIL;
286 }
287done:
288 if (result == IO_FAIL)
289 ERROR("BL2: Out of range : dst=0x%lx len=0x%lx\n", dst, len);
290
291 return result;
292}
293
294static int32_t load_bl33x(void)
295{
296 static int32_t loaded = IO_NOT_SUPPORTED;
297 uintptr_t dst, partition, handle;
298 uint32_t noload, cert, len, i;
299 uintptr_t offset;
300 int32_t rc;
301 size_t cnt;
302 const int32_t img[] = {
303 BL33_IMAGE_ID,
304 BL332_IMAGE_ID,
305 BL333_IMAGE_ID,
306 BL334_IMAGE_ID,
307 BL335_IMAGE_ID,
308 BL336_IMAGE_ID,
309 BL337_IMAGE_ID,
310 BL338_IMAGE_ID
311 };
312
313 if (loaded != IO_NOT_SUPPORTED)
314 return loaded;
315
316 for (i = 1; i < rcar_image_number; i++) {
317 rc = file_to_offset(img[i], &offset, &cert, &noload,
318 &partition);
319 if (rc != IO_SUCCESS) {
320 WARN("load_bl33x: failed to get offset\n");
321 loaded = IO_FAIL;
322 return loaded;
323 }
324
325 rcar_read_certificate((uint64_t) cert, &len, &dst);
326 ((io_drv_spec_t *) rcar_spec)->partition = partition;
327
328 rc = io_open(rcar_handle, rcar_spec, &handle);
329 if (rc != IO_SUCCESS) {
330 WARN("Failed to open FIP (%i)\n", rc);
331 loaded = IO_FAIL;
332 return loaded;
333 }
334
335 rc = io_seek(handle, IO_SEEK_SET, offset);
336 if (rc != IO_SUCCESS) {
337 WARN("load_bl33x: failed to seek\n");
338 loaded = IO_FAIL;
339 return loaded;
340 }
341
342 rc = check_load_area(dst, len);
343 if (rc != IO_SUCCESS) {
344 WARN("load_bl33x: check load area\n");
345 loaded = IO_FAIL;
346 return loaded;
347 }
348
349 rc = io_read(handle, dst, len, &cnt);
350 if (rc != IO_SUCCESS) {
351 WARN("load_bl33x: failed to read\n");
352 loaded = IO_FAIL;
353 return loaded;
354 }
355#if TRUSTED_BOARD_BOOT
356 rc = auth_mod_verify_img(img[i], (void *)dst, len);
357 if (rc) {
358 memset((void *)dst, 0x00, len);
359 loaded = IO_FAIL;
360 return loaded;
361 }
362#endif
363 io_close(handle);
364 }
365
366 loaded = IO_SUCCESS;
367
368 return loaded;
369}
370
371static int32_t rcar_dev_init(io_dev_info_t *dev_info, const uintptr_t name)
372{
373 uint64_t header[64] __aligned(FLASH_TRANS_SIZE_UNIT) = {
374 0};
375 uintptr_t handle;
376 ssize_t offset;
377 uint32_t i;
378 int32_t rc;
379 size_t cnt;
380
381 /* Obtain a reference to the image by querying the platform layer */
382 rc = plat_get_drv_source(name, &rcar_handle, &rcar_spec);
383 if (rc != IO_SUCCESS) {
384 WARN("Failed to obtain reference to img %ld (%i)\n", name, rc);
385 return IO_FAIL;
386 }
387
388 if (RCAR_CERT_LOAD == rcar_cert_load)
389 return IO_SUCCESS;
390
391 rc = io_open(rcar_handle, rcar_spec, &handle);
392 if (rc != IO_SUCCESS) {
393 WARN("Failed to access img %ld (%i)\n", name, rc);
394 return IO_FAIL;
395 }
396
397 /* get start address list */
398 /* [0] address num */
399 /* [1] BL33-1 image address */
400 /* [2] BL33-2 image address */
401 /* [3] BL33-3 image address */
402 /* [4] BL33-4 image address */
403 /* [5] BL33-5 image address */
404 /* [6] BL33-6 image address */
405 /* [7] BL33-7 image address */
406 /* [8] BL33-8 image address */
407 offset = name == EMMC_DEV_ID ? RCAR_EMMC_CERT_HEADER :
408 RCAR_FLASH_CERT_HEADER;
409 rc = io_seek(handle, IO_SEEK_SET, offset);
410 if (rc != IO_SUCCESS) {
411 WARN("Firmware Image Package header failed to seek\n");
412 goto error;
413 }
414#if RCAR_BL2_DCACHE == 1
415 inv_dcache_range((uint64_t) header, sizeof(header));
416#endif
417 rc = io_read(handle, (uintptr_t) &header, sizeof(header), &cnt);
418 if (rc != IO_SUCCESS) {
419 WARN("Firmware Image Package header failed to read\n");
420 goto error;
421 }
422
423 rcar_image_number = header[0];
424 for (i = 0; i < rcar_image_number + 2; i++) {
425 rcar_image_header[i] = header[i * 2 + 1];
426 rcar_image_header_prttn[i] = header[i * 2 + 2];
427 }
428
429 if (rcar_image_number == 0 || rcar_image_number > RCAR_MAX_BL3X_IMAGE) {
430 WARN("Firmware Image Package header check failed.\n");
431 goto error;
432 }
433
434 rc = io_seek(handle, IO_SEEK_SET, offset + RCAR_SECTOR6_CERT_OFFSET);
435 if (rc != IO_SUCCESS) {
436 WARN("Firmware Image Package header failed to seek cert\n");
437 goto error;
438 }
439#if RCAR_BL2_DCACHE == 1
440 inv_dcache_range(RCAR_SDRAM_certESS,
441 RCAR_CERT_SIZE * (2 + rcar_image_number));
442#endif
443 rc = io_read(handle, RCAR_SDRAM_certESS,
444 RCAR_CERT_SIZE * (2 + rcar_image_number), &cnt);
445 if (rc != IO_SUCCESS) {
446 WARN("cert file read error.\n");
447 goto error;
448 }
449
450 rcar_cert_load = RCAR_CERT_LOAD;
451error:
452
453 if (rc != IO_SUCCESS)
454 rc = IO_FAIL;
455
456 io_close(handle);
457
458 return rc;
459
460}
461
462static int32_t rcar_file_open(io_dev_info_t *info, const uintptr_t file_spec,
463 io_entity_t *entity)
464{
465 const io_drv_spec_t *spec = (io_drv_spec_t *) file_spec;
466 uintptr_t partition, offset, dst;
467 uint32_t noload, cert, len;
468 int32_t rc;
469
470 /* Only one file open at a time. We need to track state (ie, file
471 * cursor position). Since the header lives at * offset zero, this entry
472 * should never be zero in an active file.
473 * Once the system supports dynamic memory allocation we will allow more
474 * than one open file at a time. */
475 if (current_file.offset != 0U) {
476 WARN("rcar_file_open : Only one open file at a time.\n");
477 return IO_RESOURCES_EXHAUSTED;
478 }
479
480 rc = file_to_offset(spec->offset, &offset, &cert, &noload, &partition);
481 if (rc != IO_SUCCESS) {
482 WARN("Failed to open file name %ld (%i)\n", spec->offset, rc);
483 return IO_FAIL;
484 }
485
486 if (noload) {
487 current_file.offset = 1;
488 current_file.dst = 0;
489 current_file.size = 1;
490 current_file.position = 0;
491 current_file.no_load = noload;
492 current_file.partition = 0;
493 entity->info = (uintptr_t) &current_file;
494
495 return IO_SUCCESS;
496 }
497
498 rcar_read_certificate((uint64_t) cert, &len, &dst);
499
500 /*----------------*
501 * Baylibre: HACK *
502 *----------------*/
503 if (BL31_IMAGE_ID == spec->offset && len < RCAR_TRUSTED_SRAM_SIZE) {
504 WARN("r-car ignoring the BL31 size from certificate,"
505 "using RCAR_TRUSTED_SRAM_SIZE instead\n");
506 len = RCAR_TRUSTED_SRAM_SIZE;
507 }
508
509 current_file.partition = partition;
510 current_file.no_load = noload;
511 current_file.offset = offset;
512 current_file.position = 0;
513 current_file.size = len;
514 current_file.dst = dst;
515 entity->info = (uintptr_t) &current_file;
516
517 return IO_SUCCESS;
518}
519
520static int32_t rcar_file_len(io_entity_t *entity, size_t *length)
521{
522 *length = ((file_state_t *) entity->info)->size;
523
524 NOTICE("%s: len: 0x%08lx\n", __func__, *length);
525
526 return IO_SUCCESS;
527}
528
529static int32_t rcar_file_read(io_entity_t *entity, uintptr_t buffer,
530 size_t length, size_t *cnt)
531{
532 file_state_t *fp = (file_state_t *) entity->info;
533 ssize_t offset = fp->offset + fp->position;
534 uintptr_t handle;
535 int32_t rc;
536
537#ifdef SPD_NONE
538 static uint32_t load_bl33x_counter = 1;
539#else
540 static uint32_t load_bl33x_counter;
541#endif
542 if (current_file.no_load) {
543 *cnt = length;
544 return IO_SUCCESS;
545 }
546
547 ((io_drv_spec_t *) rcar_spec)->partition = fp->partition;
548
549 rc = io_open(rcar_handle, rcar_spec, &handle);
550 if (rc != IO_SUCCESS) {
551 WARN("Failed to open FIP (%i)\n", rc);
552 return IO_FAIL;
553 }
554
555 rc = io_seek(handle, IO_SEEK_SET, offset);
556 if (rc != IO_SUCCESS) {
557 WARN("rcar_file_read: failed to seek\n");
558 goto error;
559 }
560
561 if (load_bl33x_counter == RCAR_COUNT_LOAD_BL33) {
562 rc = check_load_area(buffer, length);
563 if (rc != IO_SUCCESS) {
564 WARN("rcar_file_read: load area err\n");
565 goto error;
566 }
567 }
568
569 rc = io_read(handle, buffer, length, cnt);
570 if (rc != IO_SUCCESS) {
571 WARN("Failed to read payload (%i)\n", rc);
572 goto error;
573 }
574
575 fp->position += *cnt;
576 io_close(handle);
577
578 load_bl33x_counter += 1;
579 if (load_bl33x_counter == RCAR_COUNT_LOAD_BL33X)
580 return load_bl33x();
581
582 return IO_SUCCESS;
583error:
584 io_close(handle);
585 return IO_FAIL;
586}
587
588static int32_t rcar_file_close(io_entity_t *entity)
589{
590 if (current_file.offset)
591 memset(&current_file, 0, sizeof(current_file));
592
593 entity->info = 0U;
594
595 return IO_SUCCESS;
596}
597
598static const io_dev_funcs_t rcar_dev_funcs = {
599 .type = &device_type_rcar,
600 .open = &rcar_file_open,
601 .seek = NULL,
602 .size = &rcar_file_len,
603 .read = &rcar_file_read,
604 .write = NULL,
605 .close = &rcar_file_close,
606 .dev_init = &rcar_dev_init,
607 .dev_close = &rcar_dev_close,
608};
609
610static const io_dev_info_t rcar_dev_info = {
611 .funcs = &rcar_dev_funcs,
612 .info = (uintptr_t) 0
613};
614
615static const io_dev_connector_t rcar_dev_connector = {
616 .dev_open = &rcar_dev_open
617};
618
619static int32_t rcar_dev_open(const uintptr_t dev_spec __attribute__ ((unused)),
620 io_dev_info_t **dev_info)
621{
622 *dev_info = (io_dev_info_t *) &rcar_dev_info;
623
624 return IO_SUCCESS;
625}
626
627static int32_t rcar_dev_close(io_dev_info_t *dev_info)
628{
629 rcar_handle = 0;
630 rcar_spec = 0;
631
632 return IO_SUCCESS;
633}
634
635int32_t rcar_register_io_dev(const io_dev_connector_t **dev_con)
636{
637 int32_t result;
638
639 result = io_register_device(&rcar_dev_info);
640 if (result == IO_SUCCESS)
641 *dev_con = &rcar_dev_connector;
642
643 return result;
644}