Changeset View
Changeset View
Standalone View
Standalone View
head/sys/dev/sfxge/common/ef10_nvram.c
Show First 20 Lines • Show All 224 Lines • ▼ Show 20 Lines | tlv_validate_state( | ||||
} | } | ||||
if (cursor->current > cursor->limit) { | if (cursor->current > cursor->limit) { | ||||
rc = EINVAL; | rc = EINVAL; | ||||
goto fail2; | goto fail2; | ||||
} | } | ||||
if (tlv_tag(cursor) != TLV_TAG_END) { | if (tlv_tag(cursor) != TLV_TAG_END) { | ||||
/* Check current item has space for tag and length */ | /* Check current item has space for tag and length */ | ||||
if (cursor->current > (cursor->limit - 2)) { | if (cursor->current > (cursor->limit - 1)) { | ||||
cursor->current = NULL; | cursor->current = NULL; | ||||
rc = EFAULT; | rc = EFAULT; | ||||
goto fail3; | goto fail3; | ||||
} | } | ||||
/* Check we have value data for current item and another tag */ | /* Check we have value data for current item and an END tag */ | ||||
if (tlv_next_item_ptr(cursor) > (cursor->limit - 1)) { | if (tlv_next_item_ptr(cursor) > cursor->limit) { | ||||
cursor->current = NULL; | cursor->current = NULL; | ||||
rc = EFAULT; | rc = EFAULT; | ||||
goto fail4; | goto fail4; | ||||
} | } | ||||
} | } | ||||
return (0); | return (0); | ||||
▲ Show 20 Lines • Show All 408 Lines • ▼ Show 20 Lines | fail1: | ||||
EFSYS_PROBE1(fail1, efx_rc_t, rc); | EFSYS_PROBE1(fail1, efx_rc_t, rc); | ||||
return (rc); | return (rc); | ||||
} | } | ||||
/* Validate buffer contents (before writing to flash) */ | /* Validate buffer contents (before writing to flash) */ | ||||
__checkReturn efx_rc_t | __checkReturn efx_rc_t | ||||
ef10_nvram_buffer_validate( | ef10_nvram_buffer_validate( | ||||
__in efx_nic_t *enp, | |||||
__in uint32_t partn, | __in uint32_t partn, | ||||
__in_bcount(partn_size) caddr_t partn_data, | __in_bcount(partn_size) caddr_t partn_data, | ||||
__in size_t partn_size) | __in size_t partn_size) | ||||
{ | { | ||||
tlv_cursor_t cursor; | tlv_cursor_t cursor; | ||||
struct tlv_partition_header *header; | struct tlv_partition_header *header; | ||||
struct tlv_partition_trailer *trailer; | struct tlv_partition_trailer *trailer; | ||||
size_t total_length; | size_t total_length; | ||||
uint32_t cksum; | uint32_t cksum; | ||||
int pos; | int pos; | ||||
efx_rc_t rc; | efx_rc_t rc; | ||||
_NOTE(ARGUNUSED(enp, partn)) | |||||
EFX_STATIC_ASSERT(sizeof (*header) <= EF10_NVRAM_CHUNK); | EFX_STATIC_ASSERT(sizeof (*header) <= EF10_NVRAM_CHUNK); | ||||
if ((partn_data == NULL) || (partn_size == 0)) { | if ((partn_data == NULL) || (partn_size == 0)) { | ||||
rc = EINVAL; | rc = EINVAL; | ||||
goto fail1; | goto fail1; | ||||
} | } | ||||
/* The partition header must be the first item (at offset zero) */ | /* The partition header must be the first item (at offset zero) */ | ||||
Show All 10 Lines | ef10_nvram_buffer_validate( | ||||
/* Check TLV partition length (includes the END tag) */ | /* Check TLV partition length (includes the END tag) */ | ||||
total_length = __LE_TO_CPU_32(header->total_length); | total_length = __LE_TO_CPU_32(header->total_length); | ||||
if (total_length > partn_size) { | if (total_length > partn_size) { | ||||
rc = EFBIG; | rc = EFBIG; | ||||
goto fail4; | 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 */ | /* Check partition ends with PARTITION_TRAILER and END tags */ | ||||
if ((rc = tlv_find(&cursor, TLV_TAG_PARTITION_TRAILER)) != 0) { | if ((rc = tlv_find(&cursor, TLV_TAG_PARTITION_TRAILER)) != 0) { | ||||
rc = EINVAL; | rc = EINVAL; | ||||
goto fail5; | goto fail6; | ||||
} | } | ||||
trailer = (struct tlv_partition_trailer *)tlv_item(&cursor); | trailer = (struct tlv_partition_trailer *)tlv_item(&cursor); | ||||
if ((rc = tlv_advance(&cursor)) != 0) { | if ((rc = tlv_advance(&cursor)) != 0) { | ||||
rc = EINVAL; | rc = EINVAL; | ||||
goto fail6; | goto fail7; | ||||
} | } | ||||
if (tlv_tag(&cursor) != TLV_TAG_END) { | if (tlv_tag(&cursor) != TLV_TAG_END) { | ||||
rc = EINVAL; | rc = EINVAL; | ||||
goto fail7; | goto fail8; | ||||
} | } | ||||
/* Check generation counts are consistent */ | /* Check generation counts are consistent */ | ||||
if (trailer->generation != header->generation) { | if (trailer->generation != header->generation) { | ||||
rc = EINVAL; | rc = EINVAL; | ||||
goto fail8; | goto fail9; | ||||
} | } | ||||
/* Verify partition checksum */ | /* Verify partition checksum */ | ||||
cksum = 0; | cksum = 0; | ||||
for (pos = 0; (size_t)pos < total_length; pos += sizeof (uint32_t)) { | for (pos = 0; (size_t)pos < total_length; pos += sizeof (uint32_t)) { | ||||
cksum += *((uint32_t *)(partn_data + pos)); | cksum += *((uint32_t *)(partn_data + pos)); | ||||
} | } | ||||
if (cksum != 0) { | if (cksum != 0) { | ||||
rc = EINVAL; | rc = EINVAL; | ||||
goto fail9; | goto fail10; | ||||
} | } | ||||
return (0); | return (0); | ||||
fail10: | |||||
EFSYS_PROBE(fail10); | |||||
fail9: | fail9: | ||||
EFSYS_PROBE(fail9); | EFSYS_PROBE(fail9); | ||||
fail8: | fail8: | ||||
EFSYS_PROBE(fail8); | EFSYS_PROBE(fail8); | ||||
fail7: | fail7: | ||||
EFSYS_PROBE(fail7); | EFSYS_PROBE(fail7); | ||||
fail6: | fail6: | ||||
EFSYS_PROBE(fail6); | EFSYS_PROBE(fail6); | ||||
fail5: | fail5: | ||||
EFSYS_PROBE(fail5); | EFSYS_PROBE(fail5); | ||||
fail4: | fail4: | ||||
EFSYS_PROBE(fail4); | EFSYS_PROBE(fail4); | ||||
fail3: | fail3: | ||||
EFSYS_PROBE(fail3); | EFSYS_PROBE(fail3); | ||||
fail2: | fail2: | ||||
EFSYS_PROBE(fail2); | EFSYS_PROBE(fail2); | ||||
fail1: | fail1: | ||||
EFSYS_PROBE1(fail1, efx_rc_t, rc); | EFSYS_PROBE1(fail1, efx_rc_t, rc); | ||||
return (rc); | 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 | __checkReturn efx_rc_t | ||||
ef10_nvram_buffer_create( | ef10_nvram_buffer_create( | ||||
__in efx_nic_t *enp, | __in uint32_t partn_type, | ||||
__in uint16_t partn_type, | __out_bcount(partn_size) | ||||
__in_bcount(partn_size) caddr_t partn_data, | caddr_t partn_data, | ||||
__in size_t partn_size) | __in size_t partn_size) | ||||
{ | { | ||||
uint32_t *buf = (uint32_t *)partn_data; | uint32_t *buf = (uint32_t *)partn_data; | ||||
efx_rc_t rc; | efx_rc_t rc; | ||||
tlv_cursor_t cursor; | tlv_cursor_t cursor; | ||||
struct tlv_partition_header header; | struct tlv_partition_header header; | ||||
struct tlv_partition_trailer trailer; | struct tlv_partition_trailer trailer; | ||||
unsigned int min_buf_size = sizeof (struct tlv_partition_header) + | unsigned int min_buf_size = sizeof (struct tlv_partition_header) + | ||||
sizeof (struct tlv_partition_trailer); | sizeof (struct tlv_partition_trailer); | ||||
if (partn_size < min_buf_size) { | if (partn_size < min_buf_size) { | ||||
rc = EINVAL; | rc = EINVAL; | ||||
goto fail1; | 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, | if ((rc = tlv_init_cursor(&cursor, buf, | ||||
(uint32_t *)((uint8_t *)buf + partn_size), | (uint32_t *)((uint8_t *)buf + partn_size), | ||||
buf)) != 0) { | buf)) != 0) { | ||||
goto fail2; | goto fail2; | ||||
} | } | ||||
header.tag = __CPU_TO_LE_32(TLV_TAG_PARTITION_HEADER); | header.tag = __CPU_TO_LE_32(TLV_TAG_PARTITION_HEADER); | ||||
header.length = __CPU_TO_LE_32(sizeof (header) - 8); | header.length = __CPU_TO_LE_32(sizeof (header) - 8); | ||||
Show All 15 Lines | ef10_nvram_buffer_create( | ||||
if ((rc = tlv_insert(&cursor, TLV_TAG_PARTITION_TRAILER, | if ((rc = tlv_insert(&cursor, TLV_TAG_PARTITION_TRAILER, | ||||
(uint8_t *)&trailer.generation, sizeof (trailer) - 8)) != 0) | (uint8_t *)&trailer.generation, sizeof (trailer) - 8)) != 0) | ||||
goto fail5; | goto fail5; | ||||
if ((rc = tlv_update_partition_len_and_cks(&cursor)) != 0) | if ((rc = tlv_update_partition_len_and_cks(&cursor)) != 0) | ||||
goto fail6; | goto fail6; | ||||
/* Check that the partition is valid. */ | /* 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) | partn_data, partn_size)) != 0) | ||||
goto fail7; | goto fail7; | ||||
return (0); | return (0); | ||||
fail7: | fail7: | ||||
EFSYS_PROBE(fail7); | EFSYS_PROBE(fail7); | ||||
fail6: | fail6: | ||||
▲ Show 20 Lines • Show All 155 Lines • ▼ Show 20 Lines | *lengthp = byte_offset(tlv_next_item_ptr(&cursor), | ||||
cursor.current); | cursor.current); | ||||
return (B_TRUE); | return (B_TRUE); | ||||
} | } | ||||
return (B_FALSE); | return (B_FALSE); | ||||
} | } | ||||
__checkReturn efx_rc_t | __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( | ef10_nvram_buffer_get_item( | ||||
__in_bcount(buffer_size) | __in_bcount(buffer_size) | ||||
caddr_t bufferp, | caddr_t bufferp, | ||||
__in size_t buffer_size, | __in size_t buffer_size, | ||||
__in uint32_t offset, | __in uint32_t offset, | ||||
__in uint32_t length, | __in uint32_t length, | ||||
__out_bcount_part(item_max_size, *lengthp) | __out uint32_t *tagp, | ||||
caddr_t itemp, | __out_bcount_part(value_max_size, *lengthp) | ||||
__in size_t item_max_size, | caddr_t valuep, | ||||
__in size_t value_max_size, | |||||
__out uint32_t *lengthp) | __out uint32_t *lengthp) | ||||
{ | { | ||||
efx_rc_t rc; | efx_rc_t rc; | ||||
tlv_cursor_t cursor; | tlv_cursor_t cursor; | ||||
uint32_t item_length; | uint32_t value_length; | ||||
if (item_max_size < length) { | if (buffer_size < (offset + length)) { | ||||
rc = ENOSPC; | rc = ENOSPC; | ||||
goto fail1; | goto fail1; | ||||
} | } | ||||
if ((rc = tlv_init_cursor_at_offset(&cursor, (uint8_t *)bufferp, | if ((rc = tlv_init_cursor_at_offset(&cursor, (uint8_t *)bufferp, | ||||
buffer_size, offset)) != 0) { | buffer_size, offset)) != 0) { | ||||
goto fail2; | goto fail2; | ||||
} | } | ||||
item_length = tlv_length(&cursor); | value_length = tlv_length(&cursor); | ||||
if (length < item_length) { | if (value_max_size < value_length) { | ||||
rc = ENOSPC; | rc = ENOSPC; | ||||
goto fail3; | 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); | return (0); | ||||
fail3: | fail3: | ||||
EFSYS_PROBE(fail3); | EFSYS_PROBE(fail3); | ||||
fail2: | fail2: | ||||
EFSYS_PROBE(fail2); | EFSYS_PROBE(fail2); | ||||
fail1: | fail1: | ||||
EFSYS_PROBE1(fail1, efx_rc_t, rc); | EFSYS_PROBE1(fail1, efx_rc_t, rc); | ||||
return (rc); | return (rc); | ||||
} | } | ||||
__checkReturn efx_rc_t | __checkReturn efx_rc_t | ||||
ef10_nvram_buffer_insert_item( | ef10_nvram_buffer_insert_item( | ||||
__in_bcount(buffer_size) | __in_bcount(buffer_size) | ||||
caddr_t bufferp, | caddr_t bufferp, | ||||
__in size_t buffer_size, | __in size_t buffer_size, | ||||
__in uint32_t offset, | __in uint32_t offset, | ||||
__in_bcount(length) caddr_t keyp, | __in uint32_t tag, | ||||
__in_bcount(length) caddr_t valuep, | |||||
__in uint32_t length, | __in uint32_t length, | ||||
__out uint32_t *lengthp) | __out uint32_t *lengthp) | ||||
{ | { | ||||
efx_rc_t rc; | efx_rc_t rc; | ||||
tlv_cursor_t cursor; | tlv_cursor_t cursor; | ||||
if ((rc = tlv_init_cursor_at_offset(&cursor, (uint8_t *)bufferp, | if ((rc = tlv_init_cursor_at_offset(&cursor, (uint8_t *)bufferp, | ||||
buffer_size, offset)) != 0) { | buffer_size, offset)) != 0) { | ||||
goto fail1; | 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) { | if (rc != 0) { | ||||
goto fail2; | goto fail2; | ||||
} | } | ||||
*lengthp = byte_offset(tlv_next_item_ptr(&cursor), | *lengthp = byte_offset(tlv_next_item_ptr(&cursor), | ||||
cursor.current); | cursor.current); | ||||
return (0); | return (0); | ||||
fail2: | fail2: | ||||
EFSYS_PROBE(fail2); | EFSYS_PROBE(fail2); | ||||
fail1: | fail1: | ||||
EFSYS_PROBE1(fail1, efx_rc_t, rc); | EFSYS_PROBE1(fail1, efx_rc_t, rc); | ||||
return (rc); | return (rc); | ||||
} | } | ||||
__checkReturn efx_rc_t | __checkReturn efx_rc_t | ||||
ef10_nvram_buffer_delete_item( | ef10_nvram_buffer_delete_item( | ||||
__in_bcount(buffer_size) | __in_bcount(buffer_size) | ||||
caddr_t bufferp, | caddr_t bufferp, | ||||
__in size_t buffer_size, | __in size_t buffer_size, | ||||
__in uint32_t offset, | __in uint32_t offset, | ||||
__in uint32_t length, | __in uint32_t length, | ||||
▲ Show 20 Lines • Show All 1,339 Lines • Show Last 20 Lines |