2 * Copyright (c) 2012-2015 Solarflare Communications Inc.
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.
10 * 2. Redistributions in binary form must reproduce the above copyright notice,
11 * this list of conditions and the following disclaimer in the documentation
12 * and/or other materials provided with the distribution.
14 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
15 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
16 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
18 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
21 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
22 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
23 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
24 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 * The views and conclusions contained in the software and documentation are
27 * those of the authors and should not be interpreted as representing official
28 * policies, either expressed or implied, of the FreeBSD Project.
31 #include <sys/cdefs.h>
32 __FBSDID("$FreeBSD$");
36 #include "efx_types.h"
40 #if EFSYS_OPT_HUNTINGTON
42 #if EFSYS_OPT_VPD || EFSYS_OPT_NVRAM
44 #include "ef10_tlv_layout.h"
46 /* Cursor for TLV partition format */
47 typedef struct tlv_cursor_s {
48 uint32_t *block; /* Base of data block */
49 uint32_t *current; /* Cursor position */
50 uint32_t *end; /* End tag position */
51 uint32_t *limit; /* Last dword of data block */
54 static __checkReturn int
56 __in tlv_cursor_t *cursor);
60 * Operations on TLV formatted partition data.
64 __in tlv_cursor_t *cursor)
68 dword = cursor->current[0];
69 tag = __LE_TO_CPU_32(dword);
76 __in tlv_cursor_t *cursor)
78 uint32_t dword, length;
80 if (tlv_tag(cursor) == TLV_TAG_END)
83 dword = cursor->current[1];
84 length = __LE_TO_CPU_32(dword);
86 return ((size_t)length);
91 __in tlv_cursor_t *cursor)
93 if (tlv_tag(cursor) == TLV_TAG_END)
96 return ((uint8_t *)(&cursor->current[2]));
101 __in tlv_cursor_t *cursor)
103 if (tlv_tag(cursor) == TLV_TAG_END)
106 return ((uint8_t *)cursor->current);
110 * TLV item DWORD length is tag + length + value (rounded up to DWORD)
111 * equivalent to tlv_n_words_for_len in mc-comms tlv.c
113 #define TLV_DWORD_COUNT(length) \
114 (1 + 1 + (((length) + sizeof (uint32_t) - 1) / sizeof (uint32_t)))
119 __in tlv_cursor_t *cursor)
123 length = tlv_length(cursor);
125 return (cursor->current + TLV_DWORD_COUNT(length));
130 __in tlv_cursor_t *cursor)
134 if ((rc = tlv_validate_state(cursor)) != 0)
137 if (cursor->current == cursor->end) {
138 /* No more tags after END tag */
139 cursor->current = NULL;
144 /* Advance to next item and validate */
145 cursor->current = tlv_next_item_ptr(cursor);
147 if ((rc = tlv_validate_state(cursor)) != 0)
157 EFSYS_PROBE1(fail1, int, rc);
164 __in tlv_cursor_t *cursor)
168 cursor->current = cursor->block;
170 if ((rc = tlv_validate_state(cursor)) != 0)
176 EFSYS_PROBE1(fail1, int, rc);
183 __in tlv_cursor_t *cursor,
188 rc = tlv_rewind(cursor);
190 if (tlv_tag(cursor) == tag)
193 rc = tlv_advance(cursor);
198 static __checkReturn int
200 __in tlv_cursor_t *cursor)
204 /* Check cursor position */
205 if (cursor->current < cursor->block) {
209 if (cursor->current > cursor->limit) {
214 if (tlv_tag(cursor) != TLV_TAG_END) {
215 /* Check current item has space for tag and length */
216 if (cursor->current > (cursor->limit - 2)) {
217 cursor->current = NULL;
222 /* Check we have value data for current item and another tag */
223 if (tlv_next_item_ptr(cursor) > (cursor->limit - 1)) {
224 cursor->current = NULL;
239 EFSYS_PROBE1(fail1, int, rc);
246 __in tlv_cursor_t *cursor,
247 __in uint32_t *block,
248 __in uint32_t *limit)
250 cursor->block = block;
251 cursor->limit = limit;
253 cursor->current = cursor->block;
256 return (tlv_validate_state(cursor));
260 tlv_init_cursor_from_size(
261 __in tlv_cursor_t *cursor,
266 limit = (uint32_t *)(block + size - sizeof (uint32_t));
267 return (tlv_init_cursor(cursor, (uint32_t *)block, limit));
272 __in tlv_cursor_t *cursor)
277 if (cursor->end == NULL) {
278 pos = cursor->current;
279 if ((rc = tlv_find(cursor, TLV_TAG_END)) != 0)
282 cursor->end = cursor->current;
283 cursor->current = pos;
289 EFSYS_PROBE1(fail1, int, rc);
295 tlv_block_length_used(
296 __in tlv_cursor_t *cursor)
300 if ((rc = tlv_validate_state(cursor)) != 0)
303 if ((rc = tlv_require_end(cursor)) != 0)
306 /* Return space used (including the END tag) */
307 return (cursor->end + 1 - cursor->block) * sizeof (uint32_t);
312 EFSYS_PROBE1(fail1, int, rc);
318 static __checkReturn uint32_t *
320 __in tlv_cursor_t *cursor,
322 __in_bcount(size) uint8_t *data,
328 ptr = cursor->current;
330 *ptr++ = __CPU_TO_LE_32(tag);
331 *ptr++ = __CPU_TO_LE_32(len);
334 ptr[(len - 1) / sizeof (uint32_t)] = 0;
335 memcpy(ptr, data, len);
336 ptr += P2ROUNDUP(len, sizeof (uint32_t)) / sizeof (*ptr);
342 static __checkReturn int
344 __in tlv_cursor_t *cursor,
352 if ((rc = tlv_validate_state(cursor)) != 0)
355 if ((rc = tlv_require_end(cursor)) != 0)
358 if (tag == TLV_TAG_END) {
363 delta = TLV_DWORD_COUNT(size);
364 if (cursor->end + 1 + delta > cursor->limit) {
369 /* Move data up: new space at cursor->current */
370 memmove(cursor->current + delta, cursor->current,
371 (cursor->end + 1 - cursor->current) * sizeof (uint32_t));
373 /* Adjust the end pointer */
374 cursor->end += delta;
376 /* Write new TLV item */
377 tlv_write(cursor, tag, data, size);
388 EFSYS_PROBE1(fail1, int, rc);
393 static __checkReturn int
395 __in tlv_cursor_t *cursor,
401 unsigned int old_ndwords;
402 unsigned int new_ndwords;
406 if ((rc = tlv_validate_state(cursor)) != 0)
409 if (tlv_tag(cursor) == TLV_TAG_END) {
413 if (tlv_tag(cursor) != tag) {
418 old_ndwords = TLV_DWORD_COUNT(tlv_length(cursor));
419 new_ndwords = TLV_DWORD_COUNT(size);
421 if ((rc = tlv_require_end(cursor)) != 0)
424 if (new_ndwords > old_ndwords) {
425 /* Expand space used for TLV item */
426 delta = new_ndwords - old_ndwords;
427 pos = cursor->current + old_ndwords;
429 if (cursor->end + 1 + delta > cursor->limit) {
434 /* Move up: new space at (cursor->current + old_ndwords) */
435 memmove(pos + delta, pos,
436 (cursor->end + 1 - pos) * sizeof (uint32_t));
438 /* Adjust the end pointer */
439 cursor->end += delta;
441 } else if (new_ndwords < old_ndwords) {
442 /* Shrink space used for TLV item */
443 delta = old_ndwords - new_ndwords;
444 pos = cursor->current + new_ndwords;
446 /* Move down: remove words at (cursor->current + new_ndwords) */
447 memmove(pos, pos + delta,
448 (cursor->end + 1 - pos) * sizeof (uint32_t));
450 /* Zero the new space at the end of the TLV chain */
451 memset(cursor->end + 1 - delta, 0, delta * sizeof (uint32_t));
453 /* Adjust the end pointer */
454 cursor->end -= delta;
458 tlv_write(cursor, tag, data, size);
471 EFSYS_PROBE1(fail1, int, rc);
476 /* Validate TLV formatted partition contents (before writing to flash) */
478 efx_nvram_tlv_validate(
481 __in_bcount(partn_size) caddr_t partn_data,
482 __in size_t partn_size)
485 struct tlv_partition_header *header;
486 struct tlv_partition_trailer *trailer;
492 EFX_STATIC_ASSERT(sizeof (*header) <= HUNTINGTON_NVRAM_CHUNK);
494 if ((partn_data == NULL) || (partn_size == 0)) {
499 /* The partition header must be the first item (at offset zero) */
500 if ((rc = tlv_init_cursor_from_size(&cursor, partn_data,
505 if (tlv_tag(&cursor) != TLV_TAG_PARTITION_HEADER) {
509 header = (struct tlv_partition_header *)tlv_item(&cursor);
511 /* Check TLV partition length (includes the END tag) */
512 total_length = __LE_TO_CPU_32(header->total_length);
513 if (total_length > partn_size) {
518 /* Check partition ends with PARTITION_TRAILER and END tags */
519 if ((rc = tlv_find(&cursor, TLV_TAG_PARTITION_TRAILER)) != 0) {
523 trailer = (struct tlv_partition_trailer *)tlv_item(&cursor);
525 if ((rc = tlv_advance(&cursor)) != 0) {
529 if (tlv_tag(&cursor) != TLV_TAG_END) {
534 /* Check generation counts are consistent */
535 if (trailer->generation != header->generation) {
540 /* Verify partition checksum */
542 for (pos = 0; (size_t)pos < total_length; pos += sizeof (uint32_t)) {
543 cksum += *((uint32_t *)(partn_data + pos));
569 EFSYS_PROBE1(fail1, int, rc);
574 /* Read and validate an entire TLV formatted partition */
575 static __checkReturn int
576 hunt_nvram_read_tlv_partition(
579 __in_bcount(partn_size) caddr_t partn_data,
580 __in size_t partn_size)
583 struct tlv_partition_header *header;
584 struct tlv_partition_trailer *trailer;
590 EFX_STATIC_ASSERT(sizeof (*header) <= HUNTINGTON_NVRAM_CHUNK);
592 if ((partn_data == NULL) || (partn_size == 0)) {
597 /* Read initial chunk of partition */
598 if ((rc = hunt_nvram_partn_read(enp, partn, 0, partn_data,
599 HUNTINGTON_NVRAM_CHUNK)) != 0) {
603 /* The partition header must be the first item (at offset zero) */
604 if ((rc = tlv_init_cursor_from_size(&cursor, partn_data,
609 if (tlv_tag(&cursor) != TLV_TAG_PARTITION_HEADER) {
613 header = (struct tlv_partition_header *)tlv_item(&cursor);
615 /* Check TLV partition length (includes the END tag) */
616 total_length = __LE_TO_CPU_32(header->total_length);
617 if (total_length > partn_size) {
622 /* Read the remaining partition content */
623 if (total_length > HUNTINGTON_NVRAM_CHUNK) {
624 if ((rc = hunt_nvram_partn_read(enp, partn,
625 HUNTINGTON_NVRAM_CHUNK,
626 partn_data + HUNTINGTON_NVRAM_CHUNK,
627 total_length - HUNTINGTON_NVRAM_CHUNK)) != 0)
631 /* Check partition ends with PARTITION_TRAILER and END tags */
632 if ((rc = tlv_find(&cursor, TLV_TAG_PARTITION_TRAILER)) != 0) {
636 trailer = (struct tlv_partition_trailer *)tlv_item(&cursor);
638 if ((rc = tlv_advance(&cursor)) != 0) {
642 if (tlv_tag(&cursor) != TLV_TAG_END) {
647 /* Check data read from partition is consistent */
648 if (trailer->generation != header->generation) {
650 * The partition data may have been modified between successive
651 * MCDI NVRAM_READ requests by the MC or another PCI function.
653 * The caller must retry to obtain consistent partition data.
659 /* Verify partition checksum */
661 for (pos = 0; (size_t)pos < total_length; pos += sizeof (uint32_t)) {
662 cksum += *((uint32_t *)(partn_data + pos));
692 EFSYS_PROBE1(fail1, int, rc);
698 * Read a single TLV item from a host memory
699 * buffer containing a TLV formatted partition.
702 hunt_nvram_buf_read_tlv(
704 __in_bcount(partn_size) caddr_t partn_data,
705 __in size_t partn_size,
707 __deref_out_bcount_opt(*sizep) caddr_t *datap,
716 if ((partn_data == NULL) || (partn_size == 0)) {
721 /* Find requested TLV tag in partition data */
722 if ((rc = tlv_init_cursor_from_size(&cursor, partn_data,
727 if ((rc = tlv_find(&cursor, tag)) != 0) {
731 value = tlv_value(&cursor);
732 length = tlv_length(&cursor);
737 /* Copy out data from TLV item */
738 EFSYS_KMEM_ALLOC(enp->en_esip, length, data);
743 memcpy(data, value, length);
758 EFSYS_PROBE1(fail1, int, rc);
765 /* Read a single TLV item from a TLV formatted partition */
767 hunt_nvram_partn_read_tlv(
771 __deref_out_bcount_opt(*sizep) caddr_t *datap,
774 caddr_t partn_data = NULL;
775 size_t partn_size = 0;
781 /* Allocate sufficient memory for the entire partition */
782 if ((rc = hunt_nvram_partn_size(enp, partn, &partn_size)) != 0)
785 if (partn_size == 0) {
790 EFSYS_KMEM_ALLOC(enp->en_esip, partn_size, partn_data);
791 if (partn_data == NULL) {
797 * Read the entire TLV partition. Retry until consistent partition
798 * contents are returned. Inconsistent data may be read if:
799 * a) the partition contents are invalid
800 * b) the MC has rebooted while we were reading the partition
801 * c) the partition has been modified while we were reading it
802 * Limit retry attempts to ensure forward progress.
806 rc = hunt_nvram_read_tlv_partition(enp, partn,
807 partn_data, partn_size);
808 } while ((rc == EAGAIN) && (--retry > 0));
811 /* Failed to obtain consistent partition data */
815 if ((rc = hunt_nvram_buf_read_tlv(enp, partn_data, partn_size,
816 tag, &data, &length)) != 0)
819 EFSYS_KMEM_FREE(enp->en_esip, partn_size, partn_data);
831 EFSYS_KMEM_FREE(enp->en_esip, partn_size, partn_data);
837 EFSYS_PROBE1(fail1, int, rc);
843 * Add or update a single TLV item in a host memory buffer containing a TLV
844 * formatted partition.
847 hunt_nvram_buf_write_tlv(
848 __inout_bcount(partn_size) caddr_t partn_data,
849 __in size_t partn_size,
851 __in_bcount(tag_size) caddr_t tag_data,
852 __in size_t tag_size,
853 __out size_t *total_lengthp)
856 struct tlv_partition_header *header;
857 struct tlv_partition_trailer *trailer;
863 /* The partition header must be the first item (at offset zero) */
864 if ((rc = tlv_init_cursor_from_size(&cursor, partn_data,
869 if (tlv_tag(&cursor) != TLV_TAG_PARTITION_HEADER) {
873 header = (struct tlv_partition_header *)tlv_item(&cursor);
875 /* Update the TLV chain to contain the new data */
876 if ((rc = tlv_find(&cursor, tag)) == 0) {
877 /* Modify existing TLV item */
878 if ((rc = tlv_modify(&cursor, tag,
879 tag_data, tag_size)) != 0)
882 /* Insert a new TLV item before the PARTITION_TRAILER */
883 rc = tlv_find(&cursor, TLV_TAG_PARTITION_TRAILER);
888 if ((rc = tlv_insert(&cursor, tag,
889 tag_data, tag_size)) != 0) {
895 /* Find the trailer tag */
896 if ((rc = tlv_find(&cursor, TLV_TAG_PARTITION_TRAILER)) != 0) {
900 trailer = (struct tlv_partition_trailer *)tlv_item(&cursor);
902 /* Update PARTITION_HEADER and PARTITION_TRAILER fields */
903 *total_lengthp = tlv_block_length_used(&cursor);
904 EFSYS_ASSERT3U(*total_lengthp, <=, partn_size);
905 generation = __LE_TO_CPU_32(header->generation) + 1;
907 header->total_length = __CPU_TO_LE_32(*total_lengthp);
908 header->generation = __CPU_TO_LE_32(generation);
909 trailer->generation = __CPU_TO_LE_32(generation);
911 /* Recompute PARTITION_TRAILER checksum */
912 trailer->checksum = 0;
914 for (pos = 0; (size_t)pos < *total_lengthp; pos += sizeof (uint32_t)) {
915 cksum += *((uint32_t *)(partn_data + pos));
917 trailer->checksum = ~cksum + 1;
932 EFSYS_PROBE1(fail1, int, rc);
937 /* Add or update a single TLV item in a TLV formatted partition */
939 hunt_nvram_partn_write_tlv(
943 __in_bcount(size) caddr_t data,
951 EFSYS_ASSERT3U(partn, ==, NVRAM_PARTITION_TYPE_DYNAMIC_CONFIG);
953 /* Allocate sufficient memory for the entire partition */
954 if ((rc = hunt_nvram_partn_size(enp, partn, &partn_size)) != 0)
957 EFSYS_KMEM_ALLOC(enp->en_esip, partn_size, partn_data);
958 if (partn_data == NULL) {
963 /* Lock the partition */
964 if ((rc = hunt_nvram_partn_lock(enp, partn)) != 0)
967 /* Read the partition contents (no need to retry when locked). */
968 if ((rc = hunt_nvram_read_tlv_partition(enp, partn,
969 partn_data, partn_size)) != 0) {
970 /* Failed to obtain consistent partition data */
974 /* Update the contents in memory */
975 if ((rc = hunt_nvram_buf_write_tlv(partn_data, partn_size,
976 tag, data, size, &total_length)) != 0)
979 /* Erase the whole partition */
980 if ((rc = hunt_nvram_partn_erase(enp, partn, 0, partn_size)) != 0)
983 /* Write new partition contents to NVRAM */
984 if ((rc = hunt_nvram_partn_write(enp, partn, 0, partn_data,
988 /* Unlock the partition */
989 hunt_nvram_partn_unlock(enp, partn);
991 EFSYS_KMEM_FREE(enp->en_esip, partn_size, partn_data);
1004 hunt_nvram_partn_unlock(enp, partn);
1008 EFSYS_KMEM_FREE(enp->en_esip, partn_size, partn_data);
1012 EFSYS_PROBE1(fail1, int, rc);
1018 hunt_nvram_partn_size(
1019 __in efx_nic_t *enp,
1020 __in unsigned int partn,
1021 __out size_t *sizep)
1025 if ((rc = efx_mcdi_nvram_info(enp, partn, sizep, NULL, NULL)) != 0)
1031 EFSYS_PROBE1(fail1, int, rc);
1037 hunt_nvram_partn_lock(
1038 __in efx_nic_t *enp,
1039 __in unsigned int partn)
1043 if ((rc = efx_mcdi_nvram_update_start(enp, partn)) != 0)
1049 EFSYS_PROBE1(fail1, int, rc);
1055 hunt_nvram_partn_read(
1056 __in efx_nic_t *enp,
1057 __in unsigned int partn,
1058 __in unsigned int offset,
1059 __out_bcount(size) caddr_t data,
1066 chunk = MIN(size, HUNTINGTON_NVRAM_CHUNK);
1068 if ((rc = efx_mcdi_nvram_read(enp, partn, offset,
1069 data, chunk)) != 0) {
1081 EFSYS_PROBE1(fail1, int, rc);
1087 hunt_nvram_partn_erase(
1088 __in efx_nic_t *enp,
1089 __in unsigned int partn,
1090 __in unsigned int offset,
1095 if ((rc = efx_mcdi_nvram_erase(enp, partn, offset, size)) != 0)
1101 EFSYS_PROBE1(fail1, int, rc);
1107 hunt_nvram_partn_write(
1108 __in efx_nic_t *enp,
1109 __in unsigned int partn,
1110 __in unsigned int offset,
1111 __out_bcount(size) caddr_t data,
1118 chunk = MIN(size, HUNTINGTON_NVRAM_CHUNK);
1120 if ((rc = efx_mcdi_nvram_write(enp, partn, offset,
1121 data, chunk)) != 0) {
1133 EFSYS_PROBE1(fail1, int, rc);
1139 hunt_nvram_partn_unlock(
1140 __in efx_nic_t *enp,
1141 __in unsigned int partn)
1147 if ((rc = efx_mcdi_nvram_update_finish(enp, partn, reboot)) != 0)
1153 EFSYS_PROBE1(fail1, int, rc);
1157 hunt_nvram_partn_set_version(
1158 __in efx_nic_t *enp,
1159 __in unsigned int partn,
1160 __in_ecount(4) uint16_t version[4])
1162 struct tlv_partition_version partn_version;
1166 /* Add or modify partition version TLV item */
1167 partn_version.version_w = __CPU_TO_LE_16(version[0]);
1168 partn_version.version_x = __CPU_TO_LE_16(version[1]);
1169 partn_version.version_y = __CPU_TO_LE_16(version[2]);
1170 partn_version.version_z = __CPU_TO_LE_16(version[3]);
1172 size = sizeof (partn_version) - (2 * sizeof (uint32_t));
1174 if ((rc = hunt_nvram_partn_write_tlv(enp,
1175 NVRAM_PARTITION_TYPE_DYNAMIC_CONFIG,
1176 TLV_TAG_PARTITION_VERSION(partn),
1177 (caddr_t)&partn_version.version_w, size)) != 0)
1183 EFSYS_PROBE1(fail1, int, rc);
1188 #endif /* EFSYS_OPT_VPD || EFSYS_OPT_NVRAM */
1192 typedef struct hunt_parttbl_entry_s {
1195 efx_nvram_type_t nvtype;
1196 } hunt_parttbl_entry_t;
1198 /* Translate EFX NVRAM types to firmware partition types */
1199 static hunt_parttbl_entry_t hunt_parttbl[] = {
1200 {NVRAM_PARTITION_TYPE_MC_FIRMWARE, 1, EFX_NVRAM_MC_FIRMWARE},
1201 {NVRAM_PARTITION_TYPE_MC_FIRMWARE, 2, EFX_NVRAM_MC_FIRMWARE},
1202 {NVRAM_PARTITION_TYPE_MC_FIRMWARE, 3, EFX_NVRAM_MC_FIRMWARE},
1203 {NVRAM_PARTITION_TYPE_MC_FIRMWARE, 4, EFX_NVRAM_MC_FIRMWARE},
1204 {NVRAM_PARTITION_TYPE_MC_FIRMWARE_BACKUP, 1, EFX_NVRAM_MC_GOLDEN},
1205 {NVRAM_PARTITION_TYPE_MC_FIRMWARE_BACKUP, 2, EFX_NVRAM_MC_GOLDEN},
1206 {NVRAM_PARTITION_TYPE_MC_FIRMWARE_BACKUP, 3, EFX_NVRAM_MC_GOLDEN},
1207 {NVRAM_PARTITION_TYPE_MC_FIRMWARE_BACKUP, 4, EFX_NVRAM_MC_GOLDEN},
1208 {NVRAM_PARTITION_TYPE_EXPANSION_ROM, 1, EFX_NVRAM_BOOTROM},
1209 {NVRAM_PARTITION_TYPE_EXPANSION_ROM, 2, EFX_NVRAM_BOOTROM},
1210 {NVRAM_PARTITION_TYPE_EXPANSION_ROM, 3, EFX_NVRAM_BOOTROM},
1211 {NVRAM_PARTITION_TYPE_EXPANSION_ROM, 4, EFX_NVRAM_BOOTROM},
1212 {NVRAM_PARTITION_TYPE_EXPROM_CONFIG_PORT0, 1, EFX_NVRAM_BOOTROM_CFG},
1213 {NVRAM_PARTITION_TYPE_EXPROM_CONFIG_PORT1, 2, EFX_NVRAM_BOOTROM_CFG},
1214 {NVRAM_PARTITION_TYPE_EXPROM_CONFIG_PORT2, 3, EFX_NVRAM_BOOTROM_CFG},
1215 {NVRAM_PARTITION_TYPE_EXPROM_CONFIG_PORT3, 4, EFX_NVRAM_BOOTROM_CFG},
1216 {NVRAM_PARTITION_TYPE_DYNAMIC_CONFIG, 1, EFX_NVRAM_DYNAMIC_CFG},
1217 {NVRAM_PARTITION_TYPE_DYNAMIC_CONFIG, 2, EFX_NVRAM_DYNAMIC_CFG},
1218 {NVRAM_PARTITION_TYPE_DYNAMIC_CONFIG, 3, EFX_NVRAM_DYNAMIC_CFG},
1219 {NVRAM_PARTITION_TYPE_DYNAMIC_CONFIG, 4, EFX_NVRAM_DYNAMIC_CFG}
1222 static __checkReturn hunt_parttbl_entry_t *
1224 __in efx_nic_t *enp,
1225 __in efx_nvram_type_t type)
1227 efx_mcdi_iface_t *emip = &(enp->en_mcdi.em_emip);
1228 hunt_parttbl_entry_t *entry;
1231 EFSYS_ASSERT3U(type, <, EFX_NVRAM_NTYPES);
1233 for (i = 0; i < EFX_ARRAY_SIZE(hunt_parttbl); i++) {
1234 entry = &hunt_parttbl[i];
1236 if (entry->port == emip->emi_port && entry->nvtype == type)
1248 __in efx_nic_t *enp)
1250 efx_mcdi_iface_t *emip = &(enp->en_mcdi.em_emip);
1251 hunt_parttbl_entry_t *entry;
1252 unsigned int npartns = 0;
1253 uint32_t *partns = NULL;
1259 /* Find supported partitions */
1260 size = MC_CMD_NVRAM_PARTITIONS_OUT_TYPE_ID_MAXNUM * sizeof (uint32_t);
1261 EFSYS_KMEM_ALLOC(enp->en_esip, size, partns);
1262 if (partns == NULL) {
1267 if ((rc = efx_mcdi_nvram_partitions(enp, (caddr_t)partns, size,
1273 * Iterate over the list of supported partition types
1274 * applicable to *this* port
1276 for (i = 0; i < EFX_ARRAY_SIZE(hunt_parttbl); i++) {
1277 entry = &hunt_parttbl[i];
1279 if (entry->port != emip->emi_port)
1282 for (j = 0; j < npartns; j++) {
1283 if (entry->partn == partns[j]) {
1284 rc = efx_mcdi_nvram_test(enp, entry->partn);
1291 EFSYS_KMEM_FREE(enp->en_esip, size, partns);
1298 EFSYS_KMEM_FREE(enp->en_esip, size, partns);
1300 EFSYS_PROBE1(fail1, int, rc);
1304 #endif /* EFSYS_OPT_DIAG */
1308 __in efx_nic_t *enp,
1309 __in efx_nvram_type_t type,
1310 __out size_t *sizep)
1312 hunt_parttbl_entry_t *entry;
1316 if ((entry = hunt_parttbl_entry(enp, type)) == NULL) {
1320 partn = entry->partn;
1322 if ((rc = hunt_nvram_partn_size(enp, partn, sizep)) != 0)
1330 EFSYS_PROBE1(fail1, int, rc);
1338 hunt_nvram_get_version(
1339 __in efx_nic_t *enp,
1340 __in efx_nvram_type_t type,
1341 __out uint32_t *subtypep,
1342 __out_ecount(4) uint16_t version[4])
1344 hunt_parttbl_entry_t *entry;
1348 if ((entry = hunt_parttbl_entry(enp, type)) == NULL) {
1352 partn = entry->partn;
1354 /* FIXME: get highest partn version from all ports */
1355 /* FIXME: return partn description if available */
1357 if ((rc = efx_mcdi_nvram_metadata(enp, partn, subtypep,
1358 version, NULL, 0)) != 0)
1366 EFSYS_PROBE1(fail1, int, rc);
1372 hunt_nvram_rw_start(
1373 __in efx_nic_t *enp,
1374 __in efx_nvram_type_t type,
1375 __out size_t *chunk_sizep)
1377 hunt_parttbl_entry_t *entry;
1381 if ((entry = hunt_parttbl_entry(enp, type)) == NULL) {
1385 partn = entry->partn;
1387 if ((rc = hunt_nvram_partn_lock(enp, partn)) != 0)
1390 if (chunk_sizep != NULL)
1391 *chunk_sizep = HUNTINGTON_NVRAM_CHUNK;
1398 EFSYS_PROBE1(fail1, int, rc);
1404 hunt_nvram_read_chunk(
1405 __in efx_nic_t *enp,
1406 __in efx_nvram_type_t type,
1407 __in unsigned int offset,
1408 __out_bcount(size) caddr_t data,
1411 hunt_parttbl_entry_t *entry;
1414 if ((entry = hunt_parttbl_entry(enp, type)) == NULL) {
1419 if ((rc = hunt_nvram_partn_read(enp, entry->partn,
1420 offset, data, size)) != 0)
1428 EFSYS_PROBE1(fail1, int, rc);
1435 __in efx_nic_t *enp,
1436 __in efx_nvram_type_t type)
1438 hunt_parttbl_entry_t *entry;
1442 if ((entry = hunt_parttbl_entry(enp, type)) == NULL) {
1447 if ((rc = hunt_nvram_partn_size(enp, entry->partn, &size)) != 0)
1450 if ((rc = hunt_nvram_partn_erase(enp, entry->partn, 0, size)) != 0)
1460 EFSYS_PROBE1(fail1, int, rc);
1466 hunt_nvram_write_chunk(
1467 __in efx_nic_t *enp,
1468 __in efx_nvram_type_t type,
1469 __in unsigned int offset,
1470 __in_bcount(size) caddr_t data,
1473 hunt_parttbl_entry_t *entry;
1476 if ((entry = hunt_parttbl_entry(enp, type)) == NULL) {
1481 if ((rc = hunt_nvram_partn_write(enp, entry->partn,
1482 offset, data, size)) != 0)
1490 EFSYS_PROBE1(fail1, int, rc);
1496 hunt_nvram_rw_finish(
1497 __in efx_nic_t *enp,
1498 __in efx_nvram_type_t type)
1500 hunt_parttbl_entry_t *entry;
1502 if ((entry = hunt_parttbl_entry(enp, type)) != NULL)
1503 hunt_nvram_partn_unlock(enp, entry->partn);
1507 hunt_nvram_set_version(
1508 __in efx_nic_t *enp,
1509 __in efx_nvram_type_t type,
1510 __in_ecount(4) uint16_t version[4])
1512 hunt_parttbl_entry_t *entry;
1516 if ((entry = hunt_parttbl_entry(enp, type)) == NULL) {
1520 partn = entry->partn;
1522 if ((rc = hunt_nvram_partn_set_version(enp, partn, version)) != 0)
1531 EFSYS_PROBE1(fail1, int, rc);
1536 #endif /* EFSYS_OPT_NVRAM */
1538 #endif /* EFSYS_OPT_HUNTINGTON */