bemanitools/src/main/ezusb/util.c

170 lines
3.5 KiB
C

#include <stdlib.h>
#include <string.h>
#include "ezusb/util.h"
#include "util/crc.h"
#include "util/fs.h"
#include "util/log.h"
#include "util/mem.h"
struct ezusb_firmware *ezusb_firmware_load(const char *file)
{
void *buffer;
size_t buffer_size;
struct ezusb_firmware *fw;
size_t pos;
log_assert(file);
pos = 0;
if (!file_load(file, &buffer, &buffer_size, false)) {
return false;
}
fw = xmalloc(sizeof(struct ezusb_firmware));
fw->crc = ((struct ezusb_firmware *) buffer)->crc;
fw->segment_count = ((struct ezusb_firmware *) buffer)->segment_count;
pos += sizeof(uint16_t) * 2;
fw->segments =
xmalloc(sizeof(struct ezusb_firmware_segment) * fw->segment_count);
for (uint16_t i = 0; i < fw->segment_count; i++) {
uint16_t size = *((uint16_t *) (buffer + pos));
pos += sizeof(uint16_t);
uint16_t offset = *((uint16_t *) (buffer + pos));
pos += sizeof(uint16_t);
fw->segments[i] = xmalloc(sizeof(uint16_t) * 2 + size);
fw->segments[i]->size = size;
fw->segments[i]->offset = offset;
memcpy(fw->segments[i]->data, buffer + pos, size);
pos += size;
}
return fw;
}
bool ezusb_firmware_save(const char *file, struct ezusb_firmware *fw)
{
size_t size;
void *buffer;
size_t pos;
bool res;
log_assert(file);
log_assert(fw);
size = 0;
pos = 0;
for (uint16_t i = 0; i < fw->segment_count; i++) {
size += fw->segments[i]->size + sizeof(uint16_t) * 2;
}
size += sizeof(uint16_t) * 2;
buffer = xmalloc(size);
((struct ezusb_firmware *) buffer)->crc = fw->crc;
((struct ezusb_firmware *) buffer)->segment_count = fw->segment_count;
pos += sizeof(uint16_t) * 2;
for (uint16_t i = 0; i < fw->segment_count; i++) {
memcpy(
buffer + pos,
fw->segments[i],
sizeof(uint16_t) * 2 + fw->segments[i]->size);
pos += sizeof(uint16_t) * 2 + fw->segments[i]->size;
}
res = file_save(file, buffer, size);
free(buffer);
return res;
}
struct ezusb_firmware *ezusb_firmware_alloc()
{
struct ezusb_firmware *fw;
fw = xmalloc(sizeof(struct ezusb_firmware));
fw->crc = 0;
fw->segment_count = 0;
fw->segments = NULL;
return fw;
}
struct ezusb_firmware_segment *
ezusb_firmware_segment_alloc(uint16_t offset, uint16_t size, void *data)
{
struct ezusb_firmware_segment *seg;
log_assert(size > 0);
log_assert(data);
seg = xmalloc(sizeof(uint16_t) * 2 + size);
seg->offset = offset;
seg->size = size;
memcpy(seg->data, data, size);
return seg;
}
void ezusb_firmware_add_segment(
struct ezusb_firmware *fw, struct ezusb_firmware_segment *segment)
{
struct ezusb_firmware_segment **tmp;
log_assert(fw);
log_assert(segment);
fw->segment_count++;
tmp = xrealloc(
fw->segments,
sizeof(struct ezusb_firmware_segment *) * fw->segment_count);
if (tmp != NULL) {
fw->segments = tmp;
}
fw->segments[fw->segment_count - 1] = segment;
}
uint16_t ezusb_firmware_crc(struct ezusb_firmware *fw)
{
uint16_t crc;
log_assert(fw);
crc = 0;
for (uint16_t i = 0; i < fw->segment_count; i++) {
crc = crc16(
fw->segments[i], sizeof(uint16_t) * 2 + fw->segments[i]->size, crc);
}
return crc;
}
void ezusb_firmware_free(struct ezusb_firmware *fw)
{
log_assert(fw);
for (uint16_t i = 0; i < fw->segment_count; i++) {
free(fw->segments[i]);
}
free(fw);
}