tool/CommandSiiWrite.cpp
changeset 1142 59be91dfcbe1
child 1151 1fc1535dec29
equal deleted inserted replaced
1141:7ffbca63fc72 1142:59be91dfcbe1
       
     1 /*****************************************************************************
       
     2  *
       
     3  * $Id$
       
     4  *
       
     5  ****************************************************************************/
       
     6 
       
     7 #include <iostream>
       
     8 #include <iomanip>
       
     9 #include <fstream>
       
    10 using namespace std;
       
    11 
       
    12 #include "CommandSiiWrite.h"
       
    13 #include "sii_crc.h"
       
    14 #include "byteorder.h"
       
    15 
       
    16 /*****************************************************************************/
       
    17 
       
    18 CommandSiiWrite::CommandSiiWrite():
       
    19     Command("sii_write", "Write SII contents to a slave.")
       
    20 {
       
    21 }
       
    22 
       
    23 /*****************************************************************************/
       
    24 
       
    25 string CommandSiiWrite::helpString() const
       
    26 {
       
    27     stringstream str;
       
    28 
       
    29     str << getName() << " [OPTIONS] <FILENAME>" << endl
       
    30         << endl 
       
    31         << getBriefDescription() << endl
       
    32         << endl
       
    33         << "The file contents are checked for validity and integrity." << endl
       
    34         << "These checks can be overridden with the --force option." << endl
       
    35         << endl
       
    36         << "Arguments:" << endl
       
    37         << "  FILENAME must be a path to a file that contains a" << endl
       
    38         << "           positive number of words." << endl
       
    39         << endl
       
    40         << "Command-specific options:" << endl
       
    41         << "  --slave -s <index>  Positive numerical ring position" << endl
       
    42         << "                      (mandatory)." << endl
       
    43         << "  --force -f          Override validity checks." << endl
       
    44         << endl
       
    45         << numericInfo();
       
    46 
       
    47     return str.str();
       
    48 }
       
    49 
       
    50 /****************************************************************************/
       
    51 
       
    52 void CommandSiiWrite::execute(MasterDevice &m, const StringVector &args)
       
    53 {
       
    54     stringstream err;
       
    55     ec_ioctl_slave_sii_t data;
       
    56     ifstream file;
       
    57     unsigned int byte_size;
       
    58     const uint16_t *categoryHeader;
       
    59     uint16_t categoryType, categorySize;
       
    60     uint8_t crc;
       
    61 
       
    62     if (slavePosition < 0) {
       
    63         err << "'" << getName() << "' requires a slave! "
       
    64             << "Please specify --slave.";
       
    65         throwInvalidUsageException(err);
       
    66     }
       
    67     data.slave_position = slavePosition;
       
    68 
       
    69     if (args.size() != 1) {
       
    70         err << "'" << getName() << "' takes exactly one argument!";
       
    71         throwInvalidUsageException(err);
       
    72     }
       
    73 
       
    74     file.open(args[0].c_str(), ifstream::in | ifstream::binary);
       
    75     if (file.fail()) {
       
    76         err << "Failed to open '" << args[0] << "'!";
       
    77         throwCommandException(err);
       
    78     }
       
    79 
       
    80     // get length of file
       
    81     file.seekg(0, ios::end);
       
    82     byte_size = file.tellg();
       
    83     file.seekg(0, ios::beg);
       
    84 
       
    85     if (!byte_size || byte_size % 2) {
       
    86         err << "Invalid file size! Must be non-zero and even.";
       
    87         throwCommandException(err);
       
    88     }
       
    89 
       
    90     data.nwords = byte_size / 2;
       
    91     if (data.nwords < 0x0041 && !force) {
       
    92         err << "SII data too short (" << data.nwords << " words)! Mimimum is"
       
    93                 " 40 fixed words + 1 delimiter. Use --force to write anyway.";
       
    94         throwCommandException(err);
       
    95     }
       
    96 
       
    97     // allocate buffer and read file into buffer
       
    98     data.words = new uint16_t[data.nwords];
       
    99     file.read((char *) data.words, byte_size);
       
   100     file.close();
       
   101 
       
   102     if (!force) {
       
   103         // calculate checksum over words 0 to 6
       
   104         crc = calcSiiCrc((const uint8_t *) data.words, 14);
       
   105         if (crc != ((const uint8_t *) data.words)[14]) {
       
   106             err << "CRC incorrect. Must be 0x"
       
   107                 << hex << setfill('0') << setw(2) << (unsigned int) crc
       
   108                 << ". Use --force to write anyway.";
       
   109             throwCommandException(err);
       
   110         }
       
   111 
       
   112         // cycle through categories to detect corruption
       
   113         categoryHeader = data.words + 0x0040U;
       
   114         categoryType = le16tocpu(*categoryHeader);
       
   115         while (categoryType != 0xffff) {
       
   116             if (categoryHeader + 1 > data.words + data.nwords) {
       
   117                 err << "SII data seem to be corrupted! "
       
   118                     << "Use --force to write anyway.";
       
   119                 throwCommandException(err);
       
   120             }
       
   121             categorySize = le16tocpu(*(categoryHeader + 1));
       
   122             if (categoryHeader + 2 + categorySize + 1
       
   123                     > data.words + data.nwords) {
       
   124                 err << "SII data seem to be corrupted! "
       
   125                     "Use --force to write anyway.";
       
   126                 throwCommandException(err);
       
   127             }
       
   128             categoryHeader += 2 + categorySize;
       
   129             categoryType = le16tocpu(*categoryHeader);
       
   130         }
       
   131     }
       
   132 
       
   133     // send data to master
       
   134     m.open(MasterDevice::ReadWrite);
       
   135     data.offset = 0;
       
   136 	m.writeSii(&data);
       
   137 }
       
   138 
       
   139 /*****************************************************************************/