From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mails.dpdk.org (mails.dpdk.org [217.70.189.124]) by inbox.dpdk.org (Postfix) with ESMTP id 44FAFA0A0C; Tue, 29 Jun 2021 14:45:27 +0200 (CEST) Received: from [217.70.189.124] (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 079AB411C5; Tue, 29 Jun 2021 14:45:27 +0200 (CEST) Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [216.205.24.124]) by mails.dpdk.org (Postfix) with ESMTP id 1120A40E01 for ; Tue, 29 Jun 2021 14:45:24 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1624970724; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: in-reply-to:in-reply-to:references:references; bh=OEsnJs2rprFCE1ZTdTgre/HSgyMbDhKeIEWZ12m/Uz8=; b=LezIc0kMTxYez6Th/YSmMcR0QDHh7Xp2zqxEcAgoZTfPwVLt+2S9K+rEpXQNtijlrnBUdR 00buFa7Vg5IIqpT+mViwmHvpD+ynGRD5AxIrbdFD9mnJ/x1k/YA7y1K37N85VQfdZ9CK91 983/OC+Hetv8ra6dXfX1zaINQQj1gqQ= Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-491-76_A6j9ZPn23DeAb3XRbpQ-1; Tue, 29 Jun 2021 08:45:19 -0400 X-MC-Unique: 76_A6j9ZPn23DeAb3XRbpQ-1 Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.phx2.redhat.com [10.5.11.15]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 9DA71800685; Tue, 29 Jun 2021 12:45:16 +0000 (UTC) Received: from RHTPC1VM0NT (ovpn-115-237.rdu2.redhat.com [10.10.115.237]) by smtp.corp.redhat.com (Postfix) with ESMTPS id E8E9B5D6AD; Tue, 29 Jun 2021 12:45:09 +0000 (UTC) From: Aaron Conole To: David Marchand Cc: dev@dpdk.org, Igor Russkikh , Michael Santana , Bruce Richardson , Rasesh Mody , Shahed Shaikh , Qiming Yang , Qi Zhang , Heinrich Kuhn , Devendra Singh Rawat , Ray Kinsella , Neil Horman , Dmitry Kozlyuk , Narcisa Ana Maria Vasile , Dmitry Malloy , Pallavi Kadam References: <20210602095836.24901-1-david.marchand@redhat.com> <20210629080632.30964-1-david.marchand@redhat.com> <20210629080632.30964-3-david.marchand@redhat.com> Date: Tue, 29 Jun 2021 08:45:08 -0400 In-Reply-To: <20210629080632.30964-3-david.marchand@redhat.com> (David Marchand's message of "Tue, 29 Jun 2021 10:06:32 +0200") Message-ID: User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/27.2 (gnu/linux) MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.15 Authentication-Results: relay.mimecast.com; auth=pass smtp.auth=CUSA124A263 smtp.mailfrom=aconole@redhat.com X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Content-Type: text/plain Subject: Re: [dpdk-dev] [PATCH v3 2/2] eal: handle compressed firmwares X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org Sender: "dev" David Marchand writes: > Introduce an internal firmware loading helper to remove code duplication > in our drivers and handle xz compressed firmwares by calling libarchive. > > This helper tries to look for .xz suffixes so that drivers are not aware > the firmwares have been compressed. > > libarchive is set as an optional dependency: without libarchive, a > runtime warning is emitted so that users know there is a compressed > firmware. > > Windows implementation is left as an empty stub. > > Signed-off-by: David Marchand > Reviewed-by: Igor Russkikh > --- > Changes since v2: > - added a comment on libarchive link dependency, > > Changes since v1: > - used pkg-config for libarchive detection, > - updated doxygen annotations, > - added internal helpers in eal_firmware.c to enhance readability, > - dropped whitespace damage in version.map, > > --- > .github/workflows/build.yml | 1 + > .travis.yml | 1 + > config/meson.build | 10 +++ > drivers/net/bnx2x/bnx2x.c | 35 +++----- > drivers/net/ice/ice_ethdev.c | 60 +++---------- > drivers/net/nfp/nfp_net.c | 57 +++---------- > drivers/net/qede/qede_main.c | 45 ++++------ > lib/eal/include/rte_firmware.h | 32 +++++++ > lib/eal/unix/eal_firmware.c | 149 +++++++++++++++++++++++++++++++++ > lib/eal/unix/meson.build | 1 + > lib/eal/version.map | 1 + > lib/eal/windows/eal.c | 9 ++ > 12 files changed, 259 insertions(+), 142 deletions(-) > create mode 100644 lib/eal/include/rte_firmware.h > create mode 100644 lib/eal/unix/eal_firmware.c > > diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml > index 7c4d6dcdbf..7dac20ddeb 100644 > --- a/.github/workflows/build.yml > +++ b/.github/workflows/build.yml > @@ -93,6 +93,7 @@ jobs: > run: sudo apt install -y ccache libnuma-dev python3-setuptools > python3-wheel python3-pip python3-pyelftools ninja-build libbsd-dev > libpcap-dev libibverbs-dev libcrypto++-dev libfdt-dev libjansson-dev > + libarchive-dev > - name: Install libabigail build dependencies if no cache is available > if: env.ABI_CHECKS == 'true' && steps.libabigail-cache.outputs.cache-hit != 'true' > run: sudo apt install -y autoconf automake libtool pkg-config libxml2-dev > diff --git a/.travis.yml b/.travis.yml > index 5b702cc9bb..23067d9e3c 100644 > --- a/.travis.yml > +++ b/.travis.yml > @@ -16,6 +16,7 @@ addons: > packages: &required_packages > - [libnuma-dev, python3-setuptools, python3-wheel, python3-pip, python3-pyelftools, ninja-build] > - [libbsd-dev, libpcap-dev, libibverbs-dev, libcrypto++-dev, libfdt-dev, libjansson-dev] > + - [libarchive-dev] > > _aarch64_packages: &aarch64_packages > - *required_packages > diff --git a/config/meson.build b/config/meson.build > index 017bb2efbb..639aa74e12 100644 > --- a/config/meson.build > +++ b/config/meson.build > @@ -172,6 +172,16 @@ if libexecinfo.found() and cc.has_header('execinfo.h') > dpdk_extra_ldflags += '-lexecinfo' > endif > > +libarchive = dependency('libarchive', required: false, method: 'pkg-config') > +if libarchive.found() > + dpdk_conf.set('RTE_HAS_LIBARCHIVE', 1) > + # Push libarchive link dependency at the project level to support > + # statically linking dpdk apps. Details at: > + # https://inbox.dpdk.org/dev/20210605004024.660267a1@sovereign/ > + add_project_link_arguments('-larchive', language: 'c') > + dpdk_extra_ldflags += '-larchive' > +endif > + > # check for libbsd > libbsd = dependency('libbsd', required: false, method: 'pkg-config') > if libbsd.found() > diff --git a/drivers/net/bnx2x/bnx2x.c b/drivers/net/bnx2x/bnx2x.c > index 654878d9de..60292753e2 100644 > --- a/drivers/net/bnx2x/bnx2x.c > +++ b/drivers/net/bnx2x/bnx2x.c > @@ -26,7 +26,9 @@ > #include > #include > #include > + > #include > +#include > #include > > #define BNX2X_PMD_VER_PREFIX "BNX2X PMD" > @@ -9655,44 +9657,33 @@ static void bnx2x_init_rte(struct bnx2x_softc *sc) > void bnx2x_load_firmware(struct bnx2x_softc *sc) > { > const char *fwname; > - int f; > - struct stat st; > + void *buf; > + size_t bufsz; > > fwname = sc->devinfo.device_id == CHIP_NUM_57711 > ? FW_NAME_57711 : FW_NAME_57810; > - f = open(fwname, O_RDONLY); > - if (f < 0) { > + if (rte_firmware_read(fwname, &buf, &bufsz) != 0) { > PMD_DRV_LOG(NOTICE, sc, "Can't open firmware file"); > return; > } > > - if (fstat(f, &st) < 0) { > - PMD_DRV_LOG(NOTICE, sc, "Can't stat firmware file"); > - close(f); > - return; > - } > - > - sc->firmware = rte_zmalloc("bnx2x_fw", st.st_size, RTE_CACHE_LINE_SIZE); > + sc->firmware = rte_zmalloc("bnx2x_fw", bufsz, RTE_CACHE_LINE_SIZE); > if (!sc->firmware) { > PMD_DRV_LOG(NOTICE, sc, "Can't allocate memory for firmware"); > - close(f); > - return; > + goto out; > } > > - if (read(f, sc->firmware, st.st_size) != st.st_size) { > - PMD_DRV_LOG(NOTICE, sc, "Can't read firmware data"); > - close(f); > - return; > - } > - close(f); > - > - sc->fw_len = st.st_size; > + sc->fw_len = bufsz; > if (sc->fw_len < FW_HEADER_LEN) { > PMD_DRV_LOG(NOTICE, sc, > "Invalid fw size: %" PRIu64, sc->fw_len); > - return; > + goto out; > } > + > + memcpy(sc->firmware, buf, sc->fw_len); > PMD_DRV_LOG(DEBUG, sc, "fw_len = %" PRIu64, sc->fw_len); > +out: > + free(buf); > } > > static void > diff --git a/drivers/net/ice/ice_ethdev.c b/drivers/net/ice/ice_ethdev.c > index d180b73c32..06da1bbd94 100644 > --- a/drivers/net/ice/ice_ethdev.c > +++ b/drivers/net/ice/ice_ethdev.c > @@ -10,6 +10,7 @@ > #include > #include > > +#include > #include > > #include "base/ice_sched.h" > @@ -1673,22 +1674,14 @@ ice_load_pkg_type(struct ice_hw *hw) > return package_type; > } > > -#ifdef RTE_EXEC_ENV_WINDOWS > -#define ice_access _access > -#else > -#define ice_access access > -#endif > - > int ice_load_pkg(struct ice_adapter *adapter, bool use_dsn, uint64_t dsn) > { > struct ice_hw *hw = &adapter->hw; > char pkg_file[ICE_MAX_PKG_FILENAME_SIZE]; > char opt_ddp_filename[ICE_MAX_PKG_FILENAME_SIZE]; > + void *buf; > + size_t bufsz; > int err; > - uint8_t *buf = NULL; > - int buf_len; > - FILE *file; > - struct stat fstat; > > if (!use_dsn) > goto no_dsn; > @@ -1698,57 +1691,31 @@ int ice_load_pkg(struct ice_adapter *adapter, bool use_dsn, uint64_t dsn) > "ice-%016" PRIx64 ".pkg", dsn); > strncpy(pkg_file, ICE_PKG_FILE_SEARCH_PATH_UPDATES, > ICE_MAX_PKG_FILENAME_SIZE); > - if (!ice_access(strcat(pkg_file, opt_ddp_filename), 0)) > + strcat(pkg_file, opt_ddp_filename); > + if (rte_firmware_read(pkg_file, &buf, &bufsz) == 0) > goto load_fw; > > strncpy(pkg_file, ICE_PKG_FILE_SEARCH_PATH_DEFAULT, > ICE_MAX_PKG_FILENAME_SIZE); > - if (!ice_access(strcat(pkg_file, opt_ddp_filename), 0)) > + strcat(pkg_file, opt_ddp_filename); > + if (rte_firmware_read(pkg_file, &buf, &bufsz) == 0) > goto load_fw; > > no_dsn: > strncpy(pkg_file, ICE_PKG_FILE_UPDATES, ICE_MAX_PKG_FILENAME_SIZE); > - if (!ice_access(pkg_file, 0)) > + if (rte_firmware_read(pkg_file, &buf, &bufsz) == 0) > goto load_fw; > + > strncpy(pkg_file, ICE_PKG_FILE_DEFAULT, ICE_MAX_PKG_FILENAME_SIZE); > - if (ice_access(pkg_file, 0)) { > + if (rte_firmware_read(pkg_file, &buf, &bufsz) < 0) { > PMD_INIT_LOG(ERR, "failed to search file path\n"); > return -1; > } > > load_fw: > - file = fopen(pkg_file, "rb"); > - if (!file) { > - PMD_INIT_LOG(ERR, "failed to open file: %s\n", pkg_file); > - return -1; > - } > - > PMD_INIT_LOG(DEBUG, "DDP package name: %s", pkg_file); > > - err = stat(pkg_file, &fstat); > - if (err) { > - PMD_INIT_LOG(ERR, "failed to get file stats\n"); > - goto out; > - } > - > - buf_len = fstat.st_size; > - buf = rte_malloc(NULL, buf_len, 0); > - > - if (!buf) { > - PMD_INIT_LOG(ERR, "failed to allocate buf of size %d for package\n", > - buf_len); > - err = -1; > - goto out; > - } > - > - err = fread(buf, buf_len, 1, file); > - if (err != 1) { > - PMD_INIT_LOG(ERR, "failed to read package data\n"); > - err = -1; > - goto out; > - } > - > - err = ice_copy_and_init_pkg(hw, buf, buf_len); > + err = ice_copy_and_init_pkg(hw, buf, bufsz); > if (err) { > PMD_INIT_LOG(ERR, "ice_copy_and_init_hw failed: %d\n", err); > goto out; > @@ -1758,13 +1725,10 @@ int ice_load_pkg(struct ice_adapter *adapter, bool use_dsn, uint64_t dsn) > adapter->active_pkg_type = ice_load_pkg_type(hw); > > out: > - fclose(file); > - rte_free(buf); > + free(buf); > return err; > } > > -#undef ice_access > - > static void > ice_base_queue_get(struct ice_pf *pf) > { > diff --git a/drivers/net/nfp/nfp_net.c b/drivers/net/nfp/nfp_net.c > index 2ee88fbfc7..879da7ef59 100644 > --- a/drivers/net/nfp/nfp_net.c > +++ b/drivers/net/nfp/nfp_net.c > @@ -29,6 +29,7 @@ > #include > #include > #include > +#include > > #include "nfpcore/nfp_cpp.h" > #include "nfpcore/nfp_nffw.h" > @@ -3366,12 +3367,10 @@ static int > nfp_fw_upload(struct rte_pci_device *dev, struct nfp_nsp *nsp, char *card) > { > struct nfp_cpp *cpp = nsp->cpp; > - int fw_f; > - char *fw_buf; > + void *fw_buf; > char fw_name[125]; > char serial[40]; > - struct stat file_stat; > - off_t fsize, bytes; > + size_t fsize; > > /* Looking for firmware file in order of priority */ > > @@ -3384,66 +3383,34 @@ nfp_fw_upload(struct rte_pci_device *dev, struct nfp_nsp *nsp, char *card) > > snprintf(fw_name, sizeof(fw_name), "%s/%s.nffw", DEFAULT_FW_PATH, > serial); > - > PMD_DRV_LOG(DEBUG, "Trying with fw file: %s", fw_name); > - fw_f = open(fw_name, O_RDONLY); > - if (fw_f >= 0) > - goto read_fw; > + if (rte_firmware_read(fw_name, &fw_buf, &fsize) == 0) > + goto load_fw; > > /* Then try the PCI name */ > snprintf(fw_name, sizeof(fw_name), "%s/pci-%s.nffw", DEFAULT_FW_PATH, > dev->device.name); > - > PMD_DRV_LOG(DEBUG, "Trying with fw file: %s", fw_name); > - fw_f = open(fw_name, O_RDONLY); > - if (fw_f >= 0) > - goto read_fw; > + if (rte_firmware_read(fw_name, &fw_buf, &fsize) == 0) > + goto load_fw; > > /* Finally try the card type and media */ > snprintf(fw_name, sizeof(fw_name), "%s/%s", DEFAULT_FW_PATH, card); > PMD_DRV_LOG(DEBUG, "Trying with fw file: %s", fw_name); > - fw_f = open(fw_name, O_RDONLY); > - if (fw_f < 0) { > + if (rte_firmware_read(fw_name, &fw_buf, &fsize) < 0) { > PMD_DRV_LOG(INFO, "Firmware file %s not found.", fw_name); > return -ENOENT; > } > > -read_fw: > - if (fstat(fw_f, &file_stat) < 0) { > - PMD_DRV_LOG(INFO, "Firmware file %s size is unknown", fw_name); > - close(fw_f); > - return -ENOENT; > - } > - > - fsize = file_stat.st_size; > - PMD_DRV_LOG(INFO, "Firmware file found at %s with size: %" PRIu64 "", > - fw_name, (uint64_t)fsize); > - > - fw_buf = malloc((size_t)fsize); > - if (!fw_buf) { > - PMD_DRV_LOG(INFO, "malloc failed for fw buffer"); > - close(fw_f); > - return -ENOMEM; > - } > - memset(fw_buf, 0, fsize); > - > - bytes = read(fw_f, fw_buf, fsize); > - if (bytes != fsize) { > - PMD_DRV_LOG(INFO, "Reading fw to buffer failed." > - "Just %" PRIu64 " of %" PRIu64 " bytes read", > - (uint64_t)bytes, (uint64_t)fsize); > - free(fw_buf); > - close(fw_f); > - return -EIO; > - } > +load_fw: > + PMD_DRV_LOG(INFO, "Firmware file found at %s with size: %zu", > + fw_name, fsize); > > PMD_DRV_LOG(INFO, "Uploading the firmware ..."); > - nfp_nsp_load_fw(nsp, fw_buf, bytes); > + nfp_nsp_load_fw(nsp, fw_buf, fsize); > PMD_DRV_LOG(INFO, "Done"); > > free(fw_buf); > - close(fw_f); > - > return 0; > } > > diff --git a/drivers/net/qede/qede_main.c b/drivers/net/qede/qede_main.c > index caa9d1d4f6..504e2c66a0 100644 > --- a/drivers/net/qede/qede_main.c > +++ b/drivers/net/qede/qede_main.c > @@ -5,7 +5,9 @@ > */ > > #include > + > #include > +#include > #include > > #include "qede_ethdev.h" > @@ -127,51 +129,40 @@ static void qed_free_stream_mem(struct ecore_dev *edev) > #ifdef CONFIG_ECORE_BINARY_FW > static int qed_load_firmware_data(struct ecore_dev *edev) > { > - int fd; > - struct stat st; > const char *fw = RTE_LIBRTE_QEDE_FW; > + void *buf; > + size_t bufsz; > + int ret; > > if (strcmp(fw, "") == 0) > strcpy(qede_fw_file, QEDE_DEFAULT_FIRMWARE); > else > strcpy(qede_fw_file, fw); > > - fd = open(qede_fw_file, O_RDONLY); > - if (fd < 0) { > - DP_ERR(edev, "Can't open firmware file\n"); > - return -ENOENT; > - } > - > - if (fstat(fd, &st) < 0) { > - DP_ERR(edev, "Can't stat firmware file\n"); > - close(fd); > + if (rte_firmware_read(qede_fw_file, &buf, &bufsz) < 0) { > + DP_ERR(edev, "Can't read firmware data: %s\n", qede_fw_file); > return -1; > } > > - edev->firmware = rte_zmalloc("qede_fw", st.st_size, > - RTE_CACHE_LINE_SIZE); > + edev->firmware = rte_zmalloc("qede_fw", bufsz, RTE_CACHE_LINE_SIZE); > if (!edev->firmware) { > DP_ERR(edev, "Can't allocate memory for firmware\n"); > - close(fd); > - return -ENOMEM; > + ret = -ENOMEM; > + goto out; > } > > - if (read(fd, edev->firmware, st.st_size) != st.st_size) { > - DP_ERR(edev, "Can't read firmware data\n"); > - close(fd); > - return -1; > - } > - > - edev->fw_len = st.st_size; > + memcpy(edev->firmware, buf, bufsz); > + edev->fw_len = bufsz; > if (edev->fw_len < 104) { > DP_ERR(edev, "Invalid fw size: %" PRIu64 "\n", > edev->fw_len); > - close(fd); > - return -EINVAL; > + ret = -EINVAL; > + goto out; > } > - > - close(fd); > - return 0; > + ret = 0; > +out: > + free(buf); > + return ret; > } > #endif > > diff --git a/lib/eal/include/rte_firmware.h b/lib/eal/include/rte_firmware.h > new file mode 100644 > index 0000000000..3389e60ca0 > --- /dev/null > +++ b/lib/eal/include/rte_firmware.h > @@ -0,0 +1,32 @@ > +/* SPDX-License-Identifier: BSD-3-Clause > + * Copyright(c) 2021 Red Hat, Inc. > + */ > + > +#ifndef __RTE_FIRMWARE_H__ > +#define __RTE_FIRMWARE_H__ > + > +#include > + > +#include > + > +/** > + * Load a firmware in a dynamically allocated buffer, dealing with compressed > + * files if libarchive is available. > + * > + * @param[in] name > + * Firmware filename to load. > + * @param[out] buf > + * Buffer allocated by this function. If this function succeeds, the > + * caller is responsible for calling free() on this buffer. > + * @param[out] bufsz > + * Size of the data in the buffer. > + * > + * @return > + * 0 if successful. > + * Negative otherwise, buf and bufsize contents are invalid. > + */ > +__rte_internal > +int > +rte_firmware_read(const char *name, void **buf, size_t *bufsz); > + > +#endif > diff --git a/lib/eal/unix/eal_firmware.c b/lib/eal/unix/eal_firmware.c > new file mode 100644 > index 0000000000..494cd5f058 > --- /dev/null > +++ b/lib/eal/unix/eal_firmware.c > @@ -0,0 +1,149 @@ > +/* SPDX-License-Identifier: BSD-3-Clause > + * Copyright(c) 2021 Red Hat, Inc. > + */ > + > +#ifdef RTE_HAS_LIBARCHIVE > +#include > +#endif > +#include > +#include > +#include > +#include > + > +#include > +#include > +#include > + > +#ifdef RTE_HAS_LIBARCHIVE > + > +struct firmware_read_ctx { > + struct archive *a; > +}; > + > +static int > +firmware_open(struct firmware_read_ctx *ctx, const char *name, size_t blocksize) > +{ > + struct archive_entry *e; > + > + ctx->a = archive_read_new(); > + if (ctx->a == NULL) > + return -1; > + if (archive_read_support_format_raw(ctx->a) != ARCHIVE_OK || > + archive_read_support_filter_xz(ctx->a) != ARCHIVE_OK || > + archive_read_open_filename(ctx->a, name, blocksize) != ARCHIVE_OK || > + archive_read_next_header(ctx->a, &e) != ARCHIVE_OK) { > + archive_read_free(ctx->a); > + ctx->a = NULL; > + return -1; > + } > + return 0; > +} > + > +static ssize_t > +firmware_read_block(struct firmware_read_ctx *ctx, void *buf, size_t count) > +{ > + return archive_read_data(ctx->a, buf, count); > +} > + > +static void > +firmware_close(struct firmware_read_ctx *ctx) > +{ > + archive_read_free(ctx->a); > + ctx->a = NULL; > +} > + > +#else /* !RTE_HAS_LIBARCHIVE */ > + > +struct firmware_read_ctx { > + int fd; > +}; > + > +static int > +firmware_open(struct firmware_read_ctx *ctx, const char *name, > + __rte_unused size_t blocksize) > +{ > + ctx->fd = open(name, O_RDONLY); > + if (ctx->fd < 0) > + return -1; > + return 0; > +} > + > +static ssize_t > +firmware_read_block(struct firmware_read_ctx *ctx, void *buf, size_t count) > +{ > + return read(ctx->fd, buf, count); > +} > + > +static void > +firmware_close(struct firmware_read_ctx *ctx) > +{ > + close(ctx->fd); > + ctx->fd = -1; > +} > + > +#endif /* !RTE_HAS_LIBARCHIVE */ > + > +static int > +firmware_read(const char *name, void **buf, size_t *bufsz) > +{ > + const size_t blocksize = 4096; > + struct firmware_read_ctx ctx; > + int ret = -1; > + int err; > + > + *buf = NULL; > + *bufsz = 0; > + > + if (firmware_open(&ctx, name, blocksize) < 0) > + return -1; > + > + do { > + void *tmp; > + > + tmp = realloc(*buf, *bufsz + blocksize); > + if (tmp == NULL) { > + free(*buf); > + *buf = NULL; > + *bufsz = 0; > + goto out; > + } > + *buf = tmp; > + > + err = firmware_read_block(&ctx, RTE_PTR_ADD(*buf, *bufsz), blocksize); > + if (err < 0) { > + free(*buf); > + *buf = NULL; > + *bufsz = 0; > + goto out; > + } > + *bufsz += err; > + > + } while (err != 0); > + > + ret = 0; > +out: > + firmware_close(&ctx); > + return ret; > +} > + > +int > +rte_firmware_read(const char *name, void **buf, size_t *bufsz) > +{ > + char path[PATH_MAX]; > + int ret; > + > + ret = firmware_read(name, buf, bufsz); > + if (ret < 0) { > + snprintf(path, sizeof(path), "%s.xz", name); > + path[PATH_MAX - 1] = '\0'; > +#ifndef RTE_HAS_LIBARCHIVE > + if (access(path, F_OK) == 0) { > + RTE_LOG(WARNING, EAL, "libarchive not available, %s cannot be decompressed\n", Maybe 'not linked' instead of 'not available'. A user might decide to install libarchive and then be confused that the error message still pops up (without realizing they need to re-compile). Otherwise, Acked-by: Aaron Conole > + path); > + } > +#else > + ret = firmware_read(path, buf, bufsz); > +#endif > + } > + return ret; > +} > diff --git a/lib/eal/unix/meson.build b/lib/eal/unix/meson.build > index dc711b4240..e3ecd3e956 100644 > --- a/lib/eal/unix/meson.build > +++ b/lib/eal/unix/meson.build > @@ -5,5 +5,6 @@ sources += files( > 'eal_file.c', > 'eal_unix_memory.c', > 'eal_unix_timer.c', > + 'eal_firmware.c', > 'rte_thread.c', > ) > diff --git a/lib/eal/version.map b/lib/eal/version.map > index fe5c3dac98..2df65c6903 100644 > --- a/lib/eal/version.map > +++ b/lib/eal/version.map > @@ -428,6 +428,7 @@ EXPERIMENTAL { > INTERNAL { > global: > > + rte_firmware_read; > rte_mem_lock; > rte_mem_map; > rte_mem_page_size; > diff --git a/lib/eal/windows/eal.c b/lib/eal/windows/eal.c > index 8483f6b02c..6fe2bdd282 100644 > --- a/lib/eal/windows/eal.c > +++ b/lib/eal/windows/eal.c > @@ -21,6 +21,7 @@ > #include > #include > #include > +#include > > #include "eal_hugepages.h" > #include "eal_trace.h" > @@ -465,3 +466,11 @@ rte_vfio_container_dma_unmap(__rte_unused int container_fd, > { > return -1; > } > + > +int > +rte_firmware_read(__rte_unused const char *name, > + __rte_unused void **buf, > + __rte_unused size_t *bufsz) > +{ > + return -1; > +}