/** * Load non-volatile stored options from non-volatile storage device * * @v nvo Non-volatile options block * @ret rc Return status code */ static int nvo_load ( struct nvo_block *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; }
/** * Parse stored options * * @v nvo Non-volatile options block * * Verifies that the options data is valid, and configures the DHCP * options block. If the data is not valid, it is replaced with an * empty options block. */ static void nvo_init_dhcpopts ( struct nvo_block *nvo ) { uint8_t *options_data; size_t options_len; /* Steal one byte for the checksum */ options_data = ( nvo->data + 1 ); options_len = ( nvo->total_len - 1 ); /* 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->total_len ); } dhcpopt_init ( &nvo->dhcpopts, options_data, options_len ); }
/** * Save non-volatile stored options back to non-volatile storage device * * @v nvo Non-volatile options block * @ret rc Return status code */ static int nvo_save ( struct nvo_block *nvo ) { 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; }
/** * Save non-volatile stored options back to non-volatile storage device * * @v nvo Non-volatile options block * @ret rc Return status code */ static int nvo_save ( struct nvo_block *nvo ) { void *data = nvo->data; uint8_t *checksum = data; struct nvo_fragment *frag; int rc; /* Recalculate checksum */ *checksum -= nvo_checksum ( nvo ); /* Write data a fragment at a time */ for ( frag = nvo->fragments ; frag->len ; frag++ ) { if ( ( rc = nvs_write ( nvo->nvs, frag->address, data, frag->len ) ) != 0 ) { DBGC ( nvo, "NVO %p could not write %zd bytes at " "%#04x\n", nvo, frag->len, frag->address ); return rc; } data += frag->len; } DBGC ( nvo, "NVO %p saved to non-volatile storage\n", nvo ); return 0; }