mirror of
https://git.proxmox.com/git/fwupd
synced 2025-08-06 09:00:55 +00:00
unifying: fix signature writing and parsing for texas bootloader
Signed-off-by: Ogier Bouvier <obouvier@logitech.com>
This commit is contained in:
parent
5c535a53ce
commit
620d973fc2
@ -93,6 +93,31 @@ lu_device_bootloader_nordic_probe (LuDevice *device, GError **error)
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
lu_device_bootloader_nordic_write_signature (LuDevice *device,
|
||||
guint16 addr, guint8 len, const guint8 *data,
|
||||
GError **error)
|
||||
{
|
||||
g_autoptr(LuDeviceBootloaderRequest) req = lu_device_bootloader_request_new();
|
||||
req->cmd = 0xC0;
|
||||
req->addr = addr;
|
||||
req->len = len;
|
||||
memcpy (req->data, data, req->len);
|
||||
if (!lu_device_bootloader_request (device, req, error)) {
|
||||
g_prefix_error (error, "failed to write sig @0x%02x: ", addr);
|
||||
return FALSE;
|
||||
}
|
||||
if (req->cmd == LU_DEVICE_BOOTLOADER_CMD_WRITE_RAM_BUFFER_INVALID_ADDR) {
|
||||
g_set_error (error,
|
||||
G_IO_ERROR,
|
||||
G_IO_ERROR_FAILED,
|
||||
"failed to write @%04x: signature is too big",
|
||||
addr);
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
lu_device_bootloader_nordic_write (LuDevice *device,
|
||||
guint16 addr, guint8 len, const guint8 *data,
|
||||
@ -132,18 +157,12 @@ lu_device_bootloader_nordic_write (LuDevice *device,
|
||||
return FALSE;
|
||||
}
|
||||
if (req->cmd == LU_DEVICE_BOOTLOADER_CMD_WRITE_NONZERO_START) {
|
||||
if (addr == 0x0000) {
|
||||
g_set_error (error,
|
||||
G_IO_ERROR,
|
||||
G_IO_ERROR_FAILED,
|
||||
"failed to write @%04x: only 1 byte write supported",
|
||||
addr);
|
||||
return FALSE;
|
||||
}
|
||||
g_debug ("wrote %d bytes at address %04x, value %02x", req->len,
|
||||
req->addr, req->data[0]);
|
||||
g_set_error (error,
|
||||
G_IO_ERROR,
|
||||
G_IO_ERROR_FAILED,
|
||||
"failed to write @%04x: byte 0x00 is not 0xff",
|
||||
"failed to write @%04x: only 1 byte write of 0xff supported",
|
||||
addr);
|
||||
return FALSE;
|
||||
}
|
||||
@ -209,12 +228,24 @@ lu_device_bootloader_nordic_write_firmware (LuDevice *device, GBytes *fw, GError
|
||||
return FALSE;
|
||||
|
||||
for (guint i = 1; i < reqs->len; i++) {
|
||||
gboolean res;
|
||||
payload = g_ptr_array_index (reqs, i);
|
||||
if (!lu_device_bootloader_nordic_write (device,
|
||||
payload->addr,
|
||||
payload->len,
|
||||
payload->data,
|
||||
error))
|
||||
|
||||
if (payload->cmd == LU_DEVICE_BOOTLOADER_CMD_WRITE_SIGNATURE) {
|
||||
res = lu_device_bootloader_nordic_write_signature(device,
|
||||
payload->addr,
|
||||
payload->len,
|
||||
payload->data,
|
||||
error);
|
||||
} else {
|
||||
res = lu_device_bootloader_nordic_write (device,
|
||||
payload->addr,
|
||||
payload->len,
|
||||
payload->data,
|
||||
error);
|
||||
}
|
||||
|
||||
if (!res)
|
||||
return FALSE;
|
||||
fu_device_set_progress_full (FU_DEVICE (device), i * 32, reqs->len * 32);
|
||||
}
|
||||
@ -228,7 +259,6 @@ lu_device_bootloader_nordic_write_firmware (LuDevice *device, GBytes *fw, GError
|
||||
error))
|
||||
return FALSE;
|
||||
|
||||
/* set the reset vector */
|
||||
if (!lu_device_bootloader_nordic_write (device,
|
||||
0x0000,
|
||||
0x01,
|
||||
|
@ -157,8 +157,14 @@ lu_device_bootloader_texas_write_firmware (LuDevice *device, GBytes *fw, GError
|
||||
}
|
||||
|
||||
/* build packet */
|
||||
req->cmd = LU_DEVICE_BOOTLOADER_CMD_WRITE_RAM_BUFFER;
|
||||
req->addr = payload->addr % 0x80;
|
||||
req->cmd = payload->cmd;
|
||||
|
||||
/* signature addresses do not need to fit inside 128 bytes */
|
||||
if (req->cmd == LU_DEVICE_BOOTLOADER_CMD_WRITE_SIGNATURE)
|
||||
req->addr = payload->addr;
|
||||
else
|
||||
req->addr = payload->addr % 0x80;
|
||||
|
||||
req->len = payload->len;
|
||||
memcpy (req->data, payload->data, payload->len);
|
||||
if (!lu_device_bootloader_request (device, req, error)) {
|
||||
@ -185,7 +191,8 @@ lu_device_bootloader_texas_write_firmware (LuDevice *device, GBytes *fw, GError
|
||||
}
|
||||
|
||||
/* flush RAM buffer to EEPROM */
|
||||
if ((payload->addr + 0x10) % 0x80 == 0) {
|
||||
if ((payload->addr + 0x10) % 0x80 == 0 &&
|
||||
req->cmd != LU_DEVICE_BOOTLOADER_CMD_WRITE_SIGNATURE) {
|
||||
guint16 addr_start = payload->addr - (7 * 0x10);
|
||||
g_debug ("addr flush @ 0x%04x for 0x%04x",
|
||||
payload->addr, addr_start);
|
||||
|
@ -58,6 +58,7 @@ lu_device_bootloader_parse_requests (LuDevice *device, GBytes *fw, GError **erro
|
||||
lines = g_strsplit_set (tmp, "\n\r", -1);
|
||||
for (guint i = 0; lines[i] != NULL; i++) {
|
||||
g_autoptr(LuDeviceBootloaderRequest) payload = NULL;
|
||||
guint8 rec_type = 0x00;
|
||||
|
||||
/* skip empty lines */
|
||||
tmp = lines[i];
|
||||
@ -77,6 +78,15 @@ lu_device_bootloader_parse_requests (LuDevice *device, GBytes *fw, GError **erro
|
||||
payload->addr = ((guint16) lu_buffer_read_uint8 (tmp + 0x03)) << 8;
|
||||
payload->addr |= lu_buffer_read_uint8 (tmp + 0x05);
|
||||
|
||||
rec_type = lu_buffer_read_uint8 (tmp + 0x07);
|
||||
|
||||
/* record type of 0xFD indicates signature data */
|
||||
if (rec_type == 0xFD) {
|
||||
payload->cmd = LU_DEVICE_BOOTLOADER_CMD_WRITE_SIGNATURE;
|
||||
} else {
|
||||
payload->cmd = LU_DEVICE_BOOTLOADER_CMD_WRITE_RAM_BUFFER;
|
||||
}
|
||||
|
||||
/* read the data, but skip the checksum byte */
|
||||
for (guint j = 0; j < payload->len; j++) {
|
||||
const gchar *ptr = tmp + 0x09 + (j * 2);
|
||||
@ -91,6 +101,12 @@ lu_device_bootloader_parse_requests (LuDevice *device, GBytes *fw, GError **erro
|
||||
payload->data[j] = lu_buffer_read_uint8 (ptr);
|
||||
}
|
||||
|
||||
/* no need to bound check signature addresses */
|
||||
if (payload->cmd == LU_DEVICE_BOOTLOADER_CMD_WRITE_SIGNATURE) {
|
||||
g_ptr_array_add (reqs, g_steal_pointer (&payload));
|
||||
continue;
|
||||
}
|
||||
|
||||
/* skip the bootloader */
|
||||
if (payload->addr > lu_device_bootloader_get_addr_hi (device)) {
|
||||
g_debug ("skipping write @ %04x", payload->addr);
|
||||
|
@ -64,7 +64,8 @@ struct _LuDeviceClass
|
||||
|
||||
#define LU_DEVICE_EP1 0x81
|
||||
#define LU_DEVICE_EP3 0x83
|
||||
#define LU_DEVICE_TIMEOUT_MS 2500
|
||||
/* Signed firmware are very long to verify on the device */
|
||||
#define LU_DEVICE_TIMEOUT_MS 20000
|
||||
|
||||
typedef enum {
|
||||
LU_DEVICE_KIND_UNKNOWN,
|
||||
|
Loading…
Reference in New Issue
Block a user