/* crc-calc.c - Calculate and set a CRC of a soil sensor combined (main + bootloader) * firmware image. The path to the firmware image is passed as the first * command-line argument. */ #include #include #include #include /* Calculate CRC of a Sense/Net packet. packet[0] is the header. * If this function is computed over a whole packet, including the * CRC at the end, a return value of 0 indicates a valid packet. */ uint16_t calc_crc(uint8_t *packet, int packet_length){ uint16_t remainder = 0xFFFF; for (int i = 0; i < packet_length; i++){ remainder ^= packet[i] << 8; for (int bit = 8; bit > 0; bit--){ if (remainder & 0x8000){ remainder = (remainder << 1) ^ 0x1021; } else { remainder = (remainder << 1); } } } return remainder; } /* Compute and set the overall CRC of the whole main firmware flash space. * A CRC is first computed for each set of six flash pages, then an * overall CRC is computed from those. */ void calc_flash_crc(uint8_t *flash){ uint8_t sixpage_crcs[64]; /* CRCs of each set of six pages. */ uint16_t temp; for(int i=0; i<32; i++){ if(31 == i){ /* Exclude the last two bytes of the last page, * as they contain the overall CRC. */ temp = calc_crc(flash + (i * 192), 190); sixpage_crcs[i * 2] = temp & 0xFF; sixpage_crcs[(i * 2) + 1] = (temp >> 8) & 0xFF; } else { temp = calc_crc(flash + (i * 192), 192); sixpage_crcs[i * 2] = temp & 0xFF; sixpage_crcs[(i * 2) + 1] = (temp >> 8) & 0xFF; } } temp = calc_crc((uint8_t *) sixpage_crcs, 64); flash[6142] = temp & 0xFF; flash[6143] = (temp >> 8) & 0xFF; } int main(int argc, char *argv[]){ if(argc != 2){ fprintf(stderr, "crc-calc: error: expected the firmware image path as the only command-line argument.\n"); return -1; } FILE *fwfile; fwfile = fopen(argv[1], "r+"); if(NULL == fwfile){ fprintf(stderr, "crc-calc: error: could not open firmware file %s\n", argv[1]); perror(NULL); return -1; } /* Check that the file isn't too large. */ fseek(fwfile, 0, SEEK_END); int fwsize = ftell(fwfile); rewind(fwfile); if(fwsize > 8192){ fprintf(stderr, "crc-calc: error: firmware file %s too large\n", argv[1]); return -1; } if(fwsize < 6144){ fprintf(stderr, "crc-calc: error: firmware file %s too small\n", argv[1]); return -1; } /* Load firmware into memory. */ char *fwbuf = malloc(6144); if(NULL == fwbuf){ fprintf(stderr, "crc-calc: error: malloc failure."); return -1; } if(6144 != fread(fwbuf, 1, 6144, fwfile)){ fprintf(stderr, "crc-calc: error: could not read firmware file.\n"); perror("calc-crc"); return -1; } rewind(fwfile); calc_flash_crc((uint8_t *) fwbuf); if(6144 != fwrite(fwbuf, 1, 6144, fwfile)){ fprintf(stderr, "crc-calc: error: could not write firmware file.\n"); perror("calc-crc"); return -1; } fclose(fwfile); free(fwbuf); return 0; }