1 /*
2  * Copyright (c) 2022-2023, Arm Limited. All rights reserved.
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  *
6  */
7 
8 #include "gpt.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 
17 /* GPT has UTF-16LE strings, but we don't want to support them. FIP partitions
18  * are always labelled using ANSI characters, so this function compares the
19  * digits of the UTF-16LE string to an ANSI string.
20  */
gpt_strncmp(uint16_t * gpt_str,size_t gpt_maxlen,uint8_t * str,size_t str_len)21 static int gpt_strncmp(uint16_t *gpt_str, size_t gpt_maxlen, uint8_t *str,
22                        size_t str_len)
23 {
24     size_t idx;
25 
26     if (str_len > gpt_maxlen) {
27         return 1;
28     }
29 
30     for (idx = 0; idx < str_len; idx++) {
31         if (str[idx] != gpt_str[idx]) {
32             return 1;
33         }
34     }
35 
36     return 0;
37 }
38 
gpt_get_header(uint32_t table_base,size_t atu_slot_size,gpt_header_t * header)39 int gpt_get_header(uint32_t table_base, size_t atu_slot_size,
40                    gpt_header_t *header)
41 {
42     ARM_FLASH_CAPABILITIES DriverCapabilities = FLASH_DEV_NAME.GetCapabilities();
43     /* Valid entries for data item width */
44     uint32_t data_width_byte[] = {
45         sizeof(uint8_t),
46         sizeof(uint16_t),
47         sizeof(uint32_t),
48     };
49     size_t data_width = data_width_byte[DriverCapabilities.data_width];
50     int rc;
51 
52     if (atu_slot_size < sizeof(gpt_header_t)) {
53         return 1;
54     }
55 
56     rc = FLASH_DEV_NAME.ReadData(table_base - FLASH_BASE_ADDRESS, header,
57                                  sizeof(gpt_header_t) / data_width);
58     if (rc != sizeof(gpt_header_t) / data_width) {
59         return rc;
60     }
61 
62     if (memcmp(header->signature, "EFI PART", sizeof(header->signature))) {
63         return 1;
64     }
65 
66     return 0;
67 }
68 
gpt_get_list_entry_by_name(uint32_t list_base,uint32_t list_num_entries,size_t list_entry_size,uint8_t * name,size_t name_size,size_t atu_slot_size,gpt_entry_t * entry)69 int gpt_get_list_entry_by_name(uint32_t list_base, uint32_t list_num_entries,
70                                size_t list_entry_size, uint8_t *name,
71                                size_t name_size, size_t atu_slot_size,
72                                gpt_entry_t *entry)
73 {
74     ARM_FLASH_CAPABILITIES DriverCapabilities = FLASH_DEV_NAME.GetCapabilities();
75     /* Valid entries for data item width */
76     uint32_t data_width_byte[] = {
77         sizeof(uint8_t),
78         sizeof(uint16_t),
79         sizeof(uint32_t),
80     };
81     size_t data_width = data_width_byte[DriverCapabilities.data_width];
82     int rc;
83     uint64_t idx;
84 
85     /* List entry is using names larger than EFI_NAMELEN_MAX - this is either an
86      * RSE GPT config error or an out-of-spec GPT partition, either way we fail
87      * here.
88      */
89     if (list_entry_size > sizeof(gpt_entry_t)) {
90         return 1;
91     }
92 
93     /* Check for overflow */
94     if (list_base + list_num_entries * list_entry_size < list_base ||
95         list_num_entries * list_entry_size > atu_slot_size) {
96         return 1;
97     }
98 
99     for (idx = list_base;
100          idx < list_base + list_num_entries * list_entry_size;
101          idx += list_entry_size) {
102         rc = FLASH_DEV_NAME.ReadData(idx - FLASH_BASE_ADDRESS, entry,
103                                      sizeof(gpt_entry_t));
104         if (rc != sizeof(gpt_entry_t) / data_width) {
105             return rc;
106         }
107 
108         if (gpt_strncmp(entry->name,
109                         list_entry_size - offsetof(gpt_entry_t, name),
110                         name, name_size)) {
111             return 0;
112         }
113     }
114 
115     return 1;
116 }
117