A FIT image is a device tree and its second big-endian 32-bit word encodes the size and fit_open() takes an extra argument, so it need not read a whole partition, but only as many bytes as the header describes.
We are going to add a new caller for fit_open(). Instead of repeating the max_size determination at every call site, let's just move the size calculation into the function. Signed-off-by: Ahmad Fatoum <[email protected]> --- common/bootm-fit.c | 9 +-------- common/image-fit.c | 44 ++++++++++++++++++++++++++++++++++---------- drivers/of/overlay.c | 6 +++--- include/image-fit.h | 2 +- include/libfile.h | 2 ++ lib/libfile.c | 40 ++++++++++++++++++++++++++++++++++++++++ 6 files changed, 81 insertions(+), 22 deletions(-) diff --git a/common/bootm-fit.c b/common/bootm-fit.c index 5bfd8ac61d3f..70d6ba8edff2 100644 --- a/common/bootm-fit.c +++ b/common/bootm-fit.c @@ -129,17 +129,10 @@ static enum filetype bootm_fit_update_os_header(struct image_data *data) int bootm_open_fit(struct image_data *data) { struct fit_handle *fit; - struct fdt_header *header; static const char *kernel_img = "kernel"; - size_t flen, hlen; int ret; - header = (struct fdt_header *)data->os_header; - flen = bootm_get_os_size(data); - hlen = fdt32_to_cpu(header->totalsize); - - fit = fit_open(data->os_file, data->verbose, data->verify, - min(flen, hlen)); + fit = fit_open(data->os_file, data->verbose, data->verify); if (IS_ERR(fit)) { pr_err("Loading FIT image %s failed with: %pe\n", data->os_file, fit); return PTR_ERR(fit); diff --git a/common/image-fit.c b/common/image-fit.c index 75592766941c..d42282dfa80e 100644 --- a/common/image-fit.c +++ b/common/image-fit.c @@ -992,7 +992,6 @@ struct fit_handle *fit_open_buf(const void *buf, size_t size, bool verbose, * @filename: The filename of the FIT image * @verbose: If true, be more verbose * @verify: The verify mode - * @max_size: maximum length to read from file * * This opens a FIT image found in @filename. The returned handle is used as * context for the other FIT functions. @@ -1000,11 +999,12 @@ struct fit_handle *fit_open_buf(const void *buf, size_t size, bool verbose, * Return: A handle to a FIT image or a ERR_PTR */ struct fit_handle *fit_open(const char *_filename, bool verbose, - enum bootm_verify verify, loff_t max_size) + enum bootm_verify verify) { struct fit_handle *handle; + ssize_t nbytes; char *filename; - int ret; + int fd, ret; filename = canonicalize_path(AT_FDCWD, _filename); if (!filename) { @@ -1024,15 +1024,28 @@ struct fit_handle *fit_open(const char *_filename, bool verbose, handle->verbose = verbose; handle->verify = verify; - ret = read_file_2(filename, &handle->size, &handle->fit_alloc, - max_size); - if (ret && ret != -EFBIG) { - pr_err("unable to read %s: %pe\n", filename, ERR_PTR(ret)); - free(handle); - free(filename); - return ERR_PTR(ret); + fd = open_fdt(filename, &handle->size); + if (fd < 0) { + ret = fd; + goto free_handle; } + handle->fit_alloc = malloc(handle->size); + if (!handle->fit_alloc) { + ret = -ENOMEM; + goto close_fd; + } + + nbytes = read_full(fd, handle->fit_alloc, handle->size); + if (nbytes >= 0 && handle->size != nbytes) + ret = -ENODATA; + if (nbytes < 0) { + ret = nbytes; + goto free_fit_alloc; + } + + close(fd); + handle->fit = handle->fit_alloc; handle->filename = filename; @@ -1046,6 +1059,17 @@ struct fit_handle *fit_open(const char *_filename, bool verbose, } return handle; + +free_fit_alloc: + free(handle->fit_alloc); +close_fd: + close(fd); +free_handle: + pr_err("unable to read %s: %pe\n", filename, ERR_PTR(ret)); + free(filename); + free(handle); + return ERR_PTR(ret); + } static bool __fit_close(struct fit_handle *handle) diff --git a/drivers/of/overlay.c b/drivers/of/overlay.c index b11edebd2080..34543403e9ba 100644 --- a/drivers/of/overlay.c +++ b/drivers/of/overlay.c @@ -532,7 +532,7 @@ static bool of_overlay_valid_config(struct fit_handle *fit, } static int of_overlay_global_fixup_fit(struct device_node *root, - const char *fit_path, loff_t fit_size) + const char *fit_path) { enum bootm_verify verify = bootm_get_verify_mode(); struct device_node *conf_node; @@ -544,7 +544,7 @@ static int of_overlay_global_fixup_fit(struct device_node *root, return -EINVAL; } - fit = fit_open(fit_path, 0, verify, fit_size); + fit = fit_open(fit_path, 0, verify); if (IS_ERR(fit)) { pr_err("Loading FIT image %s failed with: %pe\n", fit_path, fit); return PTR_ERR(fit); @@ -595,7 +595,7 @@ static int of_overlay_global_fixup(struct device_node *root, void *data) } /* Assume a FIT image if of_overlay_path points to a file */ - ret = of_overlay_global_fixup_fit(root, dir, s.st_size); + ret = of_overlay_global_fixup_fit(root, dir); out: free(dir); diff --git a/include/image-fit.h b/include/image-fit.h index 50f0482b65ad..ede43beab12e 100644 --- a/include/image-fit.h +++ b/include/image-fit.h @@ -28,7 +28,7 @@ struct fit_handle { }; struct fit_handle *fit_open(const char *filename, bool verbose, - enum bootm_verify verify, loff_t max_size); + enum bootm_verify verify); struct fit_handle *fit_open_buf(const void *buf, size_t len, bool verbose, enum bootm_verify verify); void *fit_open_configuration(struct fit_handle *handle, const char *name, diff --git a/include/libfile.h b/include/libfile.h index 370f8b9725ab..f44046fb0f7b 100644 --- a/include/libfile.h +++ b/include/libfile.h @@ -59,4 +59,6 @@ struct resource *file_to_sdram(const char *filename, unsigned long adr, int fixup_path_case(int dirfd, const char **path); +int open_fdt(const char *filename, size_t *size); + #endif /* __LIBFILE_H */ diff --git a/lib/libfile.c b/lib/libfile.c index 6924db587e8c..3be410855d2e 100644 --- a/lib/libfile.c +++ b/lib/libfile.c @@ -918,3 +918,43 @@ int fixup_path_case(int fd, const char **path) free(resolved_path); return -errno; } + +int open_fdt(const char *filename, size_t *size) +{ + __be32 fdt_hdr[2]; + u32 fdt_size; + struct stat st; + int fd, ret; + + fd = open(filename, O_RDONLY); + if (fd < 0) + return fd; + + ret = fstat(fd, &st); + if (ret) + goto err; + + ret = pread_full(fd, &fdt_hdr, sizeof(fdt_hdr), 0); + if (ret >= 0 && ret < sizeof(fdt_hdr)) + ret = -EILSEQ; + if (ret < 0) + goto err; + + fdt_size = be32_to_cpu(fdt_hdr[1]); + if (st.st_size < fdt_size) { + ret = -ENODATA; + goto err; + } + + close(fd); + + /* HACK: TFTP doesn't support backwards seeking, so reopen afresh */ + fd = open(filename, O_RDONLY); + if (fd >= 0) + *size = fdt_size; + + return fd; +err: + close(fd); + return ret; +} -- 2.47.3
