summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/machine/x76f041.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/devices/machine/x76f041.cpp')
-rw-r--r--src/devices/machine/x76f041.cpp370
1 files changed, 318 insertions, 52 deletions
diff --git a/src/devices/machine/x76f041.cpp b/src/devices/machine/x76f041.cpp
index 03fb5b65bf9..aa96ad90180 100644
--- a/src/devices/machine/x76f041.cpp
+++ b/src/devices/machine/x76f041.cpp
@@ -14,7 +14,11 @@
*/
#include "emu.h"
-#include "machine/x76f041.h"
+#include "x76f041.h"
+
+#include <cstdarg>
+#include <tuple>
+
#define VERBOSE_LEVEL ( 0 )
@@ -23,7 +27,7 @@ inline void ATTR_PRINTF( 3, 4 ) x76f041_device::verboselog( int n_level, const c
if( VERBOSE_LEVEL >= n_level )
{
va_list v;
- char buf[ 32768 ];
+ char buf[32768];
va_start( v, s_fmt );
vsprintf( buf, s_fmt, v );
va_end( v );
@@ -31,11 +35,12 @@ inline void ATTR_PRINTF( 3, 4 ) x76f041_device::verboselog( int n_level, const c
}
}
+
// device type definition
DEFINE_DEVICE_TYPE(X76F041, x76f041_device, "x76f041", "X76F041 Secure SerialFlash")
-x76f041_device::x76f041_device( const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock )
- : device_t( mconfig, X76F041, tag, owner, clock ),
+x76f041_device::x76f041_device( const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock ) :
+ device_t( mconfig, X76F041, tag, owner, clock ),
device_nvram_interface(mconfig, *this),
m_region(*this, DEVICE_SELF),
m_cs( 0 ),
@@ -48,13 +53,15 @@ x76f041_device::x76f041_device( const machine_config &mconfig, const char *tag,
m_bit( 0 ),
m_byte( 0 ),
m_command( 0 ),
- m_address( 0 )
+ m_address( 0 ),
+ m_is_password_accepted ( false )
{
}
void x76f041_device::device_start()
{
- memset( m_write_buffer, 0, sizeof( m_write_buffer ) );
+ std::fill( std::begin( m_write_buffer ), std::end( m_write_buffer ), 0 );
+ std::fill( std::begin( m_password_temp ), std::end( m_password_temp ), 0 );
save_item( NAME( m_cs ) );
save_item( NAME( m_rst ) );
@@ -67,6 +74,7 @@ void x76f041_device::device_start()
save_item( NAME( m_byte ) );
save_item( NAME( m_command ) );
save_item( NAME( m_address ) );
+ save_item( NAME( m_is_password_accepted ) );
save_item( NAME( m_write_buffer ) );
save_item( NAME( m_response_to_reset ) );
save_item( NAME( m_write_password ) );
@@ -74,9 +82,29 @@ void x76f041_device::device_start()
save_item( NAME( m_configuration_password ) );
save_item( NAME( m_configuration_registers ) );
save_item( NAME( m_data ) );
+ save_item( NAME( m_password_temp ) );
+}
+
+void x76f041_device::device_reset()
+{
+ std::fill( std::begin( m_write_buffer ), std::end( m_write_buffer ), 0 );
+ std::fill( std::begin( m_password_temp ), std::end( m_password_temp ), 0 );
+
+ m_cs = 0;
+ m_rst = 0;
+ m_scl = 0;
+ m_sdaw = 0;
+ m_sdar = 0;
+ m_state = STATE_STOP;
+ m_shift = 0;
+ m_bit = 0;
+ m_byte = 0;
+ m_command = 0;
+ m_address = 0;
+ m_is_password_accepted = false;
}
-WRITE_LINE_MEMBER( x76f041_device::write_cs )
+void x76f041_device::write_cs(int state)
{
if( m_cs != state )
{
@@ -100,7 +128,7 @@ WRITE_LINE_MEMBER( x76f041_device::write_cs )
m_cs = state;
}
-WRITE_LINE_MEMBER( x76f041_device::write_rst )
+void x76f041_device::write_rst(int state)
{
if( m_rst != state )
{
@@ -128,6 +156,15 @@ uint8_t *x76f041_device::password()
case COMMAND_READ:
return m_read_password;
+ case COMMAND_CONFIGURATION:
+ if( m_address == CONFIGURATION_PROGRAM_WRITE_PASSWORD )
+ return m_write_password;
+
+ if( m_address == CONFIGURATION_PROGRAM_READ_PASSWORD )
+ return m_read_password;
+
+ return m_configuration_password;
+
default:
return m_configuration_password;
}
@@ -135,6 +172,9 @@ uint8_t *x76f041_device::password()
void x76f041_device::password_ok()
{
+ if( m_configuration_registers[CONFIG_CR] & CR_RETRY_COUNTER_RESET_BIT )
+ m_configuration_registers[CONFIG_RC] = 0;
+
switch( m_command & 0xe0 )
{
case COMMAND_WRITE:
@@ -144,7 +184,7 @@ void x76f041_device::password_ok()
m_state = STATE_READ_DATA;
break;
case COMMAND_WRITE_USE_CONFIGURATION_PASSWORD:
- m_state = STATE_WRITE_DATA;
+ m_state = STATE_CONFIGURATION_WRITE_DATA;
break;
case COMMAND_READ_USE_CONFIGURATION_PASSWORD:
m_state = STATE_READ_DATA;
@@ -153,14 +193,22 @@ void x76f041_device::password_ok()
switch( m_address )
{
case CONFIGURATION_PROGRAM_WRITE_PASSWORD:
+ m_state = STATE_PROGRAM_WRITE_PASSWORD;
+ m_byte = 0;
break;
case CONFIGURATION_PROGRAM_READ_PASSWORD:
+ m_state = STATE_PROGRAM_READ_PASSWORD;
+ m_byte = 0;
break;
case CONFIGURATION_PROGRAM_CONFIGURATION_PASSWORD:
+ m_state = STATE_PROGRAM_CONFIGURATION_PASSWORD;
+ m_byte = 0;
break;
case CONFIGURATION_RESET_WRITE_PASSWORD:
+ m_state = STATE_RESET_WRITE_PASSWORD;
break;
case CONFIGURATION_RESET_READ_PASSWORD:
+ m_state = STATE_RESET_READ_PASSWORD;
break;
case CONFIGURATION_PROGRAM_CONFIGURATION_REGISTERS:
m_state = STATE_WRITE_CONFIGURATION_REGISTERS;
@@ -171,8 +219,10 @@ void x76f041_device::password_ok()
m_byte = 0;
break;
case CONFIGURATION_MASS_PROGRAM:
+ m_state = STATE_MASS_PROGRAM;
break;
case CONFIGURATION_MASS_ERASE:
+ m_state = STATE_MASS_ERASE;
break;
default:
break;
@@ -182,21 +232,56 @@ void x76f041_device::password_ok()
void x76f041_device::load_address()
{
- /* todo: handle other bcr bits */
- int bcr;
-
m_address = m_shift;
verboselog( 1, "-> address: %02x\n", m_address );
- if( ( m_command & 1 ) == 0 )
+ if( ( m_configuration_registers[CONFIG_CR] & CR_RETRY_COUNTER_ENABLE_BIT ) != 0 &&
+ m_configuration_registers[CONFIG_RR] == m_configuration_registers[CONFIG_RC] &&
+ ( m_configuration_registers[CONFIG_CR] & CR_UNAUTHORIZED_ACCESS_BITS ) == 0x80 )
{
- bcr = m_configuration_registers[ CONFIG_BCR1 ];
+ // No commands are allowed
+ verboselog( 1, "unauthorized access rejected\n" );
+ m_state = STATE_STOP;
+ m_sdar = 1;
+ m_byte = 0;
+ return;
}
- else
+
+ if( ( m_command & 0xe0 ) == COMMAND_CONFIGURATION )
{
- bcr = m_configuration_registers[ CONFIG_BCR2 ];
+ // Configuration commands can be used regardless of array control register bits
+ if( m_address == CONFIGURATION_RESET_WRITE_PASSWORD ||
+ m_address == CONFIGURATION_RESET_READ_PASSWORD ||
+ m_address == CONFIGURATION_MASS_PROGRAM ||
+ m_address == CONFIGURATION_MASS_ERASE )
+ {
+ verboselog( 1, "password not required\n" );
+ password_ok();
+ }
+ else
+ {
+ verboselog( 1, "send password\n" );
+ m_state = STATE_LOAD_PASSWORD;
+ m_byte = 0;
+ }
+
+ return;
+ }
+
+ if( ( m_configuration_registers[CONFIG_CR] & CR_RETRY_COUNTER_ENABLE_BIT ) != 0 &&
+ m_configuration_registers[CONFIG_RR] == m_configuration_registers[CONFIG_RC] &&
+ ( m_configuration_registers[CONFIG_CR] & CR_UNAUTHORIZED_ACCESS_BITS ) != 0x80 )
+ {
+ // Only configuration commands are allowed
+ verboselog( 1, "unauthorized access rejected\n" );
+ m_state = STATE_STOP;
+ m_sdar = 1;
+ m_byte = 0;
+ return;
}
+
+ int bcr = m_configuration_registers[( m_command & 1 ) ? CONFIG_BCR2 : CONFIG_BCR1];
if( ( m_address & 0x80 ) != 0 )
{
bcr >>= 4;
@@ -205,10 +290,11 @@ void x76f041_device::load_address()
if( ( ( m_command & 0xe0 ) == COMMAND_READ && ( bcr & BCR_Z ) != 0 && ( bcr & BCR_T ) != 0 ) ||
( ( m_command & 0xe0 ) == COMMAND_WRITE && ( bcr & BCR_Z ) != 0 ) )
{
- /* todo: find out when this is really checked. */
+ /* TODO: find out when this is really checked. */
verboselog( 1, "command not allowed\n" );
m_state = STATE_STOP;
- m_sdar = 0;
+ m_sdar = 1;
+ m_byte = 0;
}
else if( ( ( m_command & 0xe0 ) == COMMAND_WRITE && ( bcr & BCR_X ) == 0 ) ||
( ( m_command & 0xe0 ) == COMMAND_READ && ( bcr & BCR_Y ) == 0 ) )
@@ -233,7 +319,7 @@ int x76f041_device::data_offset()
return ( block_offset & 0x180 ) | ( ( block_offset + m_byte ) & 0x7f );
}
-WRITE_LINE_MEMBER( x76f041_device::write_scl )
+void x76f041_device::write_scl(int state)
{
if( m_scl != state )
{
@@ -250,7 +336,7 @@ WRITE_LINE_MEMBER( x76f041_device::write_scl )
case STATE_RESPONSE_TO_RESET:
if( m_scl != 0 && state == 0 )
{
- m_sdar = ( m_response_to_reset[ m_byte ] >> m_bit ) & 1;
+ m_sdar = ( m_response_to_reset[m_byte] >> m_bit ) & 1;
verboselog( 2, "in response to reset %d (%d/%d)\n", m_sdar, m_byte, m_bit );
m_bit++;
@@ -272,7 +358,18 @@ WRITE_LINE_MEMBER( x76f041_device::write_scl )
case STATE_LOAD_PASSWORD:
case STATE_VERIFY_PASSWORD:
case STATE_WRITE_DATA:
+ case STATE_CONFIGURATION_WRITE_DATA:
case STATE_WRITE_CONFIGURATION_REGISTERS:
+ case STATE_PROGRAM_WRITE_PASSWORD:
+ case STATE_PROGRAM_READ_PASSWORD:
+ case STATE_PROGRAM_CONFIGURATION_PASSWORD:
+ case STATE_RESET_WRITE_PASSWORD:
+ case STATE_RESET_READ_PASSWORD:
+ case STATE_MASS_PROGRAM:
+ case STATE_MASS_ERASE:
+ // FIXME: Processing on the rising edge of the clock causes sda to change state while clock is high
+ // which is not allowed. Also need to ensure that only valid device-id's and commands
+ // are acknowledged.
if( m_scl == 0 && state != 0 )
{
if( m_bit < 8 )
@@ -296,7 +393,7 @@ WRITE_LINE_MEMBER( x76f041_device::write_scl )
case STATE_LOAD_COMMAND:
m_command = m_shift;
verboselog( 1, "-> command: %02x\n", m_command );
- /* todo: verify command is valid? */
+ /* TODO: verify command is valid? */
m_state = STATE_LOAD_ADDRESS;
break;
@@ -306,22 +403,32 @@ WRITE_LINE_MEMBER( x76f041_device::write_scl )
case STATE_LOAD_PASSWORD:
verboselog( 1, "-> password: %02x\n", m_shift );
- m_write_buffer[ m_byte++ ] = m_shift;
+ m_write_buffer[m_byte++] = m_shift;
if( m_byte == sizeof( m_write_buffer ) )
{
m_state = STATE_VERIFY_PASSWORD;
+
+ // Perform the password acceptance check before verify password because
+ // password verify ack is spammed and will quickly overflow the
+ // retry counter.
+ m_is_password_accepted = memcmp( password(), m_write_buffer, sizeof( m_write_buffer ) ) == 0;
+ if( !m_is_password_accepted )
+ {
+ if( m_configuration_registers[CONFIG_CR] & CR_RETRY_COUNTER_ENABLE_BIT )
+ m_configuration_registers[CONFIG_RC]++;
+ }
}
break;
case STATE_VERIFY_PASSWORD:
verboselog( 1, "-> verify password: %02x\n", m_shift );
- /* todo: this should probably be handled as a command */
+ /* TODO: this should probably be handled as a command */
if( m_shift == 0xc0 )
{
- /* todo: this should take 10ms before it returns ok. */
- if( memcmp( password(), m_write_buffer, sizeof( m_write_buffer ) ) == 0 )
+ /* TODO: this should take 10ms before it returns ok. */
+ if( m_is_password_accepted )
{
password_ok();
}
@@ -334,15 +441,45 @@ WRITE_LINE_MEMBER( x76f041_device::write_scl )
case STATE_WRITE_DATA:
verboselog( 2, "-> data: %02x\n", m_shift );
- m_write_buffer[ m_byte++ ] = m_shift;
+ m_write_buffer[m_byte++] = m_shift;
if( m_byte == sizeof( m_write_buffer ) )
{
+ int bcr = m_configuration_registers[( m_command & 1 ) ? CONFIG_BCR2 : CONFIG_BCR1];
+ if( ( m_address & 0x80 ) != 0 )
+ {
+ bcr >>= 4;
+ }
+
+ if( ( bcr & ( BCR_Z | BCR_T ) ) == BCR_T )
+ {
+ // Bits in the data can only be set, not cleared, when in program only mode
+ bool is_unauthorized_write = false;
+
+ for( m_byte = 0; m_byte < sizeof( m_write_buffer ); m_byte++ )
+ {
+ int offset = data_offset();
+ if( m_write_buffer[m_byte] < m_data[offset] )
+ {
+ verboselog( 1, "tried to unset bits while in program only mode\n" );
+ is_unauthorized_write = true;
+ break;
+ }
+ }
+
+ if( is_unauthorized_write )
+ {
+ m_sdar = 1;
+ m_byte = 0;
+ break;
+ }
+ }
+
for( m_byte = 0; m_byte < sizeof( m_write_buffer ); m_byte++ )
{
int offset = data_offset();
- verboselog( 1, "-> data[ %03x ]: %02x\n", offset, m_write_buffer[ m_byte ] );
- m_data[ offset ] = m_write_buffer[ m_byte ];
+ verboselog( 1, "-> data[%03x]: %02x\n", offset, m_write_buffer[m_byte] );
+ m_data[offset] = m_write_buffer[m_byte];
}
m_byte = 0;
@@ -350,16 +487,109 @@ WRITE_LINE_MEMBER( x76f041_device::write_scl )
}
break;
+
+ case STATE_CONFIGURATION_WRITE_DATA:
+ // Unlike normal writes, configuration writes aren't required to be exactly 8 bytes
+ // TODO: Store data in a temporary buffer until the proper end of the command before writing
+ verboselog( 2, "-> data: %02x\n", m_shift );
+ m_data[data_offset()] = m_shift;
+ m_byte++;
+ break;
+
case STATE_WRITE_CONFIGURATION_REGISTERS:
- verboselog( 1, "-> configuration register[ %d ]: %02x\n", m_byte, m_shift );
- /* todo: write after all bytes received? */
- m_configuration_registers[ m_byte++ ] = m_shift;
+ verboselog( 1, "-> configuration register[%d]: %02x\n", m_byte, m_shift );
+ /* TODO: write after all bytes received? */
+ m_configuration_registers[m_byte++] = m_shift;
if( m_byte == sizeof( m_configuration_registers ) )
{
m_byte = 0;
}
break;
+
+ case STATE_PROGRAM_WRITE_PASSWORD:
+ verboselog( 1, "-> program write password[%d]: %02x\n", m_byte, m_shift );
+ m_password_temp[m_byte++] = m_shift;
+
+ if( m_byte == sizeof( m_password_temp ) )
+ {
+ // Read in the password twice and if the two copies match then write it to the password field
+ if( memcmp( &m_password_temp[0], &m_password_temp[8], sizeof( m_write_password ) ) == 0 )
+ {
+ std::copy_n( std::begin( m_password_temp ), sizeof( m_write_password ), std::begin ( m_write_password ) );
+ }
+ else {
+ m_sdar = 1;
+ }
+
+ std::fill( std::begin( m_password_temp ), std::end( m_password_temp ), 0 );
+
+ m_byte = 0;
+ }
+ break;
+
+ case STATE_PROGRAM_READ_PASSWORD:
+ verboselog( 1, "-> program read password[%d]: %02x\n", m_byte, m_shift );
+ m_password_temp[m_byte++] = m_shift;
+
+ if( m_byte == sizeof( m_password_temp ) )
+ {
+ if( memcmp( &m_password_temp[0], &m_password_temp[8], sizeof( m_read_password ) ) == 0 )
+ {
+ std::copy_n( std::begin( m_password_temp ), sizeof( m_read_password ), std::begin ( m_read_password ) );
+ }
+ else {
+ m_sdar = 1;
+ }
+
+ std::fill( std::begin( m_password_temp ), std::end( m_password_temp ), 0 );
+
+ m_byte = 0;
+ }
+ break;
+
+ case STATE_PROGRAM_CONFIGURATION_PASSWORD:
+ verboselog( 1, "-> program configuration password[%d]: %02x\n", m_byte, m_shift );
+ m_password_temp[m_byte++] = m_shift;
+
+ if( m_byte == sizeof( m_password_temp ) )
+ {
+ if( memcmp( &m_password_temp[0], &m_password_temp[8], sizeof( m_configuration_password ) ) == 0 )
+ {
+ std::copy_n( std::begin( m_password_temp ), sizeof( m_configuration_password ), std::begin ( m_configuration_password ) );
+ }
+ else {
+ m_sdar = 1;
+ }
+
+ std::fill( std::begin( m_password_temp ), std::end( m_password_temp ), 0 );
+
+ m_byte = 0;
+ }
+ break;
+
+ case STATE_RESET_WRITE_PASSWORD:
+ verboselog( 1, "-> reset write password\n" );
+ std::fill( std::begin( m_write_password ), std::end( m_write_password ), 0 );
+ break;
+
+ case STATE_RESET_READ_PASSWORD:
+ verboselog( 1, "-> reset read password\n" );
+ std::fill( std::begin( m_read_password ), std::end( m_read_password ), 0 );
+ break;
+
+ case STATE_MASS_PROGRAM:
+ case STATE_MASS_ERASE:
+ {
+ const uint8_t fill = m_state == STATE_MASS_ERASE ? 0xff : 0;
+ verboselog( 1, "-> mass erase %02x\n", fill );
+ std::fill( std::begin( m_data ), std::end( m_data ), fill );
+ std::fill( std::begin( m_configuration_password ), std::end( m_configuration_password ), fill );
+ std::fill( std::begin( m_configuration_registers ), std::end( m_configuration_registers ), fill );
+ std::fill( std::begin( m_write_password ), std::end( m_write_password ), fill );
+ std::fill( std::begin( m_read_password ), std::end( m_read_password ), fill );
+ break;
+ }
}
m_bit = 0;
@@ -370,6 +600,8 @@ WRITE_LINE_MEMBER( x76f041_device::write_scl )
case STATE_READ_DATA:
case STATE_READ_CONFIGURATION_REGISTERS:
+ // FIXME: Processing on the rising edge of the clock causes sda to change state while clock is high
+ // which is not allowed.
if( m_scl == 0 && state != 0 )
{
if( m_bit < 8 )
@@ -382,14 +614,14 @@ WRITE_LINE_MEMBER( x76f041_device::write_scl )
{
case STATE_READ_DATA:
offset = data_offset();
- m_shift = m_data[ offset ];
- verboselog( 1, "<- data[ %03x ]: %02x\n", offset, m_shift );
+ m_shift = m_data[offset];
+ verboselog( 1, "<- data[%03x]: %02x\n", offset, m_shift );
break;
case STATE_READ_CONFIGURATION_REGISTERS:
offset = m_byte & 7;
- m_shift = m_configuration_registers[ offset ];
- verboselog( 1, "<- configuration register[ %d ]: %02x\n", offset, m_shift );
+ m_shift = m_configuration_registers[offset];
+ verboselog( 1, "<- configuration register[%d]: %02x\n", offset, m_shift );
break;
}
}
@@ -421,7 +653,7 @@ WRITE_LINE_MEMBER( x76f041_device::write_scl )
m_scl = state;
}
-WRITE_LINE_MEMBER( x76f041_device::write_sda )
+void x76f041_device::write_sda(int state)
{
if( m_sdaw != state )
{
@@ -447,7 +679,7 @@ WRITE_LINE_MEMBER( x76f041_device::write_sda )
break;
case STATE_LOAD_PASSWORD:
- /* todo: this will be the 0xc0 command, but it's not handled as a command yet. */
+ /* TODO: this will be the 0xc0 command, but it's not handled as a command yet. */
verboselog( 1, "goto start\n" );
break;
@@ -471,7 +703,7 @@ WRITE_LINE_MEMBER( x76f041_device::write_sda )
m_sdaw = state;
}
-READ_LINE_MEMBER( x76f041_device::read_sda )
+int x76f041_device::read_sda()
{
if( m_cs != 0 )
{
@@ -520,22 +752,56 @@ void x76f041_device::nvram_default()
}
}
-void x76f041_device::nvram_read( emu_file &file )
+bool x76f041_device::nvram_read( util::read_stream &file )
{
- file.read( m_response_to_reset, sizeof( m_response_to_reset ) );
- file.read( m_write_password, sizeof( m_write_password ) );
- file.read( m_read_password, sizeof( m_read_password ) );
- file.read( m_configuration_password, sizeof( m_configuration_password ) );
- file.read( m_configuration_registers, sizeof( m_configuration_registers ) );
- file.read( m_data, sizeof( m_data ) );
+ std::error_condition err;
+ size_t actual;
+
+ std::tie( err, actual ) = read( file, m_response_to_reset, sizeof( m_response_to_reset ) );
+ if( err || ( sizeof( m_response_to_reset ) != actual ) )
+ return false;
+ std::tie( err, actual ) = read( file, m_write_password, sizeof( m_write_password ) );
+ if( err || ( sizeof( m_write_password ) != actual ) )
+ return false;
+ std::tie( err, actual ) = read( file, m_read_password, sizeof( m_read_password ) );
+ if( err || ( sizeof( m_read_password ) != actual ) )
+ return false;
+ std::tie( err, actual ) = read( file, m_configuration_password, sizeof( m_configuration_password ) );
+ if( err || ( sizeof( m_configuration_password ) != actual ) )
+ return false;
+ std::tie( err, actual ) = read( file, m_configuration_registers, sizeof( m_configuration_registers ) );
+ if( err || ( sizeof( m_configuration_registers ) != actual ) )
+ return false;
+ std::tie( err, actual ) = read( file, m_data, sizeof( m_data ) );
+ if( err || ( sizeof( m_data ) != actual ) )
+ return false;
+
+ return true;
}
-void x76f041_device::nvram_write( emu_file &file )
+bool x76f041_device::nvram_write( util::write_stream &file )
{
- file.write( m_response_to_reset, sizeof( m_response_to_reset ) );
- file.write( m_write_password, sizeof( m_write_password ) );
- file.write( m_read_password, sizeof( m_read_password ) );
- file.write( m_configuration_password, sizeof( m_configuration_password ) );
- file.write( m_configuration_registers, sizeof( m_configuration_registers ) );
- file.write( m_data, sizeof( m_data ) );
+ std::error_condition err;
+ size_t actual;
+
+ std::tie( err, actual ) = write( file, m_response_to_reset, sizeof( m_response_to_reset ) );
+ if (err)
+ return false;
+ std::tie( err, actual ) = write( file, m_write_password, sizeof( m_write_password ) );
+ if (err)
+ return false;
+ std::tie( err, actual ) = write( file, m_read_password, sizeof( m_read_password ) );
+ if (err)
+ return false;
+ std::tie( err, actual ) = write( file, m_configuration_password, sizeof( m_configuration_password ) );
+ if (err)
+ return false;
+ std::tie( err, actual ) = write( file, m_configuration_registers, sizeof( m_configuration_registers ) );
+ if (err)
+ return false;
+ std::tie( err, actual ) = write( file, m_data, sizeof( m_data ) );
+ if (err)
+ return false;
+
+ return true;
}