1 // SPDX-License-Identifier: Apache-2.0
2 /* Copyright 2013-2019 IBM Corp. */
3 
4 #include <limits.h>
5 #include <stdlib.h>
6 #include <stdio.h>
7 #include <string.h>
8 
9 #ifndef __SKIBOOT__
10 #include <sys/types.h>
11 #include <unistd.h>
12 #endif
13 
14 #include "ffs.h"
15 
16 #define __unused __attribute__((unused))
17 #define HDR_ENTRIES_NUM 30
18 
19 struct ffs_handle {
20 	struct ffs_hdr		hdr;	/* Converted header */
21 	uint32_t		toc_offset;
22 	uint32_t		max_size;
23 	/* The converted header knows how big this is */
24 	struct __ffs_hdr *cache;
25 	struct blocklevel_device *bl;
26 };
27 
ffs_checksum(void * data,size_t size)28 static uint32_t ffs_checksum(void* data, size_t size)
29 {
30 	uint32_t i, csum = 0;
31 
32 	for (i = csum = 0; i < (size/4); i++)
33 		csum ^= ((uint32_t *)data)[i];
34 	return csum;
35 }
36 
37 /* Helper functions for typesafety and size safety */
ffs_hdr_checksum(struct __ffs_hdr * hdr)38 static uint32_t ffs_hdr_checksum(struct __ffs_hdr *hdr)
39 {
40 	return ffs_checksum(hdr, sizeof(struct __ffs_hdr));
41 }
42 
ffs_entry_checksum(struct __ffs_entry * ent)43 static uint32_t ffs_entry_checksum(struct __ffs_entry *ent)
44 {
45 	return ffs_checksum(ent, sizeof(struct __ffs_entry));
46 }
47 
ffs_hdr_raw_size(int num_entries)48 static size_t ffs_hdr_raw_size(int num_entries)
49 {
50 	return sizeof(struct __ffs_hdr) + num_entries * sizeof(struct __ffs_entry);
51 }
52 
ffs_num_entries(struct ffs_hdr * hdr)53 static int ffs_num_entries(struct ffs_hdr *hdr)
54 {
55 	if (hdr->count == 0)
56 		FL_DBG("%s returned zero!\n", __func__);
57 	return hdr->count;
58 }
59 
ffs_check_convert_header(struct ffs_hdr * dst,struct __ffs_hdr * src)60 static int ffs_check_convert_header(struct ffs_hdr *dst, struct __ffs_hdr *src)
61 {
62 	if (be32_to_cpu(src->magic) != FFS_MAGIC)
63 		return FFS_ERR_BAD_MAGIC;
64 	dst->version = be32_to_cpu(src->version);
65 	if (dst->version != FFS_VERSION_1)
66 		return FFS_ERR_BAD_VERSION;
67 	if (ffs_hdr_checksum(src) != 0)
68 		return FFS_ERR_BAD_CKSUM;
69 	if (be32_to_cpu(src->entry_size) != sizeof(struct __ffs_entry))
70 		return FFS_ERR_BAD_SIZE;
71 	if ((be32_to_cpu(src->entry_size) * be32_to_cpu(src->entry_count)) >
72 			(be32_to_cpu(src->block_size) * be32_to_cpu(src->size)))
73 		return FLASH_ERR_PARM_ERROR;
74 
75 	dst->block_size = be32_to_cpu(src->block_size);
76 	dst->size = be32_to_cpu(src->size) * dst->block_size;
77 	dst->block_count = be32_to_cpu(src->block_count);
78 	dst->entries_size = be32_to_cpu(src->entry_count);
79 
80 	return 0;
81 }
82 
ffs_entry_user_to_flash(struct ffs_hdr * hdr __unused,struct __ffs_entry_user * dst,struct ffs_entry_user * src)83 static int ffs_entry_user_to_flash(struct ffs_hdr *hdr __unused,
84 		struct __ffs_entry_user *dst, struct ffs_entry_user *src)
85 {
86 	memset(dst, 0, sizeof(struct __ffs_entry_user));
87 	dst->datainteg = cpu_to_be16(src->datainteg);
88 	dst->vercheck = src->vercheck;
89 	dst->miscflags = src->miscflags;
90 
91 	return 0;
92 }
93 
ffs_entry_user_to_cpu(struct ffs_hdr * hdr __unused,struct ffs_entry_user * dst,struct __ffs_entry_user * src)94 static int ffs_entry_user_to_cpu(struct ffs_hdr *hdr __unused,
95 		struct ffs_entry_user *dst, struct __ffs_entry_user *src)
96 {
97 	memset(dst, 0, sizeof(struct ffs_entry_user));
98 	dst->datainteg = be16_to_cpu(src->datainteg);
99 	dst->vercheck = src->vercheck;
100 	dst->miscflags = src->miscflags;
101 
102 	return 0;
103 }
104 
ffs_entry_to_flash(struct ffs_hdr * hdr,struct __ffs_entry * dst,struct ffs_entry * src)105 static int ffs_entry_to_flash(struct ffs_hdr *hdr,
106 		struct __ffs_entry *dst, struct ffs_entry *src)
107 {
108 	int rc, index;
109 
110 	if (!hdr || !dst || !src)
111 		return -1;
112 
113 	for (index = 0; index < hdr->count && hdr->entries[index] != src; index++);
114 
115 	if (index == hdr->count)
116 		return FFS_ERR_PART_NOT_FOUND;
117 	index++; /* On flash indexes start at 1 */
118 	/*
119 	 * So that the checksum gets calculated correctly at least the
120 	 * dst->checksum must be zero before calling ffs_entry_checksum()
121 	 * memset()ting the entire struct to zero is probably wise as it
122 	 * appears the reserved fields are always zero.
123 	 */
124 	memset(dst, 0, sizeof(*dst));
125 
126 	memcpy(dst->name, src->name, sizeof(dst->name));
127 	dst->name[FFS_PART_NAME_MAX] = '\0';
128 	dst->base = cpu_to_be32(src->base / hdr->block_size);
129 	dst->size = cpu_to_be32(src->size / hdr->block_size);
130 	dst->pid = cpu_to_be32(src->pid);
131 	dst->id = cpu_to_be32(index);
132 	dst->type = cpu_to_be32(src->type); /* TODO: Check that it is valid? */
133 	dst->flags = cpu_to_be32(src->flags);
134 	dst->actual = cpu_to_be32(src->actual);
135 	rc = ffs_entry_user_to_flash(hdr, &dst->user, &src->user);
136 	dst->checksum = ffs_entry_checksum(dst);
137 
138 	return rc;
139 }
140 
ffs_entry_to_cpu(struct ffs_hdr * hdr,struct ffs_entry * dst,struct __ffs_entry * src)141 static int ffs_entry_to_cpu(struct ffs_hdr *hdr,
142 		struct ffs_entry *dst, struct __ffs_entry *src)
143 {
144 	int rc;
145 
146 	if (ffs_entry_checksum(src) != 0)
147 		return FFS_ERR_BAD_CKSUM;
148 
149 	memcpy(dst->name, src->name, sizeof(dst->name));
150 	dst->name[FFS_PART_NAME_MAX] = '\0';
151 	dst->base = be32_to_cpu(src->base) * hdr->block_size;
152 	dst->size = be32_to_cpu(src->size) * hdr->block_size;
153 	dst->actual = be32_to_cpu(src->actual);
154 	dst->pid = be32_to_cpu(src->pid);
155 	dst->type = be32_to_cpu(src->type); /* TODO: Check that it is valid? */
156 	dst->flags = be32_to_cpu(src->flags);
157 	rc = ffs_entry_user_to_cpu(hdr, &dst->user, &src->user);
158 
159 	return rc;
160 }
161 
ffs_entry_user_to_string(struct ffs_entry_user * user)162 char *ffs_entry_user_to_string(struct ffs_entry_user *user)
163 {
164 	char *ret;
165 
166 	if (!user)
167 		return NULL;
168 
169 	ret = strdup("----------");
170 	if (!ret)
171 		return NULL;
172 
173 	if (user->datainteg & FFS_ENRY_INTEG_ECC)
174 		ret[0] = 'E';
175 
176 	if (user->vercheck & FFS_VERCHECK_SHA512V)
177 		ret[1] = 'L';
178 
179 	if (user->vercheck & FFS_VERCHECK_SHA512EC)
180 		ret[2] = 'I';
181 
182 	if (user->miscflags & FFS_MISCFLAGS_PRESERVED)
183 		ret[3] = 'P';
184 
185 	if (user->miscflags & FFS_MISCFLAGS_READONLY)
186 		ret[4] = 'R';
187 
188 	if (user->miscflags & FFS_MISCFLAGS_BACKUP)
189 		ret[5] = 'B';
190 
191 	if (user->miscflags & FFS_MISCFLAGS_REPROVISION)
192 		ret[6] = 'F';
193 
194 	if (user->miscflags & FFS_MISCFLAGS_GOLDEN)
195 		ret[7] = 'G';
196 
197 	if (user->miscflags & FFS_MISCFLAGS_CLEARECC)
198 		ret[8] = 'C';
199 
200 	if (user->miscflags & FFS_MISCFLAGS_VOLATILE)
201 		ret[9] = 'V';
202 
203 	return ret;
204 }
205 
ffs_string_to_entry_user(const char * flags,int nflags,struct ffs_entry_user * user)206 int ffs_string_to_entry_user(const char *flags, int nflags,
207 		struct ffs_entry_user *user)
208 {
209 	int i;
210 
211 	if (!user || !flags)
212 		return FLASH_ERR_PARM_ERROR;
213 
214 	memset(user, 0, sizeof(struct ffs_entry_user));
215 	for (i = 0; i < nflags; i++) {
216 		switch (flags[i]) {
217 		case 'E':
218 			user->datainteg |= FFS_ENRY_INTEG_ECC;
219 			break;
220 		case 'L':
221 			user->vercheck |= FFS_VERCHECK_SHA512V;
222 			break;
223 		case 'I':
224 			user->vercheck |= FFS_VERCHECK_SHA512EC;
225 			break;
226 		case 'P':
227 			user->miscflags |= FFS_MISCFLAGS_PRESERVED;
228 			break;
229 		case 'R':
230 			user->miscflags |= FFS_MISCFLAGS_READONLY;
231 			break;
232 		case 'B':
233 			user->miscflags |= FFS_MISCFLAGS_BACKUP;
234 			break;
235 		case 'F':
236 			user->miscflags |= FFS_MISCFLAGS_REPROVISION;
237 			break;
238 		case 'G':
239 			user->miscflags |= FFS_MISCFLAGS_GOLDEN;
240 			break;
241 		case 'C':
242 			user->miscflags |= FFS_MISCFLAGS_CLEARECC;
243 			break;
244 		case 'V':
245 			user->miscflags |= FFS_MISCFLAGS_VOLATILE;
246 			break;
247 		default:
248 			FL_DBG("Unknown flag '%c'\n", flags[i]);
249 			return FLASH_ERR_PARM_ERROR;
250 		}
251 	}
252 
253 	return 0;
254 }
255 
has_flag(struct ffs_entry * ent,uint16_t flag)256 bool has_flag(struct ffs_entry *ent, uint16_t flag)
257 {
258 	return ((ent->user.miscflags & flag) != 0);
259 }
260 
__ffs_entry_get(struct ffs_handle * ffs,uint32_t index)261 static struct ffs_entry *__ffs_entry_get(struct ffs_handle *ffs, uint32_t index)
262 {
263 	if (index >= ffs->hdr.count)
264 		return NULL;
265 	return ffs->hdr.entries[index];
266 }
267 
ffs_entry_get(struct ffs_handle * ffs,uint32_t index)268 struct ffs_entry *ffs_entry_get(struct ffs_handle *ffs, uint32_t index)
269 {
270 	struct ffs_entry *ret = __ffs_entry_get(ffs, index);
271 	if (ret)
272 		ret->ref++;
273 	return ret;
274 }
275 
ffs_entry_put(struct ffs_entry * ent)276 struct ffs_entry *ffs_entry_put(struct ffs_entry *ent)
277 {
278 	if (!ent)
279 		return NULL;
280 
281 	ent->ref--;
282 	if (ent->ref == 0) {
283 		free(ent);
284 		ent = NULL;
285 	}
286 
287 	return ent;
288 }
289 
has_ecc(struct ffs_entry * ent)290 bool has_ecc(struct ffs_entry *ent)
291 {
292 	return ((ent->user.datainteg & FFS_ENRY_INTEG_ECC) != 0);
293 }
294 
ffs_init(uint32_t offset,uint32_t max_size,struct blocklevel_device * bl,struct ffs_handle ** ffs,bool mark_ecc)295 int ffs_init(uint32_t offset, uint32_t max_size, struct blocklevel_device *bl,
296 		struct ffs_handle **ffs, bool mark_ecc)
297 {
298 	struct __ffs_hdr blank_hdr;
299 	struct __ffs_hdr raw_hdr;
300 	struct ffs_handle *f;
301 	uint64_t total_size;
302 	int rc, i;
303 
304 	if (!ffs || !bl)
305 		return FLASH_ERR_PARM_ERROR;
306 	*ffs = NULL;
307 
308 	rc = blocklevel_get_info(bl, NULL, &total_size, NULL);
309 	if (rc) {
310 		FL_ERR("FFS: Error %d retrieving flash info\n", rc);
311 		return rc;
312 	}
313 	if (total_size > UINT_MAX)
314 		return FLASH_ERR_VERIFY_FAILURE;
315 	if ((offset + max_size) < offset)
316 		return FLASH_ERR_PARM_ERROR;
317 
318 	if ((max_size > total_size))
319 		return FLASH_ERR_PARM_ERROR;
320 
321 	/* Read flash header */
322 	rc = blocklevel_read(bl, offset, &raw_hdr, sizeof(raw_hdr));
323 	if (rc) {
324 		FL_ERR("FFS: Error %d reading flash header\n", rc);
325 		return rc;
326 	}
327 
328 	/*
329 	 * Flash controllers can get deconfigured or otherwise upset, when this
330 	 * happens they return all 0xFF bytes.
331 	 * An __ffs_hdr consisting of all 0xFF cannot be valid and it would be
332 	 * nice to drop a hint to the user to help with debugging. This will
333 	 * help quickly differentiate between flash corruption and standard
334 	 * type 'reading from the wrong place' errors vs controller errors or
335 	 * reading erased data.
336 	 */
337 	memset(&blank_hdr, UINT_MAX, sizeof(struct __ffs_hdr));
338 	if (memcmp(&blank_hdr, &raw_hdr, sizeof(struct __ffs_hdr)) == 0) {
339 		FL_ERR("FFS: Reading the flash has returned all 0xFF.\n");
340 		FL_ERR("     Are you reading erased flash?\n");
341 		FL_ERR("     Is something else using the flash controller?\n");
342 		return FLASH_ERR_BAD_READ;
343 	}
344 
345 	/* Allocate ffs_handle structure and start populating */
346 	f = calloc(1, sizeof(*f));
347 	if (!f)
348 		return FLASH_ERR_MALLOC_FAILED;
349 
350 	f->toc_offset = offset;
351 	f->max_size = max_size;
352 	f->bl = bl;
353 
354 	/* Convert and check flash header */
355 	rc = ffs_check_convert_header(&f->hdr, &raw_hdr);
356 	if (rc) {
357 		FL_INF("FFS: Flash header not found. Code: %d\n", rc);
358 		goto out;
359 	}
360 
361 	/* Check header is sane */
362 	if ((f->hdr.block_count * f->hdr.block_size) > max_size) {
363 		rc = FLASH_ERR_PARM_ERROR;
364 		FL_ERR("FFS: Flash header exceeds max flash size\n");
365 		goto out;
366 	}
367 
368 	f->hdr.entries = calloc(f->hdr.entries_size, sizeof(struct ffs_entry *));
369 
370 	/*
371 	 * Grab the entire partition header
372 	 */
373 	/* Check for overflow or a silly size */
374 	if (!f->hdr.size || f->hdr.size % f->hdr.block_size != 0) {
375 		rc = FLASH_ERR_MALLOC_FAILED;
376 		FL_ERR("FFS: Cache size overflow (0x%x * 0x%x)\n",
377 				f->hdr.block_size, f->hdr.size);
378 		goto out;
379 	}
380 
381 	FL_DBG("FFS: Partition map size: 0x%x\n", f->hdr.size);
382 
383 	/* Allocate cache */
384 	f->cache = malloc(f->hdr.size);
385 	if (!f->cache) {
386 		rc = FLASH_ERR_MALLOC_FAILED;
387 		goto out;
388 	}
389 
390 	/* Read the cached map */
391 	rc = blocklevel_read(bl, offset, f->cache, f->hdr.size);
392 	if (rc) {
393 		FL_ERR("FFS: Error %d reading flash partition map\n", rc);
394 		goto out;
395 	}
396 
397 	for (i = 0; i < f->hdr.entries_size; i++) {
398 		struct ffs_entry *ent = calloc(1, sizeof(struct ffs_entry));
399 		if (!ent) {
400 			rc = FLASH_ERR_MALLOC_FAILED;
401 			goto out;
402 		}
403 
404 		f->hdr.entries[f->hdr.count++] = ent;
405 		ent->ref = 1;
406 		rc = ffs_entry_to_cpu(&f->hdr, ent, &f->cache->entries[i]);
407 		if (rc) {
408 			FL_DBG("FFS: Failed checksum for partition %s\n",
409 					f->cache->entries[i].name);
410 			goto out;
411 		}
412 
413 		if (mark_ecc && has_ecc(ent)) {
414 			rc = blocklevel_ecc_protect(bl, ent->base, ent->size);
415 			if (rc) {
416 				FL_ERR("Failed to blocklevel_ecc_protect(0x%08x, 0x%08x)\n",
417 				       ent->base, ent->size);
418 				goto out;
419 			}
420 		}
421 	}
422 
423 out:
424 	if (rc == 0)
425 		*ffs = f;
426 	else
427 		ffs_close(f);
428 
429 	return rc;
430 }
431 
__hdr_free(struct ffs_hdr * hdr)432 static void __hdr_free(struct ffs_hdr *hdr)
433 {
434 	int i;
435 
436 	if (!hdr)
437 		return;
438 
439 	for (i = 0; i < hdr->count; i++)
440 		ffs_entry_put(hdr->entries[i]);
441 	free(hdr->entries);
442 }
443 
ffs_hdr_free(struct ffs_hdr * hdr)444 void ffs_hdr_free(struct ffs_hdr *hdr)
445 {
446 	__hdr_free(hdr);
447 	free(hdr);
448 }
449 
ffs_close(struct ffs_handle * ffs)450 void ffs_close(struct ffs_handle *ffs)
451 {
452 	__hdr_free(&ffs->hdr);
453 
454 	if (ffs->cache)
455 		free(ffs->cache);
456 
457 	free(ffs);
458 }
459 
ffs_lookup_part(struct ffs_handle * ffs,const char * name,uint32_t * part_idx)460 int ffs_lookup_part(struct ffs_handle *ffs, const char *name,
461 		    uint32_t *part_idx)
462 {
463 	struct ffs_entry **ents = ffs->hdr.entries;
464 	int i;
465 
466 	for (i = 0;
467 			i < ffs->hdr.count &&
468 			strncmp(name, ents[i]->name, FFS_PART_NAME_MAX);
469 			i++);
470 
471 	if (i == ffs->hdr.count)
472 		return FFS_ERR_PART_NOT_FOUND;
473 
474 	if (part_idx)
475 		*part_idx = i;
476 	return 0;
477 }
478 
ffs_part_info(struct ffs_handle * ffs,uint32_t part_idx,char ** name,uint32_t * start,uint32_t * total_size,uint32_t * act_size,bool * ecc)479 int ffs_part_info(struct ffs_handle *ffs, uint32_t part_idx,
480 		  char **name, uint32_t *start,
481 		  uint32_t *total_size, uint32_t *act_size, bool *ecc)
482 {
483 	struct ffs_entry *ent;
484 	char *n;
485 
486 	ent = __ffs_entry_get(ffs, part_idx);
487 	if (!ent)
488 		return FFS_ERR_PART_NOT_FOUND;
489 
490 	if (start)
491 		*start = ent->base;
492 	if (total_size)
493 		*total_size = ent->size;
494 	if (act_size)
495 		*act_size = ent->actual;
496 	if (ecc)
497 		*ecc = has_ecc(ent);
498 
499 	if (name) {
500 		n = calloc(1, FFS_PART_NAME_MAX + 1);
501 		if (!n)
502 			return FLASH_ERR_MALLOC_FAILED;
503 		memcpy(n, ent->name, FFS_PART_NAME_MAX);
504 		*name = n;
505 	}
506 	return 0;
507 }
508 
509 /*
510  * There are quite a few ways one might consider two ffs_handles to be the
511  * same. For the purposes of this function we are trying to detect a fairly
512  * specific scenario:
513  * Consecutive calls to ffs_next_side() may succeed but have gone circular.
514  * It is possible that the OTHER_SIDE partition in one TOC actually points
515  * back to the TOC to first ffs_handle.
516  * This function compares for this case, therefore the requirements are
517  * simple, the underlying blocklevel_devices must be the same along with
518  * the toc_offset and the max_size.
519  */
ffs_equal(struct ffs_handle * one,struct ffs_handle * two)520 bool ffs_equal(struct ffs_handle *one, struct ffs_handle *two)
521 {
522 	return (!one && !two) || (one && two && one->bl == two->bl
523 		&& one->toc_offset == two->toc_offset
524 		&& one->max_size == two->max_size);
525 }
526 
ffs_next_side(struct ffs_handle * ffs,struct ffs_handle ** new_ffs,bool mark_ecc)527 int ffs_next_side(struct ffs_handle *ffs, struct ffs_handle **new_ffs,
528 		bool mark_ecc)
529 {
530 	int rc;
531 	uint32_t index, offset, max_size;
532 
533 	if (!ffs || !new_ffs)
534 		return FLASH_ERR_PARM_ERROR;
535 
536 	*new_ffs = NULL;
537 
538 	rc = ffs_lookup_part(ffs, "OTHER_SIDE", &index);
539 	if (rc)
540 		return rc;
541 
542 	rc = ffs_part_info(ffs, index, NULL, &offset, &max_size, NULL, NULL);
543 	if (rc)
544 		return rc;
545 
546 	return ffs_init(offset, max_size, ffs->bl, new_ffs, mark_ecc);
547 }
548 
ffs_entry_add(struct ffs_hdr * hdr,struct ffs_entry * entry)549 int ffs_entry_add(struct ffs_hdr *hdr, struct ffs_entry *entry)
550 {
551 	const char *smallest_name;
552 	uint32_t smallest_base, toc_base;
553 	int i;
554 
555 	FL_DBG("LIBFFS: Adding '%s' at 0x%08x..0x%08x\n",
556 		entry->name, entry->base, entry->base + entry->size);
557 
558 	if (hdr->count == 0) {
559 		FL_DBG("LIBFFS: Adding an entry to an empty header\n");
560 		hdr->entries[hdr->count++] = entry;
561 	}
562 	if (entry->base + entry->size > hdr->block_size * hdr->block_count)
563 		return FFS_ERR_BAD_PART_SIZE;
564 
565 	smallest_base = entry->base;
566 	smallest_name = entry->name;
567 	toc_base = 0;
568 	/*
569 	 * TODO: This may have assumed entries was sorted
570 	 */
571 	for (i = 0; i < hdr->count; i++) {
572 		struct ffs_entry *ent = hdr->entries[i];
573 
574 		/* Don't allow same names to differ only by case */
575 		if (strncasecmp(entry->name, ent->name, FFS_PART_NAME_MAX) == 0)
576 			return FFS_ERR_BAD_PART_NAME;
577 
578 		if (entry->base >= ent->base && entry->base < ent->base + ent->size)
579 			return FFS_ERR_BAD_PART_BASE;
580 
581 		if (entry->base + entry->size > ent->base &&
582 				entry->base + entry->size < ent->base + ent->size)
583 			return FFS_ERR_BAD_PART_SIZE;
584 
585 		if (entry->actual > entry->size)
586 			return FFS_ERR_BAD_PART_SIZE;
587 
588 		if (entry->pid != FFS_PID_TOPLEVEL)
589 			return FFS_ERR_BAD_PART_PID;
590 
591 		/* First partition is the partition table */
592 		if (i == 0) {
593 			toc_base = ent->base;
594 		} else {
595 			/*
596 			 * We're looking for the partition directly
597 			 * after the toc to make sure we don't
598 			 * overflow onto it.
599 			 */
600 			if (ent->base < smallest_base && ent->base > toc_base) {
601 				smallest_base = ent->base;
602 				smallest_name = ent->name;
603 			}
604 		}
605 	}
606 	/* If the smallest base is before the TOC, don't worry */
607 	if (smallest_base > toc_base && (hdr->count + 1) * sizeof(struct __ffs_entry) +
608 			sizeof(struct __ffs_hdr) + toc_base > smallest_base) {
609 		fprintf(stderr, "Adding partition '%s' would cause partition '%s' at "
610 			"0x%08x to overlap with the header\n", entry->name, smallest_name,
611 			smallest_base);
612 		return FFS_ERR_BAD_PART_BASE;
613 	}
614 
615 	if (hdr->count == hdr->entries_size) {
616 		struct ffs_entry **old = hdr->entries;
617 
618 		hdr->entries = realloc(hdr->entries,
619 				(HDR_ENTRIES_NUM + hdr->entries_size) * sizeof(struct ffs_entry *));
620 		if (!hdr->entries) {
621 			hdr->entries = old;
622 			return FLASH_ERR_MALLOC_FAILED;
623 		}
624 		hdr->entries_size += HDR_ENTRIES_NUM;
625 	}
626 	entry->ref++;
627 	hdr->entries[hdr->count++] = entry;
628 
629 	return 0;
630 }
631 
ffs_hdr_finalise(struct blocklevel_device * bl,struct ffs_hdr * hdr)632 int ffs_hdr_finalise(struct blocklevel_device *bl, struct ffs_hdr *hdr)
633 {
634 	int num_entries, i, rc = 0;
635 	struct __ffs_hdr *real_hdr;
636 
637 	num_entries = ffs_num_entries(hdr);
638 
639 	/* A TOC shouldn't have zero partitions */
640 	if (num_entries == 0)
641 		return FFS_ERR_BAD_SIZE;
642 
643 	real_hdr = malloc(ffs_hdr_raw_size(num_entries));
644 	if (!real_hdr)
645 		return FLASH_ERR_MALLOC_FAILED;
646 
647 	/*
648 	 * So that the checksum gets calculated correctly at least the
649 	 * real_hdr->checksum must be zero before calling ffs_hdr_checksum()
650 	 * memset()ting the entire struct to zero is probably wise as it
651 	 * appears the reserved fields are always zero.
652 	 */
653 	memset(real_hdr, 0, sizeof(*real_hdr));
654 
655 	hdr->part->size = ffs_hdr_raw_size(num_entries) + hdr->block_size;
656 	/*
657 	 * So actual is in bytes. ffs_entry_to_flash() don't do the
658 	 * block_size division that we're relying on
659 	 */
660 	hdr->part->actual = (hdr->part->size / hdr->block_size) * hdr->block_size;
661 	real_hdr->magic = cpu_to_be32(FFS_MAGIC);
662 	real_hdr->version = cpu_to_be32(hdr->version);
663 	real_hdr->size = cpu_to_be32(hdr->part->size / hdr->block_size);
664 	real_hdr->entry_size = cpu_to_be32(sizeof(struct __ffs_entry));
665 	real_hdr->entry_count = cpu_to_be32(num_entries);
666 	real_hdr->block_size = cpu_to_be32(hdr->block_size);
667 	real_hdr->block_count = cpu_to_be32(hdr->block_count);
668 	real_hdr->checksum = ffs_hdr_checksum(real_hdr);
669 
670 	for (i = 0; i < hdr->count; i++) {
671 		rc = ffs_entry_to_flash(hdr, real_hdr->entries + i, hdr->entries[i]);
672 		if (rc) {
673 			fprintf(stderr, "Couldn't format all entries for new TOC\n");
674 			goto out;
675 		}
676 	}
677 
678 	/* Don't really care if this fails */
679 	blocklevel_erase(bl, hdr->part->base, hdr->size);
680 	rc = blocklevel_write(bl, hdr->part->base, real_hdr,
681 		ffs_hdr_raw_size(num_entries));
682 	if (rc)
683 		goto out;
684 
685 out:
686 	free(real_hdr);
687 	return rc;
688 }
689 
ffs_entry_user_set(struct ffs_entry * ent,struct ffs_entry_user * user)690 int ffs_entry_user_set(struct ffs_entry *ent, struct ffs_entry_user *user)
691 {
692 	if (!ent || !user)
693 		return -1;
694 
695 	/*
696 	 * Don't allow the user to specify anything we dont't know about.
697 	 * Rationale: This is the library providing access to the FFS structures.
698 	 *   If the consumer of the library knows more about FFS structures then
699 	 *   questions need to be asked.
700 	 *   The other possibility is that they've unknowningly supplied invalid
701 	 *   flags, we should tell them.
702 	 */
703 	if (user->chip)
704 		return -1;
705 	if (user->compresstype)
706 		return -1;
707 	if (user->datainteg & ~(FFS_ENRY_INTEG_ECC))
708 		return -1;
709 	if (user->vercheck & ~(FFS_VERCHECK_SHA512V | FFS_VERCHECK_SHA512EC))
710 		return -1;
711 	if (user->miscflags & ~(FFS_MISCFLAGS_PRESERVED | FFS_MISCFLAGS_BACKUP |
712 				FFS_MISCFLAGS_READONLY | FFS_MISCFLAGS_REPROVISION |
713 				FFS_MISCFLAGS_VOLATILE | FFS_MISCFLAGS_GOLDEN |
714 				FFS_MISCFLAGS_CLEARECC))
715 		return -1;
716 
717 	memcpy(&ent->user, user, sizeof(*user));
718 	return 0;
719 }
720 
ffs_entry_user_get(struct ffs_entry * ent)721 struct ffs_entry_user ffs_entry_user_get(struct ffs_entry *ent)
722 {
723 	struct ffs_entry_user user = { 0 };
724 
725 	if (ent)
726 		memcpy(&user, &ent->user, sizeof(user));
727 
728 	return user;
729 }
730 
ffs_entry_new(const char * name,uint32_t base,uint32_t size,struct ffs_entry ** r)731 int ffs_entry_new(const char *name, uint32_t base, uint32_t size, struct ffs_entry **r)
732 {
733 	struct ffs_entry *ret;
734 
735 	ret = calloc(1, sizeof(*ret));
736 	if (!ret)
737 		return FLASH_ERR_MALLOC_FAILED;
738 
739 	strncpy(ret->name, name, FFS_PART_NAME_MAX);
740 	ret->name[FFS_PART_NAME_MAX] = '\0';
741 	ret->base = base;
742 	ret->size = size;
743 	ret->actual = size;
744 	ret->pid = FFS_PID_TOPLEVEL;
745 	ret->type = FFS_TYPE_DATA;
746 	ret->ref = 1;
747 
748 	*r = ret;
749 	return 0;
750 }
751 
ffs_entry_set_act_size(struct ffs_entry * ent,uint32_t actual_size)752 int ffs_entry_set_act_size(struct ffs_entry *ent, uint32_t actual_size)
753 {
754 	if (!ent)
755 		return -1;
756 
757 	if (actual_size > ent->size)
758 		return FFS_ERR_BAD_PART_SIZE;
759 
760 	ent->actual = actual_size;
761 
762 	return 0;
763 }
764 
ffs_hdr_new(uint32_t block_size,uint32_t block_count,struct ffs_entry ** e,struct ffs_hdr ** r)765 int ffs_hdr_new(uint32_t block_size, uint32_t block_count,
766 		struct ffs_entry **e, struct ffs_hdr **r)
767 {
768 	struct ffs_hdr *ret;
769 	struct ffs_entry *part_table;
770 	int rc;
771 
772 	ret = calloc(1, sizeof(*ret));
773 	if (!ret)
774 		return FLASH_ERR_MALLOC_FAILED;
775 
776 	ret->version = FFS_VERSION_1;
777 	ret->block_size = block_size;
778 	ret->block_count = block_count;
779 	ret->entries = calloc(HDR_ENTRIES_NUM, sizeof(struct ffs_entry *));
780 	ret->entries_size = HDR_ENTRIES_NUM;
781 
782 	if (!e || !(*e)) {
783 		/* Don't know how big it will be, ffs_hdr_finalise() will fix */
784 		rc = ffs_entry_new("part", 0, 0, &part_table);
785 		if (rc) {
786 			free(ret);
787 			return rc;
788 		}
789 		if (e)
790 			*e = part_table;
791 	} else {
792 		part_table = *e;
793 	}
794 
795 	/* If the user still holds a ref to e, then inc the refcount */
796 	if (e)
797 		part_table->ref++;
798 
799 	ret->part = part_table;
800 
801 	part_table->pid = FFS_PID_TOPLEVEL;
802 	part_table->type = FFS_TYPE_PARTITION;
803 	part_table->flags = FFS_FLAGS_PROTECTED;
804 
805 	ret->entries[0] = part_table;
806 	ret->count = 1;
807 
808 	*r = ret;
809 
810 	return 0;
811 }
812 
ffs_update_act_size(struct ffs_handle * ffs,uint32_t part_idx,uint32_t act_size)813 int ffs_update_act_size(struct ffs_handle *ffs, uint32_t part_idx,
814 			uint32_t act_size)
815 {
816 	struct ffs_entry *ent;
817 	struct __ffs_entry raw_ent;
818 	uint32_t offset;
819 	int rc;
820 
821 	ent = __ffs_entry_get(ffs, part_idx);
822 	if (!ent) {
823 		FL_DBG("FFS: Entry not found\n");
824 		return FFS_ERR_PART_NOT_FOUND;
825 	}
826 	offset = ffs->toc_offset + ffs_hdr_raw_size(part_idx);
827 	FL_DBG("FFS: part index %d at offset 0x%08x\n",
828 	       part_idx, offset);
829 
830 	if (ent->actual == act_size) {
831 		FL_DBG("FFS: ent->actual alrady matches: 0x%08x==0x%08x\n",
832 		       act_size, ent->actual);
833 		return 0;
834 	}
835 	ent->actual = act_size;
836 
837 	rc = ffs_entry_to_flash(&ffs->hdr, &raw_ent, ent);
838 	if (rc)
839 		return rc;
840 
841 	return blocklevel_smart_write(ffs->bl, offset, &raw_ent, sizeof(struct __ffs_entry));
842 }
843