feat(fiptool): handle FIP in a disk partition

When FIP is programmed in a disk partition, fiptool cannot be used
directly; this forces the user to temporarily copy the partition
to a file, apply fiptool and copy back the file. This is caused by
fstat() that returns zero file size on a block special file, thus
making fiptool commands info, update, unpack and remove to exit.

For either Linux host or Linux target, recover the partition size
with ioctl() and use it as FIP file size. E.g.:
	fiptool info /dev/disk/by-partlabel/fip-a
	fiptool info /dev/mtdblock4

While there, rework two identical error log messages to provide
more details about the failure and update the date in copyright.

Signed-off-by: Antonio Borneo <antonio.borneo@foss.st.com>
Change-Id: I7cab60e577422d94c24ba7e39458f58bcebc2336
This commit is contained in:
Antonio Borneo 2022-09-22 12:15:27 +02:00
parent d3d2a5a484
commit 06e69f7c94

View file

@ -1,9 +1,12 @@
/* /*
* Copyright (c) 2016-2017, ARM Limited and Contributors. All rights reserved. * Copyright (c) 2016-2023, ARM Limited and Contributors. All rights reserved.
* *
* SPDX-License-Identifier: BSD-3-Clause * SPDX-License-Identifier: BSD-3-Clause
*/ */
#ifndef _MSC_VER
#include <sys/mount.h>
#endif
#include <sys/types.h> #include <sys/types.h>
#include <sys/stat.h> #include <sys/stat.h>
@ -298,6 +301,7 @@ static int parse_fip(const char *filename, fip_toc_header_t *toc_header_out)
fip_toc_header_t *toc_header; fip_toc_header_t *toc_header;
fip_toc_entry_t *toc_entry; fip_toc_entry_t *toc_entry;
int terminated = 0; int terminated = 0;
size_t st_size;
fp = fopen(filename, "rb"); fp = fopen(filename, "rb");
if (fp == NULL) if (fp == NULL)
@ -306,13 +310,21 @@ static int parse_fip(const char *filename, fip_toc_header_t *toc_header_out)
if (fstat(fileno(fp), &st) == -1) if (fstat(fileno(fp), &st) == -1)
log_err("fstat %s", filename); log_err("fstat %s", filename);
buf = xmalloc(st.st_size, "failed to load file into memory"); st_size = st.st_size;
if (fread(buf, 1, st.st_size, fp) != st.st_size)
#ifdef BLKGETSIZE64
if ((st.st_mode & S_IFBLK) != 0)
if (ioctl(fileno(fp), BLKGETSIZE64, &st_size) == -1)
log_err("ioctl %s", filename);
#endif
buf = xmalloc(st_size, "failed to load file into memory");
if (fread(buf, 1, st_size, fp) != st_size)
log_errx("Failed to read %s", filename); log_errx("Failed to read %s", filename);
bufend = buf + st.st_size; bufend = buf + st_size;
fclose(fp); fclose(fp);
if (st.st_size < sizeof(fip_toc_header_t)) if (st_size < sizeof(fip_toc_header_t))
log_errx("FIP %s is truncated", filename); log_errx("FIP %s is truncated", filename);
toc_header = (fip_toc_header_t *)buf; toc_header = (fip_toc_header_t *)buf;
@ -347,9 +359,11 @@ static int parse_fip(const char *filename, fip_toc_header_t *toc_header_out)
"failed to allocate image buffer, is FIP file corrupted?"); "failed to allocate image buffer, is FIP file corrupted?");
/* Overflow checks before memory copy. */ /* Overflow checks before memory copy. */
if (toc_entry->size > (uint64_t)-1 - toc_entry->offset_address) if (toc_entry->size > (uint64_t)-1 - toc_entry->offset_address)
log_errx("FIP %s is corrupted", filename); log_errx("FIP %s is corrupted: entry size exceeds 64 bit address space",
if (toc_entry->size + toc_entry->offset_address > st.st_size) filename);
log_errx("FIP %s is corrupted", filename); if (toc_entry->size + toc_entry->offset_address > st_size)
log_errx("FIP %s is corrupted: entry size exceeds FIP file size",
filename);
memcpy(image->buffer, buf + toc_entry->offset_address, memcpy(image->buffer, buf + toc_entry->offset_address,
toc_entry->size); toc_entry->size);