302 lines
9.7 KiB
C
302 lines
9.7 KiB
C
/* ************************************************************************** */
|
|
/* _____ _ */
|
|
/* packet/ack.c |_ _|__ _ _| |__ ___ _ _ */
|
|
/* | Project: libp7 | |/ _ \| | | | '_ \ / _ \ | | | */
|
|
/* | | (_) | |_| | | | | __/ |_| | */
|
|
/* By: thomas <thomas@touhey.fr> |_|\___/ \__,_|_| |_|\___|\__, |.fr */
|
|
/* Last updated: 2017/01/04 15:01:48 |___/ */
|
|
/* */
|
|
/* ************************************************************************** */
|
|
#include <libp7/internals.h>
|
|
#include <string.h>
|
|
|
|
/* ************************************************************************** */
|
|
/* Raw layout of an extended ack data */
|
|
/* ************************************************************************** */
|
|
typedef struct {
|
|
/* hardware identifier - ASCII */
|
|
unsigned char hwid[8];
|
|
/* processor identifier - ASCII */
|
|
unsigned char cpuid[16];
|
|
|
|
/* preprogrammed ROM capacity - ASCII-hex (Ko) */
|
|
unsigned char preprog_rom_capacity[8];
|
|
/* flash ROM capacity - ASCII-hex (Ko) */
|
|
unsigned char flash_rom_capacity[8];
|
|
/* RAM capacity - ASCII-hex (Ko) */
|
|
unsigned char ram_capacity[8];
|
|
|
|
/* preprogrammed ROM version - "xx.xx.xxxx" + 0xff bytes */
|
|
unsigned char preprog_rom_version[16];
|
|
|
|
/* bootcode version - "xx.xx.xxxx" + 0xff bytes */
|
|
unsigned char bootcode_version[16];
|
|
/* bootcode offset - ASCII-hex */
|
|
unsigned char bootcode_offset[8];
|
|
/* bootcode size - ASCII-hex (Ko) */
|
|
unsigned char bootcode_size[8];
|
|
|
|
/* OS version - "xx.xx.xxxx" + 0xff bytes */
|
|
unsigned char os_version[16];
|
|
/* OS offset - ASCII-hex */
|
|
unsigned char os_offset[8];
|
|
/* OS size - ASCII-hex (Ko) */
|
|
unsigned char os_size[8];
|
|
|
|
/* protocol version - "x.xx" */
|
|
unsigned char protocol_version[4];
|
|
/* product ID */
|
|
unsigned char product_id[16];
|
|
/* name set by user in SYSTEM */
|
|
unsigned char username[16];
|
|
} packetdata_ackext_t;
|
|
|
|
/* ************************************************************************** */
|
|
/* Utilities */
|
|
/* ************************************************************************** */
|
|
/**
|
|
* version_of_string:
|
|
* Get version from 16-bytes char buffer.
|
|
*
|
|
* data is not a string as it doesn't finish with an '\0'.
|
|
*
|
|
* @arg ver the version destination
|
|
* @arg data the raw version data ("xx.xx.xx" + type)
|
|
*/
|
|
|
|
static void version_of_string(p7_version_t *ver, const unsigned char *data)
|
|
{
|
|
ver->major = p7_getdec(p7_getascii(data, 2));
|
|
ver->minor = p7_getdec(p7_getascii(&data[3], 2));
|
|
ver->rev = p7_getdec(p7_getascii(&data[6], 4));
|
|
}
|
|
|
|
/**
|
|
* string_of_version:
|
|
* Put version in 16-bytes char buffer.
|
|
*
|
|
* @arg ver the version source.
|
|
* @arg data the raw version data destination ("xx.xx.xx" + type).
|
|
*/
|
|
|
|
static void string_of_version(unsigned char *data, const p7_version_t *ver)
|
|
{
|
|
/* put data */
|
|
memcpy(data, "xx.xx.xxxx\xFF\xFF\xFF\xFF\xFF\xFF", 16);
|
|
p7_putascii(data, p7_gethex(ver->major), 2);
|
|
p7_putascii(&data[3], p7_gethex(ver->minor), 2);
|
|
p7_putascii(&data[6], p7_gethex(ver->rev), 4);
|
|
}
|
|
|
|
/* ************************************************************************** */
|
|
/* Send ACK packets */
|
|
/* ************************************************************************** */
|
|
/**
|
|
* p7_send_ack:
|
|
* Send basic command acknowledge.
|
|
*
|
|
* Default response at successful packet reception.
|
|
*
|
|
* @arg handle the libp7 handle
|
|
* @arg resp get response or not
|
|
* @return the error code (0 if ok).
|
|
*/
|
|
|
|
int p7_send_ack(p7_handle_t *handle, int resp)
|
|
{
|
|
return (p7_send_basic(handle, p7_pt_ack, 0x00, resp));
|
|
}
|
|
|
|
/**
|
|
* p7_confirm_ow:
|
|
* Sends overwrite confirmation.
|
|
*
|
|
* @arg handle the libp7 handle
|
|
* @return the error code (0 if ok)
|
|
*/
|
|
|
|
int p7_confirm_ow(p7_handle_t *handle)
|
|
{
|
|
return (p7_send_basic(handle, p7_pt_ack, 0x01, 1));
|
|
}
|
|
|
|
/**
|
|
* p7_send_eack:
|
|
* Sends an extended ack.
|
|
*
|
|
* @arg handle the libp7 handle
|
|
* @arg info the libp7 server info to return.
|
|
* @return the error code (0 if ok)
|
|
*/
|
|
|
|
int p7_send_eack(p7_handle_t *handle, p7_server_t *info)
|
|
{
|
|
packetdata_ackext_t raw;
|
|
|
|
/* initialize the structure with 0xFFs */
|
|
memset(&raw, 0xFF, sizeof(packetdata_ackext_t));
|
|
|
|
/* put in the structure */
|
|
memcpy(raw.hwid, info->hwid, strnlen(info->hwid, 8));
|
|
memcpy(raw.cpuid, info->cpuid, strnlen(info->cpuid, 16));
|
|
|
|
if (!info->preprog_rom_wiped) {
|
|
p7_putascii(raw.preprog_rom_capacity, info->preprog_rom_capacity, 8);
|
|
string_of_version(raw.preprog_rom_version, &info->preprog_rom_version);
|
|
}
|
|
|
|
p7_putascii(raw.flash_rom_capacity,
|
|
p7_gethex(info->flash_rom_capacity / 1024), 8);
|
|
p7_putascii(raw.ram_capacity,
|
|
p7_gethex(info->ram_capacity / 1024), 8);
|
|
|
|
if (!info->bootcode_wiped) {
|
|
string_of_version(raw.bootcode_version, &info->bootcode_version);
|
|
p7_putascii(raw.bootcode_offset, info->bootcode_offset, 8);
|
|
p7_putascii(raw.bootcode_size,
|
|
p7_gethex(info->bootcode_size / 1024), 8);
|
|
}
|
|
|
|
if (!info->os_wiped) {
|
|
string_of_version(raw.os_version, &info->os_version);
|
|
p7_putascii(raw.os_offset, info->os_offset, 8);
|
|
p7_putascii(raw.os_size,
|
|
p7_gethex(info->os_size / 1024), 8);
|
|
}
|
|
|
|
memcpy(raw.protocol_version, "7.00", 4);
|
|
memcpy(raw.product_id, info->product_id, strnlen(info->product_id, 16));
|
|
memcpy(raw.username, info->username, strnlen(info->username, 16));
|
|
|
|
/* send the packet */
|
|
return (p7_send_ext(handle, p7_pt_ack, 0x02, &raw,
|
|
sizeof(packetdata_ackext_t), 1));
|
|
}
|
|
|
|
/* ************************************************************************** */
|
|
/* Decode an ACK packet */
|
|
/* ************************************************************************** */
|
|
/**
|
|
* cpy_string:
|
|
* Copy a string terminated with 0xFFs, with a maximum size.
|
|
*
|
|
* @arg dest the destination string.
|
|
* @arg src the source string.
|
|
* @arg n the maximum size of the string.
|
|
*/
|
|
|
|
static inline void cpy_string(char *dest, const char *src, size_t n)
|
|
{
|
|
const char *l = memchr(src, 0xFF, n);
|
|
|
|
memset(dest, 0, n + 1);
|
|
memcpy(dest, src, l ? (size_t)(l - src) : n);
|
|
}
|
|
|
|
/**
|
|
* p7_decode_ack:
|
|
* Get data from ack data field.
|
|
*
|
|
* Layout is described in the fxReverse projet documentation.
|
|
*
|
|
* @arg handle the handle
|
|
* @arg data the raw data
|
|
* @arg data_size the raw data size
|
|
* @return if there was an error
|
|
*/
|
|
|
|
int p7_decode_ack(p7_handle_t *handle,
|
|
const unsigned char *data, size_t data_size)
|
|
{
|
|
p7_packet_t *packet = handle->_response;
|
|
/* check the data size */
|
|
if (data_size != sizeof(packetdata_ackext_t)) return (1);
|
|
|
|
const packetdata_ackext_t *d = (const packetdata_ackext_t*)data;
|
|
p7_server_t *info = &packet->info;
|
|
|
|
/* log */
|
|
log_info("ack packet is extended");
|
|
|
|
/* hardware identifier */
|
|
cpy_string(info->hwid, (const char*)d->hwid, 8);
|
|
log_info("hardware identifier is '%s'", info->hwid);
|
|
/* processor identifier */
|
|
cpy_string(info->cpuid, (const char*)d->cpuid, 16);
|
|
log_info("cpu identifier is '%s'", info->cpuid);
|
|
|
|
/* preprogrammed ROM information is wiped */
|
|
info->preprog_rom_wiped = (d->preprog_rom_version[2] == 0xFF);
|
|
#if LOGLEVEL <= ll_info
|
|
if (info->preprog_rom_wiped)
|
|
log_info("Preprogrammed ROM information looks wiped out!");
|
|
#endif
|
|
/* preprogrammed ROM capacity */
|
|
info->preprog_rom_capacity =
|
|
p7_getascii(d->preprog_rom_capacity, 8) * 1000;
|
|
log_info("preprogrammed ROM capacity is %" PRIuP7INT "o",
|
|
info->preprog_rom_capacity);
|
|
/* preprogrammed ROM version */
|
|
version_of_string(&info->preprog_rom_version, d->preprog_rom_version);
|
|
log_info("preprogrammed ROM version is %02u.%02u.%04u",
|
|
info->preprog_rom_version.major, info->preprog_rom_version.minor,
|
|
info->preprog_rom_version.rev);
|
|
|
|
/* flash ROM capacity */
|
|
info->flash_rom_capacity =
|
|
p7_getdec(p7_getascii(d->flash_rom_capacity, 8)) * 1024;
|
|
log_info("flash ROM capacity is %" PRIuP7INT "KiB",
|
|
info->flash_rom_capacity / 1024);
|
|
/* RAM capacity */
|
|
info->ram_capacity =
|
|
p7_getdec(p7_getascii(d->ram_capacity, 8)) * 1024;
|
|
log_info("RAM capacity is %" PRIuP7INT "KiB",
|
|
info->ram_capacity / 1024);
|
|
|
|
/* bootcode information is wiped */
|
|
info->bootcode_wiped = (d->bootcode_version[2] == 0xFF);
|
|
#if LOGLEVEL <= ll_info
|
|
if (info->bootcode_wiped)
|
|
log_info("Bootcode information looks wiped out!");
|
|
#endif
|
|
/* bootcode version */
|
|
version_of_string(&info->bootcode_version, d->bootcode_version);
|
|
log_info("bootcode version is %02u.%02u.%04u",
|
|
info->bootcode_version.major, info->bootcode_version.minor,
|
|
info->bootcode_version.rev);
|
|
/* bootcode offset */
|
|
info->bootcode_offset = p7_getascii(d->bootcode_offset, 8);
|
|
log_info("bootcode offset is 0x%08" PRIxP7INT, info->bootcode_offset);
|
|
/* bootcode size */
|
|
info->bootcode_size = p7_getdec(p7_getascii(d->bootcode_size, 8)) * 1024;
|
|
log_info("bootcode size is %" PRIuP7INT "KiB", info->bootcode_size / 1024);
|
|
|
|
/* OS information is wiped */
|
|
info->os_wiped = (d->os_version[2] == 0xFF);
|
|
#if LOGLEVEL <= ll_info
|
|
if (info->os_wiped)
|
|
log_info("OS information looks wiped out!");
|
|
#endif
|
|
/* OS version */
|
|
version_of_string(&info->os_version, d->os_version);
|
|
log_info("OS version is %02u.%02u.%04u",
|
|
info->os_version.major, info->os_version.minor,
|
|
info->os_version.rev);
|
|
/* OS offset */
|
|
info->os_offset = p7_getascii(d->os_offset, 8);
|
|
log_info("OS offset is 0x%08" PRIxP7INT , info->os_offset);
|
|
/* OS size */
|
|
info->os_size = p7_getdec(p7_getascii(d->os_size, 8)) * 1024;
|
|
log_info("OS size is %" PRIuP7INT "KiB", info->os_size / 1024);
|
|
|
|
/* product ID */
|
|
cpy_string(info->product_id, (const char*)d->product_id, 16);
|
|
log_info("product ID is %s", info->product_id);
|
|
/* username */
|
|
cpy_string(info->username, (const char*)d->username, 16);
|
|
log_info("username is %s", info->username);
|
|
|
|
/* no error */
|
|
return (0);
|
|
}
|