1 /*
2 * Copyright (c) 2022-2023, Arm Limited. All rights reserved.
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 *
6 */
7
8 #include <string.h>
9 #include <assert.h>
10
11 #include "fip_parser.h"
12 #include "tfm_plat_defs.h"
13 #include "flash_layout.h"
14 #include "Driver_Flash.h"
15
fip_get_entry_by_uuid(const ARM_DRIVER_FLASH * flash_dev,uint32_t fip_offset,uint32_t atu_slot_size,uuid_t uuid,uint64_t * offset,size_t * size)16 enum tfm_plat_err_t fip_get_entry_by_uuid(const ARM_DRIVER_FLASH *flash_dev,
17 uint32_t fip_offset, uint32_t atu_slot_size,
18 uuid_t uuid, uint64_t *offset, size_t *size)
19 {
20 ARM_FLASH_CAPABILITIES DriverCapabilities = flash_dev->GetCapabilities();
21 assert(DriverCapabilities.data_width <= 2);
22 /* Valid entries for data item width */
23 const uint32_t data_width_byte[] = {
24 sizeof(uint8_t),
25 sizeof(uint16_t),
26 sizeof(uint32_t),
27 };
28 const size_t data_width =
29 data_width_byte[DriverCapabilities.data_width <= 2 ? DriverCapabilities.data_width : 0];
30 int rc;
31 uint32_t idx = 0;
32 fip_toc_header_t toc_header;
33 fip_toc_entry_t toc_entry;
34 uuid_t null_uuid;
35
36 /* The NULL UUID is all-zeroes */
37 memset(&null_uuid, 0, sizeof(null_uuid));
38
39 rc = flash_dev->ReadData(fip_offset, &toc_header,
40 sizeof(toc_header) / data_width);
41 if (rc != sizeof(toc_header) / data_width) {
42 return TFM_PLAT_ERR_FIP_TOC_HEADER_INVALID_READ;
43 }
44
45 if (toc_header.name != TOC_HEADER_NAME) {
46 return TFM_PLAT_ERR_FIP_TOC_HEADER_INVALID_NAME;
47 }
48
49 idx += sizeof(toc_header);
50
51 do {
52 /* Prevent reading out of bounds */
53 if (idx + sizeof(toc_entry) > atu_slot_size) {
54 return TFM_PLAT_ERR_FIP_TOC_ENTRY_OVERFLOW;
55 }
56
57 rc = flash_dev->ReadData(fip_offset + idx, &toc_entry,
58 sizeof(toc_entry) / data_width);
59 if (rc != sizeof(toc_entry) / data_width) {
60 return TFM_PLAT_ERR_FIP_TOC_ENTRY_INVALID_READ;
61 }
62
63 if (!memcmp(&uuid, &toc_entry.uuid, sizeof(uuid))) {
64 *offset = toc_entry.offset_address;
65
66 /* We can't deal with partitions that are greater than UINT32_MAX,
67 * since they aren't wholly mappable into the RSE memory space. This
68 * is in reality bounded by the ATU mappable size, but that'll be
69 * checked once the ATU region is set up, this just allows us to
70 * perform safe type-conversion.
71 */
72 if (toc_entry.size > UINT32_MAX) {
73 return TFM_PLAT_ERR_FIP_TOC_ENTRY_INVALID_SIZE;
74 }
75
76 *size = (uint32_t)toc_entry.size;
77
78 return TFM_PLAT_ERR_SUCCESS;
79 }
80
81 idx += sizeof(toc_entry);
82 /* The FIP's TOC ends in an entry with a NULL UUID. This entry's size is
83 * the size of the whole FIP. */
84 } while (memcmp(&null_uuid, &toc_entry.uuid, sizeof(uuid_t)));
85
86 /* UUID not found, return error. */
87 return TFM_PLAT_ERR_GPT_TOC_ENTRY_NOT_FOUND;
88 }
89