net/sfc/base: add buffer editing functions to boot config
authorRichard Houldsworth <rhouldsworth@solarflare.com>
Mon, 10 Sep 2018 09:33:17 +0000 (10:33 +0100)
committerFerruh Yigit <ferruh.yigit@intel.com>
Thu, 27 Sep 2018 23:41:02 +0000 (01:41 +0200)
Functions to process the DHCP option list format used by the expansion
ROM config buffers, to support extracting and updating of individual
options.
The initial use case is the driver presenting the global and per-PF
options as separate items, with the driver implementing the
synchronization of global options across the configuration buffers
for all PFs.

Signed-off-by: Richard Houldsworth <rhouldsworth@solarflare.com>
Signed-off-by: Andrew Rybchenko <arybchenko@solarflare.com>
drivers/net/sfc/base/efx.h
drivers/net/sfc/base/efx_annote.h
drivers/net/sfc/base/efx_bootcfg.c

index 099f9df..3c32277 100644 (file)
@@ -1662,6 +1662,87 @@ efx_bootcfg_write(
        __in_bcount(size)       uint8_t *data,
        __in                    size_t size);
 
+
+/*
+ * Processing routines for buffers arranged in the DHCP/BOOTP option format
+ * (see https://tools.ietf.org/html/rfc1533)
+ *
+ * Summarising the format: the buffer is a sequence of options. All options
+ * begin with a tag octet, which uniquely identifies the option.  Fixed-
+ * length options without data consist of only a tag octet.  Only options PAD
+ * (0) and END (255) are fixed length.  All other options are variable-length
+ * with a length octet following the tag octet.  The value of the length
+ * octet does not include the two octets specifying the tag and length.  The
+ * length octet is followed by "length" octets of data.
+ *
+ * Option data may be a sequence of sub-options in the same format. The data
+ * content of the encapsulating option is one or more encapsulated sub-options,
+ * with no terminating END tag is required.
+ *
+ * To be valid, the top-level sequence of options should be terminated by an
+ * END tag. The buffer should be padded with the PAD byte.
+ *
+ * When stored to NVRAM, the DHCP option format buffer is preceded by a
+ * checksum octet. The full buffer (including after the END tag) contributes
+ * to the checksum, hence the need to fill the buffer to the end with PAD.
+ */
+
+#define        EFX_DHCP_END ((uint8_t)0xff)
+#define        EFX_DHCP_PAD ((uint8_t)0)
+
+#define        EFX_DHCP_ENCAP_OPT(encapsulator, encapsulated) \
+  (uint16_t)(((encapsulator) << 8) | (encapsulated))
+
+extern __checkReturn           uint8_t
+efx_dhcp_csum(
+       __in_bcount(size)       uint8_t const *data,
+       __in                    size_t size);
+
+extern __checkReturn           efx_rc_t
+efx_dhcp_verify(
+       __in_bcount(size)       uint8_t const *data,
+       __in                    size_t size,
+       __out_opt               size_t *usedp);
+
+extern __checkReturn   efx_rc_t
+efx_dhcp_find_tag(
+       __in_bcount(buffer_length)      uint8_t *bufferp,
+       __in                            size_t buffer_length,
+       __in                            uint16_t opt,
+       __deref_out                     uint8_t **valuepp,
+       __out                           size_t *value_lengthp);
+
+extern __checkReturn   efx_rc_t
+efx_dhcp_find_end(
+       __in_bcount(buffer_length)      uint8_t *bufferp,
+       __in                            size_t buffer_length,
+       __deref_out                     uint8_t **endpp);
+
+
+extern __checkReturn   efx_rc_t
+efx_dhcp_delete_tag(
+       __inout_bcount(buffer_length)   uint8_t *bufferp,
+       __in                            size_t buffer_length,
+       __in                            uint16_t opt);
+
+extern __checkReturn   efx_rc_t
+efx_dhcp_add_tag(
+       __inout_bcount(buffer_length)   uint8_t *bufferp,
+       __in                            size_t buffer_length,
+       __in                            uint16_t opt,
+       __in_bcount_opt(value_length)   uint8_t *valuep,
+       __in                            size_t value_length);
+
+extern __checkReturn   efx_rc_t
+efx_dhcp_update_tag(
+       __inout_bcount(buffer_length)   uint8_t *bufferp,
+       __in                            size_t buffer_length,
+       __in                            uint16_t opt,
+       __in                            uint8_t *value_locationp,
+       __in_bcount_opt(value_length)   uint8_t *valuep,
+       __in                            size_t value_length);
+
+
 #endif /* EFSYS_OPT_BOOTCFG */
 
 #if EFSYS_OPT_IMAGE_LAYOUT
index 603260e..671aaed 100644 (file)
@@ -39,6 +39,7 @@
 #define        __out_bcount_part_opt(_n, _l)
 
 #define        __deref_out
+#define        __deref_inout
 
 #define        __inout
 #define        __inout_opt
index 715e18e..3b0401e 100644 (file)
 #define        BOOTCFG_PER_PF   0x800
 #define        BOOTCFG_PF_COUNT 16
 
-#define        DHCP_END ((uint8_t)0xff)
-#define        DHCP_PAD ((uint8_t)0)
+#define        DHCP_OPT_HAS_VALUE(opt) \
+       (((opt) > EFX_DHCP_PAD) && ((opt) < EFX_DHCP_END))
+
+#define        DHCP_MAX_VALUE 255
+
+#define        DHCP_ENCAPSULATOR(encap_opt) ((encap_opt) >> 8)
+#define        DHCP_ENCAPSULATED(encap_opt) ((encap_opt) & 0xff)
+#define        DHCP_IS_ENCAP_OPT(opt) DHCP_OPT_HAS_VALUE(DHCP_ENCAPSULATOR(opt))
+
+typedef struct efx_dhcp_tag_hdr_s {
+       uint8_t         tag;
+       uint8_t         length;
+} efx_dhcp_tag_hdr_t;
+
+/*
+ * Length calculations for tags with value field. PAD and END
+ * have a fixed length of 1, with no length or value field.
+ */
+#define        DHCP_FULL_TAG_LENGTH(hdr) \
+       (sizeof (efx_dhcp_tag_hdr_t) + (hdr)->length)
+
+#define        DHCP_NEXT_TAG(hdr) \
+       ((efx_dhcp_tag_hdr_t *)(((uint8_t *)(hdr)) + \
+       DHCP_FULL_TAG_LENGTH((hdr))))
+
+#define        DHCP_CALC_TAG_LENGTH(payload_len) \
+       ((payload_len) + sizeof (efx_dhcp_tag_hdr_t))
 
 
 /* Report the layout of bootcfg sectors in NVRAM partition. */
@@ -110,14 +135,11 @@ fail1:
 }
 
 
-static __checkReturn           uint8_t
-efx_bootcfg_csum(
-       __in                    efx_nic_t *enp,
+       __checkReturn           uint8_t
+efx_dhcp_csum(
        __in_bcount(size)       uint8_t const *data,
        __in                    size_t size)
 {
-       _NOTE(ARGUNUSED(enp))
-
        unsigned int pos;
        uint8_t checksum = 0;
 
@@ -126,9 +148,8 @@ efx_bootcfg_csum(
        return (checksum);
 }
 
-static __checkReturn           efx_rc_t
-efx_bootcfg_verify(
-       __in                    efx_nic_t *enp,
+       __checkReturn           efx_rc_t
+efx_dhcp_verify(
        __in_bcount(size)       uint8_t const *data,
        __in                    size_t size,
        __out_opt               size_t *usedp)
@@ -144,12 +165,12 @@ efx_bootcfg_verify(
 
                /* Consume tag */
                tag = data[offset];
-               if (tag == DHCP_END) {
+               if (tag == EFX_DHCP_END) {
                        offset++;
                        used = offset;
                        break;
                }
-               if (tag == DHCP_PAD) {
+               if (tag == EFX_DHCP_PAD) {
                        offset++;
                        continue;
                }
@@ -171,8 +192,8 @@ efx_bootcfg_verify(
                used = offset;
        }
 
-       /* Checksum the entire sector, including bytes after any DHCP_END */
-       if (efx_bootcfg_csum(enp, data, size) != 0) {
+       /* Checksum the entire sector, including bytes after any EFX_DHCP_END */
+       if (efx_dhcp_csum(data, size) != 0) {
                rc = EINVAL;
                goto fail3;
        }
@@ -192,6 +213,516 @@ fail1:
        return (rc);
 }
 
+/*
+ * Walk the entire tag set looking for option. The sought option may be
+ * encapsulated. ENOENT indicates the walk completed without finding the
+ * option. If we run out of buffer during the walk the function will return
+ * ENOSPC.
+ */
+static efx_rc_t
+efx_dhcp_walk_tags(
+       __deref_inout   uint8_t **tagpp,
+       __inout         size_t *buffer_sizep,
+       __in            uint16_t opt)
+{
+       efx_rc_t rc = 0;
+       boolean_t is_encap = B_FALSE;
+
+       if (DHCP_IS_ENCAP_OPT(opt)) {
+               /*
+                * Look for the encapsulator and, if found, limit ourselves
+                * to its payload. If it's not found then the entire tag
+                * cannot be found, so the encapsulated opt search is
+                * skipped.
+                */
+               rc = efx_dhcp_walk_tags(tagpp, buffer_sizep,
+                   DHCP_ENCAPSULATOR(opt));
+               if (rc == 0) {
+                       *buffer_sizep = ((efx_dhcp_tag_hdr_t *)*tagpp)->length;
+                       (*tagpp) += sizeof (efx_dhcp_tag_hdr_t);
+               }
+               opt = DHCP_ENCAPSULATED(opt);
+               is_encap = B_TRUE;
+       }
+
+       EFSYS_ASSERT(!DHCP_IS_ENCAP_OPT(opt));
+
+       while (rc == 0) {
+               size_t size;
+
+               if (*buffer_sizep == 0) {
+                       rc = ENOSPC;
+                       goto fail1;
+               }
+
+               if (DHCP_ENCAPSULATED(**tagpp) == opt)
+                       break;
+
+               if ((**tagpp) == EFX_DHCP_END) {
+                       rc = ENOENT;
+                       break;
+               } else if ((**tagpp) == EFX_DHCP_PAD) {
+                       size = 1;
+               } else {
+                       if (*buffer_sizep < sizeof (efx_dhcp_tag_hdr_t)) {
+                               rc = ENOSPC;
+                               goto fail2;
+                       }
+
+                       size =
+                           DHCP_FULL_TAG_LENGTH((efx_dhcp_tag_hdr_t *)*tagpp);
+               }
+
+               if (size > *buffer_sizep) {
+                       rc = ENOSPC;
+                       goto fail3;
+               }
+
+               (*tagpp) += size;
+               (*buffer_sizep) -= size;
+
+               if ((*buffer_sizep == 0) && is_encap) {
+                       /* Search within encapulator tag finished */
+                       rc = ENOENT;
+                       break;
+               }
+       }
+
+       /*
+        * Returns 0 if found otherwise ENOENT indicating search finished
+        * correctly
+        */
+       return (rc);
+
+fail3:
+       EFSYS_PROBE(fail3);
+fail2:
+       EFSYS_PROBE(fail2);
+fail1:
+       EFSYS_PROBE1(fail1, efx_rc_t, rc);
+
+       return (rc);
+}
+
+/*
+ * Locate value buffer for option in the given buffer.
+ * Returns 0 if found, ENOENT indicating search finished
+ * correctly, otherwise search failed before completion.
+ */
+       __checkReturn   efx_rc_t
+efx_dhcp_find_tag(
+       __in_bcount(buffer_length)      uint8_t *bufferp,
+       __in                            size_t buffer_length,
+       __in                            uint16_t opt,
+       __deref_out                     uint8_t **valuepp,
+       __out                           size_t *value_lengthp)
+{
+       efx_rc_t rc;
+       uint8_t *tagp = bufferp;
+       size_t len = buffer_length;
+
+       rc = efx_dhcp_walk_tags(&tagp, &len, opt);
+       if (rc == 0) {
+               efx_dhcp_tag_hdr_t *hdrp;
+
+               hdrp = (efx_dhcp_tag_hdr_t *)tagp;
+               *valuepp = (uint8_t *)(&hdrp[1]);
+               *value_lengthp = hdrp->length;
+       } else if (rc != ENOENT) {
+               goto fail1;
+       }
+
+       return (rc);
+
+fail1:
+       EFSYS_PROBE1(fail1, efx_rc_t, rc);
+
+       return (rc);
+}
+
+/*
+ * Locate the end tag in the given buffer.
+ * Returns 0 if found, ENOENT indicating search finished
+ * correctly but end tag was not found; otherwise search
+ * failed before completion.
+ */
+       __checkReturn   efx_rc_t
+efx_dhcp_find_end(
+       __in_bcount(buffer_length)      uint8_t *bufferp,
+       __in                            size_t buffer_length,
+       __deref_out                     uint8_t **endpp)
+{
+       efx_rc_t rc;
+       uint8_t *endp = bufferp;
+       size_t len = buffer_length;
+
+       rc = efx_dhcp_walk_tags(&endp, &len, EFX_DHCP_END);
+       if (rc == 0)
+               *endpp = endp;
+       else if (rc != ENOENT)
+               goto fail1;
+
+       return (rc);
+
+fail1:
+       EFSYS_PROBE1(fail1, efx_rc_t, rc);
+
+       return (rc);
+}
+
+
+/*
+ * Delete the given tag from anywhere in the buffer. Copes with
+ * encapsulated tags, and updates or deletes the encapsulating opt as
+ * necessary.
+ */
+       __checkReturn   efx_rc_t
+efx_dhcp_delete_tag(
+       __inout_bcount(buffer_length)   uint8_t *bufferp,
+       __in                            size_t buffer_length,
+       __in                            uint16_t opt)
+{
+       efx_rc_t rc;
+       efx_dhcp_tag_hdr_t *hdrp;
+       size_t len;
+       uint8_t *startp;
+       uint8_t *endp;
+
+       len = buffer_length;
+       startp = bufferp;
+
+       if (!DHCP_OPT_HAS_VALUE(DHCP_ENCAPSULATED(opt))) {
+               rc = EINVAL;
+               goto fail1;
+       }
+
+       rc = efx_dhcp_walk_tags(&startp, &len, opt);
+       if (rc != 0)
+               goto fail1;
+
+       hdrp = (efx_dhcp_tag_hdr_t *)startp;
+
+       if (DHCP_IS_ENCAP_OPT(opt)) {
+               uint8_t tag_length = DHCP_FULL_TAG_LENGTH(hdrp);
+               uint8_t *encapp = bufferp;
+               efx_dhcp_tag_hdr_t *encap_hdrp;
+
+               len = buffer_length;
+               rc = efx_dhcp_walk_tags(&encapp, &len,
+                   DHCP_ENCAPSULATOR(opt));
+               if (rc != 0)
+                       goto fail2;
+
+               encap_hdrp = (efx_dhcp_tag_hdr_t *)encapp;
+               if (encap_hdrp->length > tag_length) {
+                       encap_hdrp->length = (uint8_t)(
+                           (size_t)encap_hdrp->length - tag_length);
+               } else {
+                       /* delete the encapsulating tag */
+                       hdrp = encap_hdrp;
+               }
+       }
+
+       startp = (uint8_t *)hdrp;
+       endp = (uint8_t *)DHCP_NEXT_TAG(hdrp);
+
+       if (startp < bufferp) {
+               rc = EINVAL;
+               goto fail3;
+       }
+
+       if (endp > &bufferp[buffer_length]) {
+               rc = EINVAL;
+               goto fail4;
+       }
+
+       memmove(startp, endp,
+               buffer_length - (endp - bufferp));
+
+       return (0);
+
+fail4:
+       EFSYS_PROBE(fail4);
+fail3:
+       EFSYS_PROBE(fail3);
+fail2:
+       EFSYS_PROBE(fail2);
+fail1:
+       EFSYS_PROBE1(fail1, efx_rc_t, rc);
+
+       return (rc);
+}
+
+/*
+ * Write the tag header into write_pointp and optionally copies the payload
+ * into the space following.
+ */
+static void
+efx_dhcp_write_tag(
+       __in            uint8_t *write_pointp,
+       __in            uint16_t opt,
+       __in_bcount_opt(value_length)
+                       uint8_t *valuep,
+       __in            size_t value_length)
+{
+       efx_dhcp_tag_hdr_t *hdrp = (efx_dhcp_tag_hdr_t *)write_pointp;
+       hdrp->tag = DHCP_ENCAPSULATED(opt);
+       hdrp->length = (uint8_t)value_length;
+       if ((value_length > 0) && (valuep != NULL))
+               memcpy(&hdrp[1], valuep, value_length);
+}
+
+/*
+ * Add the given tag to the end of the buffer. Copes with creating an
+ * encapsulated tag, and updates or creates the encapsulating opt as
+ * necessary.
+ */
+       __checkReturn   efx_rc_t
+efx_dhcp_add_tag(
+       __inout_bcount(buffer_length)   uint8_t *bufferp,
+       __in                            size_t buffer_length,
+       __in                            uint16_t opt,
+       __in_bcount_opt(value_length)   uint8_t *valuep,
+       __in                            size_t value_length)
+{
+       efx_rc_t rc;
+       efx_dhcp_tag_hdr_t *encap_hdrp = NULL;
+       uint8_t *insert_pointp = NULL;
+       uint8_t *endp;
+       size_t available_space;
+       size_t added_length;
+       size_t search_size;
+       uint8_t *searchp;
+
+       if (!DHCP_OPT_HAS_VALUE(DHCP_ENCAPSULATED(opt))) {
+               rc = EINVAL;
+               goto fail1;
+       }
+
+       if (value_length > DHCP_MAX_VALUE) {
+               rc = EINVAL;
+               goto fail2;
+       }
+
+       if ((value_length > 0) && (valuep == NULL)) {
+               rc = EINVAL;
+               goto fail3;
+       }
+
+       endp = bufferp;
+       available_space = buffer_length;
+       rc = efx_dhcp_walk_tags(&endp, &available_space, EFX_DHCP_END);
+       if (rc != 0)
+               goto fail4;
+
+       searchp = bufferp;
+       search_size = buffer_length;
+       if (DHCP_IS_ENCAP_OPT(opt)) {
+               rc = efx_dhcp_walk_tags(&searchp, &search_size,
+                   DHCP_ENCAPSULATOR(opt));
+               if (rc == 0) {
+                       encap_hdrp = (efx_dhcp_tag_hdr_t *)searchp;
+
+                       /* Check encapsulated tag is not present */
+                       search_size = encap_hdrp->length;
+                       rc = efx_dhcp_walk_tags(&searchp, &search_size,
+                           opt);
+                       if (rc != ENOENT) {
+                               rc = EINVAL;
+                               goto fail5;
+                       }
+
+                       /* Check encapsulator will not overflow */
+                       if (((size_t)encap_hdrp->length +
+                           DHCP_CALC_TAG_LENGTH(value_length)) >
+                           DHCP_MAX_VALUE) {
+                               rc = E2BIG;
+                               goto fail6;
+                       }
+
+                       /* Insert at start of existing encapsulator */
+                       insert_pointp = (uint8_t *)&encap_hdrp[1];
+                       opt = DHCP_ENCAPSULATED(opt);
+               } else if (rc == ENOENT) {
+                       encap_hdrp = NULL;
+               } else {
+                       goto fail7;
+               }
+       } else {
+               /* Check unencapsulated tag is not present */
+               rc = efx_dhcp_walk_tags(&searchp, &search_size,
+                   opt);
+               if (rc != ENOENT) {
+                       rc = EINVAL;
+                       goto fail8;
+               }
+       }
+
+       if (insert_pointp == NULL) {
+               /* Insert at end of existing tags */
+               insert_pointp = endp;
+       }
+
+       /* Includes the new encapsulator tag hdr if required */
+       added_length = DHCP_CALC_TAG_LENGTH(value_length) +
+           (DHCP_IS_ENCAP_OPT(opt) ? sizeof (efx_dhcp_tag_hdr_t) : 0);
+
+       if (available_space <= added_length) {
+               rc = ENOMEM;
+               goto fail9;
+       }
+
+       memmove(insert_pointp + added_length, insert_pointp,
+           available_space - added_length);
+
+       if (DHCP_IS_ENCAP_OPT(opt)) {
+               /* Create new encapsulator header */
+               added_length -= sizeof (efx_dhcp_tag_hdr_t);
+               efx_dhcp_write_tag(insert_pointp,
+                   DHCP_ENCAPSULATOR(opt), NULL, added_length);
+               insert_pointp += sizeof (efx_dhcp_tag_hdr_t);
+       } else if (encap_hdrp)
+               /* Modify existing encapsulator header */
+               encap_hdrp->length +=
+                   ((uint8_t)DHCP_CALC_TAG_LENGTH(value_length));
+
+       efx_dhcp_write_tag(insert_pointp, opt, valuep, value_length);
+
+       return (0);
+
+fail9:
+       EFSYS_PROBE(fail9);
+fail8:
+       EFSYS_PROBE(fail8);
+fail7:
+       EFSYS_PROBE(fail7);
+fail6:
+       EFSYS_PROBE(fail6);
+fail5:
+       EFSYS_PROBE(fail5);
+fail4:
+       EFSYS_PROBE(fail4);
+fail3:
+       EFSYS_PROBE(fail3);
+fail2:
+       EFSYS_PROBE(fail2);
+fail1:
+       EFSYS_PROBE1(fail1, efx_rc_t, rc);
+
+       return (rc);
+}
+
+/*
+ * Update an existing tag to the new value. Copes with encapsulated
+ * tags, and updates the encapsulating opt as necessary.
+ */
+       __checkReturn   efx_rc_t
+efx_dhcp_update_tag(
+       __inout_bcount(buffer_length)   uint8_t *bufferp,
+       __in                            size_t buffer_length,
+       __in                            uint16_t opt,
+       __in                            uint8_t *value_locationp,
+       __in_bcount_opt(value_length)   uint8_t *valuep,
+       __in                            size_t value_length)
+{
+       efx_rc_t rc;
+       uint8_t *write_pointp = value_locationp - sizeof (efx_dhcp_tag_hdr_t);
+       efx_dhcp_tag_hdr_t *hdrp = (efx_dhcp_tag_hdr_t *)write_pointp;
+       efx_dhcp_tag_hdr_t *encap_hdrp = NULL;
+       size_t old_length;
+
+       if (!DHCP_OPT_HAS_VALUE(DHCP_ENCAPSULATED(opt))) {
+               rc = EINVAL;
+               goto fail1;
+       }
+
+       if (value_length > DHCP_MAX_VALUE) {
+               rc = EINVAL;
+               goto fail2;
+       }
+
+       if ((value_length > 0) && (valuep == NULL)) {
+               rc = EINVAL;
+               goto fail3;
+       }
+
+       old_length = hdrp->length;
+
+       if (old_length < value_length) {
+               uint8_t *endp = bufferp;
+               size_t available_space = buffer_length;
+
+               rc = efx_dhcp_walk_tags(&endp, &available_space,
+                   EFX_DHCP_END);
+               if (rc != 0)
+                       goto fail4;
+
+               if (available_space < (value_length - old_length)) {
+                       rc = EINVAL;
+                       goto fail5;
+               }
+       }
+
+       if (DHCP_IS_ENCAP_OPT(opt)) {
+               uint8_t *encapp = bufferp;
+               size_t following_encap = buffer_length;
+               size_t new_length;
+
+               rc = efx_dhcp_walk_tags(&encapp, &following_encap,
+                   DHCP_ENCAPSULATOR(opt));
+               if (rc != 0)
+                       goto fail6;
+
+               encap_hdrp = (efx_dhcp_tag_hdr_t *)encapp;
+
+               new_length = ((size_t)encap_hdrp->length +
+                   value_length - old_length);
+               /* Check encapsulator will not overflow */
+               if (new_length > DHCP_MAX_VALUE) {
+                       rc = E2BIG;
+                       goto fail7;
+               }
+
+               encap_hdrp->length = (uint8_t)new_length;
+       }
+
+       /*
+        * Move the following data up/down to accomodate the new payload
+        * length.
+        */
+       if (old_length != value_length) {
+               uint8_t *destp = (uint8_t *)DHCP_NEXT_TAG(hdrp) +
+                   value_length - old_length;
+               size_t count = &bufferp[buffer_length] -
+                   (uint8_t *)DHCP_NEXT_TAG(hdrp);
+
+               memmove(destp, DHCP_NEXT_TAG(hdrp), count);
+       }
+
+       EFSYS_ASSERT(hdrp->tag == DHCP_ENCAPSULATED(opt));
+       efx_dhcp_write_tag(write_pointp, opt, valuep, value_length);
+
+       return (0);
+
+fail7:
+       EFSYS_PROBE(fail7);
+fail6:
+       EFSYS_PROBE(fail6);
+fail5:
+       EFSYS_PROBE(fail5);
+fail4:
+       EFSYS_PROBE(fail4);
+fail3:
+       EFSYS_PROBE(fail3);
+fail2:
+       EFSYS_PROBE(fail2);
+fail1:
+       EFSYS_PROBE1(fail1, efx_rc_t, rc);
+
+       return (rc);
+}
+
+
 /*
  * Copy bootcfg sector data to a target buffer which may differ in size.
  * Optionally corrects format errors in source buffer.
@@ -206,17 +737,19 @@ efx_bootcfg_copy_sector(
        __in                    size_t data_size,
        __in                    boolean_t handle_format_errors)
 {
+       _NOTE(ARGUNUSED(enp))
+
        size_t used_bytes;
        efx_rc_t rc;
 
-       /* Minimum buffer is checksum byte and DHCP_END terminator */
+       /* Minimum buffer is checksum byte and EFX_DHCP_END terminator */
        if (data_size < 2) {
                rc = ENOSPC;
                goto fail1;
        }
 
        /* Verify that the area is correctly formatted and checksummed */
-       rc = efx_bootcfg_verify(enp, sector, sector_length,
+       rc = efx_dhcp_verify(sector, sector_length,
                                    &used_bytes);
 
        if (!handle_format_errors) {
@@ -224,8 +757,8 @@ efx_bootcfg_copy_sector(
                        goto fail2;
 
                if ((used_bytes < 2) ||
-                   (sector[used_bytes - 1] != DHCP_END)) {
-                       /* Block too short, or DHCP_END missing */
+                   (sector[used_bytes - 1] != EFX_DHCP_END)) {
+                       /* Block too short, or EFX_DHCP_END missing */
                        rc = ENOENT;
                        goto fail3;
                }
@@ -234,24 +767,24 @@ efx_bootcfg_copy_sector(
        /* Synthesize empty format on verification failure */
        if (rc != 0 || used_bytes == 0) {
                sector[0] = 0;
-               sector[1] = DHCP_END;
+               sector[1] = EFX_DHCP_END;
                used_bytes = 2;
        }
-       EFSYS_ASSERT(used_bytes >= 2);  /* checksum and DHCP_END */
+       EFSYS_ASSERT(used_bytes >= 2);  /* checksum and EFX_DHCP_END */
        EFSYS_ASSERT(used_bytes <= sector_length);
        EFSYS_ASSERT(sector_length >= 2);
 
        /*
-        * Legacy bootcfg sectors don't terminate with a DHCP_END character.
-        * Modify the returned payload so it does.
+        * Legacy bootcfg sectors don't terminate with an EFX_DHCP_END
+        * character. Modify the returned payload so it does.
         * Reinitialise the sector if there isn't room for the character.
         */
-       if (sector[used_bytes - 1] != DHCP_END) {
+       if (sector[used_bytes - 1] != EFX_DHCP_END) {
                if (used_bytes >= sector_length) {
                        sector[0] = 0;
                        used_bytes = 1;
                }
-               sector[used_bytes] = DHCP_END;
+               sector[used_bytes] = EFX_DHCP_END;
                ++used_bytes;
        }
 
@@ -274,10 +807,11 @@ efx_bootcfg_copy_sector(
                (void) memset(data + used_bytes, 0, data_size - used_bytes);
 
        /*
-        * The checksum includes trailing data after any DHCP_END character,
-        * which we've just modified (by truncation or appending DHCP_END).
+        * The checksum includes trailing data after any EFX_DHCP_END
+        * character, which we've just modified (by truncation or appending
+        * EFX_DHCP_END).
         */
-       data[0] -= efx_bootcfg_csum(enp, data, data_size);
+       data[0] -= efx_dhcp_csum(data, data_size);
 
        return (0);
 
@@ -307,7 +841,7 @@ efx_bootcfg_read(
        efx_rc_t rc;
        uint32_t sector_number;
 
-       /* Minimum buffer is checksum byte and DHCP_END terminator */
+       /* Minimum buffer is checksum byte and EFX_DHCP_END terminator */
        if (size < 2) {
                rc = ENOSPC;
                goto fail1;
@@ -343,10 +877,10 @@ efx_bootcfg_read(
        }
 
        /*
-        * We need to read the entire BOOTCFG sector to ensure we read all the
-        * tags, because legacy bootcfg sectors are not guaranteed to end with
-        * a DHCP_END character. If the user hasn't supplied a sufficiently
-        * large buffer then use our own buffer.
+        * We need to read the entire BOOTCFG sector to ensure we read all
+        * tags, because legacy bootcfg sectors are not guaranteed to end
+        * with an EFX_DHCP_END character. If the user hasn't supplied a
+        * sufficiently large buffer then use our own buffer.
         */
        if (sector_length > size) {
                EFSYS_KMEM_ALLOC(enp->en_esip, sector_length, payload);
@@ -370,28 +904,29 @@ efx_bootcfg_read(
                goto fail9;
 
        /* Verify that the area is correctly formatted and checksummed */
-       rc = efx_bootcfg_verify(enp, payload, sector_length,
+       rc = efx_dhcp_verify(payload, sector_length,
            &used_bytes);
        if (rc != 0 || used_bytes == 0) {
                payload[0] = 0;
-               payload[1] = DHCP_END;
+               payload[1] = EFX_DHCP_END;
                used_bytes = 2;
        }
 
-       EFSYS_ASSERT(used_bytes >= 2);  /* checksum and DHCP_END */
+       EFSYS_ASSERT(used_bytes >= 2);  /* checksum and EFX_DHCP_END */
        EFSYS_ASSERT(used_bytes <= sector_length);
 
        /*
-        * Legacy bootcfg sectors don't terminate with a DHCP_END character.
-        * Modify the returned payload so it does. BOOTCFG_MAX_SIZE is by
-        * definition large enough for any valid (per-port) bootcfg sector,
-        * so reinitialise the sector if there isn't room for the character.
+        * Legacy bootcfg sectors don't terminate with an EFX_DHCP_END
+        * character. Modify the returned payload so it does.
+        * BOOTCFG_MAX_SIZE is by definition large enough for any valid
+        * (per-port) bootcfg sector, so reinitialise the sector if there
+        * isn't room for the character.
         */
-       if (payload[used_bytes - 1] != DHCP_END) {
+       if (payload[used_bytes - 1] != EFX_DHCP_END) {
                if (used_bytes >= sector_length)
                        used_bytes = 1;
 
-               payload[used_bytes] = DHCP_END;
+               payload[used_bytes] = EFX_DHCP_END;
                ++used_bytes;
        }
 
@@ -417,10 +952,10 @@ efx_bootcfg_read(
                (void) memset(data + used_bytes, 0, size - used_bytes);
 
        /*
-        * The checksum includes trailing data after any DHCP_END character,
-        * which we've just modified (by truncation or appending DHCP_END).
+        * The checksum includes trailing data after any EFX_DHCP_END character,
+        * which we've just modified (by truncation or appending EFX_DHCP_END).
         */
-       data[0] -= efx_bootcfg_csum(enp, data, size);
+       data[0] -= efx_dhcp_csum(data, size);
 
        return (0);
 
@@ -490,12 +1025,16 @@ efx_bootcfg_write(
                goto fail3;
        }
 
-       if ((rc = efx_bootcfg_verify(enp, data, size, &used_bytes)) != 0)
+       if ((rc = efx_dhcp_verify(data, size, &used_bytes)) != 0)
                goto fail4;
 
-       /* The caller *must* terminate their block with a DHCP_END character */
-       if ((used_bytes < 2) || ((uint8_t)data[used_bytes - 1] != DHCP_END)) {
-               /* Block too short or DHCP_END missing */
+       /*
+        * The caller *must* terminate their block with a EFX_DHCP_END
+        * character
+        */
+       if ((used_bytes < 2) || ((uint8_t)data[used_bytes - 1] !=
+           EFX_DHCP_END)) {
+               /* Block too short or EFX_DHCP_END missing */
                rc = ENOENT;
                goto fail5;
        }
@@ -528,13 +1067,13 @@ efx_bootcfg_write(
                goto fail9;
 
        /*
-        * Insert the BOOTCFG sector into the partition, Zero out all data after
-        * the DHCP_END tag, and adjust the checksum.
+        * Insert the BOOTCFG sector into the partition, Zero out all data
+        * after the EFX_DHCP_END tag, and adjust the checksum.
         */
        (void) memset(partn_data + sector_offset, 0x0, sector_length);
        (void) memcpy(partn_data + sector_offset, data, used_bytes);
 
-       checksum = efx_bootcfg_csum(enp, data, used_bytes);
+       checksum = efx_dhcp_csum(data, used_bytes);
        partn_data[sector_offset] -= checksum;
 
        if ((rc = efx_nvram_erase(enp, EFX_NVRAM_BOOTROM_CFG)) != 0)