get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

GET /api/patches/44493/?format=api
HTTP 200 OK
Allow: GET, PUT, PATCH, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept

{
    "id": 44493,
    "url": "http://patches.dpdk.org/api/patches/44493/?format=api",
    "web_url": "http://patches.dpdk.org/project/dpdk/patch/1536572016-18134-19-git-send-email-arybchenko@solarflare.com/",
    "project": {
        "id": 1,
        "url": "http://patches.dpdk.org/api/projects/1/?format=api",
        "name": "DPDK",
        "link_name": "dpdk",
        "list_id": "dev.dpdk.org",
        "list_email": "dev@dpdk.org",
        "web_url": "http://core.dpdk.org",
        "scm_url": "git://dpdk.org/dpdk",
        "webscm_url": "http://git.dpdk.org/dpdk",
        "list_archive_url": "https://inbox.dpdk.org/dev",
        "list_archive_url_format": "https://inbox.dpdk.org/dev/{}",
        "commit_url_format": ""
    },
    "msgid": "<1536572016-18134-19-git-send-email-arybchenko@solarflare.com>",
    "list_archive_url": "https://inbox.dpdk.org/dev/1536572016-18134-19-git-send-email-arybchenko@solarflare.com",
    "date": "2018-09-10T09:33:17",
    "name": "[18/37] net/sfc/base: add buffer editing functions to boot config",
    "commit_ref": null,
    "pull_url": null,
    "state": "accepted",
    "archived": true,
    "hash": "78c340869f6b0c87f3f0e84e650d299c955b176f",
    "submitter": {
        "id": 607,
        "url": "http://patches.dpdk.org/api/people/607/?format=api",
        "name": "Andrew Rybchenko",
        "email": "arybchenko@solarflare.com"
    },
    "delegate": {
        "id": 319,
        "url": "http://patches.dpdk.org/api/users/319/?format=api",
        "username": "fyigit",
        "first_name": "Ferruh",
        "last_name": "Yigit",
        "email": "ferruh.yigit@amd.com"
    },
    "mbox": "http://patches.dpdk.org/project/dpdk/patch/1536572016-18134-19-git-send-email-arybchenko@solarflare.com/mbox/",
    "series": [
        {
            "id": 1244,
            "url": "http://patches.dpdk.org/api/series/1244/?format=api",
            "web_url": "http://patches.dpdk.org/project/dpdk/list/?series=1244",
            "date": "2018-09-10T09:33:01",
            "name": "net/sfc: update base driver",
            "version": 1,
            "mbox": "http://patches.dpdk.org/series/1244/mbox/"
        }
    ],
    "comments": "http://patches.dpdk.org/api/patches/44493/comments/",
    "check": "warning",
    "checks": "http://patches.dpdk.org/api/patches/44493/checks/",
    "tags": {},
    "related": [],
    "headers": {
        "Return-Path": "<dev-bounces@dpdk.org>",
        "X-Original-To": "patchwork@dpdk.org",
        "Delivered-To": "patchwork@dpdk.org",
        "Received": [
            "from [92.243.14.124] (localhost [127.0.0.1])\n\tby dpdk.org (Postfix) with ESMTP id A2BF48D88;\n\tMon, 10 Sep 2018 11:34:36 +0200 (CEST)",
            "from dispatch1-us1.ppe-hosted.com (dispatch1-us1.ppe-hosted.com\n\t[67.231.154.164]) by dpdk.org (Postfix) with ESMTP id AB6514C93\n\tfor <dev@dpdk.org>; Mon, 10 Sep 2018 11:33:53 +0200 (CEST)",
            "from webmail.solarflare.com (webmail.solarflare.com\n\t[12.187.104.26])\n\t(using TLSv1.2 with cipher ECDHE-RSA-AES256-SHA384 (256/256 bits))\n\t(No client certificate requested)\n\tby mx1-us1.ppe-hosted.com (Proofpoint Essentials ESMTP Server) with\n\tESMTPS id\n\tA0CDE780067 for <dev@dpdk.org>; Mon, 10 Sep 2018 09:33:52 +0000 (UTC)",
            "from ocex03.SolarFlarecom.com (10.20.40.36) by\n\tocex03.SolarFlarecom.com (10.20.40.36) with Microsoft SMTP Server\n\t(TLS) id 15.0.1395.4; Mon, 10 Sep 2018 02:33:48 -0700",
            "from opal.uk.solarflarecom.com (10.17.10.1) by\n\tocex03.SolarFlarecom.com (10.20.40.36) with Microsoft SMTP Server\n\t(TLS) id\n\t15.0.1395.4 via Frontend Transport; Mon, 10 Sep 2018 02:33:47 -0700",
            "from ukv-loginhost.uk.solarflarecom.com\n\t(ukv-loginhost.uk.solarflarecom.com [10.17.10.39])\n\tby opal.uk.solarflarecom.com (8.13.8/8.13.8) with ESMTP id\n\tw8A9XkeF023816; Mon, 10 Sep 2018 10:33:46 +0100",
            "from ukv-loginhost.uk.solarflarecom.com (localhost [127.0.0.1])\n\tby ukv-loginhost.uk.solarflarecom.com (Postfix) with ESMTP id\n\t0A5271626D1; Mon, 10 Sep 2018 10:33:46 +0100 (BST)"
        ],
        "X-Virus-Scanned": "Proofpoint Essentials engine",
        "From": "Andrew Rybchenko <arybchenko@solarflare.com>",
        "To": "<dev@dpdk.org>",
        "CC": "Richard Houldsworth <rhouldsworth@solarflare.com>",
        "Date": "Mon, 10 Sep 2018 10:33:17 +0100",
        "Message-ID": "<1536572016-18134-19-git-send-email-arybchenko@solarflare.com>",
        "X-Mailer": "git-send-email 1.8.3.1",
        "In-Reply-To": "<1536572016-18134-1-git-send-email-arybchenko@solarflare.com>",
        "References": "<1536572016-18134-1-git-send-email-arybchenko@solarflare.com>",
        "MIME-Version": "1.0",
        "Content-Type": "text/plain",
        "X-TM-AS-Product-Ver": "SMEX-12.5.0.1300-8.5.1010-24084.005",
        "X-TM-AS-Result": "No-10.304700-4.000000-10",
        "X-TMASE-MatchedRID": "6DvbVDSC/YWKbEHmVe3v3tdS6ZXIzU+eUAjrAJWsTe9tw+n+iKWyyHSm\n\tfwsFCkmdUHpA06mHFJtOMEQFWdYpZF+bIMgmNlCEH5YQyOg71ZZMkOX0UoduuUUNHQAoZf5cwnR\n\tzmxyXmk29UKhaaESj16EGFSo8CmlpPRPlAEQGtsXr/EBmiNuXt1+iEcKpKdpuSwcZtVb90bDAkt\n\tgDJtZ0AvPsTNYSi0psvlkLQCaKrTwOiz2mIwkG2Z1v5WrnSRXhVPmKrQFPhdlcKZwALwMGs2WWd\n\t1VBI96H5mqa5dNEJvdQS5VksOv9rRjaok59OjLpV96W6JwvGvdYN1akkye0qAqiCYa6w8tvLrUf\n\tzd/4z1kVvqM4RwhxWjO2fDZrH5Jy3lljvljtNt5VTfJWlqPdDP+UEb65dgmQBg19+jd1OqBlvhC\n\tcj7Gqvqe17iS7IhirlhEPkSRcxng19klrZHXStsnlbo5l7mGFZDlQswHUwh/j+yfWw+4UlD8fil\n\tvi6fr9Myl0Az/H1lD6eiBFjkywYtf6NZodn93nOJ5fBtuQzZK4IRKvHvCWchQLE16MmfDL29lME\n\t455sKIoaCjpMKQrvTnaMJxIm3pQQhpfp2AqlqlIOSHptb5txwtMFGDzaQxa/zIkW73uAA5/u66K\n\tv4HI7mJCd+Hgxis2gZL8fcHL9s9haYhpKJchaKTfLKfi4+0tfS0Ip2eEHnz3IzXlXlpamPoLR4+\n\tzsDTtCx9qoxmS2x3I9bAGss7LBvEexydp3hzOowD614myjADXYBpPQPonjQ==",
        "X-TM-AS-User-Approved-Sender": "No",
        "X-TM-AS-User-Blocked-Sender": "No",
        "X-TMASE-Result": "10--10.304700-4.000000",
        "X-TMASE-Version": "SMEX-12.5.0.1300-8.5.1010-24084.005",
        "X-MDID": "1536572033-YiiNLCv0V0-1",
        "Subject": "[dpdk-dev] [PATCH 18/37] net/sfc/base: add buffer editing functions\n\tto boot config",
        "X-BeenThere": "dev@dpdk.org",
        "X-Mailman-Version": "2.1.15",
        "Precedence": "list",
        "List-Id": "DPDK patches and discussions <dev.dpdk.org>",
        "List-Unsubscribe": "<https://mails.dpdk.org/options/dev>,\n\t<mailto:dev-request@dpdk.org?subject=unsubscribe>",
        "List-Archive": "<http://mails.dpdk.org/archives/dev/>",
        "List-Post": "<mailto:dev@dpdk.org>",
        "List-Help": "<mailto:dev-request@dpdk.org?subject=help>",
        "List-Subscribe": "<https://mails.dpdk.org/listinfo/dev>,\n\t<mailto:dev-request@dpdk.org?subject=subscribe>",
        "Errors-To": "dev-bounces@dpdk.org",
        "Sender": "\"dev\" <dev-bounces@dpdk.org>"
    },
    "content": "From: Richard Houldsworth <rhouldsworth@solarflare.com>\n\nFunctions to process the DHCP option list format used by the expansion\nROM config buffers, to support extracting and updating of individual\noptions.\nThe initial use case is the driver presenting the global and per-PF\noptions as separate items, with the driver implementing the\nsynchronization of global options across the configuration buffers\nfor all PFs.\n\nSigned-off-by: Richard Houldsworth <rhouldsworth@solarflare.com>\nSigned-off-by: Andrew Rybchenko <arybchenko@solarflare.com>\n---\n drivers/net/sfc/base/efx.h         |  81 ++++\n drivers/net/sfc/base/efx_annote.h  |   1 +\n drivers/net/sfc/base/efx_bootcfg.c | 641 ++++++++++++++++++++++++++---\n 3 files changed, 672 insertions(+), 51 deletions(-)",
    "diff": "diff --git a/drivers/net/sfc/base/efx.h b/drivers/net/sfc/base/efx.h\nindex 099f9df67..3c3227739 100644\n--- a/drivers/net/sfc/base/efx.h\n+++ b/drivers/net/sfc/base/efx.h\n@@ -1662,6 +1662,87 @@ efx_bootcfg_write(\n \t__in_bcount(size)\tuint8_t *data,\n \t__in\t\t\tsize_t size);\n \n+\n+/*\n+ * Processing routines for buffers arranged in the DHCP/BOOTP option format\n+ * (see https://tools.ietf.org/html/rfc1533)\n+ *\n+ * Summarising the format: the buffer is a sequence of options. All options\n+ * begin with a tag octet, which uniquely identifies the option.  Fixed-\n+ * length options without data consist of only a tag octet.  Only options PAD\n+ * (0) and END (255) are fixed length.  All other options are variable-length\n+ * with a length octet following the tag octet.  The value of the length\n+ * octet does not include the two octets specifying the tag and length.  The\n+ * length octet is followed by \"length\" octets of data.\n+ *\n+ * Option data may be a sequence of sub-options in the same format. The data\n+ * content of the encapsulating option is one or more encapsulated sub-options,\n+ * with no terminating END tag is required.\n+ *\n+ * To be valid, the top-level sequence of options should be terminated by an\n+ * END tag. The buffer should be padded with the PAD byte.\n+ *\n+ * When stored to NVRAM, the DHCP option format buffer is preceded by a\n+ * checksum octet. The full buffer (including after the END tag) contributes\n+ * to the checksum, hence the need to fill the buffer to the end with PAD.\n+ */\n+\n+#define\tEFX_DHCP_END ((uint8_t)0xff)\n+#define\tEFX_DHCP_PAD ((uint8_t)0)\n+\n+#define\tEFX_DHCP_ENCAP_OPT(encapsulator, encapsulated) \\\n+  (uint16_t)(((encapsulator) << 8) | (encapsulated))\n+\n+extern\t__checkReturn\t\tuint8_t\n+efx_dhcp_csum(\n+\t__in_bcount(size)\tuint8_t const *data,\n+\t__in\t\t\tsize_t size);\n+\n+extern\t__checkReturn\t\tefx_rc_t\n+efx_dhcp_verify(\n+\t__in_bcount(size)\tuint8_t const *data,\n+\t__in\t\t\tsize_t size,\n+\t__out_opt\t\tsize_t *usedp);\n+\n+extern\t__checkReturn\tefx_rc_t\n+efx_dhcp_find_tag(\n+\t__in_bcount(buffer_length)\tuint8_t *bufferp,\n+\t__in\t\t\t\tsize_t buffer_length,\n+\t__in\t\t\t\tuint16_t opt,\n+\t__deref_out\t\t\tuint8_t **valuepp,\n+\t__out\t\t\t\tsize_t *value_lengthp);\n+\n+extern\t__checkReturn\tefx_rc_t\n+efx_dhcp_find_end(\n+\t__in_bcount(buffer_length)\tuint8_t *bufferp,\n+\t__in\t\t\t\tsize_t buffer_length,\n+\t__deref_out\t\t\tuint8_t **endpp);\n+\n+\n+extern\t__checkReturn\tefx_rc_t\n+efx_dhcp_delete_tag(\n+\t__inout_bcount(buffer_length)\tuint8_t *bufferp,\n+\t__in\t\t\t\tsize_t buffer_length,\n+\t__in\t\t\t\tuint16_t opt);\n+\n+extern\t__checkReturn\tefx_rc_t\n+efx_dhcp_add_tag(\n+\t__inout_bcount(buffer_length)\tuint8_t *bufferp,\n+\t__in\t\t\t\tsize_t buffer_length,\n+\t__in\t\t\t\tuint16_t opt,\n+\t__in_bcount_opt(value_length)\tuint8_t *valuep,\n+\t__in\t\t\t\tsize_t value_length);\n+\n+extern\t__checkReturn\tefx_rc_t\n+efx_dhcp_update_tag(\n+\t__inout_bcount(buffer_length)\tuint8_t *bufferp,\n+\t__in\t\t\t\tsize_t buffer_length,\n+\t__in\t\t\t\tuint16_t opt,\n+\t__in\t\t\t\tuint8_t *value_locationp,\n+\t__in_bcount_opt(value_length)\tuint8_t *valuep,\n+\t__in\t\t\t\tsize_t value_length);\n+\n+\n #endif\t/* EFSYS_OPT_BOOTCFG */\n \n #if EFSYS_OPT_IMAGE_LAYOUT\ndiff --git a/drivers/net/sfc/base/efx_annote.h b/drivers/net/sfc/base/efx_annote.h\nindex 603260e22..671aaed3b 100644\n--- a/drivers/net/sfc/base/efx_annote.h\n+++ b/drivers/net/sfc/base/efx_annote.h\n@@ -39,6 +39,7 @@\n #define\t__out_bcount_part_opt(_n, _l)\n \n #define\t__deref_out\n+#define\t__deref_inout\n \n #define\t__inout\n #define\t__inout_opt\ndiff --git a/drivers/net/sfc/base/efx_bootcfg.c b/drivers/net/sfc/base/efx_bootcfg.c\nindex 715e18e8c..3b0401e89 100644\n--- a/drivers/net/sfc/base/efx_bootcfg.c\n+++ b/drivers/net/sfc/base/efx_bootcfg.c\n@@ -19,8 +19,33 @@\n #define\tBOOTCFG_PER_PF   0x800\n #define\tBOOTCFG_PF_COUNT 16\n \n-#define\tDHCP_END ((uint8_t)0xff)\n-#define\tDHCP_PAD ((uint8_t)0)\n+#define\tDHCP_OPT_HAS_VALUE(opt) \\\n+\t(((opt) > EFX_DHCP_PAD) && ((opt) < EFX_DHCP_END))\n+\n+#define\tDHCP_MAX_VALUE 255\n+\n+#define\tDHCP_ENCAPSULATOR(encap_opt) ((encap_opt) >> 8)\n+#define\tDHCP_ENCAPSULATED(encap_opt) ((encap_opt) & 0xff)\n+#define\tDHCP_IS_ENCAP_OPT(opt) DHCP_OPT_HAS_VALUE(DHCP_ENCAPSULATOR(opt))\n+\n+typedef struct efx_dhcp_tag_hdr_s {\n+\tuint8_t\t\ttag;\n+\tuint8_t\t\tlength;\n+} efx_dhcp_tag_hdr_t;\n+\n+/*\n+ * Length calculations for tags with value field. PAD and END\n+ * have a fixed length of 1, with no length or value field.\n+ */\n+#define\tDHCP_FULL_TAG_LENGTH(hdr) \\\n+\t(sizeof (efx_dhcp_tag_hdr_t) + (hdr)->length)\n+\n+#define\tDHCP_NEXT_TAG(hdr) \\\n+\t((efx_dhcp_tag_hdr_t *)(((uint8_t *)(hdr)) + \\\n+\tDHCP_FULL_TAG_LENGTH((hdr))))\n+\n+#define\tDHCP_CALC_TAG_LENGTH(payload_len) \\\n+\t((payload_len) + sizeof (efx_dhcp_tag_hdr_t))\n \n \n /* Report the layout of bootcfg sectors in NVRAM partition. */\n@@ -110,14 +135,11 @@ efx_bootcfg_sector_info(\n }\n \n \n-static\t__checkReturn\t\tuint8_t\n-efx_bootcfg_csum(\n-\t__in\t\t\tefx_nic_t *enp,\n+\t__checkReturn\t\tuint8_t\n+efx_dhcp_csum(\n \t__in_bcount(size)\tuint8_t const *data,\n \t__in\t\t\tsize_t size)\n {\n-\t_NOTE(ARGUNUSED(enp))\n-\n \tunsigned int pos;\n \tuint8_t checksum = 0;\n \n@@ -126,9 +148,8 @@ efx_bootcfg_csum(\n \treturn (checksum);\n }\n \n-static\t__checkReturn\t\tefx_rc_t\n-efx_bootcfg_verify(\n-\t__in\t\t\tefx_nic_t *enp,\n+\t__checkReturn\t\tefx_rc_t\n+efx_dhcp_verify(\n \t__in_bcount(size)\tuint8_t const *data,\n \t__in\t\t\tsize_t size,\n \t__out_opt\t\tsize_t *usedp)\n@@ -144,12 +165,12 @@ efx_bootcfg_verify(\n \n \t\t/* Consume tag */\n \t\ttag = data[offset];\n-\t\tif (tag == DHCP_END) {\n+\t\tif (tag == EFX_DHCP_END) {\n \t\t\toffset++;\n \t\t\tused = offset;\n \t\t\tbreak;\n \t\t}\n-\t\tif (tag == DHCP_PAD) {\n+\t\tif (tag == EFX_DHCP_PAD) {\n \t\t\toffset++;\n \t\t\tcontinue;\n \t\t}\n@@ -171,8 +192,8 @@ efx_bootcfg_verify(\n \t\tused = offset;\n \t}\n \n-\t/* Checksum the entire sector, including bytes after any DHCP_END */\n-\tif (efx_bootcfg_csum(enp, data, size) != 0) {\n+\t/* Checksum the entire sector, including bytes after any EFX_DHCP_END */\n+\tif (efx_dhcp_csum(data, size) != 0) {\n \t\trc = EINVAL;\n \t\tgoto fail3;\n \t}\n@@ -192,6 +213,516 @@ efx_bootcfg_verify(\n \treturn (rc);\n }\n \n+/*\n+ * Walk the entire tag set looking for option. The sought option may be\n+ * encapsulated. ENOENT indicates the walk completed without finding the\n+ * option. If we run out of buffer during the walk the function will return\n+ * ENOSPC.\n+ */\n+static\tefx_rc_t\n+efx_dhcp_walk_tags(\n+\t__deref_inout\tuint8_t **tagpp,\n+\t__inout\t\tsize_t *buffer_sizep,\n+\t__in\t\tuint16_t opt)\n+{\n+\tefx_rc_t rc = 0;\n+\tboolean_t is_encap = B_FALSE;\n+\n+\tif (DHCP_IS_ENCAP_OPT(opt)) {\n+\t\t/*\n+\t\t * Look for the encapsulator and, if found, limit ourselves\n+\t\t * to its payload. If it's not found then the entire tag\n+\t\t * cannot be found, so the encapsulated opt search is\n+\t\t * skipped.\n+\t\t */\n+\t\trc = efx_dhcp_walk_tags(tagpp, buffer_sizep,\n+\t\t    DHCP_ENCAPSULATOR(opt));\n+\t\tif (rc == 0) {\n+\t\t\t*buffer_sizep = ((efx_dhcp_tag_hdr_t *)*tagpp)->length;\n+\t\t\t(*tagpp) += sizeof (efx_dhcp_tag_hdr_t);\n+\t\t}\n+\t\topt = DHCP_ENCAPSULATED(opt);\n+\t\tis_encap = B_TRUE;\n+\t}\n+\n+\tEFSYS_ASSERT(!DHCP_IS_ENCAP_OPT(opt));\n+\n+\twhile (rc == 0) {\n+\t\tsize_t size;\n+\n+\t\tif (*buffer_sizep == 0) {\n+\t\t\trc = ENOSPC;\n+\t\t\tgoto fail1;\n+\t\t}\n+\n+\t\tif (DHCP_ENCAPSULATED(**tagpp) == opt)\n+\t\t\tbreak;\n+\n+\t\tif ((**tagpp) == EFX_DHCP_END) {\n+\t\t\trc = ENOENT;\n+\t\t\tbreak;\n+\t\t} else if ((**tagpp) == EFX_DHCP_PAD) {\n+\t\t\tsize = 1;\n+\t\t} else {\n+\t\t\tif (*buffer_sizep < sizeof (efx_dhcp_tag_hdr_t)) {\n+\t\t\t\trc = ENOSPC;\n+\t\t\t\tgoto fail2;\n+\t\t\t}\n+\n+\t\t\tsize =\n+\t\t\t    DHCP_FULL_TAG_LENGTH((efx_dhcp_tag_hdr_t *)*tagpp);\n+\t\t}\n+\n+\t\tif (size > *buffer_sizep) {\n+\t\t\trc = ENOSPC;\n+\t\t\tgoto fail3;\n+\t\t}\n+\n+\t\t(*tagpp) += size;\n+\t\t(*buffer_sizep) -= size;\n+\n+\t\tif ((*buffer_sizep == 0) && is_encap) {\n+\t\t\t/* Search within encapulator tag finished */\n+\t\t\trc = ENOENT;\n+\t\t\tbreak;\n+\t\t}\n+\t}\n+\n+\t/*\n+\t * Returns 0 if found otherwise ENOENT indicating search finished\n+\t * correctly\n+\t */\n+\treturn (rc);\n+\n+fail3:\n+\tEFSYS_PROBE(fail3);\n+fail2:\n+\tEFSYS_PROBE(fail2);\n+fail1:\n+\tEFSYS_PROBE1(fail1, efx_rc_t, rc);\n+\n+\treturn (rc);\n+}\n+\n+/*\n+ * Locate value buffer for option in the given buffer.\n+ * Returns 0 if found, ENOENT indicating search finished\n+ * correctly, otherwise search failed before completion.\n+ */\n+\t__checkReturn\tefx_rc_t\n+efx_dhcp_find_tag(\n+\t__in_bcount(buffer_length)\tuint8_t *bufferp,\n+\t__in\t\t\t\tsize_t buffer_length,\n+\t__in\t\t\t\tuint16_t opt,\n+\t__deref_out\t\t\tuint8_t **valuepp,\n+\t__out\t\t\t\tsize_t *value_lengthp)\n+{\n+\tefx_rc_t rc;\n+\tuint8_t *tagp = bufferp;\n+\tsize_t len = buffer_length;\n+\n+\trc = efx_dhcp_walk_tags(&tagp, &len, opt);\n+\tif (rc == 0) {\n+\t\tefx_dhcp_tag_hdr_t *hdrp;\n+\n+\t\thdrp = (efx_dhcp_tag_hdr_t *)tagp;\n+\t\t*valuepp = (uint8_t *)(&hdrp[1]);\n+\t\t*value_lengthp = hdrp->length;\n+\t} else if (rc != ENOENT) {\n+\t\tgoto fail1;\n+\t}\n+\n+\treturn (rc);\n+\n+fail1:\n+\tEFSYS_PROBE1(fail1, efx_rc_t, rc);\n+\n+\treturn (rc);\n+}\n+\n+/*\n+ * Locate the end tag in the given buffer.\n+ * Returns 0 if found, ENOENT indicating search finished\n+ * correctly but end tag was not found; otherwise search\n+ * failed before completion.\n+ */\n+\t__checkReturn\tefx_rc_t\n+efx_dhcp_find_end(\n+\t__in_bcount(buffer_length)\tuint8_t *bufferp,\n+\t__in\t\t\t\tsize_t buffer_length,\n+\t__deref_out\t\t\tuint8_t **endpp)\n+{\n+\tefx_rc_t rc;\n+\tuint8_t *endp = bufferp;\n+\tsize_t len = buffer_length;\n+\n+\trc = efx_dhcp_walk_tags(&endp, &len, EFX_DHCP_END);\n+\tif (rc == 0)\n+\t\t*endpp = endp;\n+\telse if (rc != ENOENT)\n+\t\tgoto fail1;\n+\n+\treturn (rc);\n+\n+fail1:\n+\tEFSYS_PROBE1(fail1, efx_rc_t, rc);\n+\n+\treturn (rc);\n+}\n+\n+\n+/*\n+ * Delete the given tag from anywhere in the buffer. Copes with\n+ * encapsulated tags, and updates or deletes the encapsulating opt as\n+ * necessary.\n+ */\n+\t__checkReturn\tefx_rc_t\n+efx_dhcp_delete_tag(\n+\t__inout_bcount(buffer_length)\tuint8_t *bufferp,\n+\t__in\t\t\t\tsize_t buffer_length,\n+\t__in\t\t\t\tuint16_t opt)\n+{\n+\tefx_rc_t rc;\n+\tefx_dhcp_tag_hdr_t *hdrp;\n+\tsize_t len;\n+\tuint8_t *startp;\n+\tuint8_t *endp;\n+\n+\tlen = buffer_length;\n+\tstartp = bufferp;\n+\n+\tif (!DHCP_OPT_HAS_VALUE(DHCP_ENCAPSULATED(opt))) {\n+\t\trc = EINVAL;\n+\t\tgoto fail1;\n+\t}\n+\n+\trc = efx_dhcp_walk_tags(&startp, &len, opt);\n+\tif (rc != 0)\n+\t\tgoto fail1;\n+\n+\thdrp = (efx_dhcp_tag_hdr_t *)startp;\n+\n+\tif (DHCP_IS_ENCAP_OPT(opt)) {\n+\t\tuint8_t tag_length = DHCP_FULL_TAG_LENGTH(hdrp);\n+\t\tuint8_t *encapp = bufferp;\n+\t\tefx_dhcp_tag_hdr_t *encap_hdrp;\n+\n+\t\tlen = buffer_length;\n+\t\trc = efx_dhcp_walk_tags(&encapp, &len,\n+\t\t    DHCP_ENCAPSULATOR(opt));\n+\t\tif (rc != 0)\n+\t\t\tgoto fail2;\n+\n+\t\tencap_hdrp = (efx_dhcp_tag_hdr_t *)encapp;\n+\t\tif (encap_hdrp->length > tag_length) {\n+\t\t\tencap_hdrp->length = (uint8_t)(\n+\t\t\t    (size_t)encap_hdrp->length - tag_length);\n+\t\t} else {\n+\t\t\t/* delete the encapsulating tag */\n+\t\t\thdrp = encap_hdrp;\n+\t\t}\n+\t}\n+\n+\tstartp = (uint8_t *)hdrp;\n+\tendp = (uint8_t *)DHCP_NEXT_TAG(hdrp);\n+\n+\tif (startp < bufferp) {\n+\t\trc = EINVAL;\n+\t\tgoto fail3;\n+\t}\n+\n+\tif (endp > &bufferp[buffer_length]) {\n+\t\trc = EINVAL;\n+\t\tgoto fail4;\n+\t}\n+\n+\tmemmove(startp, endp,\n+\t\tbuffer_length - (endp - bufferp));\n+\n+\treturn (0);\n+\n+fail4:\n+\tEFSYS_PROBE(fail4);\n+fail3:\n+\tEFSYS_PROBE(fail3);\n+fail2:\n+\tEFSYS_PROBE(fail2);\n+fail1:\n+\tEFSYS_PROBE1(fail1, efx_rc_t, rc);\n+\n+\treturn (rc);\n+}\n+\n+/*\n+ * Write the tag header into write_pointp and optionally copies the payload\n+ * into the space following.\n+ */\n+static\tvoid\n+efx_dhcp_write_tag(\n+\t__in\t\tuint8_t *write_pointp,\n+\t__in\t\tuint16_t opt,\n+\t__in_bcount_opt(value_length)\n+\t\t\tuint8_t *valuep,\n+\t__in\t\tsize_t value_length)\n+{\n+\tefx_dhcp_tag_hdr_t *hdrp = (efx_dhcp_tag_hdr_t *)write_pointp;\n+\thdrp->tag = DHCP_ENCAPSULATED(opt);\n+\thdrp->length = (uint8_t)value_length;\n+\tif ((value_length > 0) && (valuep != NULL))\n+\t\tmemcpy(&hdrp[1], valuep, value_length);\n+}\n+\n+/*\n+ * Add the given tag to the end of the buffer. Copes with creating an\n+ * encapsulated tag, and updates or creates the encapsulating opt as\n+ * necessary.\n+ */\n+\t__checkReturn\tefx_rc_t\n+efx_dhcp_add_tag(\n+\t__inout_bcount(buffer_length)\tuint8_t *bufferp,\n+\t__in\t\t\t\tsize_t buffer_length,\n+\t__in\t\t\t\tuint16_t opt,\n+\t__in_bcount_opt(value_length)\tuint8_t *valuep,\n+\t__in\t\t\t\tsize_t value_length)\n+{\n+\tefx_rc_t rc;\n+\tefx_dhcp_tag_hdr_t *encap_hdrp = NULL;\n+\tuint8_t *insert_pointp = NULL;\n+\tuint8_t *endp;\n+\tsize_t available_space;\n+\tsize_t added_length;\n+\tsize_t search_size;\n+\tuint8_t *searchp;\n+\n+\tif (!DHCP_OPT_HAS_VALUE(DHCP_ENCAPSULATED(opt))) {\n+\t\trc = EINVAL;\n+\t\tgoto fail1;\n+\t}\n+\n+\tif (value_length > DHCP_MAX_VALUE) {\n+\t\trc = EINVAL;\n+\t\tgoto fail2;\n+\t}\n+\n+\tif ((value_length > 0) && (valuep == NULL)) {\n+\t\trc = EINVAL;\n+\t\tgoto fail3;\n+\t}\n+\n+\tendp = bufferp;\n+\tavailable_space = buffer_length;\n+\trc = efx_dhcp_walk_tags(&endp, &available_space, EFX_DHCP_END);\n+\tif (rc != 0)\n+\t\tgoto fail4;\n+\n+\tsearchp = bufferp;\n+\tsearch_size = buffer_length;\n+\tif (DHCP_IS_ENCAP_OPT(opt)) {\n+\t\trc = efx_dhcp_walk_tags(&searchp, &search_size,\n+\t\t    DHCP_ENCAPSULATOR(opt));\n+\t\tif (rc == 0) {\n+\t\t\tencap_hdrp = (efx_dhcp_tag_hdr_t *)searchp;\n+\n+\t\t\t/* Check encapsulated tag is not present */\n+\t\t\tsearch_size = encap_hdrp->length;\n+\t\t\trc = efx_dhcp_walk_tags(&searchp, &search_size,\n+\t\t\t    opt);\n+\t\t\tif (rc != ENOENT) {\n+\t\t\t\trc = EINVAL;\n+\t\t\t\tgoto fail5;\n+\t\t\t}\n+\n+\t\t\t/* Check encapsulator will not overflow */\n+\t\t\tif (((size_t)encap_hdrp->length +\n+\t\t\t    DHCP_CALC_TAG_LENGTH(value_length)) >\n+\t\t\t    DHCP_MAX_VALUE) {\n+\t\t\t\trc = E2BIG;\n+\t\t\t\tgoto fail6;\n+\t\t\t}\n+\n+\t\t\t/* Insert at start of existing encapsulator */\n+\t\t\tinsert_pointp = (uint8_t *)&encap_hdrp[1];\n+\t\t\topt = DHCP_ENCAPSULATED(opt);\n+\t\t} else if (rc == ENOENT) {\n+\t\t\tencap_hdrp = NULL;\n+\t\t} else {\n+\t\t\tgoto fail7;\n+\t\t}\n+\t} else {\n+\t\t/* Check unencapsulated tag is not present */\n+\t\trc = efx_dhcp_walk_tags(&searchp, &search_size,\n+\t\t    opt);\n+\t\tif (rc != ENOENT) {\n+\t\t\trc = EINVAL;\n+\t\t\tgoto fail8;\n+\t\t}\n+\t}\n+\n+\tif (insert_pointp == NULL) {\n+\t\t/* Insert at end of existing tags */\n+\t\tinsert_pointp = endp;\n+\t}\n+\n+\t/* Includes the new encapsulator tag hdr if required */\n+\tadded_length = DHCP_CALC_TAG_LENGTH(value_length) +\n+\t    (DHCP_IS_ENCAP_OPT(opt) ? sizeof (efx_dhcp_tag_hdr_t) : 0);\n+\n+\tif (available_space <= added_length) {\n+\t\trc = ENOMEM;\n+\t\tgoto fail9;\n+\t}\n+\n+\tmemmove(insert_pointp + added_length, insert_pointp,\n+\t    available_space - added_length);\n+\n+\tif (DHCP_IS_ENCAP_OPT(opt)) {\n+\t\t/* Create new encapsulator header */\n+\t\tadded_length -= sizeof (efx_dhcp_tag_hdr_t);\n+\t\tefx_dhcp_write_tag(insert_pointp,\n+\t\t    DHCP_ENCAPSULATOR(opt), NULL, added_length);\n+\t\tinsert_pointp += sizeof (efx_dhcp_tag_hdr_t);\n+\t} else if (encap_hdrp)\n+\t\t/* Modify existing encapsulator header */\n+\t\tencap_hdrp->length +=\n+\t\t    ((uint8_t)DHCP_CALC_TAG_LENGTH(value_length));\n+\n+\tefx_dhcp_write_tag(insert_pointp, opt, valuep, value_length);\n+\n+\treturn (0);\n+\n+fail9:\n+\tEFSYS_PROBE(fail9);\n+fail8:\n+\tEFSYS_PROBE(fail8);\n+fail7:\n+\tEFSYS_PROBE(fail7);\n+fail6:\n+\tEFSYS_PROBE(fail6);\n+fail5:\n+\tEFSYS_PROBE(fail5);\n+fail4:\n+\tEFSYS_PROBE(fail4);\n+fail3:\n+\tEFSYS_PROBE(fail3);\n+fail2:\n+\tEFSYS_PROBE(fail2);\n+fail1:\n+\tEFSYS_PROBE1(fail1, efx_rc_t, rc);\n+\n+\treturn (rc);\n+}\n+\n+/*\n+ * Update an existing tag to the new value. Copes with encapsulated\n+ * tags, and updates the encapsulating opt as necessary.\n+ */\n+\t__checkReturn\tefx_rc_t\n+efx_dhcp_update_tag(\n+\t__inout_bcount(buffer_length)\tuint8_t *bufferp,\n+\t__in\t\t\t\tsize_t buffer_length,\n+\t__in\t\t\t\tuint16_t opt,\n+\t__in\t\t\t\tuint8_t *value_locationp,\n+\t__in_bcount_opt(value_length)\tuint8_t *valuep,\n+\t__in\t\t\t\tsize_t value_length)\n+{\n+\tefx_rc_t rc;\n+\tuint8_t *write_pointp = value_locationp - sizeof (efx_dhcp_tag_hdr_t);\n+\tefx_dhcp_tag_hdr_t *hdrp = (efx_dhcp_tag_hdr_t *)write_pointp;\n+\tefx_dhcp_tag_hdr_t *encap_hdrp = NULL;\n+\tsize_t old_length;\n+\n+\tif (!DHCP_OPT_HAS_VALUE(DHCP_ENCAPSULATED(opt))) {\n+\t\trc = EINVAL;\n+\t\tgoto fail1;\n+\t}\n+\n+\tif (value_length > DHCP_MAX_VALUE) {\n+\t\trc = EINVAL;\n+\t\tgoto fail2;\n+\t}\n+\n+\tif ((value_length > 0) && (valuep == NULL)) {\n+\t\trc = EINVAL;\n+\t\tgoto fail3;\n+\t}\n+\n+\told_length = hdrp->length;\n+\n+\tif (old_length < value_length) {\n+\t\tuint8_t *endp = bufferp;\n+\t\tsize_t available_space = buffer_length;\n+\n+\t\trc = efx_dhcp_walk_tags(&endp, &available_space,\n+\t\t    EFX_DHCP_END);\n+\t\tif (rc != 0)\n+\t\t\tgoto fail4;\n+\n+\t\tif (available_space < (value_length - old_length)) {\n+\t\t\trc = EINVAL;\n+\t\t\tgoto fail5;\n+\t\t}\n+\t}\n+\n+\tif (DHCP_IS_ENCAP_OPT(opt)) {\n+\t\tuint8_t *encapp = bufferp;\n+\t\tsize_t following_encap = buffer_length;\n+\t\tsize_t new_length;\n+\n+\t\trc = efx_dhcp_walk_tags(&encapp, &following_encap,\n+\t\t    DHCP_ENCAPSULATOR(opt));\n+\t\tif (rc != 0)\n+\t\t\tgoto fail6;\n+\n+\t\tencap_hdrp = (efx_dhcp_tag_hdr_t *)encapp;\n+\n+\t\tnew_length = ((size_t)encap_hdrp->length +\n+\t\t    value_length - old_length);\n+\t\t/* Check encapsulator will not overflow */\n+\t\tif (new_length > DHCP_MAX_VALUE) {\n+\t\t\trc = E2BIG;\n+\t\t\tgoto fail7;\n+\t\t}\n+\n+\t\tencap_hdrp->length = (uint8_t)new_length;\n+\t}\n+\n+\t/*\n+\t * Move the following data up/down to accomodate the new payload\n+\t * length.\n+\t */\n+\tif (old_length != value_length) {\n+\t\tuint8_t *destp = (uint8_t *)DHCP_NEXT_TAG(hdrp) +\n+\t\t    value_length - old_length;\n+\t\tsize_t count = &bufferp[buffer_length] -\n+\t\t    (uint8_t *)DHCP_NEXT_TAG(hdrp);\n+\n+\t\tmemmove(destp, DHCP_NEXT_TAG(hdrp), count);\n+\t}\n+\n+\tEFSYS_ASSERT(hdrp->tag == DHCP_ENCAPSULATED(opt));\n+\tefx_dhcp_write_tag(write_pointp, opt, valuep, value_length);\n+\n+\treturn (0);\n+\n+fail7:\n+\tEFSYS_PROBE(fail7);\n+fail6:\n+\tEFSYS_PROBE(fail6);\n+fail5:\n+\tEFSYS_PROBE(fail5);\n+fail4:\n+\tEFSYS_PROBE(fail4);\n+fail3:\n+\tEFSYS_PROBE(fail3);\n+fail2:\n+\tEFSYS_PROBE(fail2);\n+fail1:\n+\tEFSYS_PROBE1(fail1, efx_rc_t, rc);\n+\n+\treturn (rc);\n+}\n+\n+\n /*\n  * Copy bootcfg sector data to a target buffer which may differ in size.\n  * Optionally corrects format errors in source buffer.\n@@ -206,17 +737,19 @@ efx_bootcfg_copy_sector(\n \t__in\t\t\tsize_t data_size,\n \t__in\t\t\tboolean_t handle_format_errors)\n {\n+\t_NOTE(ARGUNUSED(enp))\n+\n \tsize_t used_bytes;\n \tefx_rc_t rc;\n \n-\t/* Minimum buffer is checksum byte and DHCP_END terminator */\n+\t/* Minimum buffer is checksum byte and EFX_DHCP_END terminator */\n \tif (data_size < 2) {\n \t\trc = ENOSPC;\n \t\tgoto fail1;\n \t}\n \n \t/* Verify that the area is correctly formatted and checksummed */\n-\trc = efx_bootcfg_verify(enp, sector, sector_length,\n+\trc = efx_dhcp_verify(sector, sector_length,\n \t\t\t\t    &used_bytes);\n \n \tif (!handle_format_errors) {\n@@ -224,8 +757,8 @@ efx_bootcfg_copy_sector(\n \t\t\tgoto fail2;\n \n \t\tif ((used_bytes < 2) ||\n-\t\t    (sector[used_bytes - 1] != DHCP_END)) {\n-\t\t\t/* Block too short, or DHCP_END missing */\n+\t\t    (sector[used_bytes - 1] != EFX_DHCP_END)) {\n+\t\t\t/* Block too short, or EFX_DHCP_END missing */\n \t\t\trc = ENOENT;\n \t\t\tgoto fail3;\n \t\t}\n@@ -234,24 +767,24 @@ efx_bootcfg_copy_sector(\n \t/* Synthesize empty format on verification failure */\n \tif (rc != 0 || used_bytes == 0) {\n \t\tsector[0] = 0;\n-\t\tsector[1] = DHCP_END;\n+\t\tsector[1] = EFX_DHCP_END;\n \t\tused_bytes = 2;\n \t}\n-\tEFSYS_ASSERT(used_bytes >= 2);\t/* checksum and DHCP_END */\n+\tEFSYS_ASSERT(used_bytes >= 2);\t/* checksum and EFX_DHCP_END */\n \tEFSYS_ASSERT(used_bytes <= sector_length);\n \tEFSYS_ASSERT(sector_length >= 2);\n \n \t/*\n-\t * Legacy bootcfg sectors don't terminate with a DHCP_END character.\n-\t * Modify the returned payload so it does.\n+\t * Legacy bootcfg sectors don't terminate with an EFX_DHCP_END\n+\t * character. Modify the returned payload so it does.\n \t * Reinitialise the sector if there isn't room for the character.\n \t */\n-\tif (sector[used_bytes - 1] != DHCP_END) {\n+\tif (sector[used_bytes - 1] != EFX_DHCP_END) {\n \t\tif (used_bytes >= sector_length) {\n \t\t\tsector[0] = 0;\n \t\t\tused_bytes = 1;\n \t\t}\n-\t\tsector[used_bytes] = DHCP_END;\n+\t\tsector[used_bytes] = EFX_DHCP_END;\n \t\t++used_bytes;\n \t}\n \n@@ -274,10 +807,11 @@ efx_bootcfg_copy_sector(\n \t\t(void) memset(data + used_bytes, 0, data_size - used_bytes);\n \n \t/*\n-\t * The checksum includes trailing data after any DHCP_END character,\n-\t * which we've just modified (by truncation or appending DHCP_END).\n+\t * The checksum includes trailing data after any EFX_DHCP_END\n+\t * character, which we've just modified (by truncation or appending\n+\t * EFX_DHCP_END).\n \t */\n-\tdata[0] -= efx_bootcfg_csum(enp, data, data_size);\n+\tdata[0] -= efx_dhcp_csum(data, data_size);\n \n \treturn (0);\n \n@@ -307,7 +841,7 @@ efx_bootcfg_read(\n \tefx_rc_t rc;\n \tuint32_t sector_number;\n \n-\t/* Minimum buffer is checksum byte and DHCP_END terminator */\n+\t/* Minimum buffer is checksum byte and EFX_DHCP_END terminator */\n \tif (size < 2) {\n \t\trc = ENOSPC;\n \t\tgoto fail1;\n@@ -343,10 +877,10 @@ efx_bootcfg_read(\n \t}\n \n \t/*\n-\t * We need to read the entire BOOTCFG sector to ensure we read all the\n-\t * tags, because legacy bootcfg sectors are not guaranteed to end with\n-\t * a DHCP_END character. If the user hasn't supplied a sufficiently\n-\t * large buffer then use our own buffer.\n+\t * We need to read the entire BOOTCFG sector to ensure we read all\n+\t * tags, because legacy bootcfg sectors are not guaranteed to end\n+\t * with an EFX_DHCP_END character. If the user hasn't supplied a\n+\t * sufficiently large buffer then use our own buffer.\n \t */\n \tif (sector_length > size) {\n \t\tEFSYS_KMEM_ALLOC(enp->en_esip, sector_length, payload);\n@@ -370,28 +904,29 @@ efx_bootcfg_read(\n \t\tgoto fail9;\n \n \t/* Verify that the area is correctly formatted and checksummed */\n-\trc = efx_bootcfg_verify(enp, payload, sector_length,\n+\trc = efx_dhcp_verify(payload, sector_length,\n \t    &used_bytes);\n \tif (rc != 0 || used_bytes == 0) {\n \t\tpayload[0] = 0;\n-\t\tpayload[1] = DHCP_END;\n+\t\tpayload[1] = EFX_DHCP_END;\n \t\tused_bytes = 2;\n \t}\n \n-\tEFSYS_ASSERT(used_bytes >= 2);\t/* checksum and DHCP_END */\n+\tEFSYS_ASSERT(used_bytes >= 2);\t/* checksum and EFX_DHCP_END */\n \tEFSYS_ASSERT(used_bytes <= sector_length);\n \n \t/*\n-\t * Legacy bootcfg sectors don't terminate with a DHCP_END character.\n-\t * Modify the returned payload so it does. BOOTCFG_MAX_SIZE is by\n-\t * definition large enough for any valid (per-port) bootcfg sector,\n-\t * so reinitialise the sector if there isn't room for the character.\n+\t * Legacy bootcfg sectors don't terminate with an EFX_DHCP_END\n+\t * character. Modify the returned payload so it does.\n+\t * BOOTCFG_MAX_SIZE is by definition large enough for any valid\n+\t * (per-port) bootcfg sector, so reinitialise the sector if there\n+\t * isn't room for the character.\n \t */\n-\tif (payload[used_bytes - 1] != DHCP_END) {\n+\tif (payload[used_bytes - 1] != EFX_DHCP_END) {\n \t\tif (used_bytes >= sector_length)\n \t\t\tused_bytes = 1;\n \n-\t\tpayload[used_bytes] = DHCP_END;\n+\t\tpayload[used_bytes] = EFX_DHCP_END;\n \t\t++used_bytes;\n \t}\n \n@@ -417,10 +952,10 @@ efx_bootcfg_read(\n \t\t(void) memset(data + used_bytes, 0, size - used_bytes);\n \n \t/*\n-\t * The checksum includes trailing data after any DHCP_END character,\n-\t * which we've just modified (by truncation or appending DHCP_END).\n+\t * The checksum includes trailing data after any EFX_DHCP_END character,\n+\t * which we've just modified (by truncation or appending EFX_DHCP_END).\n \t */\n-\tdata[0] -= efx_bootcfg_csum(enp, data, size);\n+\tdata[0] -= efx_dhcp_csum(data, size);\n \n \treturn (0);\n \n@@ -490,12 +1025,16 @@ efx_bootcfg_write(\n \t\tgoto fail3;\n \t}\n \n-\tif ((rc = efx_bootcfg_verify(enp, data, size, &used_bytes)) != 0)\n+\tif ((rc = efx_dhcp_verify(data, size, &used_bytes)) != 0)\n \t\tgoto fail4;\n \n-\t/* The caller *must* terminate their block with a DHCP_END character */\n-\tif ((used_bytes < 2) || ((uint8_t)data[used_bytes - 1] != DHCP_END)) {\n-\t\t/* Block too short or DHCP_END missing */\n+\t/*\n+\t * The caller *must* terminate their block with a EFX_DHCP_END\n+\t * character\n+\t */\n+\tif ((used_bytes < 2) || ((uint8_t)data[used_bytes - 1] !=\n+\t    EFX_DHCP_END)) {\n+\t\t/* Block too short or EFX_DHCP_END missing */\n \t\trc = ENOENT;\n \t\tgoto fail5;\n \t}\n@@ -528,13 +1067,13 @@ efx_bootcfg_write(\n \t\tgoto fail9;\n \n \t/*\n-\t * Insert the BOOTCFG sector into the partition, Zero out all data after\n-\t * the DHCP_END tag, and adjust the checksum.\n+\t * Insert the BOOTCFG sector into the partition, Zero out all data\n+\t * after the EFX_DHCP_END tag, and adjust the checksum.\n \t */\n \t(void) memset(partn_data + sector_offset, 0x0, sector_length);\n \t(void) memcpy(partn_data + sector_offset, data, used_bytes);\n \n-\tchecksum = efx_bootcfg_csum(enp, data, used_bytes);\n+\tchecksum = efx_dhcp_csum(data, used_bytes);\n \tpartn_data[sector_offset] -= checksum;\n \n \tif ((rc = efx_nvram_erase(enp, EFX_NVRAM_BOOTROM_CFG)) != 0)\n",
    "prefixes": [
        "18/37"
    ]
}