コード例 #1
0
ファイル: ecmdCommandUtils.C プロジェクト: djlambert/eCMD
uint32_t ecmdCheckExpected (ecmdDataBuffer & i_data, ecmdDataBuffer & i_expected, uint32_t & o_mismatchBit) {

  uint32_t wordCounter = 0;
  uint32_t maxBits = 32;
  uint32_t numBits = i_data.getBitLength();
  uint32_t numToFetch = numBits < maxBits ? numBits : maxBits;
  uint32_t curData, curExpected;

  /* We are going to make sure they didn't expect more data then we had */
  /* We are going to allow for odd bits in a nibble if the user provided data in hex */
  if ((i_data.getBitLength()-1)/4 > (i_expected.getBitLength()-1)/4) {
    ecmdOutputError("ecmdCheckExpected - Not enough expect data provided\n");
    o_mismatchBit = ECMD_UNSET;
    return 0;
  } else if ((i_data.getBitLength()-1)/4 < (i_expected.getBitLength()-1)/4) {
    ecmdOutputError("ecmdCheckExpected - More expect data provided than data that was retrieved\n");
    o_mismatchBit = ECMD_UNSET;
    return 0;
  }

  while (numToFetch > 0) {

    curData = i_data.getWord(wordCounter);
    curExpected = i_expected.getWord(wordCounter);

    if (numToFetch == maxBits) {
      if (curData != curExpected) {
	if (o_mismatchBit != ECMD_UNSET) {
	  uint32_t mask = 0x80000000;
	  for (uint32_t i = 0; i < numToFetch; i++, mask >>= 1) {
	    if ( (curData & mask) != (curExpected & mask) ) {
	      o_mismatchBit = (wordCounter * 32) + i;
	      break;
	    }
	  }
	}
        return 0;
      }
    }
    else {
コード例 #2
0
ファイル: PNORInstruction.C プロジェクト: mklight/eCMD
uint32_t PNORInstruction::execute(ecmdDataBuffer & o_data, InstructionStatus & o_status, Handle ** io_handle) {
    uint32_t rc = 0;

    /* set the version of this instruction in the status */
    o_status.instructionVersion = version;

#if defined(CRONUS_SERVER_SIDE)
    /* check for any previous errors to report back */
    if (error) {
        rc = o_status.rc = error;
        return rc;
    }

    switch(command) 
    {
        /*
         * GET LIST OPERATION
         */
        case PNORGETLIST:
        {
#if defined(TESTING)
            printf("PNORGETLIST\n");
#endif
            std::string ffsDevice;
            ffsDevice = "/dev/mtdblock/sfc." + deviceString;

#if defined(TESTING)
            printf("ffsData = ffs_open( \"%s\", 0x%X );\n", ffsDevice.c_str(), partitionOffset );
#else
 #if !defined(NO_GFW)
            off_t ffsDeviceOffset = partitionOffset;
            ffs_t *ffs = NULL;
            ffs = ffs_open( ffsDevice.c_str(), ffsDeviceOffset );

            if ( ffs == NULL )
            {
                std::ostringstream osse;
                osse << "PNORInstruction::execute SERVER DEBUG: Unable to open device " << ffsDevice << std::endl;
                o_status.errorMessage.append(osse.str());
                osse.clear(); osse.str(std::string());
                osse << "PNORInstruction::execute SERVER DEBUG: Listing partitions in image failed" << std::endl;
                o_status.errorMessage.append(osse.str());
                rc = o_status.rc = SERVER_PNOR_DEVICE_FAIL_OPEN;
                break;
            }

            ffs_hdr_t *ffsHdr = ffs->hdr;
 #endif
#endif

            Pnor_ffs_hdr *objHolder = new Pnor_ffs_hdr();

#if defined(TESTING)
            printf("transposing ffsData to internal Pnor_ffs_hdr object holder\n");

            objHolder->magic = 0x1;
            objHolder->version = 0x2;
            objHolder->size = 1;
            objHolder->entry_size = 0x80;
            objHolder->entry_count = 2;
            objHolder->block_size = 0x1000;
            objHolder->block_count = 0x4000;
            objHolder->checksum = 0x3;
            Pnor_ffs_entry *objEntry = new Pnor_ffs_entry();
            objEntry->base = 0x1fff;
            objEntry->size = 4096;
            objEntry->pid = 0;
            objEntry->id = 3;
            objEntry->type = 1;
            objEntry->flags = 0x0;
            objEntry->actual = 4096;
            objEntry->checksum = 0x43;
            objEntry->name = "HBBtest";
            (objHolder->entries).push_back(objEntry);
            objEntry = new Pnor_ffs_entry();
            objEntry->base = 0x0fff;
            objEntry->size = 8192;
            objEntry->pid = 0;
            objEntry->id = 2;
            objEntry->type = 3;
            objEntry->flags = 0x1;
            objEntry->actual = 8192;
            objEntry->checksum = 0x51;
            objEntry->name = "PNORtest";
            (objHolder->entries).push_back(objEntry);
#else
 #if !defined(NO_GFW)
            objHolder->magic = ffsHdr->magic;
            objHolder->version = ffsHdr->version;
            objHolder->size = ffsHdr->size;
            objHolder->entry_size = ffsHdr->entry_size;
            objHolder->entry_count = ffsHdr->entry_count;
            objHolder->block_size = ffsHdr->block_size;
            objHolder->block_count = ffsHdr->block_count;
            objHolder->checksum = ffsHdr->checksum;

            for( uint32_t idx = 0; idx < objHolder->entry_count; idx++ )
            {
                Pnor_ffs_entry *objEntry = new Pnor_ffs_entry();
                ffs_entry *ffsEntry = &(ffsHdr->entries[idx]);

                objEntry->base = ffsEntry->base;
                objEntry->size = ffsEntry->size;
                objEntry->pid = ffsEntry->pid;
                objEntry->id = ffsEntry->id;
                objEntry->type = ffsEntry->type;
                objEntry->flags = ffsEntry->flags;
                objEntry->actual = ffsEntry->actual;
                objEntry->checksum = ffsEntry->checksum;
                objEntry->name = ffsEntry->name;

                (objHolder->entries).push_back(objEntry);
            }
 #endif
#endif

            uint32_t flattensize = objHolder->flattenSize();
            uint32_t *flattenedffsData = new uint32_t[flattensize];
            rc = objHolder->flatten( (uint8_t*) flattenedffsData, flattensize );

            if ( rc ) 
            {
                std::ostringstream osse;
                osse << "PNORInstruction::execute - flattenffsData failure" << std::endl;
                o_status.errorMessage.append(osse.str());
                rc = o_status.rc = SERVER_PNOR_ERROR;
                return rc;
            }
#if defined(TESTING)
            printf("Flattened objHolder of size %d\n", flattensize);
#endif

            rc = o_data.setWordLength( flattensize );
            if ( rc ) 
            {
                std::ostringstream osse;
                osse << "PNORInstruction::execute - o_data.setWordLength(" << flattensize << ") failure" << std::endl;
                o_status.errorMessage.append(osse.str());
                rc = o_status.rc = SERVER_PNOR_ERROR;
                return rc;
            }
#if defined(TESTING)
            printf("o_data.getBitLength is %d\n", o_data.getBitLength());
#endif

            rc = o_data.insert( (uint8_t *)flattenedffsData, 0, (flattensize * 32), 0 );
            if ( rc ) 
            {
                std::ostringstream osse;
                osse << "PNORInstruction::execute - o_data.insert failure" << std::endl;
                o_status.errorMessage.append(osse.str());
                rc = o_status.rc = SERVER_PNOR_ERROR;
                return rc;
            }
#if defined(TESTING)
            printf("o_data.insert completed\n");
            printf("\n%s\n", o_data.genHexLeftStr().c_str() );
#else
 #if !defined(NO_GFW)
            rc = ffs_close( ffs );
            if ( rc ) 
            {
                std::ostringstream osse;
                osse << "PNORInstruction::execute(" << InstructionCommandToString( command )<< ") - ffs_close failure rc(" << rc << ")" << std::endl;
                o_status.errorMessage.append(osse.str());
                rc = o_status.rc = SERVER_PNOR_DEVICE_FAIL_CLOSE;
                break;
            }
 #endif
#endif
            delete flattenedffsData;
            delete objHolder;

            rc = o_status.rc = SERVER_COMMAND_COMPLETE;
            break;
        }

        /*
         * GET OPERATION
         */
        case PNORGET:
        {
#if defined(TESTING)
            printf("PNORGET\n");
#endif

            std::string ffsDevice;
            ffsDevice = "/dev/mtdblock/sfc." + deviceString;

#if defined(TESTING)
            printf("ffsData = ffs_open( \"%s\", 0x%X );\n", ffsDevice.c_str(), partitionOffset );
#else
 #if !defined(NO_GFW)
            off_t ffsDeviceOffset = partitionOffset;
            ffs_t *ffsData = NULL;
            ffsData = ffs_open( ffsDevice.c_str(), ffsDeviceOffset );

            if ( ffsData == NULL )
            {
                std::ostringstream osse;
                osse << "PNORInstruction::execute SERVER DEBUG: Unable to open device " << ffsDevice << std::endl;
                o_status.errorMessage.append(osse.str());
                osse.clear(); osse.str(std::string());
                osse << "PNORInstruction::execute SERVER DEBUG: Listing partitions in image failed" << std::endl;
                o_status.errorMessage.append(osse.str());
                rc = o_status.rc = SERVER_PNOR_DEVICE_FAIL_OPEN;
                break;
            }
 #endif
#endif

#if defined(TESTING)
            printf("iterate over ffsData\n");
#else
 #if !defined(NO_GFW)
            //partitionEntry must match a partition entry within the ffsData, find it
            ffs_hdr_t *ffsHdr = ffsData->hdr;
            ffs_entry *myFoundEntry = NULL;
            for( uint32_t idx = 0; idx < ffsHdr->entry_count; idx++ )
            {
                ffs_entry *ffsEntry = &(ffsHdr->entries[idx]);
                std::string entryName = ffsEntry->name;
                if ( entryName == partitionEntry )
                {
                    myFoundEntry = ffsEntry;
                    break;
                }
            }
            
            if ( myFoundEntry == NULL )
            {
                std::ostringstream osse;
                osse << "PNORInstruction::execute Unable to find a matching partition with name " << partitionEntry << std::endl;
                o_status.errorMessage.append(osse.str());
                rc = o_status.rc = SERVER_PNOR_PARTITION_NOT_FOUND;
                break;
            }
 #endif
#endif

#if defined(TESTING)
            printf("matched partition, now get data\n");
#else
 #if !defined(NO_GFW)
            // myFoundEntry points to the specific entry we want to read out
            if (global_server_debug) printf("myFoundEntry->type=%d, myFoundEntry->checksum=%.16X\n", myFoundEntry->type, myFoundEntry->checksum );
            if ( myFoundEntry->type == FFS_TYPE_LOGICAL )
            {
                std::ostringstream osse;
                osse << "PNORInstruction::execute Unable to get data from a logical partition for name " << partitionEntry << std::endl;
                o_status.errorMessage.append(osse.str());
                rc = o_status.rc = SERVER_PNOR_PARTITION_TYPE_INVALID;
                break;
            }
            else if ( myFoundEntry->actual == 0 )
            {
                std::ostringstream osse;
                osse << "PNORInstruction::execute Size of partition is 0, not reading anything out for name " << partitionEntry << " size(" << myFoundEntry->actual << ")" << std::endl;
                o_status.errorMessage.append(osse.str());
                rc = o_status.rc = SERVER_PNOR_PARTITION_EMPTY;
                break;
            }
            else
            {
                uint32_t bufferSize = ffsHdr->block_size * ffsData->buf_count;
                uint32_t *buffer = new uint32_t[bufferSize];
                // uses partitionOffset
                uint32_t total = 0;
                uint32_t size = myFoundEntry->actual;
                off_t offset = 0;

                if (global_server_debug) printf("bufferSize(%d), total(%d), size(%d), offset(%d)\n", bufferSize, total, size, (uint32_t) offset);

                while ( 0 < size )
                {
                    size_t count = std::min( bufferSize, size );

                    if (global_server_debug) printf("name(%s), offset(%d), count(%d), size(%d), total(%d)\n", partitionEntry.c_str(), (uint32_t) offset, count, size, total);

                    uint32_t bytesRead = ffs_entry_read( ffsData, partitionEntry.c_str(), buffer, offset, count ); 

                    if (global_server_debug) printf("post ffs_entry_read bytesRead=%d\n", bytesRead);
                    if ( bytesRead < 0 ) 
                    {
                        std::ostringstream osse;
                        osse << "PNORInstruction::execute failure in ffs_entry_read " << partitionEntry << " offset(" << offset << ") count(" << count << ")" << std::endl;
                        o_status.errorMessage.append(osse.str());
                        rc = o_status.rc = SERVER_PNOR_READ_ERROR;
                        break;
                    }
                    else if ( bytesRead != count )
                    {
                        std::ostringstream osse;
                        osse << "PNORInstruction::execute failure to read enough data from partition " << partitionEntry << " expected(" << count << ") bytesRead(" << bytesRead << ")" << std::endl;
                        o_status.errorMessage.append(osse.str());
                        rc = o_status.rc = SERVER_PNOR_READ_ERROR;
                        break;
                    }

                    o_data.growBitLength( o_data.getBitLength() + (count*32) );
                    o_data.insert( buffer, total*32, count*32, 0 );

                    size -= count; 
                    total += count;
                    offset += count;
                }

                // always attempt to close and only fallout on close if it fails
                // otherwise fallout on rc generated earlier
                rc = ffs_close( ffsData );
                if (global_server_debug) printf("post ffs_close rc=%d\n", rc);
                if ( rc ) 
                {
                    std::ostringstream osse;
                    osse << "PNORInstruction::execute(" << InstructionCommandToString( command )<< ") - ffs_close failure rc(" << rc << ")" << std::endl;
                    o_status.errorMessage.append(osse.str());
                    rc = o_status.rc = SERVER_PNOR_DEVICE_FAIL_CLOSE;
                    break;
                }
            }
 #endif
#endif
            // make sure to set rc to COMMAND_COMPLETE if not already set
            // otherwise leave rc as is so it can be returned
            if ( rc == 0 )
            {
                rc = o_status.rc = SERVER_COMMAND_COMPLETE;
            }
            break;
        }

        /*
         * PUT OPERATION
         */
        case PNORPUT:
        {
#if defined(TESTING)
            printf("PNORPUT\n");
#endif

            std::string ffsDevice;
            ffsDevice = "/dev/mtdblock/sfc." + deviceString;

#if defined(TESTING)
            printf("ffsData = ffs_open( \"%s\", 0x%X );\n", ffsDevice.c_str(), partitionOffset );
#else
 #if !defined(NO_GFW)
            off_t ffsDeviceOffset = partitionOffset;
            ffs_t *ffsData = NULL;
            ffsData = ffs_open( ffsDevice.c_str(), ffsDeviceOffset );

            if ( ffsData == NULL )
            {
                std::ostringstream osse;
                osse << "PNORInstruction::execute SERVER DEBUG: Unable to open device " << ffsDevice << std::endl;
                o_status.errorMessage.append(osse.str());
                osse.clear(); osse.str(std::string());
                osse << "PNORInstruction::execute SERVER DEBUG: Listing partitions in image failed" << std::endl;
                o_status.errorMessage.append(osse.str());
                rc = o_status.rc = SERVER_PNOR_DEVICE_FAIL_OPEN;
                break;
            }
 #endif
#endif

#if defined(TESTING)
            printf("iterate over ffsData\n");
#else
 #if !defined(NO_GFW)
            //partitionEntry must match a partition entry within the ffsData, find it
            ffs_hdr_t *ffsHdr = ffsData->hdr;
            ffs_entry *myFoundEntry = NULL;
            for( uint32_t idx = 0; idx < ffsHdr->entry_count; idx++ )
            {
                ffs_entry *ffsEntry = &(ffsHdr->entries[idx]);
                std::string entryName = ffsEntry->name;
                if ( entryName == partitionEntry )
                {
                    myFoundEntry = ffsEntry;
                    break;
                }
            }
            
            if ( myFoundEntry == NULL )
            {
                std::ostringstream osse;
                osse << "PNORInstruction::execute Unable to find a matching partition with name " << partitionEntry << std::endl;
                o_status.errorMessage.append(osse.str());
                rc = o_status.rc = SERVER_PNOR_PARTITION_NOT_FOUND;
                break;
            }
 #endif
#endif

#if defined(TESTING)
            printf("matched partition, now get data\n");
#else
 #if !defined(NO_GFW)
            // myFoundEntry points to the specific entry we want to read out
            if (global_server_debug) printf("myFoundEntry->type=%d, myFoundEntry->checksum=%.16X\n", myFoundEntry->type, myFoundEntry->checksum );
            if ( myFoundEntry->type == FFS_TYPE_LOGICAL )
            {
                std::ostringstream osse;
                osse << "PNORInstruction::execute Unable to get data from a logical partition for name " << partitionEntry << std::endl;
                o_status.errorMessage.append(osse.str());
                rc = o_status.rc = SERVER_PNOR_PARTITION_TYPE_INVALID;
                break;
            }
            else if ( myFoundEntry->actual == 0 )
            {
                std::ostringstream osse;
                osse << "PNORInstruction::execute Size of partition is 0, not reading anything out for name " << partitionEntry << " size(" << myFoundEntry->actual << ")" << std::endl;
                o_status.errorMessage.append(osse.str());
                rc = o_status.rc = SERVER_PNOR_PARTITION_EMPTY;
                break;
            }
            else
            {
                uint32_t bufferSize = ffsHdr->block_size * ffsData->buf_count;
                if ( blockSize != 0 )
                {
                    bufferSize = blockSize;
                }
                uint32_t *buffer = new uint32_t[bufferSize];
                
                uint32_t total = 0;
                uint32_t size = myFoundEntry->actual;
                off_t offset = 0;   

                if (global_server_debug) printf("bufferSize(%d), total(%d), size(%d), offset(%d), o_data.getWordLength()(%d)\n", bufferSize, total, size, (uint32_t) offset, o_data.getWordLength());

                if ( pnorFlags & INSTRUCTION_PNOR_FLAG_ERASE_PARTITION )
                {
                    // get first word from o_data (most likely 0)
                    uint32_t myWord = o_data.getWord(0);
                    // set the data buffer to the size of the partition
                    o_data.setWordLength(size);
                    // set each word in the buffer to myWord
                    for( uint32_t idx=0; idx < size; idx++ )
                    {
                        o_data.setWord( idx, myWord );
                    }
                    if (global_server_debug) printf("erasing buffer with value (%d) for each word\n", myWord);
                } 

                if ( o_data.getWordLength() != size )
                {
                    std::ostringstream osse;
                    osse << "PNORInstruction::execute size mismatch for " << partitionEntry << " size(" << size << ") is not equal to input size(" << o_data.getWordLength() << ")" << std::endl;
                    o_status.errorMessage.append(osse.str());
                    rc = o_status.rc = SERVER_PNOR_WRITE_ERROR;
                    break;
                }

                while ( 0 < size )
                {
                    size_t count = std::min( bufferSize, size );

                    if (global_server_debug) printf("name(%s), offset(%d), count(%d), size(%d), total(%d)\n", partitionEntry.c_str(), (uint32_t) offset, count, size, total);

                    // copy data from the ecmdDataBuffer into buffer for count (uint32_t's)
                    memset( buffer, 0x0, bufferSize );
                    o_data.extract( buffer, total * 32, count * 32 );

                    uint32_t bytesWritten = ffs_entry_write( ffsData, partitionEntry.c_str(), buffer, offset, count ); 

                    uint32_t fsyncRc = ffs_fsync( ffsData );

                    if (global_server_debug) printf("post ffs_entry_write bytesWritten=%d\n", bytesWritten);
                    if ( bytesWritten < 0 ) 
                    {
                        std::ostringstream osse;
                        osse << "PNORInstruction::execute failure in ffs_entry_write " << partitionEntry << " offset(" << offset << ") count(" << count << ")" << std::endl;
                        o_status.errorMessage.append(osse.str());
                        rc = o_status.rc = SERVER_PNOR_WRITE_ERROR;
                        break;
                    }
                    else if ( bytesWritten != count )
                    {
                        std::ostringstream osse;
                        osse << "PNORInstruction::execute failure to read enough data from partition " << partitionEntry << " expected(" << count << ") bytesWritten(" << bytesWritten << ")" << std::endl;
                        o_status.errorMessage.append(osse.str());
                        rc = o_status.rc = SERVER_PNOR_WRITE_ERROR;
                        break;
                    }
                    if ( fsyncRc < 0 )
                    {
                        std::ostringstream osse;
                        osse << "PNORInstruction::execute failure in ffs_fsync " << partitionEntry << " fsyncRc(" << fsyncRc << ")" << std::endl;
                        o_status.errorMessage.append(osse.str());
                        rc = o_status.rc = SERVER_PNOR_FSYNC_ERROR;
                        break;
                    }
                    
                    size -= count;
                    total += count;
                    offset += count;
                }
                // always attempt to close and only fallout on close if it fails
                // otherwise fallout on rc generated earlier
                rc = ffs_close( ffsData );
                if (global_server_debug) printf("post ffs_close rc=%d\n", rc);
                if ( rc ) 
                {
                    std::ostringstream osse;
                    osse << "PNORInstruction::execute(" << InstructionCommandToString( command )<< ") - ffs_close failure rc(" << rc << ")" << std::endl;
                    o_status.errorMessage.append(osse.str());
                    rc = o_status.rc = SERVER_PNOR_DEVICE_FAIL_CLOSE;
                    break;
                }
            } 
 #endif
#endif

            // make sure to set rc to COMMAND_COMPLETE if not already set
            // otherwise leave rc as is so it can be returned
            if ( rc == 0 )
            {
                rc = o_status.rc = SERVER_COMMAND_COMPLETE;
            }
            break;
        }
        default:
            rc = o_status.rc = SERVER_COMMAND_NOT_SUPPORTED;
            break;
    }

#endif // CRONUS_SERVER_SIDE

  return rc;
}