Download raw body.
iwx: support pnvm data in firmware image
On 2026 Mar 03 (Tue) at 15:25:49 +0100 (+0100), Stefan Sperling wrote:
:Newer firmware images for BZ devices have a segment which contains
:data that was previously distributed in separate .pnvm files.
:
:If the firmware image contains pnvm data we must use it instead of
:the external file. The external file might be incompatible.
:
:ok?
OK
:
:diff /usr/src
:path + /usr/src
:commit - c58e64aeb4e092373382ec4900136445f091367c
:blob - da9e3d2d42cdbb343313ea89ddfa6a89e1d39a31
:file + sys/dev/pci/if_iwx.c
:--- sys/dev/pci/if_iwx.c
:+++ sys/dev/pci/if_iwx.c
:@@ -1183,6 +1183,9 @@ iwx_fw_info_free(struct iwx_fw_info *fw)
: free(fw->iml, M_DEVBUF, fw->iml_len);
: fw->iml = NULL;
: fw->iml_len = 0;
:+ free(fw->pnvm, M_DEVBUF, fw->pnvm_len);
:+ fw->pnvm = NULL;
:+ fw->pnvm_len = 0;
: }
:
: #define IWX_FW_ADDR_CACHE_CONTROL 0xC0000000
:@@ -1550,6 +1553,19 @@ iwx_read_firmware(struct iwx_softc *sc)
: case IWX_UCODE_TLV_FW_RECOVERY_INFO:
: break;
:
:+ case IWX_UCODE_TLV_PNVM_DATA:
:+ if (fw->pnvm != NULL)
:+ break;
:+ fw->pnvm = malloc(tlv_len, M_DEVBUF,
:+ M_WAITOK | M_CANFAIL);
:+ if (fw->pnvm == NULL) {
:+ err = ENOMEM;
:+ goto parse_out;
:+ }
:+ memcpy(fw->pnvm, tlv_data, tlv_len);
:+ fw->pnvm_len = tlv_len;
:+ break;
:+
: case IWX_UCODE_TLV_FW_FSEQ_VERSION:
: case IWX_UCODE_TLV_PHY_INTEGRATION_VERSION:
: case IWX_UCODE_TLV_FW_NUM_STATIONS:
:@@ -4294,6 +4310,7 @@ iwx_load_pnvm(struct iwx_softc *sc)
: int s, err = 0;
: u_char *pnvm_data = NULL;
: size_t pnvm_size = 0;
:+ struct iwx_fw_info *fw = &sc->sc_fw;
:
: if (sc->sc_sku_id[0] == 0 &&
: sc->sc_sku_id[1] == 0 &&
:@@ -4302,18 +4319,28 @@ iwx_load_pnvm(struct iwx_softc *sc)
:
: if (sc->sc_pnvm_name) {
: if (sc->pnvm_dma.vaddr == NULL) {
:- err = loadfirmware(sc->sc_pnvm_name,
:- &pnvm_data, &pnvm_size);
:- if (err) {
:- printf("%s: could not read %s (error %d)\n",
:- DEVNAME(sc), sc->sc_pnvm_name, err);
:- return err;
:- }
:+ /* Prefer PNVM data embedded in firmware image. */
:+ if (fw->pnvm) {
:+ err = iwx_pnvm_parse(sc, fw->pnvm,
:+ fw->pnvm_len);
:+ if (err && err != ENOENT)
:+ return err;
:+ } else {
:+ err = loadfirmware(sc->sc_pnvm_name,
:+ &pnvm_data, &pnvm_size);
:+ if (err) {
:+ printf("%s: could not read %s "
:+ "(error %d)\n",
:+ DEVNAME(sc), sc->sc_pnvm_name,
:+ err);
:+ return err;
:+ }
:
:- err = iwx_pnvm_parse(sc, pnvm_data, pnvm_size);
:- if (err && err != ENOENT) {
:- free(pnvm_data, M_DEVBUF, pnvm_size);
:- return err;
:+ err = iwx_pnvm_parse(sc, pnvm_data, pnvm_size);
:+ if (err && err != ENOENT) {
:+ free(pnvm_data, M_DEVBUF, pnvm_size);
:+ return err;
:+ }
: }
: } else
: iwx_ctxt_info_gen3_set_pnvm(sc);
:commit - c58e64aeb4e092373382ec4900136445f091367c
:blob - 1af2759f445d0b05c35efd4ec8ff9ddab3ca419c
:file + sys/dev/pci/if_iwxreg.h
:--- sys/dev/pci/if_iwxreg.h
:+++ sys/dev/pci/if_iwxreg.h
:@@ -1584,6 +1584,7 @@ struct iwx_ucode_header {
: #define IWX_UCODE_TLV_SEC_TABLE_ADDR 66
: #define IWX_UCODE_TLV_D3_KEK_KCK_ADDR 67
: #define IWX_UCODE_TLV_CURRENT_PC 68
:+#define IWX_UCODE_TLV_PNVM_DATA 74
:
: #define IWX_UCODE_TLV_CONST_BASE 0x100
: #define IWX_UCODE_TLV_FW_NUM_STATIONS (IWX_UCODE_TLV_CONST_BASE + 0)
:commit - c58e64aeb4e092373382ec4900136445f091367c
:blob - 7be82818bc54423e510492e7b7e8974a0f63000d
:file + sys/dev/pci/if_iwxvar.h
:--- sys/dev/pci/if_iwxvar.h
:+++ sys/dev/pci/if_iwxvar.h
:@@ -173,6 +173,13 @@ struct iwx_fw_info {
: /* Copy of firmware image loader found in file. */
: uint8_t *iml;
: size_t iml_len;
:+
:+ /*
:+ * Copy of PNVM image found in file.
:+ * Used in preference to external .pnvm file if present.
:+ */
:+ uint8_t *pnvm;
:+ size_t pnvm_len;
: };
:
: struct iwx_nvm_data {
:
iwx: support pnvm data in firmware image