Ejemplo n.º 1
0
int main (int argc, const char * argv[]) {
	FILE *fp, *fp_write;
	AtmelGenericRecord arec;
	IHexRecord irec;
	SRecord srec;
	int addr; 
	int nodeid; 

	if (argc < 3) {
		fprintf(stderr, "Usage: %s <file format> <file>\n", argv[0]);
		fprintf(stderr, "This program will print the records saved in a generic,\nIntel HEX, or Motorola S-Record formatted file.\n\n");
		fprintf(stderr, "<file format> can be generic, ihex, or srecord.\n");
		fprintf(stderr, "<file> is the path to the file containing the records.\n");
		return -1;
	}

	fp = fopen(argv[2], "r");
	
	if (fp == NULL) {
		perror("Error opening file!");
		return -1;
	}

	fp_write = fopen(argv[3], "w");

	if (fp_write == NULL) {
		perror("Error opening file!");
		return -1;
	}

	addr = strtol(argv[4], (char **)NULL, 16);
	nodeid = strtol(argv[5], (char **)NULL, 10);


	if (strcasecmp(argv[1], "generic") == 0) {
		while (Read_AtmelGenericRecord(&arec, fp) == ATMEL_GENERIC_OK) {
			Print_AtmelGenericRecord(&arec);
			printf("\n");
		}
	} else if (strcasecmp(argv[1], "ihex") == 0) {
		while (Read_IHexRecord(&irec, fp) == IHEX_OK) {
			Write_IHexRecord(&irec, fp_write, addr, nodeid);
		}
	} else if (strcasecmp(argv[1], "srecord") == 0) {
		while (Read_SRecord(&srec, fp) == SRECORD_OK) {
			Print_SRecord(&srec);
			printf("\n");
		}
	} else {
		fprintf(stderr, "Invalid file format specified!\n");
		fclose(fp);
		fclose(fp_write); 
		return -1;
	}

	fclose(fp);
	return 0;
}
Ejemplo n.º 2
0
int byte_stream_ihex_read(struct ByteStream *self, uint8_t *data, uint32_t *address) {
    struct byte_stream_ihex_state *state = (struct byte_stream_ihex_state *)self->state;
    int ret;

    if (state->availBytes == 0) {
        do {
            /* Read the next record */
            ret = Read_IHexRecord(&(state->iRec), self->in);
            switch (ret) {
                case IHEX_OK:
                    break;
                case IHEX_ERROR_NEWLINE:
                    continue;
                case IHEX_ERROR_EOF:
                    return STREAM_EOF;
                case IHEX_ERROR_FILE:
                    self->error = "Error reading Intel HEX formatted file!";
                    return STREAM_ERROR_INPUT;
                case IHEX_ERROR_INVALID_RECORD:
                    self->error = "Invalid Intel HEX formatted file!";
                    return STREAM_ERROR_INPUT;
                default:
                    self->error = "Unknown error reading Intel HEX formatted file!";
                    return STREAM_ERROR_INPUT;
            }

        /* Continue reading until we get a data record */
        } while(state->iRec.type != IHEX_TYPE_00);

        /* Update our available bytes counter */
        state->availBytes = state->iRec.dataLen;
    }

    if (state->availBytes) {
        /* Copy over next low byte (assuming little-endian) */
        *data = state->iRec.data[ (state->iRec.dataLen - state->availBytes) ];
        *address = (uint32_t)state->iRec.address + (uint32_t)(state->iRec.dataLen - state->availBytes);
        state->availBytes--;
    }

    return 0;
}
Ejemplo n.º 3
0
int flashIHexFile(FIL* file)
{
    IHexRecord irec;
    flashsector_t sector;
    bool erasedSectors[FLASH_SECTOR_COUNT] = { FALSE };
    flashaddr_t baseAddress = 0;
    flashaddr_t address = 0;

    while (Read_IHexRecord(&irec, file) == IHEX_OK)
    {
        switch (irec.type)
        {
        case IHEX_TYPE_00:    /**< Data Record */
            /* Compute the target address in flash */
            address = baseAddress + irec.address;

            /* Erase the corresponding addresses if needed */
            for (sector = flashSectorAt(address); sector <= flashSectorAt(address + irec.dataLen - 1); ++sector)
            {
                /* Check if the sector has been erased during this IHex flashing procedure to
                   prevent erasing already written data */
                if (erasedSectors[sector] == TRUE)
                    continue;

                /* Check if the sector in flash needs to be erased */
                if (flashIsErased(flashSectorBegin(sector), flashSectorSize(sector)) == FALSE)
                {
                    /* Erase the sector */
                    if (flashSectorErase(sector) != FLASH_RETURN_SUCCESS)
                        return BOOTLOADER_ERROR_BADFLASH;
                }

                /* Set the erased flag to prevent erasing the same sector twice during
                   the IHex flashing procedure */
                erasedSectors[sector] = TRUE;
            }

            /* Write the data in flash */
            if (flashWrite(address, (const char*)irec.data, irec.dataLen) != FLASH_RETURN_SUCCESS)
                return BOOTLOADER_ERROR_BADFLASH;
            break;

        case IHEX_TYPE_04:    /**< Extended Linear Address Record */
            /* Compute the base address of the following data records */
            baseAddress = irec.data[0];
            baseAddress <<= 8;
            baseAddress += irec.data[1];
            baseAddress <<= 16;
            break;

        case IHEX_TYPE_01:    /**< End of File Record */
            /* Check that the end of file record is at the end of the file... */
            return f_eof(file) ? BOOTLOADER_SUCCESS : BOOTLOADER_ERROR_BADHEX;

        case IHEX_TYPE_05:    /**< Start Linear Address Record */
            /* Ignored */
            break;

        case IHEX_TYPE_02:    /**< Extended Segment Address Record */
        case IHEX_TYPE_03:    /**< Start Segment Address Record */
            /* Not supported */
            return BOOTLOADER_ERROR_BADHEX;
        }
    }

    return BOOTLOADER_ERROR_BADHEX;
}
Ejemplo n.º 4
0
/* write fn to device */
int nrf_program_nrf24lu(devp dev, const char *fn){
    unsigned char cmd[2], data[64], *flash_copy, dirty_bv[64];
    FILE *fp = NULL;
    int ecode, block, page, rc;
    unsigned int first_addr, last_addr;
    IHexRecord record;

    printf("Programming nRF24LU\n");
    /* read the entire ROM into memory
     *
     * Why? Because Nordic doesn't have decent software. Their flash write
     * command erases the page first, instead of letting me decide if the page
     * should be erased first.
     *
     * Byte-level writing is offered by using a read-modify-write operation.
     * It would be smarter to operate on a per-page basis, but Intel HEX files
     * are not guaranteed to have sequential addressing. Since Nordic screwed
     * up and wild IHX files are adhoc, let's work with the whole 32k flash
     * memory at once.
     */
    if((flash_copy = malloc(FLASH_SIZE)) == NULL){
        ecode = -4;
        goto err;
    }
    printf("[*] Reading device.\n");
    for(block = 0; block < 0x200; block++){
        /* set address MSB */
        if((block % 0x100) == 0){
            cmd[0] = 0x06;
            cmd[1] = (unsigned char)(block / 256);
            if(nrf_cmd(dev, cmd, 2, data, 1)){
                ecode = -2;
                goto err;
            }
        }
        /* request the block */
        cmd[0] = 0x03;
        cmd[1] = (unsigned char)block;
        if(nrf_cmd(dev, cmd, 2, &flash_copy[block2addr(block)], 64)){
            ecode = -2;
            goto err;
        }
    }

    /* overwrite in-memory with IHX contents */
    if((fp = fopen(fn, "r")) == NULL){
        ecode = -1;
        goto err;
    }
    memset(dirty_bv, 0, sizeof(dirty_bv));
    while((rc = Read_IHexRecord(&record, fp)) == IHEX_OK &&
            record.type != IHEX_TYPE_01){
        if(record.type != IHEX_TYPE_00){
            /* we cannot process segment or linear ihex files */
            printf("[!] IHX file contains segment or linear addressing.\n");
            ecode = -5;
            goto err;
        }
        /* first and last byte that is touched by this record */
        first_addr = record.address;
        last_addr = record.address + record.dataLen - 1;
        if(!addr_valid(first_addr) || !addr_valid(last_addr)){
            printf("[!] IHX record touches invalid or protected bytes: "
                    "0x%04X - 0x%04X\n", first_addr, last_addr);
            ecode = -6;
            goto err;
        }
        /* only write if the ihx record changes memory */
        if(memcmp(&flash_copy[first_addr], record.data, record.dataLen)){
            /* copy record into memory */
            memcpy(&flash_copy[first_addr], record.data, record.dataLen);
            /* mark dirty blocks */
            for(block = addr2block(first_addr); block <= addr2block(last_addr);
                    block++){
                /* check the block since we might have some *really* long
                 * record
                 */
                if(!addr_valid(block2addr(block))){
                    printf("[!] IHX record touches invalid or protected bytes:"
                            " 0x%04X\n", block2addr(block));
                    ecode = -6;
                    goto err;
                }
                bitset(dirty_bv, block);
            }
        }
    }
    if(rc != IHEX_OK && rc != IHEX_ERROR_EOF){
        /* we had an error that isn't EOF */
        ecode = -4;
        goto err;
    }

    /* write to flash */
    printf("[*] Writing device");
    fflush(stdout);
    for(page = 0; page < 64; page++){
        /* Each page is 8 blocks, which conviently maps to our dirty bit vector
         * on byte boundries.
         */
        if(dirty_bv[page]){
            printf(".");
            fflush(stdout);
            if(nrf_write_page(dev, page, &flash_copy[page2addr(page)])){
                printf("\n[!] Write failed.\n");
                ecode = -7;
                goto err;
            }
        }
    }
    printf("\n");

    /* verify */
    printf("[*] Verifying device");
    fflush(stdout);
    for(block = 0; block < 512; block++){
        if(bitisset(dirty_bv, block)){
            if(nrf_compare_block(dev, block, &flash_copy[block2addr(block)])){
                printf("\n[!] Block %d failed.\n", block);
                ecode = -8;
                goto err;
            } else {
                printf(".");
                fflush(stdout);
            }
        }
    }
    printf("\n");

    ecode = 0;
err:
    if(flash_copy){
        free(flash_copy);
    }
    if(fp){
        fclose(fp);
    }
    return ecode;
}