tool/CommandSiiWrite.cpp
changeset 1161 d1324ac71232
parent 1157 04d1c950cf9d
child 1166 006244d53f68
equal deleted inserted replaced
1160:f02ff486b313 1161:d1324ac71232
    35         << "The file contents are checked for validity and integrity." << endl
    35         << "The file contents are checked for validity and integrity." << endl
    36         << "These checks can be overridden with the --force option." << endl
    36         << "These checks can be overridden with the --force option." << endl
    37         << endl
    37         << endl
    38         << "Arguments:" << endl
    38         << "Arguments:" << endl
    39         << "  FILENAME must be a path to a file that contains a" << endl
    39         << "  FILENAME must be a path to a file that contains a" << endl
    40         << "           positive number of words." << endl
    40         << "           positive number of words. If it is '-'," << endl
       
    41         << "           data are read from stdin." << endl
    41         << endl
    42         << endl
    42         << "Command-specific options:" << endl
    43         << "Command-specific options:" << endl
    43         << "  --alias    -a <alias>" << endl
    44         << "  --alias    -a <alias>" << endl
    44         << "  --position -p <pos>    Slave selection. See the help of" << endl
    45         << "  --position -p <pos>    Slave selection. See the help of" << endl
    45         << "                         the 'slaves' command." << endl
    46         << "                         the 'slaves' command." << endl
    52 
    53 
    53 /****************************************************************************/
    54 /****************************************************************************/
    54 
    55 
    55 void CommandSiiWrite::execute(MasterDevice &m, const StringVector &args)
    56 void CommandSiiWrite::execute(MasterDevice &m, const StringVector &args)
    56 {
    57 {
    57     SlaveList slaves;
       
    58     stringstream err;
    58     stringstream err;
    59     ec_ioctl_slave_sii_t data;
    59     ec_ioctl_slave_sii_t data;
    60     ifstream file;
    60     ifstream file;
    61     unsigned int byte_size;
    61     SlaveList slaves;
    62     const uint16_t *categoryHeader;
       
    63     uint16_t categoryType, categorySize;
       
    64     uint8_t crc;
       
    65 
    62 
    66     if (args.size() != 1) {
    63     if (args.size() != 1) {
    67         err << "'" << getName() << "' takes exactly one argument!";
    64         err << "'" << getName() << "' takes exactly one argument!";
    68         throwInvalidUsageException(err);
    65         throwInvalidUsageException(err);
    69     }
    66     }
    70 
    67 
    71     file.open(args[0].c_str(), ifstream::in | ifstream::binary);
    68     if (args[0] == "-") {
    72     if (file.fail()) {
    69         loadSiiData(&data, cin);
    73         err << "Failed to open '" << args[0] << "'!";
    70     } else {
    74         throwCommandException(err);
    71         file.open(args[0].c_str(), ifstream::in | ifstream::binary);
       
    72         if (file.fail()) {
       
    73             err << "Failed to open '" << args[0] << "'!";
       
    74             throwCommandException(err);
       
    75         }
       
    76         loadSiiData(&data, file);
       
    77         file.close();
    75     }
    78     }
    76 
    79 
    77     // get length of file
       
    78     file.seekg(0, ios::end);
       
    79     byte_size = file.tellg();
       
    80     file.seekg(0, ios::beg);
       
    81 
       
    82     if (!byte_size || byte_size % 2) {
       
    83         err << "Invalid file size! Must be non-zero and even.";
       
    84         throwCommandException(err);
       
    85     }
       
    86 
       
    87     data.nwords = byte_size / 2;
       
    88     if (data.nwords < 0x0041 && !force) {
       
    89         err << "SII data too short (" << data.nwords << " words)! Mimimum is"
       
    90                 " 40 fixed words + 1 delimiter. Use --force to write anyway.";
       
    91         throwCommandException(err);
       
    92     }
       
    93 
       
    94     // allocate buffer and read file into buffer
       
    95     data.words = new uint16_t[data.nwords];
       
    96     file.read((char *) data.words, byte_size);
       
    97     file.close();
       
    98 
       
    99     if (!force) {
    80     if (!force) {
   100         // calculate checksum over words 0 to 6
    81         try {
   101         crc = calcSiiCrc((const uint8_t *) data.words, 14);
    82             checkSiiData(&data);
   102         if (crc != ((const uint8_t *) data.words)[14]) {
    83         } catch (CommandException &e) {
   103             err << "CRC incorrect. Must be 0x"
    84             delete [] data.words;
   104                 << hex << setfill('0') << setw(2) << (unsigned int) crc
    85             throw e;
   105                 << ". Use --force to write anyway.";
       
   106             throwCommandException(err);
       
   107         }
       
   108 
       
   109         // cycle through categories to detect corruption
       
   110         categoryHeader = data.words + 0x0040U;
       
   111         categoryType = le16tocpu(*categoryHeader);
       
   112         while (categoryType != 0xffff) {
       
   113             if (categoryHeader + 1 > data.words + data.nwords) {
       
   114                 err << "SII data seem to be corrupted! "
       
   115                     << "Use --force to write anyway.";
       
   116                 throwCommandException(err);
       
   117             }
       
   118             categorySize = le16tocpu(*(categoryHeader + 1));
       
   119             if (categoryHeader + 2 + categorySize + 1
       
   120                     > data.words + data.nwords) {
       
   121                 err << "SII data seem to be corrupted! "
       
   122                     "Use --force to write anyway.";
       
   123                 throwCommandException(err);
       
   124             }
       
   125             categoryHeader += 2 + categorySize;
       
   126             categoryType = le16tocpu(*categoryHeader);
       
   127         }
    86         }
   128     }
    87     }
   129 
    88 
   130     m.open(MasterDevice::ReadWrite);
    89     try {
       
    90         m.open(MasterDevice::ReadWrite);
       
    91     } catch (MasterDeviceException &e) {
       
    92         delete [] data.words;
       
    93         throw e;
       
    94     }
       
    95 
   131     slaves = selectedSlaves(m);
    96     slaves = selectedSlaves(m);
   132     if (slaves.size() != 1) {
    97     if (slaves.size() != 1) {
       
    98         delete [] data.words;
   133         throwSingleSlaveRequired(slaves.size());
    99         throwSingleSlaveRequired(slaves.size());
   134     }
   100     }
   135     data.slave_position = slaves.front().position;
   101     data.slave_position = slaves.front().position;
   136 
   102 
   137     // send data to master
   103     // send data to master
   138     data.offset = 0;
   104     data.offset = 0;
   139 	m.writeSii(&data);
   105     try {
       
   106         m.writeSii(&data);
       
   107     } catch (MasterDeviceException &e) {
       
   108         delete [] data.words;
       
   109         throw e;
       
   110     }
       
   111 
       
   112     if (getVerbosity() == Verbose) {
       
   113         cerr << "SII writing finished." << endl;
       
   114     }
       
   115 
       
   116     delete [] data.words;
   140 }
   117 }
   141 
   118 
   142 /*****************************************************************************/
   119 /*****************************************************************************/
       
   120 
       
   121 void CommandSiiWrite::loadSiiData(
       
   122         ec_ioctl_slave_sii_t *data,
       
   123         const istream &in
       
   124         )
       
   125 {
       
   126     stringstream err;
       
   127     ostringstream tmp;
       
   128 
       
   129     tmp << in.rdbuf();
       
   130     string const &contents = tmp.str();
       
   131 
       
   132     if (getVerbosity() == Verbose) {
       
   133         cerr << "Read " << contents.size() << " bytes of SII data." << endl;
       
   134     }
       
   135 
       
   136     if (!contents.size() || contents.size() % 2) {
       
   137         err << "Invalid data size " << contents.size() << "! "
       
   138             << "Must be non-zero and even.";
       
   139         throwCommandException(err);
       
   140     }
       
   141     data->nwords = contents.size() / 2;
       
   142 
       
   143     // allocate buffer and read file into buffer
       
   144     data->words = new uint16_t[data->nwords];
       
   145     contents.copy((char *) data->words, contents.size());
       
   146 }
       
   147 
       
   148 /*****************************************************************************/
       
   149 
       
   150 void CommandSiiWrite::checkSiiData(
       
   151         const ec_ioctl_slave_sii_t *data
       
   152         )
       
   153 {
       
   154     stringstream err;
       
   155     const uint16_t *categoryHeader;
       
   156     uint16_t categoryType, categorySize;
       
   157     uint8_t crc;
       
   158 
       
   159     if (data->nwords < 0x0041) {
       
   160         err << "SII data too short (" << data->nwords << " words)! Mimimum is"
       
   161             " 40 fixed words + 1 delimiter. Use --force to write anyway.";
       
   162         throwCommandException(err);
       
   163     }
       
   164 
       
   165     // calculate checksum over words 0 to 6
       
   166     crc = calcSiiCrc((const uint8_t *) data->words, 14);
       
   167     if (crc != ((const uint8_t *) data->words)[14]) {
       
   168         err << "CRC incorrect. Must be 0x"
       
   169             << hex << setfill('0') << setw(2) << (unsigned int) crc
       
   170             << ". Use --force to write anyway.";
       
   171         throwCommandException(err);
       
   172     }
       
   173 
       
   174     // cycle through categories to detect corruption
       
   175     categoryHeader = data->words + 0x0040U;
       
   176     categoryType = le16tocpu(*categoryHeader);
       
   177     while (categoryType != 0xffff) {
       
   178         if (categoryHeader + 1 > data->words + data->nwords) {
       
   179             err << "SII data seem to be corrupted! "
       
   180                 << "Use --force to write anyway.";
       
   181             throwCommandException(err);
       
   182         }
       
   183         categorySize = le16tocpu(*(categoryHeader + 1));
       
   184         if (categoryHeader + 2 + categorySize + 1
       
   185                 > data->words + data->nwords) {
       
   186             err << "SII data seem to be corrupted! "
       
   187                 "Use --force to write anyway.";
       
   188             throwCommandException(err);
       
   189         }
       
   190         categoryHeader += 2 + categorySize;
       
   191         categoryType = le16tocpu(*categoryHeader);
       
   192     }
       
   193 }
       
   194 
       
   195 /*****************************************************************************/