iPXE
Functions | Variables
nvo.c File Reference

Non-volatile stored options. More...

#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <ipxe/dhcp.h>
#include <ipxe/nvs.h>
#include <ipxe/nvo.h>

Go to the source code of this file.

Functions

 FILE_LICENCE (GPL2_OR_LATER_OR_UBDL)
static unsigned int nvo_checksum (struct nvo_block *nvo)
 Calculate checksum over non-volatile stored options.
static int nvo_realloc (struct nvo_block *nvo, size_t len)
 Reallocate non-volatile stored options block.
static int nvo_realloc_dhcpopt (struct dhcp_options *options, size_t len)
 Reallocate non-volatile stored options DHCP option block.
static int nvo_load (struct nvo_block *nvo)
 Load non-volatile stored options from non-volatile storage device.
static int nvo_save (struct nvo_block *nvo)
 Save non-volatile stored options back to non-volatile storage device.
int nvo_applies (struct settings *settings __unused, const struct setting *setting)
 Check applicability of NVO setting.
static int nvo_store (struct settings *settings, const struct setting *setting, const void *data, size_t len)
 Store value of NVO setting.
static int nvo_fetch (struct settings *settings, struct setting *setting, void *data, size_t len)
 Fetch value of NVO setting.
void nvo_init (struct nvo_block *nvo, struct nvs_device *nvs, size_t address, size_t len, int(*resize)(struct nvo_block *nvo, size_t len), struct refcnt *refcnt)
 Initialise non-volatile stored options.
int register_nvo (struct nvo_block *nvo, struct settings *parent)
 Register non-volatile stored options.
void unregister_nvo (struct nvo_block *nvo)
 Unregister non-volatile stored options.

Variables

static struct settings_operations nvo_settings_operations
 NVO settings operations.

Detailed Description

Non-volatile stored options.

Definition in file nvo.c.


Function Documentation

FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL  )
static unsigned int nvo_checksum ( struct nvo_block nvo) [static]

Calculate checksum over non-volatile stored options.

Parameters:
nvoNon-volatile options block
Return values:
sumChecksum

Definition at line 46 of file nvo.c.

References nvo_block::data, data, and nvo_block::len.

Referenced by nvo_load(), and nvo_save().

                                                           {
        uint8_t *data = nvo->data;
        uint8_t sum = 0;
        unsigned int i;

        for ( i = 0 ; i < nvo->len ; i++ ) {
                sum += *(data++);
        }
        return sum;
}
static int nvo_realloc ( struct nvo_block nvo,
size_t  len 
) [static]

Reallocate non-volatile stored options block.

Parameters:
nvoNon-volatile options block
lenNew length
Return values:
rcReturn status code

Definition at line 64 of file nvo.c.

References dhcp_options::alloc_len, dhcp_options::data, nvo_block::data, DBGC, nvo_block::dhcpopts, ENOMEM, nvo_block::len, len, NULL, realloc(), and dhcp_options::used_len.

Referenced by nvo_realloc_dhcpopt(), register_nvo(), and unregister_nvo().

                                                             {
        void *new_data;

        /* Reallocate data */
        new_data = realloc ( nvo->data, len );
        if ( ! new_data ) {
                DBGC ( nvo, "NVO %p could not allocate %zd bytes\n",
                       nvo, len );
                return -ENOMEM;
        }
        nvo->data = new_data;
        nvo->len = len;

        /* Update DHCP option block */
        if ( len ) {
                nvo->dhcpopts.data = ( nvo->data + 1 /* checksum */ );
                nvo->dhcpopts.alloc_len = ( len - 1 /* checksum */ );
        } else {
                nvo->dhcpopts.data = NULL;
                nvo->dhcpopts.used_len = 0;
                nvo->dhcpopts.alloc_len = 0;
        }

        return 0;
}
static int nvo_realloc_dhcpopt ( struct dhcp_options options,
size_t  len 
) [static]

Reallocate non-volatile stored options DHCP option block.

Parameters:
optionsDHCP option block
lenNew length
Return values:
rcReturn status code

Definition at line 97 of file nvo.c.

References container_of, DBGC, dhcpopt_no_realloc(), nvo_block::dhcpopts, nvo_realloc(), rc, nvo_block::resize, and strerror().

Referenced by nvo_init().

                                                                            {
        struct nvo_block *nvo =
                container_of ( options, struct nvo_block, dhcpopts );
        int rc;

        /* Refuse to reallocate if we have no way to resize the block */
        if ( ! nvo->resize )
                return dhcpopt_no_realloc ( options, len );

        /* Allow one byte for the checksum (if any data is present) */
        if ( len )
                len += 1;

        /* Resize underlying non-volatile options block */
        if ( ( rc = nvo->resize ( nvo, len ) ) != 0 ) {
                DBGC ( nvo, "NVO %p could not resize to %zd bytes: %s\n",
                       nvo, len, strerror ( rc ) );
                return rc;
        }

        /* Reallocate in-memory options block */
        if ( ( rc = nvo_realloc ( nvo, len ) ) != 0 )
                return rc;

        return 0;
}
static int nvo_load ( struct nvo_block nvo) [static]

Load non-volatile stored options from non-volatile storage device.

Parameters:
nvoNon-volatile options block
Return values:
rcReturn status code

Definition at line 130 of file nvo.c.

References nvo_block::address, dhcp_options::data, nvo_block::data, DBGC, dhcpopt_update_used_len(), nvo_block::dhcpopts, nvo_block::len, memset(), nvo_checksum(), nvo_block::nvs, nvs_read(), rc, and strerror().

Referenced by register_nvo().

                                              {
        uint8_t *options_data = nvo->dhcpopts.data;
        int rc;

        /* Skip reading zero-length NVO fields */
        if ( nvo->len == 0 ) {
                DBGC ( nvo, "NVO %p is empty; skipping load\n", nvo );
                return 0;
        }

        /* Read data */
        if ( ( rc = nvs_read ( nvo->nvs, nvo->address, nvo->data,
                               nvo->len ) ) != 0 ) {
                DBGC ( nvo, "NVO %p could not read %zd bytes at %#04x: %s\n",
                       nvo, nvo->len, nvo->address, strerror ( rc ) );
                return rc;
        }

        /* If checksum fails, or options data starts with a zero,
         * assume the whole block is invalid.  This should capture the
         * case of random initial contents.
         */
        if ( ( nvo_checksum ( nvo ) != 0 ) || ( options_data[0] == 0 ) ) {
                DBGC ( nvo, "NVO %p has checksum %02x and initial byte %02x; "
                       "assuming empty\n", nvo, nvo_checksum ( nvo ),
                       options_data[0] );
                memset ( nvo->data, 0, nvo->len );
        }

        /* Rescan DHCP option block */
        dhcpopt_update_used_len ( &nvo->dhcpopts );

        DBGC ( nvo, "NVO %p loaded from non-volatile storage\n", nvo );
        return 0;
}
static int nvo_save ( struct nvo_block nvo) [static]

Save non-volatile stored options back to non-volatile storage device.

Parameters:
nvoNon-volatile options block
Return values:
rcReturn status code

Definition at line 172 of file nvo.c.

References nvo_block::address, checksum, nvo_block::data, DBGC, nvo_block::len, nvo_checksum(), nvo_block::nvs, nvs_write(), rc, and strerror().

Referenced by nvo_store().

                                              {
        uint8_t *checksum = nvo->data;
        int rc;

        /* Recalculate checksum, if applicable */
        if ( nvo->len > 0 )
                *checksum -= nvo_checksum ( nvo );

        /* Write data */
        if ( ( rc = nvs_write ( nvo->nvs, nvo->address, nvo->data,
                                nvo->len ) ) != 0 ) {
                DBGC ( nvo, "NVO %p could not write %zd bytes at %#04x: %s\n",
                       nvo, nvo->len, nvo->address, strerror ( rc ) );
                return rc;
        }

        DBGC ( nvo, "NVO %p saved to non-volatile storage\n", nvo );
        return 0;
}
int nvo_applies ( struct settings *settings  __unused,
const struct setting setting 
)

Check applicability of NVO setting.

Parameters:
settingsSettings block
settingSetting
Return values:
appliesSetting applies within this settings block

Definition at line 199 of file nvo.c.

References dhcpopt_applies(), NULL, setting::scope, and setting::tag.

Referenced by efi_snp_hii_setting_applies().

                                                  {

        return ( ( setting->scope == NULL ) &&
                 dhcpopt_applies ( setting->tag ) );
}
static int nvo_store ( struct settings settings,
const struct setting setting,
const void *  data,
size_t  len 
) [static]

Store value of NVO setting.

Parameters:
settingsSettings block
settingSetting to store
dataSetting data, or NULL to clear setting
lenLength of setting data
Return values:
rcReturn status code

Definition at line 215 of file nvo.c.

References container_of, DBGC, dhcpopt_store(), nvo_block::dhcpopts, nvo_save(), rc, strerror(), and setting::tag.

                                                      {
        struct nvo_block *nvo =
                container_of ( settings, struct nvo_block, settings );
        int rc;

        /* Update stored options */
        if ( ( rc = dhcpopt_store ( &nvo->dhcpopts, setting->tag,
                                    data, len ) ) != 0 ) {
                DBGC ( nvo, "NVO %p could not store %zd bytes: %s\n",
                       nvo, len, strerror ( rc ) );
                return rc;
        }

        /* Save updated options to NVS */
        if ( ( rc = nvo_save ( nvo ) ) != 0 )
                return rc;

        return 0;
}
static int nvo_fetch ( struct settings settings,
struct setting setting,
void *  data,
size_t  len 
) [static]

Fetch value of NVO setting.

Parameters:
settingsSettings block
settingSetting to fetch
dataBuffer to fill with setting data
lenLength of buffer
Return values:
lenLength of setting data, or negative error

The actual length of the setting will be returned even if the buffer was too small.

Definition at line 248 of file nvo.c.

References container_of, dhcpopt_fetch(), nvo_block::dhcpopts, and setting::tag.

                                                {
        struct nvo_block *nvo =
                container_of ( settings, struct nvo_block, settings );

        return dhcpopt_fetch ( &nvo->dhcpopts, setting->tag, data, len );
}
void nvo_init ( struct nvo_block nvo,
struct nvs_device nvs,
size_t  address,
size_t  len,
int(*)(struct nvo_block *nvo, size_t len resize,
struct refcnt refcnt 
)

Initialise non-volatile stored options.

Parameters:
nvoNon-volatile options block
nvsUnderlying non-volatile storage device
addressAddress within NVS device
lenLength of non-volatile options data
resizeResize method
refcntContaining object reference counter, or NULL

Definition at line 273 of file nvo.c.

References nvo_block::address, address, dhcpopt_init(), nvo_block::dhcpopts, nvo_block::len, len, NULL, nvo_realloc_dhcpopt(), nvo_block::nvs, nvo_block::resize, nvo_block::settings, and settings_init().

Referenced by falcon_probe_spi(), myri10ge_nv_init(), nvs_vpd_nvo_init(), and realtek_init_eeprom().

                                        {
        nvo->nvs = nvs;
        nvo->address = address;
        nvo->len = len;
        nvo->resize = resize;
        dhcpopt_init ( &nvo->dhcpopts, NULL, 0, nvo_realloc_dhcpopt );
        settings_init ( &nvo->settings, &nvo_settings_operations,
                        refcnt, NULL );
}
int register_nvo ( struct nvo_block nvo,
struct settings parent 
)

Register non-volatile stored options.

Parameters:
nvoNon-volatile options block
parentParent settings block, or NULL
Return values:
rcReturn status code

Definition at line 293 of file nvo.c.

References DBGC, nvo_block::len, nvo_load(), nvo_realloc(), NVO_SETTINGS_NAME, rc, register_settings(), and nvo_block::settings.

Referenced by efab_probe(), hermon_register_netdev(), myri10ge_nv_init(), and realtek_probe().

                                                                    {
        int rc;

        /* Allocate memory for options */
        if ( ( rc = nvo_realloc ( nvo, nvo->len ) ) != 0 )
                goto err_realloc;

        /* Read data from NVS */
        if ( ( rc = nvo_load ( nvo ) ) != 0 )
                goto err_load;

        /* Register settings */
        if ( ( rc = register_settings ( &nvo->settings, parent,
                                        NVO_SETTINGS_NAME ) ) != 0 )
                goto err_register;

        DBGC ( nvo, "NVO %p registered\n", nvo );
        return 0;
        
 err_register:
 err_load:
        nvo_realloc ( nvo, 0 );
 err_realloc:
        return rc;
}
void unregister_nvo ( struct nvo_block nvo)

Unregister non-volatile stored options.

Parameters:
nvoNon-volatile options block

Definition at line 324 of file nvo.c.

References DBGC, nvo_realloc(), nvo_block::settings, and unregister_settings().

Referenced by efab_remove(), hermon_register_netdev(), hermon_unregister_netdev(), myri10ge_nv_fini(), and realtek_remove().

                                              {
        unregister_settings ( &nvo->settings );
        nvo_realloc ( nvo, 0 );
        DBGC ( nvo, "NVO %p unregistered\n", nvo );
}

Variable Documentation

Initial value:
 {
        .applies = nvo_applies,
        .store = nvo_store,
        .fetch = nvo_fetch,
}

NVO settings operations.

Definition at line 257 of file nvo.c.