mirror of
https://git.proxmox.com/git/fwupd
synced 2025-07-26 04:46:55 +00:00
genesys: scaler: Remove FuGenesysMtkFooter and XOR encryption
This commit is contained in:
parent
0c8079b13c
commit
0fbd5e17fe
@ -15,6 +15,8 @@
|
|||||||
#include "fu-genesys-scaler-device.h"
|
#include "fu-genesys-scaler-device.h"
|
||||||
#include "fu-genesys-scaler-firmware.h"
|
#include "fu-genesys-scaler-firmware.h"
|
||||||
|
|
||||||
|
#define GENESYS_SCALER_BANK_SIZE 0x200000U
|
||||||
|
|
||||||
#define GENESYS_SCALER_MSTAR_READ 0x7a
|
#define GENESYS_SCALER_MSTAR_READ 0x7a
|
||||||
#define GENESYS_SCALER_MSTAR_WRITE 0x7b
|
#define GENESYS_SCALER_MSTAR_WRITE 0x7b
|
||||||
#define GENESYS_SCALER_MSTAR_DATA_OUT 0x7c
|
#define GENESYS_SCALER_MSTAR_DATA_OUT 0x7c
|
||||||
@ -72,7 +74,6 @@ struct _FuGenesysScalerDevice {
|
|||||||
guint16 gpio_out_reg;
|
guint16 gpio_out_reg;
|
||||||
guint16 gpio_en_reg;
|
guint16 gpio_en_reg;
|
||||||
guint8 gpio_val;
|
guint8 gpio_val;
|
||||||
FuGenesysMtkFooter footer;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
G_DEFINE_TYPE(FuGenesysScalerDevice, fu_genesys_scaler_device, FU_TYPE_DEVICE)
|
G_DEFINE_TYPE(FuGenesysScalerDevice, fu_genesys_scaler_device, FU_TYPE_DEVICE)
|
||||||
@ -1720,70 +1721,27 @@ fu_genesys_scaler_device_prepare_firmware(FuDevice *device,
|
|||||||
{
|
{
|
||||||
FuGenesysScalerDevice *self = FU_GENESYS_SCALER_DEVICE(device);
|
FuGenesysScalerDevice *self = FU_GENESYS_SCALER_DEVICE(device);
|
||||||
g_autoptr(FuFirmware) firmware = fu_genesys_scaler_firmware_new();
|
g_autoptr(FuFirmware) firmware = fu_genesys_scaler_firmware_new();
|
||||||
g_autoptr(FuFirmware) footer = fu_firmware_new();
|
g_autoptr(GBytes) blob_payload = NULL;
|
||||||
g_autoptr(FuFirmware) payload = fu_firmware_new();
|
g_autoptr(GBytes) blob_public_key = NULL;
|
||||||
g_autoptr(GBytes) fw_payload = NULL;
|
|
||||||
g_autoptr(GBytes) fw_footer = NULL;
|
|
||||||
|
|
||||||
/* parse firmware */
|
/* parse firmware */
|
||||||
if (!fu_firmware_parse(firmware, fw, flags, error))
|
if (!fu_firmware_parse(firmware, fw, flags, error))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
/* payload */
|
/* check public-key */
|
||||||
fw_payload = fu_common_bytes_new_offset(fw,
|
blob_public_key =
|
||||||
0,
|
fu_firmware_get_image_by_id_bytes(firmware, FU_FIRMWARE_ID_SIGNATURE, error);
|
||||||
g_bytes_get_size(fw) - sizeof(FuGenesysMtkFooter),
|
if (blob_public_key == NULL)
|
||||||
error);
|
|
||||||
if (fw_payload == NULL)
|
|
||||||
return NULL;
|
return NULL;
|
||||||
if (!fu_firmware_parse(payload, fw_payload, flags, error))
|
|
||||||
return NULL;
|
|
||||||
fu_firmware_set_id(payload, FU_FIRMWARE_ID_PAYLOAD);
|
|
||||||
fu_firmware_add_image(firmware, payload);
|
|
||||||
|
|
||||||
/* check size */
|
|
||||||
if (g_bytes_get_size(fw_payload) > fu_device_get_firmware_size_max(device)) {
|
|
||||||
g_set_error(error,
|
|
||||||
FWUPD_ERROR,
|
|
||||||
FWUPD_ERROR_INVALID_FILE,
|
|
||||||
"firmware too large, got 0x%x, expected <= 0x%x",
|
|
||||||
(guint)g_bytes_get_size(fw_payload),
|
|
||||||
(guint)fu_device_get_firmware_size_max(device));
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* footer */
|
|
||||||
fw_footer = fu_common_bytes_new_offset(fw,
|
|
||||||
g_bytes_get_size(fw) - sizeof(FuGenesysMtkFooter),
|
|
||||||
sizeof(FuGenesysMtkFooter),
|
|
||||||
error);
|
|
||||||
if (!fu_firmware_parse(footer, fw_footer, flags, error))
|
|
||||||
return NULL;
|
|
||||||
if (!fu_memcpy_safe((guint8 *)&self->footer,
|
|
||||||
sizeof(self->footer),
|
|
||||||
0, /* dst */
|
|
||||||
g_bytes_get_data(fw_footer, NULL),
|
|
||||||
g_bytes_get_size(fw_footer),
|
|
||||||
0, /* src */
|
|
||||||
sizeof(self->footer),
|
|
||||||
error))
|
|
||||||
return NULL;
|
|
||||||
fu_genesys_scaler_firmware_decrypt((guint8 *)&self->footer, sizeof(self->footer));
|
|
||||||
if (g_getenv("FWUPD_GENESYS_SCALER_VERBOSE") != NULL) {
|
if (g_getenv("FWUPD_GENESYS_SCALER_VERBOSE") != NULL) {
|
||||||
fu_common_dump_raw(G_LOG_DOMAIN,
|
fu_common_dump_raw(G_LOG_DOMAIN,
|
||||||
"Footer",
|
"PublicKey",
|
||||||
(const guint8 *)&self->footer,
|
g_bytes_get_data(blob_public_key, NULL),
|
||||||
sizeof(self->footer));
|
g_bytes_get_size(blob_public_key));
|
||||||
}
|
}
|
||||||
if (memcmp(self->footer.data.header.default_head,
|
if (memcmp(g_bytes_get_data(blob_public_key, NULL),
|
||||||
MTK_RSA_HEADER,
|
|
||||||
sizeof(self->footer.data.header.default_head)) != 0) {
|
|
||||||
g_set_error_literal(error, FWUPD_ERROR, FWUPD_ERROR_INTERNAL, "invalid footer");
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
if (memcmp(&self->footer.data.public_key,
|
|
||||||
&self->public_key,
|
&self->public_key,
|
||||||
sizeof(self->footer.data.public_key) && sizeof(self->public_key)) != 0 &&
|
sizeof(self->public_key)) != 0 &&
|
||||||
(flags & FWUPD_INSTALL_FLAG_FORCE) == 0) {
|
(flags & FWUPD_INSTALL_FLAG_FORCE) == 0) {
|
||||||
g_set_error_literal(error,
|
g_set_error_literal(error,
|
||||||
FWUPD_ERROR,
|
FWUPD_ERROR,
|
||||||
@ -1791,8 +1749,20 @@ fu_genesys_scaler_device_prepare_firmware(FuDevice *device,
|
|||||||
"mismatch public-key");
|
"mismatch public-key");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
fu_firmware_set_id(footer, FU_FIRMWARE_ID_HEADER);
|
|
||||||
fu_firmware_add_image(firmware, footer);
|
/* check size */
|
||||||
|
blob_payload = fu_firmware_get_image_by_id_bytes(firmware, FU_FIRMWARE_ID_PAYLOAD, error);
|
||||||
|
if (blob_payload == NULL)
|
||||||
|
return NULL;
|
||||||
|
if (g_bytes_get_size(blob_payload) > fu_device_get_firmware_size_max(device)) {
|
||||||
|
g_set_error(error,
|
||||||
|
FWUPD_ERROR,
|
||||||
|
FWUPD_ERROR_INVALID_FILE,
|
||||||
|
"firmware too large, got 0x%x, expected <= 0x%x",
|
||||||
|
(guint)g_bytes_get_size(blob_payload),
|
||||||
|
(guint)fu_device_get_firmware_size_max(device));
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
/* success */
|
/* success */
|
||||||
return g_steal_pointer(&firmware);
|
return g_steal_pointer(&firmware);
|
||||||
@ -1806,7 +1776,7 @@ fu_genesys_scaler_device_write_firmware(FuDevice *device,
|
|||||||
GError **error)
|
GError **error)
|
||||||
{
|
{
|
||||||
FuGenesysScalerDevice *self = FU_GENESYS_SCALER_DEVICE(device);
|
FuGenesysScalerDevice *self = FU_GENESYS_SCALER_DEVICE(device);
|
||||||
guint addr = fu_firmware_get_addr(firmware);
|
guint addr = 0;
|
||||||
gsize size;
|
gsize size;
|
||||||
const guint8 *data;
|
const guint8 *data;
|
||||||
g_autofree guint8 *buf = NULL;
|
g_autofree guint8 *buf = NULL;
|
||||||
@ -1818,11 +1788,8 @@ fu_genesys_scaler_device_write_firmware(FuDevice *device,
|
|||||||
fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_WRITE, 54, NULL);
|
fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_WRITE, 54, NULL);
|
||||||
fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_VERIFY, 42, NULL);
|
fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_VERIFY, 42, NULL);
|
||||||
|
|
||||||
/* sanity check */
|
if (fu_device_has_flag(device, FWUPD_DEVICE_FLAG_DUAL_IMAGE))
|
||||||
if (fu_device_has_flag(device, FWUPD_DEVICE_FLAG_DUAL_IMAGE) && addr == 0) {
|
addr = GENESYS_SCALER_BANK_SIZE;
|
||||||
g_set_error(error, FWUPD_ERROR, FWUPD_ERROR_INVALID_FILE, "invalid address");
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
payload = fu_firmware_get_image_by_id(firmware, FU_FIRMWARE_ID_PAYLOAD, error);
|
payload = fu_firmware_get_image_by_id(firmware, FU_FIRMWARE_ID_PAYLOAD, error);
|
||||||
if (payload == NULL)
|
if (payload == NULL)
|
||||||
|
@ -12,26 +12,11 @@
|
|||||||
|
|
||||||
struct _FuGenesysScalerFirmware {
|
struct _FuGenesysScalerFirmware {
|
||||||
FuFirmwareClass parent_instance;
|
FuFirmwareClass parent_instance;
|
||||||
FuGenesysMtkFooter footer;
|
FuGenesysPublicKey public_key;
|
||||||
guint protect_sector_addr[2];
|
|
||||||
gsize protect_sector_size[2];
|
|
||||||
guint public_key_addr;
|
|
||||||
gsize public_key_size;
|
|
||||||
guint second_image_program_addr;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
G_DEFINE_TYPE(FuGenesysScalerFirmware, fu_genesys_scaler_firmware, FU_TYPE_FIRMWARE)
|
G_DEFINE_TYPE(FuGenesysScalerFirmware, fu_genesys_scaler_firmware, FU_TYPE_FIRMWARE)
|
||||||
|
|
||||||
void
|
|
||||||
fu_genesys_scaler_firmware_decrypt(guint8 *buf, gsize bufsz)
|
|
||||||
{
|
|
||||||
const gchar *key = "mstar";
|
|
||||||
const gsize keylen = strlen(key);
|
|
||||||
|
|
||||||
for (guint i = 0; i < bufsz; i++)
|
|
||||||
buf[i] ^= key[i % keylen];
|
|
||||||
}
|
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
fu_genesys_scaler_firmware_parse(FuFirmware *firmware,
|
fu_genesys_scaler_firmware_parse(FuFirmware *firmware,
|
||||||
GBytes *fw,
|
GBytes *fw,
|
||||||
@ -43,87 +28,41 @@ fu_genesys_scaler_firmware_parse(FuFirmware *firmware,
|
|||||||
FuGenesysScalerFirmware *self = FU_GENESYS_SCALER_FIRMWARE(firmware);
|
FuGenesysScalerFirmware *self = FU_GENESYS_SCALER_FIRMWARE(firmware);
|
||||||
gsize bufsz = 0;
|
gsize bufsz = 0;
|
||||||
const guint8 *buf = g_bytes_get_data(fw, &bufsz);
|
const guint8 *buf = g_bytes_get_data(fw, &bufsz);
|
||||||
|
g_autoptr(FuFirmware) firmware_payload = NULL;
|
||||||
|
g_autoptr(FuFirmware) firmware_public_key = NULL;
|
||||||
|
g_autoptr(GBytes) blob_payload = NULL;
|
||||||
|
g_autoptr(GBytes) blob_public_key = NULL;
|
||||||
|
|
||||||
if (!fu_memcpy_safe((guint8 *)&self->footer,
|
if (!fu_memcpy_safe((guint8 *)&self->public_key,
|
||||||
sizeof(self->footer),
|
sizeof(self->public_key),
|
||||||
0, /* dst */
|
0, /* dst */
|
||||||
buf,
|
buf,
|
||||||
bufsz,
|
bufsz,
|
||||||
bufsz - sizeof(self->footer), /* src */
|
bufsz - sizeof(self->public_key), /* src */
|
||||||
sizeof(self->footer),
|
sizeof(self->public_key),
|
||||||
error))
|
error))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
fu_genesys_scaler_firmware_decrypt((guint8 *)&self->footer, sizeof(self->footer));
|
fu_common_dump_raw(G_LOG_DOMAIN,
|
||||||
if (memcmp(self->footer.data.header.default_head,
|
"PublicKey",
|
||||||
MTK_RSA_HEADER,
|
(const guint8 *)&self->public_key,
|
||||||
sizeof(self->footer.data.header.default_head)) != 0) {
|
sizeof(self->public_key));
|
||||||
g_autofree gchar *str = NULL;
|
if (memcmp(self->public_key.N, "N = ", 4) != 0 ||
|
||||||
str = fu_common_strsafe((const gchar *)self->footer.data.header.default_head,
|
memcmp(self->public_key.E, "E = ", 4) != 0) {
|
||||||
sizeof(self->footer.data.header.default_head));
|
g_set_error_literal(error, FWUPD_ERROR, FWUPD_ERROR_INTERNAL, "invalid public-key");
|
||||||
g_set_error(error,
|
|
||||||
FWUPD_ERROR,
|
|
||||||
FWUPD_ERROR_INTERNAL,
|
|
||||||
"invalid footer, expected %s, and got %s",
|
|
||||||
MTK_RSA_HEADER,
|
|
||||||
str);
|
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (self->footer.data.header.configuration_setting.bits.second_image) {
|
/* set payload */
|
||||||
guint32 addr;
|
blob_payload = g_bytes_new(buf, bufsz - sizeof(self->public_key));
|
||||||
if (!fu_common_read_uint32_safe(
|
firmware_payload = fu_firmware_new_from_bytes(blob_payload);
|
||||||
self->footer.data.header.second_image_program_addr,
|
fu_firmware_set_id(firmware_payload, FU_FIRMWARE_ID_PAYLOAD);
|
||||||
sizeof(self->footer.data.header.second_image_program_addr),
|
fu_firmware_add_image(firmware, firmware_payload);
|
||||||
0,
|
|
||||||
&addr,
|
|
||||||
G_LITTLE_ENDIAN,
|
|
||||||
error))
|
|
||||||
return FALSE;
|
|
||||||
if (addr % GENESYS_SCALER_BANK_SIZE != 0) {
|
|
||||||
g_set_error(error,
|
|
||||||
FWUPD_ERROR,
|
|
||||||
FWUPD_ERROR_INVALID_FILE,
|
|
||||||
"invalid address, expected a multiple of 0x%x, and got 0x%x",
|
|
||||||
GENESYS_SCALER_BANK_SIZE,
|
|
||||||
addr);
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
self->second_image_program_addr = addr;
|
|
||||||
fu_firmware_set_addr(firmware, addr);
|
|
||||||
}
|
|
||||||
if (self->footer.data.header.configuration_setting.bits.decrypt_mode) {
|
|
||||||
if (!fu_common_read_uint32_safe(
|
|
||||||
self->footer.data.header.scaler_public_key_addr,
|
|
||||||
sizeof(self->footer.data.header.scaler_public_key_addr),
|
|
||||||
0,
|
|
||||||
&self->public_key_addr,
|
|
||||||
G_LITTLE_ENDIAN,
|
|
||||||
error))
|
|
||||||
return FALSE;
|
|
||||||
self->public_key_size = 0x1000;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (self->footer.data.header.configuration_setting.bits.special_protect_sector) {
|
/* set public-key */
|
||||||
if (self->footer.data.header.protect_sector[0].area.size) {
|
blob_public_key = g_bytes_new(&self->public_key, sizeof(self->public_key));
|
||||||
self->protect_sector_addr[0] =
|
firmware_public_key = fu_firmware_new_from_bytes(blob_public_key);
|
||||||
(self->footer.data.header.protect_sector[0].area.addr_high << 16) |
|
fu_firmware_set_id(firmware_public_key, FU_FIRMWARE_ID_SIGNATURE);
|
||||||
(self->footer.data.header.protect_sector[0].area.addr_low[1] << 8) |
|
fu_firmware_add_image(firmware, firmware_public_key);
|
||||||
(self->footer.data.header.protect_sector[0].area.addr_low[0]);
|
|
||||||
self->protect_sector_addr[0] *= 0x1000;
|
|
||||||
self->protect_sector_size[0] =
|
|
||||||
self->footer.data.header.protect_sector[0].area.size * 0x1000;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (self->footer.data.header.protect_sector[1].area.size) {
|
|
||||||
self->protect_sector_addr[1] =
|
|
||||||
(self->footer.data.header.protect_sector[1].area.addr_high << 16) |
|
|
||||||
(self->footer.data.header.protect_sector[1].area.addr_low[1] << 8) |
|
|
||||||
(self->footer.data.header.protect_sector[1].area.addr_low[0]);
|
|
||||||
self->protect_sector_addr[1] *= 0x1000;
|
|
||||||
self->protect_sector_size[1] =
|
|
||||||
self->footer.data.header.protect_sector[1].area.size * 0x1000;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* success */
|
/* success */
|
||||||
return TRUE;
|
return TRUE;
|
||||||
@ -135,82 +74,14 @@ fu_genesys_scaler_firmware_export(FuFirmware *firmware,
|
|||||||
XbBuilderNode *bn)
|
XbBuilderNode *bn)
|
||||||
{
|
{
|
||||||
FuGenesysScalerFirmware *self = FU_GENESYS_SCALER_FIRMWARE(firmware);
|
FuGenesysScalerFirmware *self = FU_GENESYS_SCALER_FIRMWARE(firmware);
|
||||||
|
gchar N[0x200 + 1] = {'\0'};
|
||||||
|
gchar E[0x006 + 1] = {'\0'};
|
||||||
|
|
||||||
if (self->footer.data.header.model_name[0] != '\0') {
|
memcpy(N, self->public_key.N + 4, sizeof(N) - 1);
|
||||||
fu_xmlb_builder_insert_kv(bn,
|
fu_xmlb_builder_insert_kv(bn, "N", N);
|
||||||
"model_name",
|
|
||||||
(const gchar *)self->footer.data.header.model_name);
|
|
||||||
}
|
|
||||||
if (self->footer.data.header.scaler_group[0] != '\0') {
|
|
||||||
fu_xmlb_builder_insert_kv(bn,
|
|
||||||
"scaler_group",
|
|
||||||
(const gchar *)self->footer.data.header.scaler_group);
|
|
||||||
}
|
|
||||||
if (self->footer.data.header.panel_type[0] != '\0') {
|
|
||||||
fu_xmlb_builder_insert_kv(bn,
|
|
||||||
"panel_type",
|
|
||||||
(const gchar *)self->footer.data.header.panel_type);
|
|
||||||
}
|
|
||||||
if (self->footer.data.header.scaler_packet_date[0] != '\0') {
|
|
||||||
fu_xmlb_builder_insert_kv(
|
|
||||||
bn,
|
|
||||||
"scaler_packet_date",
|
|
||||||
(const gchar *)self->footer.data.header.scaler_packet_date);
|
|
||||||
}
|
|
||||||
if (self->footer.data.header.scaler_packet_version[0] != '\0') {
|
|
||||||
fu_xmlb_builder_insert_kv(
|
|
||||||
bn,
|
|
||||||
"scaler_packet_version",
|
|
||||||
(const gchar *)self->footer.data.header.scaler_packet_version);
|
|
||||||
}
|
|
||||||
fu_xmlb_builder_insert_kx(bn,
|
|
||||||
"configuration_setting",
|
|
||||||
self->footer.data.header.configuration_setting.r8);
|
|
||||||
|
|
||||||
if (self->footer.data.header.configuration_setting.bits.second_image)
|
memcpy(E, self->public_key.E + 4, sizeof(E) - 1);
|
||||||
fu_xmlb_builder_insert_kx(bn,
|
fu_xmlb_builder_insert_kv(bn, "E", E);
|
||||||
"second_image_program_addr",
|
|
||||||
self->second_image_program_addr);
|
|
||||||
|
|
||||||
if (self->footer.data.header.configuration_setting.bits.decrypt_mode) {
|
|
||||||
gchar N[0x200 + 1] = {'\0'};
|
|
||||||
gchar E[0x006 + 1] = {'\0'};
|
|
||||||
|
|
||||||
fu_xmlb_builder_insert_kx(bn, "public_key_addr", self->public_key_addr);
|
|
||||||
fu_xmlb_builder_insert_kx(bn, "public_key_size", self->public_key_size);
|
|
||||||
|
|
||||||
memcpy(N, self->footer.data.public_key.N + 4, sizeof(N) - 1);
|
|
||||||
fu_xmlb_builder_insert_kv(bn, "N", N);
|
|
||||||
|
|
||||||
memcpy(E, self->footer.data.public_key.E + 4, sizeof(E) - 1);
|
|
||||||
fu_xmlb_builder_insert_kv(bn, "E", E);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (self->footer.data.header.configuration_setting.bits.special_protect_sector) {
|
|
||||||
if (self->protect_sector_size[0]) {
|
|
||||||
fu_xmlb_builder_insert_kx(bn,
|
|
||||||
"protect_sector_addr0",
|
|
||||||
self->protect_sector_addr[0]);
|
|
||||||
fu_xmlb_builder_insert_kx(bn,
|
|
||||||
"protect_sector_size0",
|
|
||||||
self->protect_sector_size[0]);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (self->protect_sector_size[1]) {
|
|
||||||
fu_xmlb_builder_insert_kx(bn,
|
|
||||||
"protect_sector_addr1",
|
|
||||||
self->protect_sector_addr[1]);
|
|
||||||
fu_xmlb_builder_insert_kx(bn,
|
|
||||||
"protect_sector_size1",
|
|
||||||
self->protect_sector_size[1]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (self->footer.data.header.configuration_setting.bits.boot_code_size_in_header) {
|
|
||||||
fu_xmlb_builder_insert_kx(bn,
|
|
||||||
"boot_code_size",
|
|
||||||
self->footer.data.header.boot_code_size);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
@ -220,10 +91,23 @@ fu_genesys_scaler_firmware_build(FuFirmware *firmware, XbNode *n, GError **error
|
|||||||
const gchar *tmp;
|
const gchar *tmp;
|
||||||
|
|
||||||
/* optional properties */
|
/* optional properties */
|
||||||
tmp = xb_node_query_text(n, "model_name", NULL);
|
tmp = xb_node_query_text(n, "N", NULL);
|
||||||
if (tmp != NULL) {
|
if (tmp != NULL) {
|
||||||
if (!fu_memcpy_safe((guint8 *)&self->footer.data.header.model_name,
|
if (!fu_memcpy_safe((guint8 *)&self->public_key.N,
|
||||||
sizeof(self->footer.data.header.model_name),
|
sizeof(self->public_key.N),
|
||||||
|
0x0, /* dst */
|
||||||
|
(const guint8 *)tmp,
|
||||||
|
strlen(tmp),
|
||||||
|
0x0, /* src */
|
||||||
|
strlen(tmp),
|
||||||
|
error))
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
tmp = xb_node_query_text(n, "E", NULL);
|
||||||
|
if (tmp != NULL) {
|
||||||
|
if (!fu_memcpy_safe((guint8 *)&self->public_key.E,
|
||||||
|
sizeof(self->public_key.E),
|
||||||
0x0, /* dst */
|
0x0, /* dst */
|
||||||
(const guint8 *)tmp,
|
(const guint8 *)tmp,
|
||||||
strlen(tmp),
|
strlen(tmp),
|
||||||
@ -241,7 +125,6 @@ static GBytes *
|
|||||||
fu_genesys_scaler_firmware_write(FuFirmware *firmware, GError **error)
|
fu_genesys_scaler_firmware_write(FuFirmware *firmware, GError **error)
|
||||||
{
|
{
|
||||||
FuGenesysScalerFirmware *self = FU_GENESYS_SCALER_FIRMWARE(firmware);
|
FuGenesysScalerFirmware *self = FU_GENESYS_SCALER_FIRMWARE(firmware);
|
||||||
FuGenesysMtkFooter footer = {0x0};
|
|
||||||
g_autoptr(GByteArray) buf = g_byte_array_new();
|
g_autoptr(GByteArray) buf = g_byte_array_new();
|
||||||
g_autoptr(GBytes) blob = NULL;
|
g_autoptr(GBytes) blob = NULL;
|
||||||
|
|
||||||
@ -251,27 +134,8 @@ fu_genesys_scaler_firmware_write(FuFirmware *firmware, GError **error)
|
|||||||
return NULL;
|
return NULL;
|
||||||
fu_byte_array_append_bytes(buf, blob);
|
fu_byte_array_append_bytes(buf, blob);
|
||||||
|
|
||||||
/* "encrypted" footer */
|
/* public-key */
|
||||||
if (!fu_memcpy_safe((guint8 *)&footer,
|
g_byte_array_append(buf, (const guint8 *)&self->public_key, sizeof(self->public_key));
|
||||||
sizeof(footer),
|
|
||||||
0, /* dst */
|
|
||||||
(guint8 *)&self->footer,
|
|
||||||
sizeof(self->footer),
|
|
||||||
0, /* src */
|
|
||||||
sizeof(footer),
|
|
||||||
error))
|
|
||||||
return NULL;
|
|
||||||
if (!fu_memcpy_safe((guint8 *)&footer.data.header.default_head,
|
|
||||||
sizeof(footer.data.header.default_head),
|
|
||||||
0, /* dst */
|
|
||||||
(guint8 *)&MTK_RSA_HEADER,
|
|
||||||
strlen(MTK_RSA_HEADER),
|
|
||||||
0, /* src */
|
|
||||||
strlen(MTK_RSA_HEADER),
|
|
||||||
error))
|
|
||||||
return NULL;
|
|
||||||
fu_genesys_scaler_firmware_decrypt((guint8 *)&footer, sizeof(footer));
|
|
||||||
g_byte_array_append(buf, (const guint8 *)&footer, sizeof(footer));
|
|
||||||
|
|
||||||
/* success */
|
/* success */
|
||||||
return g_byte_array_free_to_bytes(g_steal_pointer(&buf));
|
return g_byte_array_free_to_bytes(g_steal_pointer(&buf));
|
||||||
|
@ -19,132 +19,5 @@ G_DECLARE_FINAL_TYPE(FuGenesysScalerFirmware,
|
|||||||
|
|
||||||
#define GENESYS_SCALER_BANK_SIZE 0x200000U
|
#define GENESYS_SCALER_BANK_SIZE 0x200000U
|
||||||
|
|
||||||
#define MTK_RSA_HEADER "MTK_RSA_HEADER"
|
|
||||||
|
|
||||||
typedef struct __attribute__((packed)) {
|
|
||||||
guint8 default_head[14];
|
|
||||||
guint8 reserved_0e_0f[2];
|
|
||||||
guint8 model_name[16];
|
|
||||||
guint8 reserved_20;
|
|
||||||
guint8 size[2];
|
|
||||||
guint8 reserved_23_27[5];
|
|
||||||
guint8 scaler_group[10];
|
|
||||||
guint8 reserved_32_53[34];
|
|
||||||
guint8 panel_type[10];
|
|
||||||
guint8 scaler_packet_date[8];
|
|
||||||
guint8 reserved_66_67[2];
|
|
||||||
guint8 scaler_packet_version[4];
|
|
||||||
guint8 reserved_6c_7f[20];
|
|
||||||
union {
|
|
||||||
guint8 r8;
|
|
||||||
struct {
|
|
||||||
/*
|
|
||||||
* Decrypt Mode:
|
|
||||||
*
|
|
||||||
* 0: Scaler decrypt
|
|
||||||
* 1: ISP Tool decrypt
|
|
||||||
*/
|
|
||||||
guint8 decrypt_mode : 1;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Second Image:
|
|
||||||
*
|
|
||||||
* 0: 1st image or dual image; programming address at 0x000000
|
|
||||||
* 1: 2nd image; programming address set by .second_image_program_addr
|
|
||||||
*/
|
|
||||||
guint8 second_image : 1;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Dual image turn:
|
|
||||||
*
|
|
||||||
* 0: fix second programing address set by .second_image_program_addr
|
|
||||||
* 1: support “Dual image turn” rule
|
|
||||||
* - TSUM: Not supported
|
|
||||||
* - MST9U: ISP Tool need update to DUT least version image address
|
|
||||||
* - HAWK: Not supported
|
|
||||||
*/
|
|
||||||
guint8 dual_image_turn : 1;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Special Protect Sector:
|
|
||||||
*
|
|
||||||
* 0: No Special Protect sector
|
|
||||||
* 1: Support Special Protect sector
|
|
||||||
*/
|
|
||||||
guint8 special_protect_sector : 1;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* HAWK bypass mode
|
|
||||||
*
|
|
||||||
* 0: No support HAWK bypass mode
|
|
||||||
* 1: Support HAWK bypass mode
|
|
||||||
*/
|
|
||||||
guint8 hawk_bypass_mode : 1;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Boot Code Size in header
|
|
||||||
*
|
|
||||||
* 0: Follow original search bin address rule
|
|
||||||
* 1: Get Boot code size from header set by .boot_code_size
|
|
||||||
*/
|
|
||||||
guint8 boot_code_size_in_header : 1;
|
|
||||||
|
|
||||||
/* Reserved */
|
|
||||||
guint8 reserved_6_7 : 2;
|
|
||||||
} __attribute__((packed)) bits;
|
|
||||||
} configuration_setting;
|
|
||||||
|
|
||||||
guint8 reserved_81_85[5];
|
|
||||||
|
|
||||||
/* If configuration_setting.bits.second_image set */
|
|
||||||
guint8 second_image_program_addr[4];
|
|
||||||
|
|
||||||
/*
|
|
||||||
* If configuration_setting.bits.decrypt is set
|
|
||||||
*
|
|
||||||
* TSUM/HAWK: ISP Tool need protect flash public address can’t erase and write
|
|
||||||
* MST9U: Not supported
|
|
||||||
*/
|
|
||||||
guint8 scaler_public_key_addr[4];
|
|
||||||
|
|
||||||
/*
|
|
||||||
* If configuration_setting.bits.special_protect_sector is set
|
|
||||||
*
|
|
||||||
* ISP Tool can't erase "Special Protect Sector" area.
|
|
||||||
*
|
|
||||||
* [19:00]: Protect continuous sector start.
|
|
||||||
* [23:20]: Protect sector continuous number.
|
|
||||||
*
|
|
||||||
* Examples: If need to protect FA000 ~FFFFF, Special Protect sector = 0x6000FA;
|
|
||||||
* If need to protect FA000 only, Special Protect sector = 0x1000FA;
|
|
||||||
* If no need to protect, Special Protect sector = 0x000000;
|
|
||||||
*/
|
|
||||||
union {
|
|
||||||
guint8 r24[3];
|
|
||||||
struct {
|
|
||||||
guint8 addr_low[2];
|
|
||||||
guint8 addr_high : 4;
|
|
||||||
guint8 size : 4;
|
|
||||||
} __attribute__((packed)) area;
|
|
||||||
} protect_sector[2];
|
|
||||||
|
|
||||||
/*
|
|
||||||
* If configuration.bits .second_image and .dual_image_turn are set
|
|
||||||
* and .boot_code_size.
|
|
||||||
*/
|
|
||||||
guint32 boot_code_size;
|
|
||||||
} FuGenesysMtkRsaHeader;
|
|
||||||
|
|
||||||
typedef union __attribute__((packed)) {
|
|
||||||
guint8 raw[0x312];
|
|
||||||
struct {
|
|
||||||
FuGenesysPublicKey public_key;
|
|
||||||
FuGenesysMtkRsaHeader header;
|
|
||||||
} data;
|
|
||||||
} FuGenesysMtkFooter;
|
|
||||||
|
|
||||||
void
|
|
||||||
fu_genesys_scaler_firmware_decrypt(guint8 *buf, gsize bufsz);
|
|
||||||
|
|
||||||
FuFirmware *
|
FuFirmware *
|
||||||
fu_genesys_scaler_firmware_new(void);
|
fu_genesys_scaler_firmware_new(void);
|
||||||
|
Binary file not shown.
Loading…
Reference in New Issue
Block a user