static int write_image(struct cli_state *s, struct params *p, const char *argv0) { int status; FILE *f; long data_size; struct bladerf_image *image = NULL; f = expand_and_open(p->data_file, "rb"); if (!f) { return CMD_RET_FILEOP; } if (fseek(f, 0, SEEK_END) != 0) { status = CMD_RET_FILEOP; goto write_image_out; } data_size = ftell(f); if (data_size < 0) { status = CMD_RET_FILEOP; goto write_image_out; } if ((uint32_t)data_size > p->max_length) { status = CMD_RET_INVPARAM; cli_err(s, argv0, "The provided data file is too large for the specified flash region."); goto write_image_out; } if (fseek(f, 0, SEEK_SET) != 0) { status = CMD_RET_FILEOP; goto write_image_out; } image = bladerf_alloc_image(p->type, p->address, data_size); if (!image) { status = CMD_RET_MEM; goto write_image_out; } if (fread(image->data, 1, data_size, f) != (size_t)data_size) { status = CMD_RET_FILEOP; goto write_image_out; } memcpy(image->serial, p->serial, BLADERF_SERIAL_LENGTH - 1); status = bladerf_image_write(image, p->img_file); if (status != 0) { s->last_lib_error = status; status = CMD_RET_LIBBLADERF; } write_image_out: fclose(f); bladerf_free_image(image); return status; }
struct bladerf_image * bladerf_alloc_cal_image(bladerf_fpga_size fpga_size, uint16_t vctcxo_trim) { struct bladerf_image *image; int status; image = bladerf_alloc_image(BLADERF_IMAGE_TYPE_CALIBRATION, BLADERF_FLASH_ADDR_CAL, BLADERF_FLASH_BYTE_LEN_CAL); if (!image) { return NULL; } status = make_cal_region(fpga_size, vctcxo_trim, image->data, image->length); if (status != 0) { bladerf_free_image(image); image = NULL; } return image; }
static int print_image_metadata(struct cli_state *s, struct params *p, const char *argv0) { int status = 0; struct bladerf_image *image; char datetime[64]; struct tm *timeval; time_t time_tmp; int i; image = bladerf_alloc_image(BLADERF_IMAGE_TYPE_INVALID, 0, 0); if (!image) { return CMD_RET_MEM; } status = bladerf_image_read(image, p->img_file); if (status == 0) { printf("\n"); printf("Checksum: "); for (i = 0; i < BLADERF_IMAGE_CHECKSUM_LEN; i++) { printf("%02x", image->checksum[i]); } printf("\nImage format version: %d.%d.%d\n", image->version.major, image->version.minor, image->version.patch); time_tmp = image->timestamp; timeval = localtime(&time_tmp); if (timeval) { memset(datetime, 0, sizeof(datetime)); strftime(datetime, sizeof(datetime) - 1, "%Y-%m-%d %H:%M:%S", timeval); } else { strncpy(datetime, "Invalid value", sizeof(datetime)); } printf("Timestamp: %s\n", datetime); printf("Serial #: %s\n", image->serial); switch (image->type) { case BLADERF_IMAGE_TYPE_RAW: printf("Image type: Raw\n"); break; case BLADERF_IMAGE_TYPE_CALIBRATION: printf("Image type: Calibration data\n"); break; case BLADERF_IMAGE_TYPE_FIRMWARE: printf("Image type: Firmware\n"); break; case BLADERF_IMAGE_TYPE_FPGA_40KLE: printf("Image type: 40 kLE FPGA metadata and bitstream\n"); break; case BLADERF_IMAGE_TYPE_FPGA_115KLE: printf("Image type: 115 kLE FPGA metadata and bitstream\n"); break; default: printf("Type: Unknown\n"); break; } printf("Address: 0x%08" PRIx32 "\n", image->address); printf("Length: 0x%08" PRIx32 "\n", image->length); printf("\n"); } else { if (status == BLADERF_ERR_INVAL) { cli_err(s, argv0, "Image contains invalid fields or data."); status = CMD_RET_INVPARAM; } s->last_lib_error = status; status = CMD_RET_LIBBLADERF; } bladerf_free_image(image); return status; }
/* See libbladeRF's dc_cal_table.c for the packed table data format */ int calibrate_dc_gen_tbl(struct cli_state *s, bladerf_module module, const char *filename, unsigned int f_low, unsigned f_inc, unsigned int f_high) { int retval, status; size_t off; struct bladerf_lms_dc_cals lms_dc_cals; unsigned int f; struct settings settings; bladerf_loopback loopback_backup; struct bladerf_image *image = NULL; const uint16_t magic = HOST_TO_LE16(0x1ab1); const uint32_t reserved = HOST_TO_LE32(0x00000000); const uint32_t tbl_version = HOST_TO_LE32(0x00000001); const size_t lms_data_size = 10; /* 10 uint8_t register values */ const uint32_t n_frequencies = (f_high - f_low) / f_inc + 1; const uint32_t n_frequencies_le = HOST_TO_LE32(n_frequencies); const size_t entry_size = sizeof(uint32_t) + /* Frequency */ 2 * sizeof(int16_t); /* DC I and Q valus */ const size_t table_size = n_frequencies * entry_size; const size_t data_size = sizeof(magic) + sizeof(reserved) + sizeof(tbl_version) + sizeof(n_frequencies_le) + lms_data_size + table_size; assert(data_size <= UINT_MAX); status = backup_and_update_settings(s->dev, module, &settings); if (status != 0) { return status; } status = bladerf_get_loopback(s->dev, &loopback_backup); if (status != 0) { return status; } status = bladerf_lms_get_dc_cals(s->dev, &lms_dc_cals); if (status != 0) { goto out; } if (module == BLADERF_MODULE_RX) { image = bladerf_alloc_image(BLADERF_IMAGE_TYPE_RX_DC_CAL, 0xffffffff, (unsigned int) data_size); } else { image = bladerf_alloc_image(BLADERF_IMAGE_TYPE_TX_DC_CAL, 0xffffffff, (unsigned int) data_size); } if (image == NULL) { status = BLADERF_ERR_MEM; goto out; } status = bladerf_get_serial(s->dev, image->serial); if (status != 0) { goto out; } if (module == BLADERF_MODULE_RX) { status = bladerf_set_loopback(s->dev, BLADERF_LB_NONE); if (status != 0) { goto out; } } off = 0; memcpy(&image->data[off], &magic, sizeof(magic)); off += sizeof(magic); memcpy(&image->data[off], &reserved, sizeof(reserved)); off += sizeof(reserved); memcpy(&image->data[off], &tbl_version, sizeof(tbl_version)); off += sizeof(tbl_version); memcpy(&image->data[off], &n_frequencies_le, sizeof(n_frequencies_le)); off += sizeof(n_frequencies_le); image->data[off++] = (uint8_t)lms_dc_cals.lpf_tuning; image->data[off++] = (uint8_t)lms_dc_cals.tx_lpf_i; image->data[off++] = (uint8_t)lms_dc_cals.tx_lpf_q; image->data[off++] = (uint8_t)lms_dc_cals.rx_lpf_i; image->data[off++] = (uint8_t)lms_dc_cals.rx_lpf_q; image->data[off++] = (uint8_t)lms_dc_cals.dc_ref; image->data[off++] = (uint8_t)lms_dc_cals.rxvga2a_i; image->data[off++] = (uint8_t)lms_dc_cals.rxvga2a_q; image->data[off++] = (uint8_t)lms_dc_cals.rxvga2b_i; image->data[off++] = (uint8_t)lms_dc_cals.rxvga2b_q; putchar('\n'); for (f = f_low; f <= f_high; f += f_inc) { const uint32_t frequency = HOST_TO_LE32((uint32_t)f); int16_t dc_i, dc_q; printf(" Calibrating @ %u Hz...", f); status = bladerf_set_frequency(s->dev, module, f); if (status != 0) { goto out; } if (module == BLADERF_MODULE_RX) { int16_t error_i, error_q; status = calibrate_dc_rx(s, &dc_i, &dc_q, &error_i, &error_q); printf(" I=%-4d (avg: %-4d), Q=%-4d (avg: %-4d)\r", dc_i, error_i, dc_q, error_q); } else { float error_i, error_q; status = calibrate_dc_tx(s, &dc_i, &dc_q, &error_i, &error_q); printf(" I=%-4d (avg: %3.3f), Q=%-4d (avg: %3.3f)\r", dc_i, error_i, dc_q, error_q); } if (status != 0) { goto out; } fflush(stdout); dc_i = HOST_TO_LE16(dc_i); dc_q = HOST_TO_LE16(dc_q); memcpy(&image->data[off], &frequency, sizeof(frequency)); off += sizeof(frequency); memcpy(&image->data[off], &dc_i, sizeof(dc_i)); off += sizeof(dc_i); memcpy(&image->data[off], &dc_q, sizeof(dc_q)); off += sizeof(dc_q); } status = bladerf_image_write(image, filename); printf("\n Done.\n\n"); out: retval = status; if (module == BLADERF_MODULE_RX) { status = bladerf_set_loopback(s->dev, loopback_backup); retval = first_error(retval, status); } status = bladerf_enable_module(s->dev, BLADERF_MODULE_RX, false); retval = first_error(retval, status); status = restore_settings(s->dev, module, &settings); retval = first_error(retval, status); bladerf_free_image(image); return retval; }
int cmd_flash_init_cal(struct cli_state *state, int argc, char **argv) { int rv; bool ok; uint16_t dac; bladerf_fpga_size fpga_size; struct bladerf_image *image = NULL; if(argc != 3 && argc != 4) { return CMD_RET_NARGS; } rv = str2fpga(argv[1], &fpga_size); if (rv != 0) { cli_err(state, argv[0], "Invalid FPGA provided."); return rv; } dac = str2uint(argv[2], 0, 0xffff, &ok); if(!ok) { cli_err(state, argv[0], "Invalid VCTCXO trim value provided."); return CMD_RET_INVPARAM; } image = bladerf_alloc_cal_image(fpga_size, dac); if (!image) { return CMD_RET_MEM; } if (argc == 3) { rv = flash_check_state(state, argv[0]); if (rv != 0) { goto cmd_flash_init_cal_out; } rv = bladerf_program_flash_unaligned(state->dev, image->address, image->data, image->length); if(rv < 0) { cli_err(state, argv[0], "Failed to write calibration data.\n" "\n" "This may have resulted in a corrupted flash. If the device fails to\n" "boot at the next power cycle, re-flash the firmware.\n" "\n" "See the following page for more information:\n" " https://github.com/Nuand/bladeRF/wiki/Upgrading-bladeRF-firmware\n" ); state->last_lib_error = rv; rv = CMD_RET_LIBBLADERF; } else { rv = 0; } } else { assert(argc == 4); rv = bladerf_image_write(image, argv[3]); } cmd_flash_init_cal_out: bladerf_free_image(image); return rv; }
/* See libbladeRF's dc_cal_table.c for the packed table data format */ int calibrate_dc_gen_tbl(struct cli_state *s, bladerf_module module, const char *filename, unsigned int f_low, unsigned f_inc, unsigned int f_high) { int retval, status; size_t off; struct bladerf_lms_dc_cals lms_dc_cals; unsigned int f; struct settings settings; bladerf_loopback loopback_backup; struct bladerf_image *image = NULL; FILE *write_check; const uint16_t magic = HOST_TO_LE16(0x1ab1); const uint32_t reserved = HOST_TO_LE32(0x00000000); const uint32_t tbl_version = HOST_TO_LE32(0x00000001); const size_t lms_data_size = 10; /* 10 uint8_t register values */ const uint32_t n_frequencies = (f_high - f_low) / f_inc + 1; const uint32_t n_frequencies_le = HOST_TO_LE32(n_frequencies); const size_t entry_size = sizeof(uint32_t) + /* Frequency */ 2 * sizeof(int16_t); /* DC I and Q valus */ const size_t table_size = n_frequencies * entry_size; const size_t data_size = sizeof(magic) + sizeof(reserved) + sizeof(tbl_version) + sizeof(n_frequencies_le) + lms_data_size + table_size; assert(data_size <= UINT_MAX); /* This operation may take a bit of time, so let's make sure we * actually have write access before kicking things off. Note that * access is checked later when the file is actually written. */ write_check = fopen(filename, "wb"); if (write_check == NULL) { if (errno == EACCES) { return BLADERF_ERR_PERMISSION; } else { return BLADERF_ERR_IO; } } else { fclose(write_check); /* Not much we care to do if this fails. Throw away the return value * to make this explicit to our static analysis tools */ (void) remove(filename); } status = backup_and_update_settings(s->dev, module, &settings); if (status != 0) { return status; } status = bladerf_get_loopback(s->dev, &loopback_backup); if (status != 0) { return status; } status = bladerf_lms_get_dc_cals(s->dev, &lms_dc_cals); if (status != 0) { goto out; } if (module == BLADERF_MODULE_RX) { image = bladerf_alloc_image(BLADERF_IMAGE_TYPE_RX_DC_CAL, 0xffffffff, (unsigned int) data_size); } else { image = bladerf_alloc_image(BLADERF_IMAGE_TYPE_TX_DC_CAL, 0xffffffff, (unsigned int) data_size); } if (image == NULL) { status = BLADERF_ERR_MEM; goto out; } status = bladerf_get_serial(s->dev, image->serial); if (status != 0) { goto out; } if (module == BLADERF_MODULE_RX) { status = bladerf_set_loopback(s->dev, BLADERF_LB_NONE); if (status != 0) { goto out; } } off = 0; memcpy(&image->data[off], &magic, sizeof(magic)); off += sizeof(magic); memcpy(&image->data[off], &reserved, sizeof(reserved)); off += sizeof(reserved); memcpy(&image->data[off], &tbl_version, sizeof(tbl_version)); off += sizeof(tbl_version); memcpy(&image->data[off], &n_frequencies_le, sizeof(n_frequencies_le)); off += sizeof(n_frequencies_le); image->data[off++] = (uint8_t)lms_dc_cals.lpf_tuning; image->data[off++] = (uint8_t)lms_dc_cals.tx_lpf_i; image->data[off++] = (uint8_t)lms_dc_cals.tx_lpf_q; image->data[off++] = (uint8_t)lms_dc_cals.rx_lpf_i; image->data[off++] = (uint8_t)lms_dc_cals.rx_lpf_q; image->data[off++] = (uint8_t)lms_dc_cals.dc_ref; image->data[off++] = (uint8_t)lms_dc_cals.rxvga2a_i; image->data[off++] = (uint8_t)lms_dc_cals.rxvga2a_q; image->data[off++] = (uint8_t)lms_dc_cals.rxvga2b_i; image->data[off++] = (uint8_t)lms_dc_cals.rxvga2b_q; putchar('\n'); for (f = f_low; f <= f_high; f += f_inc) { const uint32_t frequency = HOST_TO_LE32((uint32_t)f); int16_t dc_i, dc_q; printf(" Calibrating @ %u Hz...", f); status = bladerf_set_frequency(s->dev, module, f); if (status != 0) { goto out; } if (module == BLADERF_MODULE_RX) { int16_t error_i, error_q; status = calibrate_dc_rx(s, &dc_i, &dc_q, &error_i, &error_q); printf(" I=%-4d (avg: %-4d), Q=%-4d (avg: %-4d)\r", dc_i, error_i, dc_q, error_q); } else { float error_i, error_q; status = calibrate_dc_tx(s, &dc_i, &dc_q, &error_i, &error_q); printf(" I=%-4d (avg: %3.3f), Q=%-4d (avg: %3.3f)\r", dc_i, error_i, dc_q, error_q); } if (status != 0) { goto out; } fflush(stdout); dc_i = HOST_TO_LE16(dc_i); dc_q = HOST_TO_LE16(dc_q); memcpy(&image->data[off], &frequency, sizeof(frequency)); off += sizeof(frequency); memcpy(&image->data[off], &dc_i, sizeof(dc_i)); off += sizeof(dc_i); memcpy(&image->data[off], &dc_q, sizeof(dc_q)); off += sizeof(dc_q); } status = bladerf_image_write(image, filename); printf("\n Done.\n\n"); out: retval = status; if (module == BLADERF_MODULE_RX) { status = bladerf_set_loopback(s->dev, loopback_backup); retval = first_error(retval, status); } status = bladerf_enable_module(s->dev, BLADERF_MODULE_RX, false); retval = first_error(retval, status); status = restore_settings(s->dev, module, &settings); retval = first_error(retval, status); bladerf_free_image(image); return retval; }
int cmd_flash_restore(struct cli_state *state, int argc, char **argv) { int rv; struct bladerf_image *image = NULL; struct options opt; uint32_t addr, len; memset(&opt, 0, sizeof(opt)); rv = parse_argv(state, argc, argv, &opt); if (rv < 0) return rv; rv = flash_check_state(state, argv[0]); if (rv != 0) { goto cmd_flash_restore_out; } image = bladerf_alloc_image(BLADERF_IMAGE_TYPE_INVALID, 0, 0); if (!image) { rv = CMD_RET_MEM; goto cmd_flash_restore_out; } rv = bladerf_image_read(image, opt.file); if (rv < 0) { rv_error(rv, "Failed to read flash image from file."); goto cmd_flash_restore_out; } if (opt.override_defaults) { addr = opt.address; len = u32_min(opt.len, image->length); if (len < opt.len) { printf(" Warning: Reduced length because only %u bytes are in " "the image.\n", opt.len); } } else { addr = image->address; len = image->length; } rv = bladerf_program_flash_unaligned(state->dev, addr, image->data, len); if (rv < 0) { cli_err(state, argv[0], "Failed to restore flash region.\n" "\n" "Flash contents may be corrupted. If the device fails to boot at successive\n" "power-ons, see the following wiki page for recovery instructions:" " https://github.com/Nuand/bladeRF/wiki/Upgrading-bladeRF-firmware" ); goto cmd_flash_restore_out; } rv = CMD_RET_OK; cmd_flash_restore_out: free(opt.file); bladerf_free_image(image); return rv; }