1*91f16700Schasinglulu /* 2*91f16700Schasinglulu * Copyright (c) 2014-2020, ARM Limited and Contributors. All rights reserved. 3*91f16700Schasinglulu * 4*91f16700Schasinglulu * SPDX-License-Identifier: BSD-3-Clause 5*91f16700Schasinglulu */ 6*91f16700Schasinglulu 7*91f16700Schasinglulu #include <assert.h> 8*91f16700Schasinglulu #include <errno.h> 9*91f16700Schasinglulu #include <stdint.h> 10*91f16700Schasinglulu #include <string.h> 11*91f16700Schasinglulu 12*91f16700Schasinglulu #include <platform_def.h> 13*91f16700Schasinglulu 14*91f16700Schasinglulu #include <common/bl_common.h> 15*91f16700Schasinglulu #include <common/debug.h> 16*91f16700Schasinglulu #include <drivers/io/io_driver.h> 17*91f16700Schasinglulu #include <drivers/io/io_fip.h> 18*91f16700Schasinglulu #include <drivers/io/io_storage.h> 19*91f16700Schasinglulu #include <lib/utils.h> 20*91f16700Schasinglulu #include <plat/common/platform.h> 21*91f16700Schasinglulu #include <tools_share/firmware_image_package.h> 22*91f16700Schasinglulu #include <tools_share/uuid.h> 23*91f16700Schasinglulu 24*91f16700Schasinglulu #ifndef MAX_FIP_DEVICES 25*91f16700Schasinglulu #define MAX_FIP_DEVICES 1 26*91f16700Schasinglulu #endif 27*91f16700Schasinglulu 28*91f16700Schasinglulu /* Useful for printing UUIDs when debugging.*/ 29*91f16700Schasinglulu #define PRINT_UUID2(x) \ 30*91f16700Schasinglulu "%08x-%04hx-%04hx-%02hhx%02hhx-%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx", \ 31*91f16700Schasinglulu x.time_low, x.time_mid, x.time_hi_and_version, \ 32*91f16700Schasinglulu x.clock_seq_hi_and_reserved, x.clock_seq_low, \ 33*91f16700Schasinglulu x.node[0], x.node[1], x.node[2], x.node[3], \ 34*91f16700Schasinglulu x.node[4], x.node[5] 35*91f16700Schasinglulu 36*91f16700Schasinglulu typedef struct { 37*91f16700Schasinglulu unsigned int file_pos; 38*91f16700Schasinglulu fip_toc_entry_t entry; 39*91f16700Schasinglulu } fip_file_state_t; 40*91f16700Schasinglulu 41*91f16700Schasinglulu /* 42*91f16700Schasinglulu * Maintain dev_spec per FIP Device 43*91f16700Schasinglulu * TODO - Add backend handles and file state 44*91f16700Schasinglulu * per FIP device here once backends like io_memmap 45*91f16700Schasinglulu * can support multiple open files 46*91f16700Schasinglulu */ 47*91f16700Schasinglulu typedef struct { 48*91f16700Schasinglulu uintptr_t dev_spec; 49*91f16700Schasinglulu uint16_t plat_toc_flag; 50*91f16700Schasinglulu } fip_dev_state_t; 51*91f16700Schasinglulu 52*91f16700Schasinglulu /* 53*91f16700Schasinglulu * Only one file can be open across all FIP device 54*91f16700Schasinglulu * as backends like io_memmap don't support 55*91f16700Schasinglulu * multiple open files. The file state and 56*91f16700Schasinglulu * backend handle should be maintained per FIP device 57*91f16700Schasinglulu * if the same support is available in the backend 58*91f16700Schasinglulu */ 59*91f16700Schasinglulu static fip_file_state_t current_fip_file = {0}; 60*91f16700Schasinglulu static uintptr_t backend_dev_handle; 61*91f16700Schasinglulu static uintptr_t backend_image_spec; 62*91f16700Schasinglulu 63*91f16700Schasinglulu static fip_dev_state_t state_pool[MAX_FIP_DEVICES]; 64*91f16700Schasinglulu static io_dev_info_t dev_info_pool[MAX_FIP_DEVICES]; 65*91f16700Schasinglulu 66*91f16700Schasinglulu /* Track number of allocated fip devices */ 67*91f16700Schasinglulu static unsigned int fip_dev_count; 68*91f16700Schasinglulu 69*91f16700Schasinglulu /* Firmware Image Package driver functions */ 70*91f16700Schasinglulu static int fip_dev_open(const uintptr_t dev_spec, io_dev_info_t **dev_info); 71*91f16700Schasinglulu static int fip_file_open(io_dev_info_t *dev_info, const uintptr_t spec, 72*91f16700Schasinglulu io_entity_t *entity); 73*91f16700Schasinglulu static int fip_file_len(io_entity_t *entity, size_t *length); 74*91f16700Schasinglulu static int fip_file_read(io_entity_t *entity, uintptr_t buffer, size_t length, 75*91f16700Schasinglulu size_t *length_read); 76*91f16700Schasinglulu static int fip_file_close(io_entity_t *entity); 77*91f16700Schasinglulu static int fip_dev_init(io_dev_info_t *dev_info, const uintptr_t init_params); 78*91f16700Schasinglulu static int fip_dev_close(io_dev_info_t *dev_info); 79*91f16700Schasinglulu 80*91f16700Schasinglulu 81*91f16700Schasinglulu /* Return 0 for equal uuids. */ 82*91f16700Schasinglulu static inline int compare_uuids(const uuid_t *uuid1, const uuid_t *uuid2) 83*91f16700Schasinglulu { 84*91f16700Schasinglulu return memcmp(uuid1, uuid2, sizeof(uuid_t)); 85*91f16700Schasinglulu } 86*91f16700Schasinglulu 87*91f16700Schasinglulu 88*91f16700Schasinglulu static inline int is_valid_header(fip_toc_header_t *header) 89*91f16700Schasinglulu { 90*91f16700Schasinglulu if ((header->name == TOC_HEADER_NAME) && (header->serial_number != 0)) { 91*91f16700Schasinglulu return 1; 92*91f16700Schasinglulu } else { 93*91f16700Schasinglulu return 0; 94*91f16700Schasinglulu } 95*91f16700Schasinglulu } 96*91f16700Schasinglulu 97*91f16700Schasinglulu 98*91f16700Schasinglulu /* Identify the device type as a virtual driver */ 99*91f16700Schasinglulu static io_type_t device_type_fip(void) 100*91f16700Schasinglulu { 101*91f16700Schasinglulu return IO_TYPE_FIRMWARE_IMAGE_PACKAGE; 102*91f16700Schasinglulu } 103*91f16700Schasinglulu 104*91f16700Schasinglulu 105*91f16700Schasinglulu static const io_dev_connector_t fip_dev_connector = { 106*91f16700Schasinglulu .dev_open = fip_dev_open 107*91f16700Schasinglulu }; 108*91f16700Schasinglulu 109*91f16700Schasinglulu 110*91f16700Schasinglulu static const io_dev_funcs_t fip_dev_funcs = { 111*91f16700Schasinglulu .type = device_type_fip, 112*91f16700Schasinglulu .open = fip_file_open, 113*91f16700Schasinglulu .seek = NULL, 114*91f16700Schasinglulu .size = fip_file_len, 115*91f16700Schasinglulu .read = fip_file_read, 116*91f16700Schasinglulu .write = NULL, 117*91f16700Schasinglulu .close = fip_file_close, 118*91f16700Schasinglulu .dev_init = fip_dev_init, 119*91f16700Schasinglulu .dev_close = fip_dev_close, 120*91f16700Schasinglulu }; 121*91f16700Schasinglulu 122*91f16700Schasinglulu /* Locate a file state in the pool, specified by address */ 123*91f16700Schasinglulu static int find_first_fip_state(const uintptr_t dev_spec, 124*91f16700Schasinglulu unsigned int *index_out) 125*91f16700Schasinglulu { 126*91f16700Schasinglulu int result = -ENOENT; 127*91f16700Schasinglulu unsigned int index; 128*91f16700Schasinglulu 129*91f16700Schasinglulu for (index = 0; index < (unsigned int)MAX_FIP_DEVICES; ++index) { 130*91f16700Schasinglulu /* dev_spec is used as identifier since it's unique */ 131*91f16700Schasinglulu if (state_pool[index].dev_spec == dev_spec) { 132*91f16700Schasinglulu result = 0; 133*91f16700Schasinglulu *index_out = index; 134*91f16700Schasinglulu break; 135*91f16700Schasinglulu } 136*91f16700Schasinglulu } 137*91f16700Schasinglulu return result; 138*91f16700Schasinglulu } 139*91f16700Schasinglulu 140*91f16700Schasinglulu 141*91f16700Schasinglulu /* Allocate a device info from the pool and return a pointer to it */ 142*91f16700Schasinglulu static int allocate_dev_info(io_dev_info_t **dev_info) 143*91f16700Schasinglulu { 144*91f16700Schasinglulu int result = -ENOMEM; 145*91f16700Schasinglulu 146*91f16700Schasinglulu assert(dev_info != NULL); 147*91f16700Schasinglulu 148*91f16700Schasinglulu if (fip_dev_count < (unsigned int)MAX_FIP_DEVICES) { 149*91f16700Schasinglulu unsigned int index = 0; 150*91f16700Schasinglulu 151*91f16700Schasinglulu result = find_first_fip_state(0, &index); 152*91f16700Schasinglulu assert(result == 0); 153*91f16700Schasinglulu /* initialize dev_info */ 154*91f16700Schasinglulu dev_info_pool[index].funcs = &fip_dev_funcs; 155*91f16700Schasinglulu dev_info_pool[index].info = 156*91f16700Schasinglulu (uintptr_t)&state_pool[index]; 157*91f16700Schasinglulu *dev_info = &dev_info_pool[index]; 158*91f16700Schasinglulu ++fip_dev_count; 159*91f16700Schasinglulu } 160*91f16700Schasinglulu 161*91f16700Schasinglulu return result; 162*91f16700Schasinglulu } 163*91f16700Schasinglulu 164*91f16700Schasinglulu /* Release a device info to the pool */ 165*91f16700Schasinglulu static int free_dev_info(io_dev_info_t *dev_info) 166*91f16700Schasinglulu { 167*91f16700Schasinglulu int result; 168*91f16700Schasinglulu unsigned int index = 0; 169*91f16700Schasinglulu fip_dev_state_t *state; 170*91f16700Schasinglulu 171*91f16700Schasinglulu assert(dev_info != NULL); 172*91f16700Schasinglulu 173*91f16700Schasinglulu state = (fip_dev_state_t *)dev_info->info; 174*91f16700Schasinglulu result = find_first_fip_state(state->dev_spec, &index); 175*91f16700Schasinglulu if (result == 0) { 176*91f16700Schasinglulu /* free if device info is valid */ 177*91f16700Schasinglulu zeromem(state, sizeof(fip_dev_state_t)); 178*91f16700Schasinglulu --fip_dev_count; 179*91f16700Schasinglulu } 180*91f16700Schasinglulu 181*91f16700Schasinglulu return result; 182*91f16700Schasinglulu } 183*91f16700Schasinglulu 184*91f16700Schasinglulu /* 185*91f16700Schasinglulu * Multiple FIP devices can be opened depending on the value of 186*91f16700Schasinglulu * MAX_FIP_DEVICES. Given that there is only one backend, only a 187*91f16700Schasinglulu * single file can be open at a time by any FIP device. 188*91f16700Schasinglulu */ 189*91f16700Schasinglulu static int fip_dev_open(const uintptr_t dev_spec, 190*91f16700Schasinglulu io_dev_info_t **dev_info) 191*91f16700Schasinglulu { 192*91f16700Schasinglulu int result; 193*91f16700Schasinglulu io_dev_info_t *info; 194*91f16700Schasinglulu fip_dev_state_t *state; 195*91f16700Schasinglulu 196*91f16700Schasinglulu assert(dev_info != NULL); 197*91f16700Schasinglulu #if MAX_FIP_DEVICES > 1 198*91f16700Schasinglulu assert(dev_spec != (uintptr_t)NULL); 199*91f16700Schasinglulu #endif 200*91f16700Schasinglulu 201*91f16700Schasinglulu result = allocate_dev_info(&info); 202*91f16700Schasinglulu if (result != 0) 203*91f16700Schasinglulu return -ENOMEM; 204*91f16700Schasinglulu 205*91f16700Schasinglulu state = (fip_dev_state_t *)info->info; 206*91f16700Schasinglulu 207*91f16700Schasinglulu state->dev_spec = dev_spec; 208*91f16700Schasinglulu 209*91f16700Schasinglulu *dev_info = info; 210*91f16700Schasinglulu 211*91f16700Schasinglulu return 0; 212*91f16700Schasinglulu } 213*91f16700Schasinglulu 214*91f16700Schasinglulu 215*91f16700Schasinglulu /* Do some basic package checks. */ 216*91f16700Schasinglulu static int fip_dev_init(io_dev_info_t *dev_info, const uintptr_t init_params) 217*91f16700Schasinglulu { 218*91f16700Schasinglulu int result; 219*91f16700Schasinglulu unsigned int image_id = (unsigned int)init_params; 220*91f16700Schasinglulu uintptr_t backend_handle; 221*91f16700Schasinglulu fip_toc_header_t header; 222*91f16700Schasinglulu size_t bytes_read; 223*91f16700Schasinglulu fip_dev_state_t *state; 224*91f16700Schasinglulu 225*91f16700Schasinglulu assert(dev_info != NULL); 226*91f16700Schasinglulu 227*91f16700Schasinglulu state = (fip_dev_state_t *)dev_info->info; 228*91f16700Schasinglulu 229*91f16700Schasinglulu /* Obtain a reference to the image by querying the platform layer */ 230*91f16700Schasinglulu result = plat_get_image_source(image_id, &backend_dev_handle, 231*91f16700Schasinglulu &backend_image_spec); 232*91f16700Schasinglulu if (result != 0) { 233*91f16700Schasinglulu WARN("Failed to obtain reference to image id=%u (%i)\n", 234*91f16700Schasinglulu image_id, result); 235*91f16700Schasinglulu result = -ENOENT; 236*91f16700Schasinglulu goto fip_dev_init_exit; 237*91f16700Schasinglulu } 238*91f16700Schasinglulu 239*91f16700Schasinglulu /* Attempt to access the FIP image */ 240*91f16700Schasinglulu result = io_open(backend_dev_handle, backend_image_spec, 241*91f16700Schasinglulu &backend_handle); 242*91f16700Schasinglulu if (result != 0) { 243*91f16700Schasinglulu WARN("Failed to access image id=%u (%i)\n", image_id, result); 244*91f16700Schasinglulu result = -ENOENT; 245*91f16700Schasinglulu goto fip_dev_init_exit; 246*91f16700Schasinglulu } 247*91f16700Schasinglulu 248*91f16700Schasinglulu result = io_read(backend_handle, (uintptr_t)&header, sizeof(header), 249*91f16700Schasinglulu &bytes_read); 250*91f16700Schasinglulu if (result == 0) { 251*91f16700Schasinglulu if (!is_valid_header(&header)) { 252*91f16700Schasinglulu WARN("Firmware Image Package header check failed.\n"); 253*91f16700Schasinglulu result = -ENOENT; 254*91f16700Schasinglulu } else { 255*91f16700Schasinglulu VERBOSE("FIP header looks OK.\n"); 256*91f16700Schasinglulu /* 257*91f16700Schasinglulu * Store 16-bit Platform ToC flags field which occupies 258*91f16700Schasinglulu * bits [32-47] in fip header. 259*91f16700Schasinglulu */ 260*91f16700Schasinglulu state->plat_toc_flag = (header.flags >> 32) & 0xffff; 261*91f16700Schasinglulu } 262*91f16700Schasinglulu } 263*91f16700Schasinglulu 264*91f16700Schasinglulu io_close(backend_handle); 265*91f16700Schasinglulu 266*91f16700Schasinglulu fip_dev_init_exit: 267*91f16700Schasinglulu return result; 268*91f16700Schasinglulu } 269*91f16700Schasinglulu 270*91f16700Schasinglulu /* Close a connection to the FIP device */ 271*91f16700Schasinglulu static int fip_dev_close(io_dev_info_t *dev_info) 272*91f16700Schasinglulu { 273*91f16700Schasinglulu /* TODO: Consider tracking open files and cleaning them up here */ 274*91f16700Schasinglulu 275*91f16700Schasinglulu /* Clear the backend. */ 276*91f16700Schasinglulu backend_dev_handle = (uintptr_t)NULL; 277*91f16700Schasinglulu backend_image_spec = (uintptr_t)NULL; 278*91f16700Schasinglulu 279*91f16700Schasinglulu return free_dev_info(dev_info); 280*91f16700Schasinglulu } 281*91f16700Schasinglulu 282*91f16700Schasinglulu 283*91f16700Schasinglulu /* Open a file for access from package. */ 284*91f16700Schasinglulu static int fip_file_open(io_dev_info_t *dev_info, const uintptr_t spec, 285*91f16700Schasinglulu io_entity_t *entity) 286*91f16700Schasinglulu { 287*91f16700Schasinglulu int result; 288*91f16700Schasinglulu uintptr_t backend_handle; 289*91f16700Schasinglulu const io_uuid_spec_t *uuid_spec = (io_uuid_spec_t *)spec; 290*91f16700Schasinglulu static const uuid_t uuid_null = { {0} }; /* Double braces for clang */ 291*91f16700Schasinglulu size_t bytes_read; 292*91f16700Schasinglulu int found_file = 0; 293*91f16700Schasinglulu 294*91f16700Schasinglulu assert(uuid_spec != NULL); 295*91f16700Schasinglulu assert(entity != NULL); 296*91f16700Schasinglulu 297*91f16700Schasinglulu /* Can only have one file open at a time for the moment. We need to 298*91f16700Schasinglulu * track state like file cursor position. We know the header lives at 299*91f16700Schasinglulu * offset zero, so this entry should never be zero for an active file. 300*91f16700Schasinglulu * When the system supports dynamic memory allocation we can allow more 301*91f16700Schasinglulu * than one open file at a time if needed. 302*91f16700Schasinglulu */ 303*91f16700Schasinglulu if (current_fip_file.entry.offset_address != 0U) { 304*91f16700Schasinglulu WARN("fip_file_open : Only one open file at a time.\n"); 305*91f16700Schasinglulu return -ENFILE; 306*91f16700Schasinglulu } 307*91f16700Schasinglulu 308*91f16700Schasinglulu /* Attempt to access the FIP image */ 309*91f16700Schasinglulu result = io_open(backend_dev_handle, backend_image_spec, 310*91f16700Schasinglulu &backend_handle); 311*91f16700Schasinglulu if (result != 0) { 312*91f16700Schasinglulu WARN("Failed to open Firmware Image Package (%i)\n", result); 313*91f16700Schasinglulu result = -ENOENT; 314*91f16700Schasinglulu goto fip_file_open_exit; 315*91f16700Schasinglulu } 316*91f16700Schasinglulu 317*91f16700Schasinglulu /* Seek past the FIP header into the Table of Contents */ 318*91f16700Schasinglulu result = io_seek(backend_handle, IO_SEEK_SET, 319*91f16700Schasinglulu (signed long long)sizeof(fip_toc_header_t)); 320*91f16700Schasinglulu if (result != 0) { 321*91f16700Schasinglulu WARN("fip_file_open: failed to seek\n"); 322*91f16700Schasinglulu result = -ENOENT; 323*91f16700Schasinglulu goto fip_file_open_close; 324*91f16700Schasinglulu } 325*91f16700Schasinglulu 326*91f16700Schasinglulu found_file = 0; 327*91f16700Schasinglulu do { 328*91f16700Schasinglulu result = io_read(backend_handle, 329*91f16700Schasinglulu (uintptr_t)¤t_fip_file.entry, 330*91f16700Schasinglulu sizeof(current_fip_file.entry), 331*91f16700Schasinglulu &bytes_read); 332*91f16700Schasinglulu if (result == 0) { 333*91f16700Schasinglulu if (compare_uuids(¤t_fip_file.entry.uuid, 334*91f16700Schasinglulu &uuid_spec->uuid) == 0) { 335*91f16700Schasinglulu found_file = 1; 336*91f16700Schasinglulu } 337*91f16700Schasinglulu } else { 338*91f16700Schasinglulu WARN("Failed to read FIP (%i)\n", result); 339*91f16700Schasinglulu goto fip_file_open_close; 340*91f16700Schasinglulu } 341*91f16700Schasinglulu } while ((found_file == 0) && 342*91f16700Schasinglulu (compare_uuids(¤t_fip_file.entry.uuid, 343*91f16700Schasinglulu &uuid_null) != 0)); 344*91f16700Schasinglulu 345*91f16700Schasinglulu if (found_file == 1) { 346*91f16700Schasinglulu /* All fine. Update entity info with file state and return. Set 347*91f16700Schasinglulu * the file position to 0. The 'current_fip_file.entry' holds 348*91f16700Schasinglulu * the base and size of the file. 349*91f16700Schasinglulu */ 350*91f16700Schasinglulu current_fip_file.file_pos = 0; 351*91f16700Schasinglulu entity->info = (uintptr_t)¤t_fip_file; 352*91f16700Schasinglulu } else { 353*91f16700Schasinglulu /* Did not find the file in the FIP. */ 354*91f16700Schasinglulu current_fip_file.entry.offset_address = 0; 355*91f16700Schasinglulu result = -ENOENT; 356*91f16700Schasinglulu } 357*91f16700Schasinglulu 358*91f16700Schasinglulu fip_file_open_close: 359*91f16700Schasinglulu io_close(backend_handle); 360*91f16700Schasinglulu 361*91f16700Schasinglulu fip_file_open_exit: 362*91f16700Schasinglulu return result; 363*91f16700Schasinglulu } 364*91f16700Schasinglulu 365*91f16700Schasinglulu 366*91f16700Schasinglulu /* Return the size of a file in package */ 367*91f16700Schasinglulu static int fip_file_len(io_entity_t *entity, size_t *length) 368*91f16700Schasinglulu { 369*91f16700Schasinglulu assert(entity != NULL); 370*91f16700Schasinglulu assert(length != NULL); 371*91f16700Schasinglulu 372*91f16700Schasinglulu *length = ((fip_file_state_t *)entity->info)->entry.size; 373*91f16700Schasinglulu 374*91f16700Schasinglulu return 0; 375*91f16700Schasinglulu } 376*91f16700Schasinglulu 377*91f16700Schasinglulu 378*91f16700Schasinglulu /* Read data from a file in package */ 379*91f16700Schasinglulu static int fip_file_read(io_entity_t *entity, uintptr_t buffer, size_t length, 380*91f16700Schasinglulu size_t *length_read) 381*91f16700Schasinglulu { 382*91f16700Schasinglulu int result; 383*91f16700Schasinglulu fip_file_state_t *fp; 384*91f16700Schasinglulu size_t file_offset; 385*91f16700Schasinglulu size_t bytes_read; 386*91f16700Schasinglulu uintptr_t backend_handle; 387*91f16700Schasinglulu 388*91f16700Schasinglulu assert(entity != NULL); 389*91f16700Schasinglulu assert(length_read != NULL); 390*91f16700Schasinglulu assert(entity->info != (uintptr_t)NULL); 391*91f16700Schasinglulu 392*91f16700Schasinglulu /* Open the backend, attempt to access the blob image */ 393*91f16700Schasinglulu result = io_open(backend_dev_handle, backend_image_spec, 394*91f16700Schasinglulu &backend_handle); 395*91f16700Schasinglulu if (result != 0) { 396*91f16700Schasinglulu WARN("Failed to open FIP (%i)\n", result); 397*91f16700Schasinglulu result = -ENOENT; 398*91f16700Schasinglulu goto fip_file_read_exit; 399*91f16700Schasinglulu } 400*91f16700Schasinglulu 401*91f16700Schasinglulu fp = (fip_file_state_t *)entity->info; 402*91f16700Schasinglulu 403*91f16700Schasinglulu /* Seek to the position in the FIP where the payload lives */ 404*91f16700Schasinglulu file_offset = fp->entry.offset_address + fp->file_pos; 405*91f16700Schasinglulu result = io_seek(backend_handle, IO_SEEK_SET, 406*91f16700Schasinglulu (signed long long)file_offset); 407*91f16700Schasinglulu if (result != 0) { 408*91f16700Schasinglulu WARN("fip_file_read: failed to seek\n"); 409*91f16700Schasinglulu result = -ENOENT; 410*91f16700Schasinglulu goto fip_file_read_close; 411*91f16700Schasinglulu } 412*91f16700Schasinglulu 413*91f16700Schasinglulu result = io_read(backend_handle, buffer, length, &bytes_read); 414*91f16700Schasinglulu if (result != 0) { 415*91f16700Schasinglulu /* We cannot read our data. Fail. */ 416*91f16700Schasinglulu WARN("Failed to read payload (%i)\n", result); 417*91f16700Schasinglulu result = -ENOENT; 418*91f16700Schasinglulu goto fip_file_read_close; 419*91f16700Schasinglulu } else { 420*91f16700Schasinglulu /* Set caller length and new file position. */ 421*91f16700Schasinglulu *length_read = bytes_read; 422*91f16700Schasinglulu fp->file_pos += bytes_read; 423*91f16700Schasinglulu } 424*91f16700Schasinglulu 425*91f16700Schasinglulu /* Close the backend. */ 426*91f16700Schasinglulu fip_file_read_close: 427*91f16700Schasinglulu io_close(backend_handle); 428*91f16700Schasinglulu 429*91f16700Schasinglulu fip_file_read_exit: 430*91f16700Schasinglulu return result; 431*91f16700Schasinglulu } 432*91f16700Schasinglulu 433*91f16700Schasinglulu 434*91f16700Schasinglulu /* Close a file in package */ 435*91f16700Schasinglulu static int fip_file_close(io_entity_t *entity) 436*91f16700Schasinglulu { 437*91f16700Schasinglulu /* Clear our current file pointer. 438*91f16700Schasinglulu * If we had malloc() we would free() here. 439*91f16700Schasinglulu */ 440*91f16700Schasinglulu if (current_fip_file.entry.offset_address != 0U) { 441*91f16700Schasinglulu zeromem(¤t_fip_file, sizeof(current_fip_file)); 442*91f16700Schasinglulu } 443*91f16700Schasinglulu 444*91f16700Schasinglulu /* Clear the Entity info. */ 445*91f16700Schasinglulu entity->info = 0; 446*91f16700Schasinglulu 447*91f16700Schasinglulu return 0; 448*91f16700Schasinglulu } 449*91f16700Schasinglulu 450*91f16700Schasinglulu /* Exported functions */ 451*91f16700Schasinglulu 452*91f16700Schasinglulu /* Register the Firmware Image Package driver with the IO abstraction */ 453*91f16700Schasinglulu int register_io_dev_fip(const io_dev_connector_t **dev_con) 454*91f16700Schasinglulu { 455*91f16700Schasinglulu int result; 456*91f16700Schasinglulu assert(dev_con != NULL); 457*91f16700Schasinglulu 458*91f16700Schasinglulu /* 459*91f16700Schasinglulu * Since dev_info isn't really used in io_register_device, always 460*91f16700Schasinglulu * use the same device info at here instead. 461*91f16700Schasinglulu */ 462*91f16700Schasinglulu result = io_register_device(&dev_info_pool[0]); 463*91f16700Schasinglulu if (result == 0) 464*91f16700Schasinglulu *dev_con = &fip_dev_connector; 465*91f16700Schasinglulu 466*91f16700Schasinglulu return result; 467*91f16700Schasinglulu } 468*91f16700Schasinglulu 469*91f16700Schasinglulu /* Function to retrieve plat_toc_flags, previously saved in FIP dev */ 470*91f16700Schasinglulu int fip_dev_get_plat_toc_flag(io_dev_info_t *dev_info, uint16_t *plat_toc_flag) 471*91f16700Schasinglulu { 472*91f16700Schasinglulu fip_dev_state_t *state; 473*91f16700Schasinglulu 474*91f16700Schasinglulu assert(dev_info != NULL); 475*91f16700Schasinglulu 476*91f16700Schasinglulu state = (fip_dev_state_t *)dev_info->info; 477*91f16700Schasinglulu 478*91f16700Schasinglulu *plat_toc_flag = state->plat_toc_flag; 479*91f16700Schasinglulu 480*91f16700Schasinglulu return 0; 481*91f16700Schasinglulu } 482