2 * Copyright (c) 2017 Broadcom. All rights reserved.
3 * The term "Broadcom" refers to Broadcom Limited and/or its subsidiaries.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
8 * 1. Redistributions of source code must retain the above copyright notice,
9 * this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright notice,
12 * this list of conditions and the following disclaimer in the documentation
13 * and/or other materials provided with the distribution.
15 * 3. Neither the name of the copyright holder nor the names of its contributors
16 * may be used to endorse or promote products derived from this software
17 * without specific prior written permission.
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
23 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
39 #if !defined(__OCS_VPD_H__)
43 * @brief VPD buffer structure
54 * @brief return next VPD byte
56 * Returns next VPD byte and updates accumulated checksum
58 * @param vpd pointer to vpd buffer
60 * @return returns next byte for success, or a negative error code value for failure.
65 vpdnext(vpdbuf_t *vpd)
68 if (vpd->offset < vpd->length) {
69 rc = vpd->buffer[vpd->offset++];
76 * @brief return true if no more vpd buffer data
78 * return true if the vpd buffer data has been completely consumed
80 * @param vpd pointer to vpd buffer
82 * @return returns true if no more data
86 vpddone(vpdbuf_t *vpd)
88 return vpd->offset >= vpd->length;
91 * @brief return pointer to current VPD data location
93 * Returns a pointer to the current location in the VPD data
95 * @param vpd pointer to vpd buffer
97 * @return pointer to current VPD data location
100 static inline uint8_t *
101 vpdref(vpdbuf_t *vpd)
103 return &vpd->buffer[vpd->offset];
106 #define VPD_LARGE_RESOURCE_TYPE_ID_STRING_TAG 0x82
107 #define VPD_LARGE_RESOURCE_TYPE_R_TAG 0x90
108 #define VPD_LARGE_RESOURCE_TYPE_W_TAG 0x91
109 #define VPD_SMALL_RESOURCE_TYPE_END_TAG 0x78
112 * @brief find a VPD entry
114 * Finds a VPD entry given the two character code
116 * @param vpddata pointer to raw vpd data buffer
117 * @param vpddata_length length of vpddata buffer in bytes
118 * @param key key to look up
120 * @return returns a pointer to the key location or NULL if not found or checksum error
123 static inline uint8_t *
124 ocs_find_vpd(uint8_t *vpddata, uint32_t vpddata_length, const char *key)
127 uint8_t *pret = NULL;
131 vpdbuf.buffer = (uint8_t*) vpddata;
132 vpdbuf.length = vpddata_length;
136 while (!vpddone(&vpdbuf)) {
137 int type = vpdnext(&vpdbuf);
143 if (type == VPD_SMALL_RESOURCE_TYPE_END_TAG) {
147 len_lo = vpdnext(&vpdbuf);
148 len_hi = vpdnext(&vpdbuf);
149 len = len_lo + (len_hi << 8);
151 if ((type == VPD_LARGE_RESOURCE_TYPE_R_TAG) || (type == VPD_LARGE_RESOURCE_TYPE_W_TAG)) {
158 rc0 = vpdnext(&vpdbuf);
159 rc1 = vpdnext(&vpdbuf);
161 /* Mark this location */
162 pstart = vpdref(&vpdbuf);
164 sublen = vpdnext(&vpdbuf);
166 /* Adjust remaining len */
169 /* check for match with request */
170 if ((c0 == rc0) && (c1 == rc1)) {
172 for (i = 0; i < sublen; i++) {
175 /* check for "RV" end */
176 } else if ('R' == rc0 && 'V' == rc1) {
178 /* Read the checksum */
179 for (i = 0; i < sublen; i++) {
183 /* The accumulated checksum should be zero here */
184 if (vpdbuf.checksum != 0) {
185 ocs_log_test(NULL, "checksum error\n");
190 for (i = 0; i < sublen; i++) {
196 for (i = 0; i < len; i++) {