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