forked from len0rd/rockbox
imxtools: move firmware read/write to library
Split the ugly firmware read/write into a API function and a much simplified code. Also the code can now report progress. Change-Id: I3f998eaf0c067c6da42b1d2dd9c5a5bf43c6915d
This commit is contained in:
parent
0778184782
commit
950f4bdc02
3 changed files with 261 additions and 190 deletions
|
|
@ -31,6 +31,8 @@
|
|||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <inttypes.h>
|
||||
#include <errno.h>
|
||||
#include "rbscsi.h"
|
||||
#include "misc.h"
|
||||
#include "stmp_scsi.h"
|
||||
|
|
@ -147,7 +149,7 @@ static int do_info(void)
|
|||
cprintf_field(" Number of drives:", " %u\n", info.nr_drives);
|
||||
if(info.has.size)
|
||||
{
|
||||
cprintf_field(" Media size:", " %llu ", (unsigned long long)info.size);
|
||||
cprintf_field(" Media size:", " %" PRIu64 " ", info.size);
|
||||
cprintf(RED, "(%.3f %s)\n", get_size_natural(info.size), get_size_suffix(info.size));
|
||||
}
|
||||
if(info.has.alloc_size)
|
||||
|
|
@ -226,17 +228,17 @@ static int do_info(void)
|
|||
continue;
|
||||
if(info.has.sector_size)
|
||||
{
|
||||
cprintf_field(" Sector size:", " %llu ", (unsigned long long)info.sector_size);
|
||||
cprintf_field(" Sector size:", " %" PRIu32 " ", info.sector_size);
|
||||
cprintf(RED, "(%.3f %s)\n", get_size_natural(info.sector_size), get_size_suffix(info.sector_size));
|
||||
}
|
||||
if(info.has.erase_size)
|
||||
{
|
||||
cprintf_field(" Erase size:", " %llu ", (unsigned long long)info.erase_size);
|
||||
cprintf_field(" Erase size:", " %" PRIu32 " ", info.erase_size);
|
||||
cprintf(RED, "(%.3f %s)\n", get_size_natural(info.erase_size), get_size_suffix(info.erase_size));
|
||||
}
|
||||
if(info.has.size)
|
||||
{
|
||||
cprintf_field(" Drive size:", " %llu ", (unsigned long long)info.size);
|
||||
cprintf_field(" Drive size:", " %" PRIu64 " ", info.size);
|
||||
cprintf(RED, "(%.3f %s)\n", get_size_natural(info.size), get_size_suffix(info.size));
|
||||
}
|
||||
if(info.has.sector_count)
|
||||
|
|
@ -282,92 +284,70 @@ static int do_info(void)
|
|||
return 0;
|
||||
}
|
||||
|
||||
struct rw_fw_context_t
|
||||
{
|
||||
int tot_size;
|
||||
int cur_size;
|
||||
int last_percent;
|
||||
FILE *f;
|
||||
bool read;
|
||||
};
|
||||
|
||||
int rw_fw(void *user, void *buf, size_t size)
|
||||
{
|
||||
struct rw_fw_context_t *ctx = user;
|
||||
int this_percent = (ctx->cur_size * 100LLU) / ctx->tot_size;
|
||||
if(this_percent != ctx->last_percent && (this_percent % 5) == 0)
|
||||
{
|
||||
cprintf(RED, "%d%%", this_percent);
|
||||
cprintf(YELLOW, "...");
|
||||
fflush(stdout);
|
||||
}
|
||||
ctx->last_percent = this_percent;
|
||||
int ret = -1;
|
||||
if(ctx->read)
|
||||
ret = fread(buf, size, 1, ctx->f);
|
||||
else
|
||||
ret = fwrite(buf, size, 1, ctx->f);
|
||||
ctx->cur_size += size;
|
||||
if(ret != 1)
|
||||
return -1;
|
||||
else
|
||||
return size;
|
||||
}
|
||||
|
||||
void rw_finish(struct rw_fw_context_t *ctx)
|
||||
{
|
||||
if(ctx->last_percent == 100)
|
||||
return;
|
||||
cprintf(RED, "100%%\n");
|
||||
}
|
||||
|
||||
void do_extract(const char *file)
|
||||
{
|
||||
FILE *f = NULL;
|
||||
cprintf(BLUE, "Extracting firmware...\n");
|
||||
|
||||
struct stmp_logical_media_table_t *table = NULL;
|
||||
int ret = stmp_get_logical_media_table(g_dev_fd, &table);
|
||||
if(ret)
|
||||
{
|
||||
cprintf(GREY, "Cannot get logical table: %d\n", ret);
|
||||
goto Lend;
|
||||
}
|
||||
int entry = 0;
|
||||
while(entry < table->header.count)
|
||||
if(table->entry[entry].type == SCSI_STMP_DRIVE_TYPE_SYSTEM &&
|
||||
table->entry[entry].tag == SCSI_STMP_DRIVE_TAG_SYSTEM_BOOT)
|
||||
break;
|
||||
else
|
||||
entry++;
|
||||
if(entry == table->header.count)
|
||||
{
|
||||
cprintf(GREY, "Cannot find firmware partition\n");
|
||||
goto Lend;
|
||||
}
|
||||
uint8_t drive_no = table->entry[entry].drive_no;
|
||||
uint64_t drive_sz = table->entry[entry].size;
|
||||
if(g_debug)
|
||||
{
|
||||
cprintf(RED, "* ");
|
||||
cprintf_field("Drive: ", "%#x\n", drive_no);
|
||||
cprintf(RED, "* ");
|
||||
cprintf_field("Size: ", "%#llx\n", (unsigned long long)drive_sz);
|
||||
}
|
||||
struct stmp_logical_drive_info_t info;
|
||||
ret = stmp_get_logical_drive_info(g_dev_fd, drive_no, &info);
|
||||
if(ret || !info.has.sector_size)
|
||||
{
|
||||
cprintf(GREY, "Cannot get sector size\n");
|
||||
goto Lend;
|
||||
}
|
||||
unsigned sector_size = info.sector_size;
|
||||
if(g_debug)
|
||||
{
|
||||
cprintf(RED, "* ");
|
||||
cprintf_field("Sector size: ", "%lu\n", (unsigned long)sector_size);
|
||||
}
|
||||
uint8_t *sector = malloc(sector_size);
|
||||
ret = stmp_read_logical_drive_sectors(g_dev_fd, drive_no, 0, 1, sector, sector_size);
|
||||
if(ret)
|
||||
{
|
||||
cprintf(GREY, "Cannot read first sector: %d\n", ret);
|
||||
goto Lend;
|
||||
}
|
||||
uint32_t fw_size = *(uint32_t *)(sector + 0x1c) * 16;
|
||||
if(g_debug)
|
||||
{
|
||||
cprintf(RED, "* ");
|
||||
cprintf_field("Firmware size: ", "%#x\n", fw_size);
|
||||
}
|
||||
|
||||
f = fopen(file, "wb");
|
||||
FILE *f = fopen(file, "wb");
|
||||
if(f == NULL)
|
||||
{
|
||||
cprintf(GREY, "Cannot open '%s' for writing: %m\n", file);
|
||||
goto Lend;
|
||||
cprintf(GREY, "Cannot open output file: %s\n", strerror(errno));
|
||||
return;
|
||||
}
|
||||
|
||||
for(int sec = 0; sec * sector_size < fw_size; sec++)
|
||||
int ret = stmp_read_firmware(g_dev_fd, NULL, NULL);
|
||||
if(ret < 0)
|
||||
{
|
||||
ret = stmp_read_logical_drive_sectors(g_dev_fd, drive_no, sec, 1, sector, sector_size);
|
||||
if(ret)
|
||||
{
|
||||
cprintf(GREY, "Cannot read sector %d: %d\n", sec, ret);
|
||||
goto Lend;
|
||||
}
|
||||
if(fwrite(sector, sector_size, 1, f) != 1)
|
||||
{
|
||||
cprintf(GREY, "Write failed: %m\n");
|
||||
goto Lend;
|
||||
}
|
||||
cprintf(GREY, "Cannot get firmware size: %d\n", ret);
|
||||
return;
|
||||
}
|
||||
cprintf(BLUE, "Done\n");
|
||||
Lend:
|
||||
free(table);
|
||||
if(f)
|
||||
fclose(f);
|
||||
struct rw_fw_context_t ctx;
|
||||
ctx.tot_size = ret;
|
||||
ctx.cur_size = 0;
|
||||
ctx.f = f;
|
||||
ctx.last_percent = -1;
|
||||
ctx.read = false;
|
||||
ret = stmp_read_firmware(g_dev_fd, &ctx, &rw_fw);
|
||||
if(ret < 0)
|
||||
cprintf(GREY, "Cannot read firmware: %d\n", ret);
|
||||
rw_finish(&ctx);
|
||||
fclose(f);
|
||||
}
|
||||
|
||||
void do_write(const char *file, int want_a_brick)
|
||||
|
|
@ -379,115 +359,25 @@ void do_write(const char *file, int want_a_brick)
|
|||
cprintf(GREY, "option on the command line and do not complain if you end up with a brick ;)\n");
|
||||
return;
|
||||
}
|
||||
FILE *f = NULL;
|
||||
cprintf(BLUE, "Writing firmware...\n");
|
||||
|
||||
struct stmp_logical_media_table_t *table = NULL;
|
||||
int ret = stmp_get_logical_media_table(g_dev_fd, &table);
|
||||
if(ret)
|
||||
{
|
||||
cprintf(GREY, "Cannot get logical table: %d\n", ret);
|
||||
goto Lend;
|
||||
}
|
||||
int entry = 0;
|
||||
while(entry < table->header.count)
|
||||
if(table->entry[entry].type == SCSI_STMP_DRIVE_TYPE_SYSTEM &&
|
||||
table->entry[entry].tag == SCSI_STMP_DRIVE_TAG_SYSTEM_BOOT)
|
||||
break;
|
||||
else
|
||||
entry++;
|
||||
if(entry == table->header.count)
|
||||
{
|
||||
cprintf(GREY, "Cannot find firmware partition\n");
|
||||
goto Lend;
|
||||
}
|
||||
uint8_t drive_no = table->entry[entry].drive_no;
|
||||
uint64_t drive_sz = table->entry[entry].size;
|
||||
if(g_debug)
|
||||
{
|
||||
cprintf(RED, "* ");
|
||||
cprintf_field("Drive: ", "%#x\n", drive_no);
|
||||
cprintf(RED, "* ");
|
||||
cprintf_field("Size: ", "%#llx\n", (unsigned long long)drive_sz);
|
||||
}
|
||||
struct stmp_logical_drive_info_t info;
|
||||
ret = stmp_get_logical_drive_info(g_dev_fd, drive_no, &info);
|
||||
if(ret || !info.has.sector_size)
|
||||
{
|
||||
cprintf(GREY, "Cannot get sector size\n");
|
||||
goto Lend;
|
||||
}
|
||||
unsigned sector_size = info.sector_size;
|
||||
uint8_t *sector = malloc(sector_size);
|
||||
|
||||
/* sanity check by reading first sector */
|
||||
ret = stmp_read_logical_drive_sectors(g_dev_fd, drive_no, 0, 1, sector, sector_size);
|
||||
if(ret)
|
||||
{
|
||||
cprintf(GREY, "Cannot read first sector: %d\n", ret);
|
||||
return;
|
||||
}
|
||||
uint32_t sig = *(uint32_t *)(sector + 0x14);
|
||||
if(sig != 0x504d5453)
|
||||
{
|
||||
cprintf(GREY, "There is something wrong: the first sector doesn't have the STMP signature. Bailing out...\n");
|
||||
return;
|
||||
}
|
||||
|
||||
f = fopen(file, "rb");
|
||||
FILE *f = fopen(file, "rb");
|
||||
if(f == NULL)
|
||||
{
|
||||
cprintf(GREY, "Cannot open '%s' for writing: %m\n", file);
|
||||
goto Lend;
|
||||
cprintf(GREY, "Cannot open output file: %s\n", strerror(errno));
|
||||
return;
|
||||
}
|
||||
struct rw_fw_context_t ctx;
|
||||
fseek(f, 0, SEEK_END);
|
||||
int fw_size = ftell(f);
|
||||
ctx.tot_size = ftell(f);
|
||||
fseek(f, 0, SEEK_SET);
|
||||
if(g_debug)
|
||||
{
|
||||
cprintf(RED, "* ");
|
||||
cprintf_field("Firmware size: ", "%#x\n", fw_size);
|
||||
}
|
||||
/* sanity check size */
|
||||
if((uint64_t)fw_size > drive_sz)
|
||||
{
|
||||
cprintf(GREY, "You cannot write a firmware greater than the partition size.\n");
|
||||
goto Lend;
|
||||
}
|
||||
|
||||
int percent = -1;
|
||||
for(int off = 0; off < fw_size; off += sector_size)
|
||||
{
|
||||
int sec = off / sector_size;
|
||||
int this_percent = (sec * 100) / (fw_size / sector_size);
|
||||
if(this_percent != percent && (this_percent % 5) == 0)
|
||||
{
|
||||
cprintf(RED, "%d%%", this_percent);
|
||||
cprintf(YELLOW, "...");
|
||||
fflush(stdout);
|
||||
}
|
||||
percent = this_percent;
|
||||
int xfer_len = MIN(fw_size - off, (int)sector_size);
|
||||
if(fread(sector, xfer_len, 1, f) != 1)
|
||||
{
|
||||
cprintf(GREY, "Read failed: %m\n");
|
||||
goto Lend;
|
||||
}
|
||||
/* NOTE transfer a whole sector even if incomplete, the device won't access
|
||||
* partial sectors */
|
||||
if(xfer_len < (int)sector_size)
|
||||
memset(sector + xfer_len, 0, sector_size - xfer_len);
|
||||
ret = stmp_write_logical_drive_sectors(g_dev_fd, drive_no, sec, 1, sector, sector_size);
|
||||
if(ret)
|
||||
{
|
||||
cprintf(GREY, "Cannot write sector %d: %d\n", sec, ret);
|
||||
goto Lend;
|
||||
}
|
||||
}
|
||||
cprintf(BLUE, "Done\n");
|
||||
Lend:
|
||||
if(f)
|
||||
fclose(f);
|
||||
ctx.cur_size = 0;
|
||||
ctx.f = f;
|
||||
ctx.last_percent = -1;
|
||||
ctx.read = true;
|
||||
int ret = stmp_write_firmware(g_dev_fd, &ctx, &rw_fw);
|
||||
if(ret < 0)
|
||||
cprintf(GREY, "Cannot write firmware: %d\n", ret);
|
||||
rw_finish(&ctx);
|
||||
fclose(f);
|
||||
}
|
||||
|
||||
static void usage(void)
|
||||
|
|
@ -586,14 +476,14 @@ int main(int argc, char **argv)
|
|||
rb_scsi_device_t scsi_dev = rb_scsi_open(argv[optind], g_debug ? RB_SCSI_DEBUG : 0, NULL, scsi_printf);
|
||||
if(scsi_dev == 0)
|
||||
{
|
||||
cprintf(GREY, "Cannot open device: %m\n");
|
||||
cprintf(GREY, "Cannot open device\n");
|
||||
ret = 1;
|
||||
goto Lend;
|
||||
}
|
||||
g_dev_fd = stmp_open(scsi_dev, g_debug ? STMP_DEBUG : 0, NULL, scsi_printf);
|
||||
if(g_dev_fd == 0)
|
||||
{
|
||||
cprintf(GREY, "Cannot open stmp device: %m\n");
|
||||
cprintf(GREY, "Cannot open stmp device\n");
|
||||
ret = 2;
|
||||
goto Lend;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,7 +23,6 @@
|
|||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#define _BSD_SOURCE
|
||||
#include <endian.h>
|
||||
#include "stmp_scsi.h"
|
||||
|
||||
#define MIN(a, b) ((a) < (b) ? (a) : (b))
|
||||
|
|
@ -131,6 +130,7 @@ int stmp_sense_analysis(stmp_device_t dev, int status, uint8_t *sense, int sense
|
|||
for(int i = 0; i < sense_size; i++)
|
||||
stmp_printf(dev, " %02x", sense[i]);
|
||||
stmp_printf(dev, "\n");
|
||||
rb_scsi_decode_sense(dev->dev, sense, sense_size);
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
|
@ -614,3 +614,176 @@ int stmp_get_logical_drive_info(stmp_device_t dev, uint8_t drive, struct stmp_lo
|
|||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int stmp_read_firmware(stmp_device_t dev, void *user, stmp_fw_rw_fn_t fn)
|
||||
{
|
||||
/* read logicial table */
|
||||
uint8_t *sector = NULL;
|
||||
struct stmp_logical_media_table_t *table = NULL;
|
||||
int ret = stmp_get_logical_media_table(dev, &table);
|
||||
if(ret)
|
||||
{
|
||||
stmp_printf(dev, "Cannot get logical table: %d\n", ret);
|
||||
return -1;
|
||||
}
|
||||
/* locate firmware partition */
|
||||
int entry = 0;
|
||||
while(entry < table->header.count)
|
||||
if(table->entry[entry].type == SCSI_STMP_DRIVE_TYPE_SYSTEM &&
|
||||
table->entry[entry].tag == SCSI_STMP_DRIVE_TAG_SYSTEM_BOOT)
|
||||
break;
|
||||
else
|
||||
entry++;
|
||||
if(entry == table->header.count)
|
||||
{
|
||||
stmp_printf(dev, "Cannot find firmware partition\n");
|
||||
goto Lerr;
|
||||
}
|
||||
uint8_t drive_no = table->entry[entry].drive_no;
|
||||
uint64_t drive_sz = table->entry[entry].size;
|
||||
stmp_debugf(dev, "Firmware drive: %#x\n", drive_no);
|
||||
stmp_debugf(dev, "Firmware max size: %#llx\n", (unsigned long long)drive_sz);
|
||||
/* get drive info */
|
||||
struct stmp_logical_drive_info_t info;
|
||||
ret = stmp_get_logical_drive_info(dev, drive_no, &info);
|
||||
if(ret || !info.has.sector_size)
|
||||
{
|
||||
stmp_printf(dev, "Cannot get sector size\n");
|
||||
goto Lerr;
|
||||
}
|
||||
unsigned sector_size = info.sector_size;
|
||||
stmp_debugf(dev, "Firmware sector size: %lu\n", (unsigned long)sector_size);
|
||||
/* allocate a buffer for one sector */
|
||||
sector = malloc(sector_size);
|
||||
/* read the first sector to check it is correct and get the total size */
|
||||
ret = stmp_read_logical_drive_sectors(dev, drive_no, 0, 1, sector, sector_size);
|
||||
if(ret)
|
||||
{
|
||||
stmp_printf(dev, "Cannot read first sector: %d\n", ret);
|
||||
goto Lerr;
|
||||
}
|
||||
uint32_t sig = *(uint32_t *)(sector + 0x14);
|
||||
if(sig != 0x504d5453)
|
||||
{
|
||||
stmp_printf(dev, "There is something wrong: the first sector doesn't have the STMP signature.\n");
|
||||
goto Lerr;
|
||||
}
|
||||
uint32_t fw_size = *(uint32_t *)(sector + 0x1c) * 16; /* see SB file format */
|
||||
stmp_debugf(dev, "Firmware size: %#x\n", fw_size);
|
||||
/* if fn is NULL, just return the size immediately */
|
||||
if(fn != NULL)
|
||||
{
|
||||
/* read all sectors one by one */
|
||||
for(int sec = 0; sec * sector_size < fw_size; sec++)
|
||||
{
|
||||
ret = stmp_read_logical_drive_sectors(dev, drive_no, sec, 1, sector, sector_size);
|
||||
if(ret)
|
||||
{
|
||||
stmp_printf(dev, "Cannot read sector %d: %d\n", sec, ret);
|
||||
goto Lerr;
|
||||
}
|
||||
int xfer_len = MIN(sector_size, fw_size - sec * sector_size);
|
||||
ret = fn(user, sector, xfer_len);
|
||||
if(ret != xfer_len)
|
||||
{
|
||||
stmp_printf(dev, "User write failed: %d\n", ret);
|
||||
goto Lerr;
|
||||
}
|
||||
}
|
||||
}
|
||||
ret = fw_size;
|
||||
Lend:
|
||||
free(table);
|
||||
if(sector)
|
||||
free(sector);
|
||||
return ret;
|
||||
Lerr:
|
||||
ret = -1;
|
||||
goto Lend;
|
||||
}
|
||||
|
||||
int stmp_write_firmware(stmp_device_t dev, void *user, stmp_fw_rw_fn_t fn)
|
||||
{
|
||||
/* read logicial table */
|
||||
struct stmp_logical_media_table_t *table = NULL;
|
||||
int ret = stmp_get_logical_media_table(dev, &table);
|
||||
if(ret)
|
||||
{
|
||||
stmp_printf(dev, "Cannot get logical table: %d\n", ret);
|
||||
return -1;
|
||||
}
|
||||
/* locate firmware partition */
|
||||
int entry = 0;
|
||||
while(entry < table->header.count)
|
||||
if(table->entry[entry].type == SCSI_STMP_DRIVE_TYPE_SYSTEM &&
|
||||
table->entry[entry].tag == SCSI_STMP_DRIVE_TAG_SYSTEM_BOOT)
|
||||
break;
|
||||
else
|
||||
entry++;
|
||||
if(entry == table->header.count)
|
||||
{
|
||||
stmp_printf(dev, "Cannot find firmware partition\n");
|
||||
goto Lerr;
|
||||
}
|
||||
uint8_t drive_no = table->entry[entry].drive_no;
|
||||
uint64_t drive_sz = table->entry[entry].size;
|
||||
stmp_debugf(dev, "Firmware drive: %#x\n", drive_no);
|
||||
stmp_debugf(dev, "Firmware max size: %#llx\n", (unsigned long long)drive_sz);
|
||||
/* get drive info */
|
||||
struct stmp_logical_drive_info_t info;
|
||||
ret = stmp_get_logical_drive_info(dev, drive_no, &info);
|
||||
if(ret || !info.has.sector_size)
|
||||
{
|
||||
stmp_printf(dev, "Cannot get sector size\n");
|
||||
goto Lerr;
|
||||
}
|
||||
unsigned sector_size = info.sector_size;
|
||||
stmp_debugf(dev, "Firmware sector size: %lu\n", (unsigned long)sector_size);
|
||||
/* allocate a buffer for one sector */
|
||||
uint8_t *sector = malloc(sector_size);
|
||||
/* read the first sector to check it is correct and get the total size */
|
||||
ret = fn(user, sector, sector_size);
|
||||
/* the whole file could be smaller than one sector, but it must be greater
|
||||
* then the header size */
|
||||
if(ret < 0x20)
|
||||
{
|
||||
stmp_printf(dev, "User read failed: %d\n", ret);
|
||||
goto Lerr;
|
||||
}
|
||||
uint32_t sig = *(uint32_t *)(sector + 0x14);
|
||||
if(sig != 0x504d5453)
|
||||
{
|
||||
stmp_printf(dev, "There is something wrong: the first sector doesn't have the STMP signature.\n");
|
||||
goto Lerr;
|
||||
}
|
||||
uint32_t fw_size = *(uint32_t *)(sector + 0x1c) * 16; /* see SB file format */
|
||||
stmp_debugf(dev, "Firmware size: %#x\n", fw_size);
|
||||
/* write all sectors one by one */
|
||||
for(int sec = 0; sec * sector_size < fw_size; sec++)
|
||||
{
|
||||
int xfer_len = MIN(sector_size, fw_size - sec * sector_size);
|
||||
/* avoid rereading the first sector */
|
||||
if(sec != 0)
|
||||
ret = fn(user, sector, xfer_len);
|
||||
if(ret != xfer_len)
|
||||
{
|
||||
stmp_printf(dev, "User read failed: %d\n", ret);
|
||||
goto Lerr;
|
||||
}
|
||||
if(ret < (int)sector_size)
|
||||
memset(sector + ret, 0, sector_size - ret);
|
||||
ret = stmp_write_logical_drive_sectors(dev, drive_no, sec, 1, sector, sector_size);
|
||||
if(ret)
|
||||
{
|
||||
stmp_printf(dev, "Cannot write sector %d: %d\n", sec, ret);
|
||||
goto Lerr;
|
||||
}
|
||||
}
|
||||
ret = fw_size;
|
||||
Lend:
|
||||
free(table);
|
||||
return ret;
|
||||
Lerr:
|
||||
ret = -1;
|
||||
goto Lend;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -355,6 +355,14 @@ int stmp_read_logical_drive_sectors(stmp_device_t dev, uint8_t drive, uint64_t a
|
|||
uint32_t count, void *buffer, int buffer_size);
|
||||
int stmp_write_logical_drive_sectors(stmp_device_t dev, uint8_t drive, uint64_t address,
|
||||
uint32_t count, void *buffer, int buffer_size);
|
||||
/* return <0 on error, or firmware size in bytes otherwise,
|
||||
* if not NULL, the read/write function will be called as many times as needed to provide
|
||||
* the entire firmware, it should return number of bytes read/written on success or -1 on error
|
||||
* in all cases, the total size of the firmware is based on the header
|
||||
* if NULL for read, return firmware size */
|
||||
typedef int (*stmp_fw_rw_fn_t)(void *user, void *buf, size_t size);
|
||||
int stmp_read_firmware(stmp_device_t dev, void *user, stmp_fw_rw_fn_t fn);
|
||||
int stmp_write_firmware(stmp_device_t dev, void *user, stmp_fw_rw_fn_t fn);
|
||||
/* string helpers */
|
||||
const char *stmp_get_logical_media_type_string(uint32_t type);
|
||||
const char *stmp_get_logical_media_vendor_string(uint32_t type);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue