blob: 477a58c6ffca2d3e3ddaa1795c2d5837aad183fc [file] [log] [blame]
Furquan Shaikhd7fb6a92021-09-16 22:04:11 -07001/* BPDT version 1.6 support */
2/* SPDX-License-Identifier: GPL-2.0-only */
3
4#include <sys/types.h>
5
6#include "cse_serger.h"
7
8struct bpdt_header {
9 uint32_t signature; /* BPDT_SIGNATURE */
10 uint16_t descriptor_count;
11 uint16_t version; /* Layout 1.6 = 1 */
12 uint16_t reserved;
13 uint8_t whole_checksum;
14 uint8_t rom_checksum;
15 uint32_t ifwi_version;
16 struct {
17 uint16_t major;
18 uint16_t minor;
19 uint16_t build;
20 uint16_t hotfix;
21 } fit_tool_version;
22} __packed;
23
24struct cse_layout {
25 uint8_t rom_bypass[16];
26 uint32_t data_offset;
27 uint32_t data_size;
28 uint32_t bp1_offset;
29 uint32_t bp1_size;
30 uint32_t bp2_offset;
31 uint32_t bp2_size;
32 uint32_t bp3_offset;
33 uint32_t bp3_size;
34 uint32_t reserved[16];
35 uint8_t checksum;
36} __packed;
37
38static bool match_version(const struct buffer *buff)
39{
40 const uint8_t *data = buffer_get(buff);
41 const uint32_t sig = read_le32(data);
42 const uint16_t version = read_at_le16(data, offsetof(struct bpdt_header, version));
43
44 if (sig != BPDT_SIGNATURE) {
45 ERROR("Invalid BPDT signature(0x%x)!\n", sig);
46 return false;
47 }
48
49 return version == BPDT_VERSION_1_6;
50}
51
52static bpdt_hdr_ptr create_bpdt_hdr(void)
53{
54 struct bpdt_header *h = malloc(sizeof(*h));
55
56 if (!h)
57 return NULL;
58
59 h->signature = BPDT_SIGNATURE;
60 h->descriptor_count = 0;
61 h->version = BPDT_VERSION_1_6;
62 h->reserved = 0;
63 /* TODO(b/202549343): Need to calculate checksum */
64 h->whole_checksum = 0;
65 h->rom_checksum = 0;
66 h->ifwi_version = 0;
67 h->fit_tool_version.major = 0;
68 h->fit_tool_version.minor = 0;
69 h->fit_tool_version.build = 0;
70 h->fit_tool_version.hotfix = 0;
71
Solomon Alan-Deia2503fa2022-10-29 08:30:23 -060072 return h;
Furquan Shaikhd7fb6a92021-09-16 22:04:11 -070073}
74
75static void print_bpdt_hdr(const bpdt_hdr_ptr ptr)
76{
77 struct bpdt_header *h = ptr;
78
79 printf(" * BPDT header\n");
80 printf("%-25s 0x%-23.8x\n", "Signature", h->signature);
81 printf("%-25s %-25d\n", "Descriptor count", h->descriptor_count);
82 printf("%-25s %d (Layout 1.6)\n", "BPDT Version", h->version);
83 printf("%-25s 0x%-23x\n", "Reserved", h->reserved);
84 printf("%-25s 0x%-23x\n", "Whole Checksum", h->whole_checksum);
85 printf("%-25s 0x%-23x\n", "ROM Checksum", h->rom_checksum);
86 printf("%-25s 0x%-23x\n", "IFWI Version", h->ifwi_version);
87 printf("%-25s %d.%d.%d.%d(%.2x.%.2x.%.2x.%.2x)\n", "FIT Tool Version",
88 h->fit_tool_version.major, h->fit_tool_version.minor,
89 h->fit_tool_version.build, h->fit_tool_version.hotfix,
90 h->fit_tool_version.major, h->fit_tool_version.minor,
91 h->fit_tool_version.build, h->fit_tool_version.hotfix);
92}
93
94static bpdt_hdr_ptr read_bpdt_hdr(struct buffer *buff)
95{
96 struct bpdt_header *h = malloc(sizeof(*h));
97
98 if (!h)
99 return NULL;
100
101 READ_MEMBER(buff, h->signature);
102 READ_MEMBER(buff, h->descriptor_count);
103 READ_MEMBER(buff, h->version);
104 READ_MEMBER(buff, h->reserved);
105 READ_MEMBER(buff, h->whole_checksum);
106 READ_MEMBER(buff, h->rom_checksum);
107 READ_MEMBER(buff, h->ifwi_version);
108 READ_MEMBER(buff, h->fit_tool_version);
109
110 return h;
111}
112
113static int write_bpdt_hdr(struct buffer *buff, const bpdt_hdr_ptr ptr)
114{
115 struct bpdt_header *h = ptr;
116
117 if (buffer_size(buff) < sizeof(struct bpdt_header)) {
118 ERROR("Not enough size in buffer for BPDT header!\n");
119 return -1;
120 }
121
122 WRITE_MEMBER(buff, h->signature);
123 WRITE_MEMBER(buff, h->descriptor_count);
124 WRITE_MEMBER(buff, h->version);
125 WRITE_MEMBER(buff, h->reserved);
126 WRITE_MEMBER(buff, h->whole_checksum);
127 WRITE_MEMBER(buff, h->rom_checksum);
128 WRITE_MEMBER(buff, h->ifwi_version);
129 WRITE_MEMBER(buff, h->fit_tool_version);
130
131 return 0;
132}
133
134static size_t get_bpdt_entry_count(const bpdt_hdr_ptr ptr)
135{
136 return ((const struct bpdt_header *)ptr)->descriptor_count;
137}
138
139static void inc_bpdt_entry_count(bpdt_hdr_ptr ptr)
140{
141 struct bpdt_header *h = ptr;
142 h->descriptor_count++;
143}
144
Furquan Shaikh8b4ca152021-10-09 23:06:09 -0700145static cse_layout_ptr create_cse_layout(const struct region *r)
Furquan Shaikhd7fb6a92021-09-16 22:04:11 -0700146{
147 struct cse_layout *l = malloc(sizeof(*l));
148
149 if (!l)
150 return NULL;
151
Nico Huberd7612e92024-01-11 18:50:50 +0100152 l->data_offset = region_offset(&r[DP]);
153 l->data_size = region_sz(&r[DP]);
154 l->bp1_offset = region_offset(&r[BP1]);
155 l->bp1_size = region_sz(&r[BP1]);
156 l->bp2_offset = region_offset(&r[BP2]);
157 l->bp2_size = region_sz(&r[BP2]);
158 l->bp3_offset = region_offset(&r[BP3]);
159 l->bp3_size = region_sz(&r[BP3]);
Furquan Shaikhd7fb6a92021-09-16 22:04:11 -0700160 l->checksum = 0; /* unused */
161
Solomon Alan-Deia2503fa2022-10-29 08:30:23 -0600162 return l;
Furquan Shaikhd7fb6a92021-09-16 22:04:11 -0700163}
164
165static void print_cse_layout(const cse_layout_ptr ptr)
166{
167 struct cse_layout *l = ptr;
168
169 printf(" * CSE Layout\n\n");
170 printf("ROM Bypass: ");
171 for (size_t i = 0; i < sizeof(l->rom_bypass); i++)
172 printf("0x%x ", l->rom_bypass[i]);
173 printf("\n");
174 printf("Data partition offset: 0x%x\n", l->data_offset);
175 printf("Data partition size: 0x%x\n", l->data_size);
176 printf("BP1 offset: 0x%x\n", l->bp1_offset);
177 printf("BP1 size: 0x%x\n", l->bp1_size);
178 printf("BP2 offset: 0x%x\n", l->bp2_offset);
179 printf("BP2 size: 0x%x\n", l->bp2_size);
180 printf("BP3 offset: 0x%x\n", l->bp3_offset);
181 printf("BP3 size: 0x%x\n", l->bp3_size);
182 printf("Checksum: 0x%x\n", l->checksum);
183}
184
185static cse_layout_ptr read_cse_layout(struct buffer *buff)
186{
187 struct cse_layout *l = malloc(sizeof(*l));
188
189 if (!l)
190 return NULL;
191
192 READ_MEMBER(buff, l->rom_bypass);
193 READ_MEMBER(buff, l->data_offset);
194 READ_MEMBER(buff, l->data_size);
195 READ_MEMBER(buff, l->bp1_offset);
196 READ_MEMBER(buff, l->bp1_size);
197 READ_MEMBER(buff, l->bp2_offset);
198 READ_MEMBER(buff, l->bp2_size);
199 READ_MEMBER(buff, l->bp3_offset);
200 READ_MEMBER(buff, l->bp3_size);
201 READ_MEMBER(buff, l->reserved);
202 READ_MEMBER(buff, l->checksum);
203
204 return l;
205}
206
207static int write_cse_layout(struct buffer *buff, const cse_layout_ptr ptr)
208{
209 struct cse_layout *l = ptr;
210
211 if (buffer_size(buff) < sizeof(struct cse_layout)) {
212 ERROR("Not enough size in buffer for CSE layout!\n");
213 return -1;
214 }
215
216 WRITE_MEMBER(buff, l->rom_bypass);
217 WRITE_MEMBER(buff, l->data_offset);
218 WRITE_MEMBER(buff, l->data_size);
219 WRITE_MEMBER(buff, l->bp1_offset);
220 WRITE_MEMBER(buff, l->bp1_size);
221 WRITE_MEMBER(buff, l->bp2_offset);
222 WRITE_MEMBER(buff, l->bp2_size);
223 WRITE_MEMBER(buff, l->bp3_offset);
224 WRITE_MEMBER(buff, l->bp3_size);
225 WRITE_MEMBER(buff, l->reserved);
226 WRITE_MEMBER(buff, l->checksum);
227
228 return 0;
229}
230
231static void update_checksum(bpdt_hdr_ptr ptr, struct bpdt_entry *e)
232{
233 (void)ptr;
234 (void)e;
235
236 /* TODO(b/202549343) */
237 ERROR("Update checksum is not supported for 1.6!\n");
238}
239
240static bool validate_checksum(bpdt_hdr_ptr ptr, struct bpdt_entry *e)
241{
242 (void)e;
243 (void)ptr;
244
245 /* TODO(b/202549343) */
246 ERROR("Validate checksum is not supported for 1.6!\n");
247
248 return true;
249}
250
251const struct bpdt_ops bpdt_1_6_ops = {
252 .match_version = match_version,
253
254 .create_hdr = create_bpdt_hdr,
255 .print_hdr = print_bpdt_hdr,
256 .read_hdr = read_bpdt_hdr,
257 .write_hdr = write_bpdt_hdr,
258
259 .get_entry_count = get_bpdt_entry_count,
260 .inc_entry_count = inc_bpdt_entry_count,
261
262 .create_layout = create_cse_layout,
263 .print_layout = print_cse_layout,
264 .read_layout = read_cse_layout,
265 .write_layout = write_cse_layout,
266
267 .update_checksum = update_checksum,
268 .validate_checksum = validate_checksum,
269
270 .subpart_hdr_version = SUBPART_HDR_VERSION_1,
271 .subpart_entry_version = SUBPART_ENTRY_VERSION_1,
272};