mirror of https://github.com/ipxe/ipxe.git
Added nvo_save()
parent
cc9bcb99a0
commit
ab4e1dba3f
|
@ -29,34 +29,35 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Calculate total length of non-volatile stored options
|
* Calculate checksum over non-volatile stored options
|
||||||
*
|
*
|
||||||
* @v nvo Non-volatile options block
|
* @v nvo Non-volatile options block
|
||||||
* @ret total_len Total length of all fragments
|
* @ret sum Checksum
|
||||||
*/
|
*/
|
||||||
static size_t nvo_total_len ( struct nvo_block *nvo ) {
|
static unsigned int nvo_checksum ( struct nvo_block *nvo ) {
|
||||||
struct nvo_fragment *fragment = nvo->fragments;
|
uint8_t *data = nvo->options->data;
|
||||||
size_t total_len = 0;
|
uint8_t sum = 0;
|
||||||
|
unsigned int i;
|
||||||
|
|
||||||
for ( ; fragment->len ; fragment++ ) {
|
for ( i = 0 ; i < nvo->total_len ; i++ ) {
|
||||||
total_len += fragment->len;
|
sum += *(data++);
|
||||||
}
|
}
|
||||||
|
return sum;
|
||||||
return total_len;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Read non-volatile stored options from non-volatile storage device
|
* Load non-volatile stored options from non-volatile storage device
|
||||||
*
|
*
|
||||||
* @v nvo Non-volatile options block
|
* @v nvo Non-volatile options block
|
||||||
* @ret rc Return status code
|
* @ret rc Return status code
|
||||||
*/
|
*/
|
||||||
static int nvo_read ( struct nvo_block *nvo ) {
|
static int nvo_load ( struct nvo_block *nvo ) {
|
||||||
struct nvo_fragment *fragment = nvo->fragments;
|
|
||||||
void *data = nvo->options->data;
|
void *data = nvo->options->data;
|
||||||
|
struct nvo_fragment *fragment;
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
for ( ; fragment->len ; fragment++ ) {
|
/* Read data a fragment at a time */
|
||||||
|
for ( fragment = nvo->fragments ; fragment->len ; fragment++ ) {
|
||||||
if ( ( rc = nvs_read ( nvo->nvs, fragment->address,
|
if ( ( rc = nvs_read ( nvo->nvs, fragment->address,
|
||||||
data, fragment->len ) ) != 0 ) {
|
data, fragment->len ) ) != 0 ) {
|
||||||
DBG ( "NVO %p could not read %zd bytes at %#04x\n",
|
DBG ( "NVO %p could not read %zd bytes at %#04x\n",
|
||||||
|
@ -69,32 +70,55 @@ static int nvo_read ( struct nvo_block *nvo ) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Save non-volatile stored options back to non-volatile storage device
|
||||||
|
*
|
||||||
|
* @v nvo Non-volatile options block
|
||||||
|
* @ret rc Return status code
|
||||||
|
*/
|
||||||
|
int nvo_save ( struct nvo_block *nvo ) {
|
||||||
|
void *data = nvo->options->data;
|
||||||
|
uint8_t *checksum = ( data + nvo->total_len - 1 );
|
||||||
|
struct nvo_fragment *fragment;
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
/* Recalculate checksum */
|
||||||
|
checksum -= nvo_checksum ( nvo );
|
||||||
|
|
||||||
|
/* Write data a fragment at a time */
|
||||||
|
for ( fragment = nvo->fragments ; fragment->len ; fragment++ ) {
|
||||||
|
if ( ( rc = nvs_write ( nvo->nvs, fragment->address,
|
||||||
|
data, fragment->len ) ) != 0 ) {
|
||||||
|
DBG ( "NVO %p could not write %zd bytes at %#04x\n",
|
||||||
|
nvo, fragment->len, fragment->address );
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
data += fragment->len;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parse stored options
|
* Parse stored options
|
||||||
*
|
*
|
||||||
* @v nvo Non-volatile options block
|
* @v nvo Non-volatile options block
|
||||||
* @v total_len Total length of options data
|
|
||||||
*
|
*
|
||||||
* Verifies that the options data is valid, and configures the DHCP
|
* Verifies that the options data is valid, and configures the DHCP
|
||||||
* options block. If the data is not valid, it is replaced with an
|
* options block. If the data is not valid, it is replaced with an
|
||||||
* empty options block.
|
* empty options block.
|
||||||
*/
|
*/
|
||||||
static void nvo_init_dhcp ( struct nvo_block *nvo, size_t total_len ) {
|
static void nvo_init_dhcp ( struct nvo_block *nvo ) {
|
||||||
struct dhcp_option_block *options = nvo->options;
|
struct dhcp_option_block *options = nvo->options;
|
||||||
struct dhcp_option *option;
|
struct dhcp_option *option;
|
||||||
uint8_t sum;
|
|
||||||
unsigned int i;
|
|
||||||
|
|
||||||
/* Steal one byte for the checksum */
|
/* Steal one byte for the checksum */
|
||||||
options->max_len = ( total_len - 1 );
|
options->max_len = ( nvo->total_len - 1 );
|
||||||
|
|
||||||
/* Verify checksum over whole block */
|
/* Verify checksum over whole block */
|
||||||
for ( sum = 0, i = 0 ; i < total_len ; i++ ) {
|
if ( nvo_checksum ( nvo ) != 0 ) {
|
||||||
sum += * ( ( uint8_t * ) ( options->data + i ) );
|
|
||||||
}
|
|
||||||
if ( sum != 0 ) {
|
|
||||||
DBG ( "NVO %p has bad checksum %02x; assuming empty\n",
|
DBG ( "NVO %p has bad checksum %02x; assuming empty\n",
|
||||||
nvo, sum );
|
nvo, nvo_checksum ( nvo ) );
|
||||||
goto empty;
|
goto empty;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -134,24 +158,28 @@ static void nvo_init_dhcp ( struct nvo_block *nvo, size_t total_len ) {
|
||||||
* @ret rc Return status code
|
* @ret rc Return status code
|
||||||
*/
|
*/
|
||||||
int nvo_register ( struct nvo_block *nvo ) {
|
int nvo_register ( struct nvo_block *nvo ) {
|
||||||
size_t total_len;
|
struct nvo_fragment *fragment = nvo->fragments;
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
|
/* Calculate total length of all fragments */
|
||||||
|
nvo->total_len = 0;
|
||||||
|
for ( fragment = nvo->fragments ; fragment->len ; fragment++ ) {
|
||||||
|
nvo->total_len += fragment->len;
|
||||||
|
}
|
||||||
|
|
||||||
/* Allocate memory for options and read in from NVS */
|
/* Allocate memory for options and read in from NVS */
|
||||||
total_len = nvo_total_len ( nvo );
|
nvo->options = alloc_dhcp_options ( nvo->total_len );
|
||||||
nvo->options = alloc_dhcp_options ( total_len );
|
|
||||||
if ( ! nvo->options ) {
|
if ( ! nvo->options ) {
|
||||||
DBG ( "NVO %p could not allocate %zd bytes\n",
|
DBG ( "NVO %p could not allocate %zd bytes\n",
|
||||||
nvo, total_len );
|
nvo, nvo->total_len );
|
||||||
rc = -ENOMEM;
|
rc = -ENOMEM;
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
if ( ( rc = nvo_load ( nvo ) ) != 0 )
|
||||||
if ( ( rc = nvo_read ( nvo ) ) != 0 )
|
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
/* Verify and register options */
|
/* Verify and register options */
|
||||||
nvo_init_dhcp ( nvo, total_len );
|
nvo_init_dhcp ( nvo );
|
||||||
register_dhcp_options ( nvo->options );
|
register_dhcp_options ( nvo->options );
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -33,11 +33,17 @@ struct nvo_block {
|
||||||
* The list is terminated by a fragment with a length of zero.
|
* The list is terminated by a fragment with a length of zero.
|
||||||
*/
|
*/
|
||||||
struct nvo_fragment *fragments;
|
struct nvo_fragment *fragments;
|
||||||
|
/** Total length of all fragments
|
||||||
|
*
|
||||||
|
* This field is filled in by nvo_register().
|
||||||
|
*/
|
||||||
|
size_t total_len;
|
||||||
/** DHCP options block */
|
/** DHCP options block */
|
||||||
struct dhcp_option_block *options;
|
struct dhcp_option_block *options;
|
||||||
};
|
};
|
||||||
|
|
||||||
extern int nvo_register ( struct nvo_block *nvo );
|
extern int nvo_register ( struct nvo_block *nvo );
|
||||||
|
extern int nvo_save ( struct nvo_block *nvo );
|
||||||
extern void nvo_unregister ( struct nvo_block *nvo );
|
extern void nvo_unregister ( struct nvo_block *nvo );
|
||||||
|
|
||||||
#endif /* _GPXE_NVO_H */
|
#endif /* _GPXE_NVO_H */
|
||||||
|
|
Loading…
Reference in New Issue