siena_vpd.c revision 49ef7e0638c8b771d8a136eae78b1c0f99acc8e0
/*
* Copyright (c) 2009-2015 Solarflare Communications Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are
* those of the authors and should not be interpreted as representing official
* policies, either expressed or implied, of the FreeBSD Project.
*/
#include "efx.h"
#include "efx_impl.h"
#if EFSYS_OPT_VPD
#if EFSYS_OPT_SIENA
static __checkReturn efx_rc_t
{
unsigned int vpd_offset;
unsigned int vpd_length;
unsigned int hdr_length;
unsigned int pos;
unsigned int region;
/* Allocate sufficient memory for the entire static cfg area */
goto fail1;
goto fail2;
}
goto fail3;
/* Verify the magic number */
goto fail4;
}
/* All future versions of the structure must be backwards compatable */
/* Verify the hdr doesn't overflow the sector size */
goto fail5;
}
/* Read the remainder of scfg + static vpd */
if (region > SIENA_NVRAM_CHUNK) {
region - SIENA_NVRAM_CHUNK)) != 0)
goto fail6;
}
/* Verify checksum */
cksum = 0;
if (cksum != 0) {
goto fail7;
}
if (vpd_length == 0)
else {
/* Copy the vpd data out */
goto fail8;
}
}
*sizep = vpd_length;
return (0);
return (rc);
}
{
unsigned partn;
/*
* We need the static VPD sector to present a unified static+dynamic
* VPD, that is, basically on every read, write, verify cycle. Since
* it should *never* change we can just cache it here.
*/
goto fail1;
goto fail2;
}
return (0);
return (rc);
}
{
/*
* This function returns the total size the user should allocate
* for all VPD operations. We've already cached the static vpd,
* so we just need to return an upper bound on the dynamic vpd.
* Since the dynamic_config structure can change under our feet,
* (as version numbers are inserted), just be safe and return the
* total size of the dynamic_config *sector*
*/
goto fail1;
return (0);
return (rc);
}
{
unsigned int vpd_length;
unsigned int vpd_offset;
unsigned int dcfg_partn;
goto fail1;
if (vpd_length > size) {
goto fail2;
}
/* Pad data with all-1s, consistent with update operations */
return (0);
return (rc);
}
{
unsigned int scont;
unsigned int dcont;
/*
* Strictly you could take the view that dynamic vpd is optional.
* paradigm, we require dynamic vpd. siena_vpd_reinit() will
* reinitialize it as required.
*/
goto fail1;
/*
* Verify that there is no duplication between the static and
* dynamic cfg sectors.
*/
goto done;
dcont = 0;
while (1) {
goto fail2;
if (dcont == 0)
break;
/*
* Skip the RV keyword. It should be present in both the static
* and dynamic cfg sectors.
*/
continue;
scont = 0;
while (1) {
if ((rc = efx_vpd_hunk_next(
goto fail3;
if (scont == 0)
break;
goto fail4;
}
}
}
done:
return (0);
return (rc);
}
{
/*
* Only create a PID if the dynamic cfg doesn't have one
*/
else {
unsigned int offset;
if (rc == 0)
else
goto fail1;
}
goto fail2;
return (0);
return (rc);
}
{
unsigned int offset;
/* Attempt to satisfy the request from svpd first */
return (0);
goto fail1;
}
/* And then from the provided data buffer */
goto fail2;
return (0);
return (rc);
}
{
/* If the provided (tag,keyword) exists in svpd, then it is readonly */
unsigned int offset;
goto fail1;
}
}
goto fail2;
return (0);
return (rc);
}
{
return (ENOTSUP);
}
{
unsigned int vpd_offset;
unsigned int dcfg_partn;
unsigned int hdr_length;
unsigned int pos;
/* Determine total length of all tags */
goto fail1;
/* Lock dynamic config sector for write, and read structure only */
goto fail2;
goto fail3;
goto fail4;
/* Allocated memory should have room for the new VPD */
goto fail5;
}
/* Copy in new vpd and update header */
/* Update the checksum */
cksum = 0;
/* Erase and write the new sector */
goto fail6;
/* Write out the new structure to nvram */
vpd_offset + vpd_length)) != 0)
goto fail7;
return (0);
return (rc);
}
void
{
}
}
#endif /* EFSYS_OPT_SIENA */
#endif /* EFSYS_OPT_VPD */