boolean Protocol::parseByte(uint8_t data) { switch(m_mode) { case MODE_HEADER0: case MODE_PAYLOAD_READY: // If we get new data before a payload is handled, just start over. if(data == HEADER0) { reset(); m_mode = MODE_HEADER1; updateCRC(data); } else { } break; case MODE_HEADER1: if(data == HEADER1) { m_mode = MODE_LENGTH; updateCRC(data); } else { reset(); } break; case MODE_LENGTH: if(data <= MAX_DATA_SIZE && data > 0) { m_mode = MODE_PAYLOAD; m_expectedLength = data; updateCRC(data); } else { reset(); } break; case MODE_PAYLOAD: addByte(data); if(m_packetLength >= m_expectedLength) { // TODO: why >= and not just ==? m_mode = MODE_CRC; } break; case MODE_CRC: if(data == m_crc) { m_mode = MODE_PAYLOAD_READY; } else { reset(); } break; default: reset(); } return (m_mode == MODE_PAYLOAD_READY); }
/** * Transmit a NACK through the telemetry link. * \param[in] objId the ObjectID we rejected */ bool UAVTalk::transmitNack(quint32 objId) { int dataOffset = 8; txBuffer[0] = SYNC_VAL; txBuffer[1] = TYPE_NACK; qToLittleEndian<quint32>(objId, &txBuffer[4]); // Calculate checksum txBuffer[dataOffset] = updateCRC(0, txBuffer, dataOffset); qToLittleEndian<quint16>(dataOffset, &txBuffer[2]); // Send buffer, check that the transmit backlog does not grow above limit if ( io->bytesToWrite() < TX_BUFFER_SIZE ) { io->write((const char*)txBuffer, dataOffset+CHECKSUM_LENGTH); } else { ++stats.txErrors; return false; } // Update stats stats.txBytes += 8+CHECKSUM_LENGTH; // Done return true; }
/** * Transmit a NACK through the telemetry link. * This method is separate from transmitsingleobject because we are * using an objectID for an unknown object. * \param[in] objId the ObjectID we rejected */ bool UAVTalk::transmitNack(quint32 objId) { int dataOffset = 8; txBuffer[0] = SYNC_VAL; txBuffer[1] = TYPE_NACK; qToLittleEndian<quint32>(objId, &txBuffer[4]); // Calculate checksum txBuffer[dataOffset] = updateCRC(0, txBuffer, dataOffset); qToLittleEndian<quint16>(dataOffset, &txBuffer[2]); // Send buffer, check that the transmit backlog does not grow above limit if (io && io->isWritable() && io->bytesToWrite() < TX_BUFFER_SIZE ) { io->write((const char*)txBuffer, dataOffset+CHECKSUM_LENGTH); if(useUDPMirror) { udpSocketRx->writeDatagram((const char*)txBuffer,dataOffset+CHECKSUM_LENGTH,QHostAddress::LocalHost,udpSocketTx->localPort()); } } else { ++stats.txErrors; return false; } // Update stats stats.txBytes += 8+CHECKSUM_LENGTH; // Done return true; }
void bs_put_byte(u_int8_t c) { assert(INRANGE(output_bs.byte_p, output_bs.byte_window, output_bs.byte_end)); if (output_bs.byte_p == output_bs.byte_end) bs_flush_byte(&output_bs); updateCRC(output_bs.crc, c); *output_bs.byte_p++ = c; } /* bs_put_byte */
bool DS18B20::duty(OneWireHub *hub) { const uint8_t cmd = hub->recv(); //if (hub->getError()) return false; switch (cmd) { case 0x44: // CONVERT T --> start a new measurement conversion //hub->sendBit(1); // 1 is passive ... break; case 0x4E: // WRITE SCRATCHPAD // write 3 byte of data to scratchpad[1:3] hub->recv(&scratchpad[2], 3); updateCRC(); break; case 0xBE: // READ SCRATCHPAD hub->send(scratchpad, 9); if (hub->getError()) return false; break; case 0x48: // COPY SCRATCHPAD to EEPROM // send1 if parasite power is used break; case 0xB8: // RECALL E2 (EEPROM to 3byte from Scratchpad) //hub->sendBit(1); // signal that OP is done // 1 is passive ... break; case 0xB4: // READ POWER SUPPLY //hub->sendBit(1); // 1: say i am external powered, 0: uses parasite power, // 1 is passive, so ommit it ... break; // READ TIME SLOTS, respond with 1 if conversion is done, not usable with parasite power // write trim2 0x63 // copy trim2 0x64 // read trim2 0x68 // read trim1 0x93 // copy trim1 0x94 // write trim1 0x95 case 0xEC: // TODO: Alarm search command, respond if flag is set break; default: hub->raiseSlaveError(cmd); break; }; return true; };
//=================== DS18S20 ========================================== DS18B20::DS18B20(byte ID1, byte ID2, byte ID3, byte ID4, byte ID5, byte ID6, byte ID7): OneWireItem(ID1, ID2, ID3, ID4, ID5, ID6, ID7){ this->scratchpad[0] = 0xB4; // TLSB this->scratchpad[1] = 0x09; // TMSB this->scratchpad[2] = 0x4B; // THRE this->scratchpad[3] = 0x46; // TLRE this->scratchpad[4] = 0x1F; // Conf this->scratchpad[5] = 0xFF; // 0xFF this->scratchpad[6] = 0x00; // Rese this->scratchpad[7] = 0x10; // 0x10 this->scratchpad[8] = 0x00; // CRC updateCRC(); }
DS18B20::DS18B20(uint8_t ID1, uint8_t ID2, uint8_t ID3, uint8_t ID4, uint8_t ID5, uint8_t ID6, uint8_t ID7) : OneWireItem(ID1, ID2, ID3, ID4, ID5, ID6, ID7) { scratchpad[0] = 0xA0; // TLSB --> 10 degC as std scratchpad[1] = 0x00; // TMSB scratchpad[2] = 0x4B; // THRE --> Trigger register TH scratchpad[3] = 0x46; // TLRE --> TLow scratchpad[4] = 0x7F; // Conf // = 0 R1 R0 1 1 1 1 1 --> R=0 9bit, R=3 12bit scratchpad[5] = 0xFF; // 0xFF scratchpad[6] = 0x00; // Reset scratchpad[7] = 0x10; // 0x10 updateCRC(); // update scratchpad[8] }
void DS18B20::settemp(float temp) { word ret = 0; bool Neg = temp < 0; temp = abs(temp); ret = round(floor(temp)) << 4; if (Neg){ ret = ret | 0x8000; } ret = ret | byte(16*((temp - (int)temp) * 100)/100); this->scratchpad[0] = byte(ret); this->scratchpad[1] = byte(ret >> 8); updateCRC(); }
// use always 12bit mode! also 9,10,11,12 bit possible bitPosition seems to stay the same void DS18B20::setTempRaw(const int16_t value_raw) { int16_t value = value_raw; if (value > 0) { value &= 0x0FFF; } else { value = -value; value |= 0xF000; }; scratchpad[0] = uint8_t(value); scratchpad[1] = uint8_t(value >> 8); // TODO: if alarms implemented - compare TH,TL with (value>>4 & 0xFF) (bit 11to4) // if out of bounds >=TH, <=TL trigger flag updateCRC(); };
/** * Send an object through the telemetry link. * \param[in] obj Object handle to send * \param[in] type Transaction type * \return Success (true), Failure (false) */ bool UAVTalk::transmitSingleObject(UAVObject* obj, quint8 type, bool allInstances) { qint32 length; qint32 dataOffset; quint32 objId; quint16 instId; quint16 allInstId = ALL_INSTANCES; // Setup type and object id fields objId = obj->getObjID(); txBuffer[0] = SYNC_VAL; txBuffer[1] = type; qToLittleEndian<quint32>(objId, &txBuffer[4]); // Setup instance ID if one is required if ( obj->isSingleInstance() ) { dataOffset = 8; } else { // Check if all instances are requested if (allInstances) { qToLittleEndian<quint16>(allInstId, &txBuffer[8]); } else { instId = obj->getInstID(); qToLittleEndian<quint16>(instId, &txBuffer[8]); } dataOffset = 10; } // Determine data length if (type == TYPE_OBJ_REQ || type == TYPE_ACK) { length = 0; } else { length = obj->getNumBytes(); } // Check length if (length >= MAX_PAYLOAD_LENGTH) { return false; } // Copy data (if any) if (length > 0) { if ( !obj->pack(&txBuffer[dataOffset]) ) { return false; } } qToLittleEndian<quint16>(dataOffset + length, &txBuffer[2]); // Calculate checksum txBuffer[dataOffset+length] = updateCRC(0, txBuffer, dataOffset + length); // Send buffer, check that the transmit backlog does not grow above limit if ( io->bytesToWrite() < TX_BUFFER_SIZE ) { io->write((const char*)txBuffer, dataOffset+length+CHECKSUM_LENGTH); } else { ++stats.txErrors; return false; } // Update stats ++stats.txObjects; stats.txBytes += dataOffset+length+CHECKSUM_LENGTH; stats.txObjectBytes += length; // Done return true; }
/** * Process an byte from the telemetry stream. * \param[in] rxbyte Received byte * \return Success (true), Failure (false) */ bool UAVTalk::processInputByte(quint8 rxbyte) { // Update stats stats.rxBytes++; rxPacketLength++; // update packet byte count // Receive state machine switch (rxState) { case STATE_SYNC: if (rxbyte != SYNC_VAL) { UAVTALK_QXTLOG_DEBUG("UAVTalk: Sync->Sync (" + QString::number(rxbyte) + " " + QString("0x%1").arg(rxbyte,2,16) + ")"); break; } // Initialize and update CRC rxCS = updateCRC(0, rxbyte); rxPacketLength = 1; rxState = STATE_TYPE; UAVTALK_QXTLOG_DEBUG("UAVTalk: Sync->Type"); break; case STATE_TYPE: // Update CRC rxCS = updateCRC(rxCS, rxbyte); if ((rxbyte & TYPE_MASK) != TYPE_VER) { rxState = STATE_SYNC; UAVTALK_QXTLOG_DEBUG("UAVTalk: Type->Sync"); break; } rxType = rxbyte; packetSize = 0; rxState = STATE_SIZE; UAVTALK_QXTLOG_DEBUG("UAVTalk: Type->Size"); rxCount = 0; break; case STATE_SIZE: // Update CRC rxCS = updateCRC(rxCS, rxbyte); if (rxCount == 0) { packetSize += rxbyte; rxCount++; UAVTALK_QXTLOG_DEBUG("UAVTalk: Size->Size"); break; } packetSize += (quint32)rxbyte << 8; if (packetSize < MIN_HEADER_LENGTH || packetSize > MAX_HEADER_LENGTH + MAX_PAYLOAD_LENGTH) { // incorrect packet size rxState = STATE_SYNC; UAVTALK_QXTLOG_DEBUG("UAVTalk: Size->Sync"); break; } rxCount = 0; rxState = STATE_OBJID; UAVTALK_QXTLOG_DEBUG("UAVTalk: Size->ObjID"); break; case STATE_OBJID: // Update CRC rxCS = updateCRC(rxCS, rxbyte); rxTmpBuffer[rxCount++] = rxbyte; if (rxCount < 4) { UAVTALK_QXTLOG_DEBUG("UAVTalk: ObjID->ObjID"); break; } // Search for object, if not found reset state machine rxObjId = (qint32)qFromLittleEndian<quint32>(rxTmpBuffer); { UAVObject *rxObj = objMngr->getObject(rxObjId); if (rxObj == NULL && rxType != TYPE_OBJ_REQ) { stats.rxErrors++; rxState = STATE_SYNC; UAVTALK_QXTLOG_DEBUG("UAVTalk: ObjID->Sync (badtype)"); break; } // Determine data length if (rxType == TYPE_OBJ_REQ || rxType == TYPE_ACK || rxType == TYPE_NACK) { rxLength = 0; rxInstanceLength = 0; } else { rxLength = rxObj->getNumBytes(); rxInstanceLength = (rxObj->isSingleInstance() ? 0 : 2); } // Check length and determine next state if (rxLength >= MAX_PAYLOAD_LENGTH) { stats.rxErrors++; rxState = STATE_SYNC; UAVTALK_QXTLOG_DEBUG("UAVTalk: ObjID->Sync (oversize)"); break; } // Check the lengths match if ((rxPacketLength + rxInstanceLength + rxLength) != packetSize) { // packet error - mismatched packet size stats.rxErrors++; rxState = STATE_SYNC; UAVTALK_QXTLOG_DEBUG("UAVTalk: ObjID->Sync (length mismatch)"); break; } // Check if this is a single instance object (i.e. if the instance ID field is coming next) if (rxObj == NULL) { // This is a non-existing object, just skip to checksum // and we'll send a NACK next. rxState = STATE_CS; UAVTALK_QXTLOG_DEBUG("UAVTalk: ObjID->CSum (no obj)"); rxInstId = 0; rxCount = 0; } else if (rxObj->isSingleInstance()) { // If there is a payload get it, otherwise receive checksum if (rxLength > 0) { rxState = STATE_DATA; UAVTALK_QXTLOG_DEBUG("UAVTalk: ObjID->Data (needs data)"); } else { rxState = STATE_CS; UAVTALK_QXTLOG_DEBUG("UAVTalk: ObjID->Checksum"); } rxInstId = 0; rxCount = 0; } else { rxState = STATE_INSTID; UAVTALK_QXTLOG_DEBUG("UAVTalk: ObjID->InstID"); rxCount = 0; } } break; case STATE_INSTID: // Update CRC rxCS = updateCRC(rxCS, rxbyte); rxTmpBuffer[rxCount++] = rxbyte; if (rxCount < 2) { UAVTALK_QXTLOG_DEBUG("UAVTalk: InstID->InstID"); break; } rxInstId = (qint16)qFromLittleEndian<quint16>(rxTmpBuffer); rxCount = 0; // If there is a payload get it, otherwise receive checksum if (rxLength > 0) { rxState = STATE_DATA; UAVTALK_QXTLOG_DEBUG("UAVTalk: InstID->Data"); } else { rxState = STATE_CS; UAVTALK_QXTLOG_DEBUG("UAVTalk: InstID->CSum"); } break; case STATE_DATA: // Update CRC rxCS = updateCRC(rxCS, rxbyte); rxBuffer[rxCount++] = rxbyte; if (rxCount < rxLength) { UAVTALK_QXTLOG_DEBUG("UAVTalk: Data->Data"); break; } rxState = STATE_CS; UAVTALK_QXTLOG_DEBUG("UAVTalk: Data->CSum"); rxCount = 0; break; case STATE_CS: // The CRC byte rxCSPacket = rxbyte; if (rxCS != rxCSPacket) { // packet error - faulty CRC stats.rxErrors++; rxState = STATE_SYNC; UAVTALK_QXTLOG_DEBUG("UAVTalk: CSum->Sync (badcrc)"); break; } if (rxPacketLength != packetSize + 1) { // packet error - mismatched packet size stats.rxErrors++; rxState = STATE_SYNC; UAVTALK_QXTLOG_DEBUG("UAVTalk: CSum->Sync (length mismatch)"); break; } mutex->lock(); receiveObject(rxType, rxObjId, rxInstId, rxBuffer, rxLength); stats.rxObjectBytes += rxLength; stats.rxObjects++; mutex->unlock(); rxState = STATE_SYNC; UAVTALK_QXTLOG_DEBUG("UAVTalk: CSum->Sync (OK)"); break; default: rxState = STATE_SYNC; stats.rxErrors++; UAVTALK_QXTLOG_DEBUG("UAVTalk: ???->Sync"); } // Done return true; }
/** * Process an byte from the telemetry stream. * \param[in] rxbyte Received byte * \return Success (true), Failure (false) */ bool UAVTalk::processInputByte(quint8 rxbyte) { if (!objMngr || !io) // Pip return false; // Update stats stats.rxBytes++; rxPacketLength++; // update packet byte count // Receive state machine switch (rxState) { case STATE_SYNC: if (rxbyte != SYNC_VAL) break; // Initialize and update CRC rxCS = updateCRC(0, rxbyte); rxPacketLength = 1; rxState = STATE_TYPE; break; case STATE_TYPE: // Update CRC rxCS = updateCRC(rxCS, rxbyte); if ((rxbyte & TYPE_MASK) != TYPE_VER) { rxState = STATE_SYNC; break; } rxType = rxbyte; packetSize = 0; rxState = STATE_SIZE; rxCount = 0; break; case STATE_SIZE: // Update CRC rxCS = updateCRC(rxCS, rxbyte); if (rxCount == 0) { packetSize += rxbyte; rxCount++; break; } packetSize += (quint32)rxbyte << 8; if (packetSize < MIN_HEADER_LENGTH || packetSize > MAX_HEADER_LENGTH + MAX_PAYLOAD_LENGTH) { // incorrect packet size rxState = STATE_SYNC; break; } rxCount = 0; rxState = STATE_OBJID; break; case STATE_OBJID: // Update CRC rxCS = updateCRC(rxCS, rxbyte); rxTmpBuffer[rxCount++] = rxbyte; if (rxCount < 4) break; // Search for object, if not found reset state machine rxObjId = (qint32)qFromLittleEndian<quint32>(rxTmpBuffer); { UAVObject *rxObj = objMngr->getObject(rxObjId); if (rxObj == NULL) { stats.rxErrors++; rxState = STATE_SYNC; break; } // Determine data length if (rxType == TYPE_OBJ_REQ || rxType == TYPE_ACK) rxLength = 0; else rxLength = rxObj->getNumBytes(); // Check length and determine next state if (rxLength >= MAX_PAYLOAD_LENGTH) { stats.rxErrors++; rxState = STATE_SYNC; break; } // Check the lengths match if ((rxPacketLength + rxLength) != packetSize) { // packet error - mismatched packet size stats.rxErrors++; rxState = STATE_SYNC; break; } // Check if this is a single instance object (i.e. if the instance ID field is coming next) if (rxObj->isSingleInstance()) { // If there is a payload get it, otherwise receive checksum if (rxLength > 0) rxState = STATE_DATA; else rxState = STATE_CS; rxInstId = 0; rxCount = 0; } else { rxState = STATE_INSTID; rxCount = 0; } } break; case STATE_INSTID: // Update CRC rxCS = updateCRC(rxCS, rxbyte); rxTmpBuffer[rxCount++] = rxbyte; if (rxCount < 2) break; rxInstId = (qint16)qFromLittleEndian<quint16>(rxTmpBuffer); rxCount = 0; // If there is a payload get it, otherwise receive checksum if (rxLength > 0) rxState = STATE_DATA; else rxState = STATE_CS; break; case STATE_DATA: // Update CRC rxCS = updateCRC(rxCS, rxbyte); rxBuffer[rxCount++] = rxbyte; if (rxCount < rxLength) break; rxState = STATE_CS; rxCount = 0; break; case STATE_CS: // The CRC byte rxCSPacket = rxbyte; if (rxCS != rxCSPacket) { // packet error - faulty CRC stats.rxErrors++; rxState = STATE_SYNC; break; } if (rxPacketLength != packetSize + 1) { // packet error - mismatched packet size stats.rxErrors++; rxState = STATE_SYNC; break; } mutex->lock(); receiveObject(rxType, rxObjId, rxInstId, rxBuffer, rxLength); stats.rxObjectBytes += rxLength; stats.rxObjects++; mutex->unlock(); rxState = STATE_SYNC; break; default: rxState = STATE_SYNC; stats.rxErrors++; } // Done return true; }
void Protocol::addByte(uint8_t data) { m_packetData[m_packetLength] = data; m_packetLength +=1; updateCRC(data); }
int main(int argc, char* argv[]) { printf("[i] Make fimware.\n"); if(argc < 5){ // не задано имя файла прошивки printf("[!] Set file names!\n"); help2(); return -1; } bool isDlink = false; size_t size_result=0, size_bcm=0, size_cfe=0, size_sqsh=0, size_kernel=0, size_name=0; FILE* fresult=0, *fbcm=0, *fcfe=0, *fsqsh=0, *fkernel=0, *fname=0; // имя файла задаётся первым параметром char* file_bcm = argv[1]; printf("[i] bcm file: %s\n", file_bcm); fbcm = fopen(file_bcm, "rb"); if(fbcm){ size_bcm = getFileSize(fbcm); } // проверим длину заголовка if(size_bcm!=BCM_LENGTH){ printf("[!] Error: wrong bcm file size: %s (%d bytes)\n", file_bcm, size_bcm); help2(); return -1; } char* file_cfe = argv[2]; printf("[i] cfe file: %s\n", file_cfe); fcfe = fopen(file_cfe, "rb"); if(fcfe){ size_cfe = getFileSize(fcfe); } char* file_sqsh = argv[3]; printf("[i] sqsh file: %s\n", file_sqsh); fsqsh = fopen(file_sqsh, "rb"); if(fsqsh){ size_sqsh = getFileSize(fsqsh); } char* file_kernel = argv[4]; printf("[i] kernel file: %s\n", file_kernel); fkernel = fopen(file_kernel, "rb"); if(fkernel){ size_kernel = getFileSize(fkernel); } char* file_name = 0; // для прошивки от D-link-а if(argc>5){ isDlink = true; file_name = argv[5]; printf("[i] name file: %s\n", file_name); fname = fopen(file_name, "rb"); if(fname){ size_name = getFileSize(fname); } // проверим длину названия if(size_name!=NAME_LENGTH){ printf("[!] Error: wrong name file size: %s (%d bytes)\n", file_name, size_name); help2(); return -1; } } size_result = size_bcm + size_cfe + size_sqsh + size_kernel + size_name; if(!fbcm || !fcfe || !fsqsh || !fkernel){ printf("[!] Error: cant open files!\n"); return -2; } if(isDlink && !fname){ printf("[!] Error: cant open name-file!\n"); return -2; } printf("[i] result size: %d\n", size_result); fresult = fopen(result_file, "wb+"); if(!fresult){ printf("[!] Error: cant open file for writing: %s!\n", result_file); return -2; } // // буфер для сохранения // uchar* buf = new uchar [size_result]; if(!buf){ printf("[!] Error: cant allocate memory!\n"); return -4; } // // считываем файлы в общий буфер // // bcm fread(buf, size_bcm, 1, fbcm); // cfe fread((uint8_t *) (buf + size_bcm), size_cfe, 1, fcfe); // sqsh fread((uint8_t *) (buf + size_bcm + size_cfe), size_sqsh, 1, fsqsh); // kernel fread((uint8_t *) (buf + size_bcm + size_cfe + size_sqsh), size_kernel, 1, fkernel); // name if(isDlink){ fread((uint8_t *) (buf + size_bcm + size_cfe + size_sqsh + size_kernel), size_name, 1, fname); } // // рассчёт CRC // uint32_t crc=CRC32_INIT_VALUE, crc_bcm=CRC32_INIT_VALUE, crc_image=CRC32_INIT_VALUE, crc_rootfs=CRC32_INIT_VALUE, crc_kernel=CRC32_INIT_VALUE; char file_crc[16], header_crc[16], image_crc[16], rootfs_crc[16], kernel_crc[16]; // CRC образа cfe+sqsh+kernel crc_image = getCRC32String((uint8_t *) (buf + size_bcm), size_cfe+size_sqsh+size_kernel, image_crc); printf("[i] CRC image\t\t: 0x%s\n", image_crc); if(isDlink){ // CRC образа cfe+sqsh+kernel+name crc_image = getCRC32String((uint8_t *) (buf + size_bcm), size_cfe+size_sqsh+size_kernel+size_name, image_crc); printf("[i] D-link CRC image\t\t: 0x%s\n", image_crc); } // CRC корневой файловой системы crc_rootfs = getCRC32String((uint8_t *) (buf + size_bcm + size_cfe), size_sqsh, rootfs_crc); printf("[i] CRC sqsh\t\t: 0x%s\n", rootfs_crc); // CRC ядра crc_kernel = getCRC32String((uint8_t *) (buf + size_bcm + size_cfe + size_sqsh), size_kernel, kernel_crc); printf("[i] CRC kernel\t\t: 0x%s\n", kernel_crc); // // запись размеров // printf("[i] update size...\n"); // totalImageLen = cfe+sqsh+kernel uint32_t place = TAG_VER_LEN+SIG_LEN+SIG_LEN_2+CHIP_ID_LEN+BOARD_ID_LEN+FLAG_LEN; updateLength(buf, place, size_cfe + size_sqsh + size_kernel); if(isDlink){ // totalImageLen = cfe+sqsh+kernel+name updateLength(buf, place, size_cfe + size_sqsh + size_kernel + size_name); } // cfe place += IMAGE_LEN + ADDRESS_LEN; updateLength(buf, place, size_cfe); // rootFS place += IMAGE_LEN + ADDRESS_LEN; updateLength(buf, place, size_sqsh); // kernel place += IMAGE_LEN + ADDRESS_LEN; updateLength(buf, place, size_kernel); // // запись CRC // // образа (cfe+sqsh+kernel) printf("[i] update image CRC...\n"); updateCRC(buf, TAG_LEN - 2*TOKEN_LEN, crc_image); // файловой системы printf("[i] update sqsh CRC...\n"); updateCRC(buf, TAG_LEN - 2*TOKEN_LEN + 4, crc_rootfs); // ядра printf("[i] update kernel CRC...\n"); updateCRC(buf, TAG_LEN - 2*TOKEN_LEN + 8, crc_kernel); // // теперь, с новыми CRC в заголовке - нужно // пересчитать CRC самого заголовка // // рассчёт CRC заголовка crc_bcm = getCRC32String((uint8_t *) (buf), size_bcm-TOKEN_LEN, header_crc); printf("[i] CRC header\t\t: 0x%s\n", header_crc); // обновляем printf("[i] update header CRC...\n"); updateCRC(buf, TAG_LEN - TOKEN_LEN, crc_bcm); printf("[i] write file: %s\n", result_file); // // записываем результат в файл // fwrite(buf, size_result, 1, fresult); // закрытие файлов fclose(fbcm); fclose(fcfe); fclose(fsqsh); fclose(fkernel); fclose(fresult); printf("[i] Done.\n"); info(); return 0; }