From bb5c3b169113773bc932725af0b8c3be3fdcb5eb Mon Sep 17 00:00:00 2001 From: Richard Houldsworth Date: Mon, 10 Sep 2018 10:33:19 +0100 Subject: [PATCH] net/sfc/base: generalise EF10 NVRAM buffer interface The SFN driver's PartitionControl WMI object requires an API to parse and filter partition data in TLV format, particularly for the Dynamic Config partition. The ef10_nvram_buffer functions provide this functionality but are tied to use with license partition only. Modify functions so they are applicable to all TLV partitions and add functions to support in-place tag modification. Signed-off-by: Richard Houldsworth Signed-off-by: Andrew Rybchenko --- drivers/net/sfc/base/ef10_impl.h | 43 +++++++-- drivers/net/sfc/base/ef10_nvram.c | 153 ++++++++++++++++++++++++------ drivers/net/sfc/base/efx_impl.h | 2 +- drivers/net/sfc/base/efx_lic.c | 15 ++- drivers/net/sfc/base/efx_nvram.c | 2 +- 5 files changed, 174 insertions(+), 41 deletions(-) diff --git a/drivers/net/sfc/base/ef10_impl.h b/drivers/net/sfc/base/ef10_impl.h index 2abd699a09..503f023621 100644 --- a/drivers/net/sfc/base/ef10_impl.h +++ b/drivers/net/sfc/base/ef10_impl.h @@ -477,17 +477,21 @@ ef10_nvram_partn_set_version( extern __checkReturn efx_rc_t ef10_nvram_buffer_validate( - __in efx_nic_t *enp, __in uint32_t partn, __in_bcount(buffer_size) caddr_t bufferp, __in size_t buffer_size); +extern void +ef10_nvram_buffer_init( + __out_bcount(buffer_size) + caddr_t bufferp, + __in size_t buffer_size); + extern __checkReturn efx_rc_t ef10_nvram_buffer_create( - __in efx_nic_t *enp, - __in uint16_t partn_type, - __in_bcount(buffer_size) + __in uint32_t partn_type, + __out_bcount(buffer_size) caddr_t bufferp, __in size_t buffer_size); @@ -515,6 +519,16 @@ ef10_nvram_buffer_find_item( __out uint32_t *startp, __out uint32_t *lengthp); +extern __checkReturn efx_rc_t +ef10_nvram_buffer_peek_item( + __in_bcount(buffer_size) + caddr_t bufferp, + __in size_t buffer_size, + __in uint32_t offset, + __out uint32_t *tagp, + __out uint32_t *lengthp, + __out uint32_t *value_offsetp); + extern __checkReturn efx_rc_t ef10_nvram_buffer_get_item( __in_bcount(buffer_size) @@ -522,9 +536,10 @@ ef10_nvram_buffer_get_item( __in size_t buffer_size, __in uint32_t offset, __in uint32_t length, - __out_bcount_part(item_max_size, *lengthp) - caddr_t itemp, - __in size_t item_max_size, + __out uint32_t *tagp, + __out_bcount_part(value_max_size, *lengthp) + caddr_t valuep, + __in size_t value_max_size, __out uint32_t *lengthp); extern __checkReturn efx_rc_t @@ -533,7 +548,19 @@ ef10_nvram_buffer_insert_item( caddr_t bufferp, __in size_t buffer_size, __in uint32_t offset, - __in_bcount(length) caddr_t keyp, + __in uint32_t tag, + __in_bcount(length) caddr_t valuep, + __in uint32_t length, + __out uint32_t *lengthp); + +extern __checkReturn efx_rc_t +ef10_nvram_buffer_modify_item( + __in_bcount(buffer_size) + caddr_t bufferp, + __in size_t buffer_size, + __in uint32_t offset, + __in uint32_t tag, + __in_bcount(length) caddr_t valuep, __in uint32_t length, __out uint32_t *lengthp); diff --git a/drivers/net/sfc/base/ef10_nvram.c b/drivers/net/sfc/base/ef10_nvram.c index 96ea5624a7..8d1b64f250 100644 --- a/drivers/net/sfc/base/ef10_nvram.c +++ b/drivers/net/sfc/base/ef10_nvram.c @@ -203,14 +203,14 @@ tlv_validate_state( if (tlv_tag(cursor) != TLV_TAG_END) { /* Check current item has space for tag and length */ - if (cursor->current > (cursor->limit - 2)) { + if (cursor->current > (cursor->limit - 1)) { cursor->current = NULL; rc = EFAULT; goto fail3; } - /* Check we have value data for current item and another tag */ - if (tlv_next_item_ptr(cursor) > (cursor->limit - 1)) { + /* Check we have value data for current item and an END tag */ + if (tlv_next_item_ptr(cursor) > cursor->limit) { cursor->current = NULL; rc = EFAULT; goto fail4; @@ -635,7 +635,6 @@ fail1: /* Validate buffer contents (before writing to flash) */ __checkReturn efx_rc_t ef10_nvram_buffer_validate( - __in efx_nic_t *enp, __in uint32_t partn, __in_bcount(partn_size) caddr_t partn_data, __in size_t partn_size) @@ -648,7 +647,6 @@ ef10_nvram_buffer_validate( int pos; efx_rc_t rc; - _NOTE(ARGUNUSED(enp, partn)) EFX_STATIC_ASSERT(sizeof (*header) <= EF10_NVRAM_CHUNK); if ((partn_data == NULL) || (partn_size == 0)) { @@ -675,26 +673,32 @@ ef10_nvram_buffer_validate( goto fail4; } + /* Check partition header matches partn */ + if (__LE_TO_CPU_16(header->type_id) != partn) { + rc = EINVAL; + goto fail5; + } + /* Check partition ends with PARTITION_TRAILER and END tags */ if ((rc = tlv_find(&cursor, TLV_TAG_PARTITION_TRAILER)) != 0) { rc = EINVAL; - goto fail5; + goto fail6; } trailer = (struct tlv_partition_trailer *)tlv_item(&cursor); if ((rc = tlv_advance(&cursor)) != 0) { rc = EINVAL; - goto fail6; + goto fail7; } if (tlv_tag(&cursor) != TLV_TAG_END) { rc = EINVAL; - goto fail7; + goto fail8; } /* Check generation counts are consistent */ if (trailer->generation != header->generation) { rc = EINVAL; - goto fail8; + goto fail9; } /* Verify partition checksum */ @@ -704,11 +708,13 @@ ef10_nvram_buffer_validate( } if (cksum != 0) { rc = EINVAL; - goto fail9; + goto fail10; } return (0); +fail10: + EFSYS_PROBE(fail10); fail9: EFSYS_PROBE(fail9); fail8: @@ -731,13 +737,24 @@ fail1: return (rc); } + void +ef10_nvram_buffer_init( + __out_bcount(buffer_size) + caddr_t bufferp, + __in size_t buffer_size) +{ + uint32_t *buf = (uint32_t *)bufferp; + + memset(buf, 0xff, buffer_size); + tlv_init_block(buf); +} __checkReturn efx_rc_t ef10_nvram_buffer_create( - __in efx_nic_t *enp, - __in uint16_t partn_type, - __in_bcount(partn_size) caddr_t partn_data, + __in uint32_t partn_type, + __out_bcount(partn_size) + caddr_t partn_data, __in size_t partn_size) { uint32_t *buf = (uint32_t *)partn_data; @@ -753,9 +770,8 @@ ef10_nvram_buffer_create( goto fail1; } - memset(buf, 0xff, partn_size); + ef10_nvram_buffer_init(partn_data, partn_size); - tlv_init_block(buf); if ((rc = tlv_init_cursor(&cursor, buf, (uint32_t *)((uint8_t *)buf + partn_size), buf)) != 0) { @@ -787,7 +803,7 @@ ef10_nvram_buffer_create( goto fail6; /* Check that the partition is valid. */ - if ((rc = ef10_nvram_buffer_validate(enp, partn_type, + if ((rc = ef10_nvram_buffer_validate(partn_type, partn_data, partn_size)) != 0) goto fail7; @@ -958,6 +974,48 @@ ef10_nvram_buffer_find_item( return (B_FALSE); } + __checkReturn efx_rc_t +ef10_nvram_buffer_peek_item( + __in_bcount(buffer_size) + caddr_t bufferp, + __in size_t buffer_size, + __in uint32_t offset, + __out uint32_t *tagp, + __out uint32_t *lengthp, + __out uint32_t *value_offsetp) +{ + efx_rc_t rc; + tlv_cursor_t cursor; + uint32_t tag; + + if ((rc = tlv_init_cursor_at_offset(&cursor, (uint8_t *)bufferp, + buffer_size, offset)) != 0) { + goto fail1; + } + + tag = tlv_tag(&cursor); + *tagp = tag; + if (tag == TLV_TAG_END) { + /* + * To allow stepping over the END tag, report the full tag + * length and a zero length value. + */ + *lengthp = sizeof (tag); + *value_offsetp = sizeof (tag); + } else { + *lengthp = byte_offset(tlv_next_item_ptr(&cursor), + cursor.current); + *value_offsetp = byte_offset((uint32_t *)tlv_value(&cursor), + cursor.current); + } + return (0); + +fail1: + EFSYS_PROBE1(fail1, efx_rc_t, rc); + + return (rc); +} + __checkReturn efx_rc_t ef10_nvram_buffer_get_item( __in_bcount(buffer_size) @@ -965,16 +1023,17 @@ ef10_nvram_buffer_get_item( __in size_t buffer_size, __in uint32_t offset, __in uint32_t length, - __out_bcount_part(item_max_size, *lengthp) - caddr_t itemp, - __in size_t item_max_size, + __out uint32_t *tagp, + __out_bcount_part(value_max_size, *lengthp) + caddr_t valuep, + __in size_t value_max_size, __out uint32_t *lengthp) { efx_rc_t rc; tlv_cursor_t cursor; - uint32_t item_length; + uint32_t value_length; - if (item_max_size < length) { + if (buffer_size < (offset + length)) { rc = ENOSPC; goto fail1; } @@ -984,14 +1043,15 @@ ef10_nvram_buffer_get_item( goto fail2; } - item_length = tlv_length(&cursor); - if (length < item_length) { + value_length = tlv_length(&cursor); + if (value_max_size < value_length) { rc = ENOSPC; goto fail3; } - memcpy(itemp, tlv_value(&cursor), item_length); + memcpy(valuep, tlv_value(&cursor), value_length); - *lengthp = item_length; + *tagp = tlv_tag(&cursor); + *lengthp = value_length; return (0); @@ -1011,7 +1071,8 @@ ef10_nvram_buffer_insert_item( caddr_t bufferp, __in size_t buffer_size, __in uint32_t offset, - __in_bcount(length) caddr_t keyp, + __in uint32_t tag, + __in_bcount(length) caddr_t valuep, __in uint32_t length, __out uint32_t *lengthp) { @@ -1023,7 +1084,44 @@ ef10_nvram_buffer_insert_item( goto fail1; } - rc = tlv_insert(&cursor, TLV_TAG_LICENSE, (uint8_t *)keyp, length); + rc = tlv_insert(&cursor, tag, (uint8_t *)valuep, length); + + if (rc != 0) + goto fail2; + + *lengthp = byte_offset(tlv_next_item_ptr(&cursor), + cursor.current); + + return (0); + +fail2: + EFSYS_PROBE(fail2); +fail1: + EFSYS_PROBE1(fail1, efx_rc_t, rc); + + return (rc); +} + + __checkReturn efx_rc_t +ef10_nvram_buffer_modify_item( + __in_bcount(buffer_size) + caddr_t bufferp, + __in size_t buffer_size, + __in uint32_t offset, + __in uint32_t tag, + __in_bcount(length) caddr_t valuep, + __in uint32_t length, + __out uint32_t *lengthp) +{ + efx_rc_t rc; + tlv_cursor_t cursor; + + if ((rc = tlv_init_cursor_at_offset(&cursor, (uint8_t *)bufferp, + buffer_size, offset)) != 0) { + goto fail1; + } + + rc = tlv_modify(&cursor, tag, (uint8_t *)valuep, length); if (rc != 0) { goto fail2; @@ -1042,6 +1140,7 @@ fail1: return (rc); } + __checkReturn efx_rc_t ef10_nvram_buffer_delete_item( __in_bcount(buffer_size) diff --git a/drivers/net/sfc/base/efx_impl.h b/drivers/net/sfc/base/efx_impl.h index 0764df5de2..78df430182 100644 --- a/drivers/net/sfc/base/efx_impl.h +++ b/drivers/net/sfc/base/efx_impl.h @@ -509,7 +509,7 @@ typedef struct efx_nvram_ops_s { uint32_t *, uint16_t *); efx_rc_t (*envo_partn_set_version)(efx_nic_t *, uint32_t, uint16_t *); - efx_rc_t (*envo_buffer_validate)(efx_nic_t *, uint32_t, + efx_rc_t (*envo_buffer_validate)(uint32_t, caddr_t, size_t); } efx_nvram_ops_t; #endif /* EFSYS_OPT_NVRAM */ diff --git a/drivers/net/sfc/base/efx_lic.c b/drivers/net/sfc/base/efx_lic.c index 49c00347f7..2b06e2d1e2 100644 --- a/drivers/net/sfc/base/efx_lic.c +++ b/drivers/net/sfc/base/efx_lic.c @@ -1158,10 +1158,12 @@ efx_lic_v3_read_key( __in size_t key_max_size, __out uint32_t *lengthp) { + uint32_t tag; + _NOTE(ARGUNUSED(enp)) return ef10_nvram_buffer_get_item(bufferp, buffer_size, - offset, length, keyp, key_max_size, lengthp); + offset, length, &tag, keyp, key_max_size, lengthp); } __checkReturn efx_rc_t @@ -1179,7 +1181,7 @@ efx_lic_v3_write_key( EFSYS_ASSERT(length <= EFX_LICENSE_V3_KEY_LENGTH_MAX); return ef10_nvram_buffer_insert_item(bufferp, buffer_size, - offset, keyp, length, lengthp); + offset, TLV_TAG_LICENSE, keyp, length, lengthp); } __checkReturn efx_rc_t @@ -1221,8 +1223,10 @@ efx_lic_v3_create_partition( { efx_rc_t rc; + _NOTE(ARGUNUSED(enp)) + /* Construct empty partition */ - if ((rc = ef10_nvram_buffer_create(enp, + if ((rc = ef10_nvram_buffer_create( NVRAM_PARTITION_TYPE_LICENSE, bufferp, buffer_size)) != 0) { rc = EFAULT; @@ -1246,13 +1250,16 @@ efx_lic_v3_finish_partition( { efx_rc_t rc; + _NOTE(ARGUNUSED(enp)) + if ((rc = ef10_nvram_buffer_finish(bufferp, buffer_size)) != 0) { goto fail1; } /* Validate completed partition */ - if ((rc = ef10_nvram_buffer_validate(enp, NVRAM_PARTITION_TYPE_LICENSE, + if ((rc = ef10_nvram_buffer_validate( + NVRAM_PARTITION_TYPE_LICENSE, bufferp, buffer_size)) != 0) { goto fail2; } diff --git a/drivers/net/sfc/base/efx_nvram.c b/drivers/net/sfc/base/efx_nvram.c index f3107bbb57..9000fe886d 100644 --- a/drivers/net/sfc/base/efx_nvram.c +++ b/drivers/net/sfc/base/efx_nvram.c @@ -468,7 +468,7 @@ efx_nvram_validate( goto fail1; if (envop->envo_buffer_validate != NULL) { - if ((rc = envop->envo_buffer_validate(enp, partn, + if ((rc = envop->envo_buffer_validate(partn, partn_data, partn_size)) != 0) goto fail2; } -- 2.20.1