mirror of
https://git.proxmox.com/git/fwupd
synced 2025-08-04 05:26:58 +00:00
Add a new plugin to handle HP M2xfd monitors
Added support for genesys logic devices.
This commit is contained in:
parent
cc19be590a
commit
9466e778f5
@ -352,6 +352,8 @@ def _build(bld: Builder) -> None:
|
||||
Fuzzer("ebitdo"),
|
||||
Fuzzer("elanfp"),
|
||||
Fuzzer("elantp"),
|
||||
Fuzzer("genesys-scaler", srcdir="genesys", pattern="genesys-scaler-firmware"),
|
||||
Fuzzer("genesys-usbhub", srcdir="genesys", pattern="genesys-usbhub-firmware"),
|
||||
Fuzzer("pixart", srcdir="pixart-rf", pattern="pxi-firmware"),
|
||||
Fuzzer("redfish-smbios", srcdir="redfish", pattern="redfish-smbios"),
|
||||
Fuzzer("synaptics-prometheus", pattern="synaprom-firmware"),
|
||||
|
@ -435,6 +435,7 @@ done
|
||||
%{_libdir}/fwupd-plugins-%{fwupdplugin_version}/libfu_plugin_ep963x.so
|
||||
%{_libdir}/fwupd-plugins-%{fwupdplugin_version}/libfu_plugin_fastboot.so
|
||||
%{_libdir}/fwupd-plugins-%{fwupdplugin_version}/libfu_plugin_fresco_pd.so
|
||||
%{_libdir}/fwupd-plugins-%{fwupdplugin_version}/libfu_plugin_genesys.so
|
||||
%{_libdir}/fwupd-plugins-%{fwupdplugin_version}/libfu_plugin_gpio.so
|
||||
%{_libdir}/fwupd-plugins-%{fwupdplugin_version}/libfu_plugin_hailuck.so
|
||||
%{_libdir}/fwupd-plugins-%{fwupdplugin_version}/libfu_plugin_iommu.so
|
||||
|
134
plugins/genesys/README.md
Normal file
134
plugins/genesys/README.md
Normal file
@ -0,0 +1,134 @@
|
||||
# Genesys Logic
|
||||
|
||||
## Introduction
|
||||
|
||||
This plugin allows updating the Genesys Logic USB Hub devices.
|
||||
|
||||
* GL3523
|
||||
* GL3590
|
||||
|
||||
Additionally, this plugin allows updating the MStar Semiconductor Scaler connected via an I²C bus.
|
||||
|
||||
* TSUM G
|
||||
|
||||
## Firmware Format
|
||||
|
||||
The daemon will decompress the cabinet archives and extract the firmware blob in an unspecified binary file format.
|
||||
|
||||
This plugin supports the following protocol IDs:
|
||||
|
||||
* com.genesys.usbhub
|
||||
* com.mstarsemi.scaler
|
||||
|
||||
## GUID Generation
|
||||
|
||||
These devices use the standard USB DeviceInstanceId values for the USB Hub, e.g.
|
||||
|
||||
* HP Mxfd FHD Monitor: `USB\VID_03F0&PID_0610`
|
||||
|
||||
These devices also use custom GUID values for the Scaler, e.g.
|
||||
|
||||
* HP M24fd USB-C Monitor: `GENESYS_SCALER\MSTAR_TSUM_G&PUBKEY_B335BDCE-7073-5D0E-9BD3-9B69C1A6899F`
|
||||
* HP M27fd USB-C Monitor: `GENESYS_SCALER\MSTAR_TSUM_G&PUBKEY_847A3650-8648-586B-83C8-8B53714F37E3`
|
||||
|
||||
The Public Key is product-specific and is required to identify the product.
|
||||
|
||||
## Quirk Use
|
||||
|
||||
This plugin uses the following plugin-specific quirks:
|
||||
|
||||
### has-mstar-scaler
|
||||
|
||||
USB Hub has a MStar Semiconductor Scaler attached via I²C.
|
||||
|
||||
Since 1.7.6.
|
||||
|
||||
### GenesysUsbhubSwitchRequest
|
||||
|
||||
USB Hub Switch Request value.
|
||||
|
||||
* HP Mxfd FHD Monitors: `0xA1`
|
||||
|
||||
Since 1.7.6.
|
||||
|
||||
### GenesysUsbhubReadRequest
|
||||
|
||||
USB Hub Read Request value.
|
||||
|
||||
* HP Mxfd FHD Monitors: `0xA2`
|
||||
|
||||
Since 1.7.6.
|
||||
|
||||
### GenesysUsbhubWriteRequest
|
||||
|
||||
USB Hub Write Request value.
|
||||
|
||||
* HP Mxfd FHD Monitors: `0xA3`
|
||||
|
||||
Since 1.7.6.
|
||||
|
||||
### use-i2c-ch0
|
||||
|
||||
Scalar uses I²C channel 0.
|
||||
|
||||
Since 1.7.6.
|
||||
|
||||
### pause-r2-cpu
|
||||
|
||||
Scalar pause R2 CPU.
|
||||
|
||||
Since 1.7.6.
|
||||
|
||||
### GenesysScalerDeviceTransferSize
|
||||
|
||||
Scaler Block size to use for transfers.
|
||||
|
||||
* MStar Semiconductor TSUM G: `0x40`
|
||||
|
||||
Since 1.7.6.
|
||||
|
||||
### GenesysScalerGpioOutputRegister
|
||||
|
||||
Scaler GPIO Output Register value.
|
||||
|
||||
* MStar Semiconductor TSUM G: `0x0426`
|
||||
|
||||
Since 1.7.6.
|
||||
|
||||
### GenesysScalerGpioEnableRegister
|
||||
|
||||
Scaler GPIO Enable Register value.
|
||||
|
||||
* MStar Semiconductor TSUM G: `0x0428`
|
||||
|
||||
Since 1.7.6.
|
||||
|
||||
### GenesysScalerGpioValue
|
||||
|
||||
Scaler GPIO value.
|
||||
|
||||
* MStar Semiconductor TSUM G: `0x01`
|
||||
|
||||
Since 1.7.6.
|
||||
|
||||
## Runtime Requirement
|
||||
|
||||
The USB Hub devices and its attached Scaler require libgusb version [0.3.8][1] or later to be detected.
|
||||
|
||||
## Update Behavior
|
||||
|
||||
The devices are independently updated at runtime using USB control transfers.
|
||||
|
||||
The firmware is deployed when the device is in normal runtime mode, and the device will reset when the new firmware has been written.
|
||||
|
||||
The HP Mxfd FHD Monitors must be connected to host via the USB-C cable to apply an update. The devices remain functional during the update; the Scaler update is ~10 minute long.
|
||||
|
||||
## Vendor ID Security
|
||||
|
||||
The vendor ID is set from the USB vendor, for example set to `USB:0x03F0` for HP.
|
||||
|
||||
## External Interface Access
|
||||
|
||||
This plugin requires read/write access to `/dev/bus/usb`.
|
||||
|
||||
[1]: https://github.com/hughsie/libgusb/commit/4e118c154dde70e196c4381bd97790a9413c3552
|
29
plugins/genesys/fu-genesys-common.h
Normal file
29
plugins/genesys/fu-genesys-common.h
Normal file
@ -0,0 +1,29 @@
|
||||
/*
|
||||
* Copyright (C) 2021 Gaël PORTAY <gael.portay@collabora.com>
|
||||
*
|
||||
* SPDX-License-Identifier: LGPL-2.1+
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
typedef struct {
|
||||
guint8 reg;
|
||||
guint8 expected_val;
|
||||
} FuGenesysWaitFlashRegisterHelper;
|
||||
|
||||
typedef struct __attribute__((packed)) {
|
||||
guint8 tool_string_version; /* 0xff = not supported */
|
||||
|
||||
/* byte arrays are ASCII encoded and not NUL terminated */
|
||||
guint8 mask_project_code[4];
|
||||
guint8 mask_project_hardware[1]; /* 0=a, 1=b... */
|
||||
guint8 mask_project_firmware[2]; /* 01,02,03... */
|
||||
guint8 mask_project_ic_type[6]; /* 352310=GL3523-10 (ASCII string) */
|
||||
|
||||
guint8 running_project_code[4];
|
||||
guint8 running_project_hardware[1];
|
||||
guint8 running_project_firmware[2];
|
||||
guint8 running_project_ic_type[6];
|
||||
|
||||
guint8 firmware_version[4]; /* MMmm=MM.mm (ASCII string) */
|
||||
} FuGenesysStaticToolString;
|
1820
plugins/genesys/fu-genesys-scaler-device.c
Normal file
1820
plugins/genesys/fu-genesys-scaler-device.c
Normal file
File diff suppressed because it is too large
Load Diff
19
plugins/genesys/fu-genesys-scaler-device.h
Normal file
19
plugins/genesys/fu-genesys-scaler-device.h
Normal file
@ -0,0 +1,19 @@
|
||||
/*
|
||||
* Copyright (C) 2021 Gaël PORTAY <gael.portay@collabora.com>
|
||||
*
|
||||
* SPDX-License-Identifier: LGPL-2.1+
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <fwupdplugin.h>
|
||||
|
||||
#define FU_TYPE_GENESYS_SCALER_DEVICE (fu_genesys_scaler_device_get_type())
|
||||
G_DECLARE_FINAL_TYPE(FuGenesysScalerDevice,
|
||||
fu_genesys_scaler_device,
|
||||
FU,
|
||||
GENESYS_SCALER_DEVICE,
|
||||
FuDevice)
|
||||
|
||||
FuGenesysScalerDevice *
|
||||
fu_genesys_scaler_device_new(FuContext *ctx);
|
287
plugins/genesys/fu-genesys-scaler-firmware.c
Normal file
287
plugins/genesys/fu-genesys-scaler-firmware.c
Normal file
@ -0,0 +1,287 @@
|
||||
/*
|
||||
* Copyright (C) 2021 Gaël PORTAY <gael.portay@collabora.com>
|
||||
*
|
||||
* SPDX-License-Identifier: LGPL-2.1+
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <fwupdplugin.h>
|
||||
|
||||
#include "fu-genesys-scaler-firmware.h"
|
||||
|
||||
struct _FuGenesysScalerFirmware {
|
||||
FuFirmwareClass parent_instance;
|
||||
FuGenesysMtkFooter footer;
|
||||
guint protect_sector_addr[2];
|
||||
gsize protect_sector_size[2];
|
||||
guint public_key_addr;
|
||||
gsize public_key_size;
|
||||
guint addr;
|
||||
};
|
||||
|
||||
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
|
||||
fu_genesys_scaler_firmware_parse(FuFirmware *firmware,
|
||||
GBytes *fw,
|
||||
guint64 addr_start,
|
||||
guint64 addr_end,
|
||||
FwupdInstallFlags flags,
|
||||
GError **error)
|
||||
{
|
||||
FuGenesysScalerFirmware *self = FU_GENESYS_SCALER_FIRMWARE(firmware);
|
||||
gsize bufsz = 0;
|
||||
const guint8 *buf = g_bytes_get_data(fw, &bufsz);
|
||||
|
||||
buf = g_bytes_get_data(fw, &bufsz);
|
||||
if (!fu_memcpy_safe((guint8 *)&self->footer,
|
||||
sizeof(self->footer),
|
||||
0, /* dst */
|
||||
buf,
|
||||
bufsz,
|
||||
bufsz - sizeof(self->footer), /* src */
|
||||
sizeof(self->footer),
|
||||
error))
|
||||
return FALSE;
|
||||
fu_genesys_scaler_firmware_decrypt((guint8 *)&self->footer, sizeof(self->footer));
|
||||
if (memcmp(self->footer.data.header.default_head,
|
||||
MTK_RSA_HEADER,
|
||||
sizeof(self->footer.data.header.default_head)) != 0) {
|
||||
g_autofree gchar *str = NULL;
|
||||
str = fu_common_strsafe((const gchar *)self->footer.data.header.default_head,
|
||||
sizeof(self->footer.data.header.default_head));
|
||||
g_set_error(error,
|
||||
FWUPD_ERROR,
|
||||
FWUPD_ERROR_INTERNAL,
|
||||
"invalid footer, expected %s, and got %s",
|
||||
MTK_RSA_HEADER,
|
||||
str);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (self->footer.data.header.configuration_setting.bits.second_image) {
|
||||
if (!fu_common_read_uint32_safe(
|
||||
self->footer.data.header.second_image_program_addr,
|
||||
sizeof(self->footer.data.header.second_image_program_addr),
|
||||
0,
|
||||
&self->addr,
|
||||
G_LITTLE_ENDIAN,
|
||||
error))
|
||||
return FALSE;
|
||||
}
|
||||
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) {
|
||||
if (self->footer.data.header.protect_sector[0].area.size) {
|
||||
self->protect_sector_addr[0] =
|
||||
(self->footer.data.header.protect_sector[0].area.addr_high << 16) |
|
||||
(self->footer.data.header.protect_sector[0].area.addr_low[1] << 8) |
|
||||
(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 */
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
fu_genesys_scaler_firmware_export(FuFirmware *firmware,
|
||||
FuFirmwareExportFlags flags,
|
||||
XbBuilderNode *bn)
|
||||
{
|
||||
FuGenesysScalerFirmware *self = FU_GENESYS_SCALER_FIRMWARE(firmware);
|
||||
|
||||
if (self->footer.data.header.model_name[0] != '\0') {
|
||||
fu_xmlb_builder_insert_kv(bn,
|
||||
"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)
|
||||
fu_xmlb_builder_insert_kx(bn, "second_image_program_addr", self->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);
|
||||
}
|
||||
fu_xmlb_builder_insert_kx(bn, "addr", self->addr);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
fu_genesys_scaler_firmware_build(FuFirmware *firmware, XbNode *n, GError **error)
|
||||
{
|
||||
FuGenesysScalerFirmware *self = FU_GENESYS_SCALER_FIRMWARE(firmware);
|
||||
const gchar *tmp;
|
||||
|
||||
/* optional properties */
|
||||
tmp = xb_node_query_text(n, "model_name", NULL);
|
||||
if (tmp != NULL) {
|
||||
if (!fu_memcpy_safe((guint8 *)&self->footer.data.header.model_name,
|
||||
sizeof(self->footer.data.header.model_name),
|
||||
0x0, /* dst */
|
||||
(const guint8 *)tmp,
|
||||
strlen(tmp),
|
||||
0x0, /* src */
|
||||
strlen(tmp),
|
||||
error))
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* success */
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static GBytes *
|
||||
fu_genesys_scaler_firmware_write(FuFirmware *firmware, GError **error)
|
||||
{
|
||||
FuGenesysScalerFirmware *self = FU_GENESYS_SCALER_FIRMWARE(firmware);
|
||||
FuGenesysMtkFooter footer = {0x0};
|
||||
g_autoptr(GByteArray) buf = g_byte_array_new();
|
||||
g_autoptr(GBytes) blob = NULL;
|
||||
|
||||
/* payload */
|
||||
blob = fu_firmware_get_bytes(firmware, error);
|
||||
if (blob == NULL)
|
||||
return NULL;
|
||||
fu_byte_array_append_bytes(buf, blob);
|
||||
|
||||
/* "encrypted" footer */
|
||||
if (!fu_memcpy_safe((guint8 *)&footer,
|
||||
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 */
|
||||
return g_byte_array_free_to_bytes(g_steal_pointer(&buf));
|
||||
}
|
||||
|
||||
static void
|
||||
fu_genesys_scaler_firmware_init(FuGenesysScalerFirmware *self)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
fu_genesys_scaler_firmware_class_init(FuGenesysScalerFirmwareClass *klass)
|
||||
{
|
||||
FuFirmwareClass *klass_firmware = FU_FIRMWARE_CLASS(klass);
|
||||
klass_firmware->parse = fu_genesys_scaler_firmware_parse;
|
||||
klass_firmware->export = fu_genesys_scaler_firmware_export;
|
||||
klass_firmware->build = fu_genesys_scaler_firmware_build;
|
||||
klass_firmware->write = fu_genesys_scaler_firmware_write;
|
||||
}
|
||||
|
||||
FuFirmware *
|
||||
fu_genesys_scaler_firmware_new(void)
|
||||
{
|
||||
return FU_FIRMWARE(g_object_new(FU_TYPE_GENESYS_SCALER_FIRMWARE, NULL));
|
||||
}
|
149
plugins/genesys/fu-genesys-scaler-firmware.h
Normal file
149
plugins/genesys/fu-genesys-scaler-firmware.h
Normal file
@ -0,0 +1,149 @@
|
||||
/*
|
||||
* Copyright (C) 2021 Gaël PORTAY <gael.portay@collabora.com>
|
||||
*
|
||||
* SPDX-License-Identifier: LGPL-2.1+
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <fwupdplugin.h>
|
||||
|
||||
#define FU_TYPE_GENESYS_SCALER_FIRMWARE (fu_genesys_scaler_firmware_get_type())
|
||||
G_DECLARE_FINAL_TYPE(FuGenesysScalerFirmware,
|
||||
fu_genesys_scaler_firmware,
|
||||
FU,
|
||||
GENESYS_SCALER_FIRMWARE,
|
||||
FuFirmware)
|
||||
|
||||
#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 {
|
||||
guint32 r32;
|
||||
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 {
|
||||
struct {
|
||||
guint8 N[0x206];
|
||||
guint8 E[0x00c];
|
||||
} __attribute__((packed)) public_key;
|
||||
FuGenesysMtkRsaHeader header;
|
||||
} data;
|
||||
} FuGenesysMtkFooter;
|
||||
|
||||
void
|
||||
fu_genesys_scaler_firmware_decrypt(guint8 *buf, gsize bufsz);
|
||||
|
||||
FuFirmware *
|
||||
fu_genesys_scaler_firmware_new(void);
|
1359
plugins/genesys/fu-genesys-usbhub-device.c
Normal file
1359
plugins/genesys/fu-genesys-usbhub-device.c
Normal file
File diff suppressed because it is too large
Load Diff
16
plugins/genesys/fu-genesys-usbhub-device.h
Normal file
16
plugins/genesys/fu-genesys-usbhub-device.h
Normal file
@ -0,0 +1,16 @@
|
||||
/*
|
||||
* Copyright (C) 2021 Ricardo Cañuelo <ricardo.canuelo@collabora.com>
|
||||
*
|
||||
* SPDX-License-Identifier: LGPL-2.1+
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <fwupdplugin.h>
|
||||
|
||||
#define FU_TYPE_GENESYS_USBHUB_DEVICE (fu_genesys_usbhub_device_get_type())
|
||||
G_DECLARE_FINAL_TYPE(FuGenesysUsbhubDevice,
|
||||
fu_genesys_usbhub_device,
|
||||
FU,
|
||||
GENESYS_USBHUB_DEVICE,
|
||||
FuUsbDevice)
|
391
plugins/genesys/fu-genesys-usbhub-firmware.c
Normal file
391
plugins/genesys/fu-genesys-usbhub-firmware.c
Normal file
@ -0,0 +1,391 @@
|
||||
/*
|
||||
* Copyright (C) 2021 Gaël PORTAY <gael.portay@collabora.com>
|
||||
*
|
||||
* SPDX-License-Identifier: LGPL-2.1+
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <fwupdplugin.h>
|
||||
|
||||
#include "fu-genesys-common.h"
|
||||
#include "fu-genesys-usbhub-firmware.h"
|
||||
|
||||
struct _FuGenesysUsbhubFirmware {
|
||||
FuFirmwareClass parent_instance;
|
||||
FuGenesysStaticToolString static_ts;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE(FuGenesysUsbhubFirmware, fu_genesys_usbhub_firmware, FU_TYPE_FIRMWARE)
|
||||
|
||||
static gboolean
|
||||
fu_genesys_usbhub_firmware_verify(const guint8 *buf, gsize bufsz, guint16 code_size, GError **error)
|
||||
{
|
||||
guint16 fw_checksum, checksum;
|
||||
|
||||
/* check code-size */
|
||||
if (code_size < sizeof(checksum)) {
|
||||
g_set_error(error,
|
||||
FWUPD_ERROR,
|
||||
FWUPD_ERROR_INVALID_FILE,
|
||||
"code-size is too small: %u bytes",
|
||||
code_size);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* get checksum */
|
||||
if (!fu_common_read_uint16_safe(buf,
|
||||
bufsz,
|
||||
code_size - sizeof(checksum),
|
||||
&fw_checksum,
|
||||
G_BIG_ENDIAN,
|
||||
error))
|
||||
return FALSE;
|
||||
|
||||
/* calculate checksum */
|
||||
checksum = fu_common_sum16(buf, code_size - sizeof(checksum));
|
||||
if (checksum != fw_checksum) {
|
||||
g_set_error(error,
|
||||
FWUPD_ERROR,
|
||||
FWUPD_ERROR_INTERNAL,
|
||||
"checksum mismatch, got 0x%04x, expected 0x%04x",
|
||||
checksum,
|
||||
fw_checksum);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
fu_genesys_usbhub_firmware_parse(FuFirmware *firmware,
|
||||
GBytes *fw,
|
||||
guint64 addr_start,
|
||||
guint64 addr_end,
|
||||
FwupdInstallFlags flags,
|
||||
GError **error)
|
||||
{
|
||||
FuGenesysUsbhubFirmware *self = FU_GENESYS_USBHUB_FIRMWARE(firmware);
|
||||
gsize bufsz = 0;
|
||||
const guint8 *buf = g_bytes_get_data(fw, &bufsz);
|
||||
guint8 sign[4];
|
||||
guint16 code_size = 0x6000;
|
||||
guint16 version_raw = 0;
|
||||
gboolean is3590 = FALSE;
|
||||
g_autofree gchar *version = NULL;
|
||||
|
||||
/* check signature */
|
||||
if (!fu_memcpy_safe(sign,
|
||||
sizeof(sign),
|
||||
0, /* dst */
|
||||
buf,
|
||||
bufsz,
|
||||
0xfc,
|
||||
sizeof(sign),
|
||||
error))
|
||||
return FALSE;
|
||||
|
||||
if (memcmp(sign, "XROM", sizeof(sign)) != 0 && memcmp(sign, "SRON", sizeof(sign)) != 0) {
|
||||
g_set_error_literal(error,
|
||||
FWUPD_ERROR,
|
||||
FWUPD_ERROR_NOT_SUPPORTED,
|
||||
"signature not supported");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* get static tool string */
|
||||
if (!fu_memcpy_safe((guint8 *)&self->static_ts,
|
||||
sizeof(self->static_ts),
|
||||
0, /* dst */
|
||||
buf,
|
||||
bufsz,
|
||||
0x221, /* src */
|
||||
sizeof(self->static_ts),
|
||||
error))
|
||||
return FALSE;
|
||||
|
||||
/* not a GL3523, is GL3590? */
|
||||
if (memcmp(self->static_ts.mask_project_ic_type, "3523", 4) != 0) {
|
||||
if (!fu_memcpy_safe((guint8 *)&self->static_ts,
|
||||
sizeof(self->static_ts),
|
||||
0, /* dst */
|
||||
buf,
|
||||
bufsz,
|
||||
0x241, /* src */
|
||||
sizeof(self->static_ts),
|
||||
error))
|
||||
return FALSE;
|
||||
|
||||
/* not a GL3590 either */
|
||||
if (memcmp(self->static_ts.mask_project_ic_type, "3590", 4) != 0) {
|
||||
g_autofree gchar *tmp =
|
||||
fu_common_strsafe((const gchar *)&self->static_ts.mask_project_ic_type,
|
||||
sizeof(self->static_ts.mask_project_ic_type));
|
||||
g_set_error(error,
|
||||
FWUPD_ERROR,
|
||||
FWUPD_ERROR_NOT_SUPPORTED,
|
||||
"IC type %s not supported",
|
||||
tmp);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
is3590 = TRUE;
|
||||
}
|
||||
|
||||
/* unsupported static tool string */
|
||||
if (self->static_ts.tool_string_version == 0xff) {
|
||||
g_set_error_literal(error,
|
||||
FWUPD_ERROR,
|
||||
FWUPD_ERROR_NOT_SUPPORTED,
|
||||
"Static Tool String not supported");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* deduce code size */
|
||||
if (!is3590) {
|
||||
guint8 ic_type_revision;
|
||||
|
||||
code_size = 0x6000;
|
||||
ic_type_revision = 10 * (self->static_ts.mask_project_ic_type[4] - '0') +
|
||||
(self->static_ts.mask_project_ic_type[5] - '0');
|
||||
if (ic_type_revision == 50)
|
||||
code_size = 0x8000;
|
||||
} else {
|
||||
code_size = 0x6000;
|
||||
}
|
||||
|
||||
/* calculate checksum */
|
||||
if ((flags & FWUPD_INSTALL_FLAG_IGNORE_CHECKSUM) == 0)
|
||||
if (!fu_genesys_usbhub_firmware_verify(buf, bufsz, code_size, error))
|
||||
return FALSE;
|
||||
|
||||
/* get firmware version */
|
||||
if (!fu_common_read_uint16_safe(buf, bufsz, 0x10E, &version_raw, G_LITTLE_ENDIAN, error))
|
||||
return FALSE;
|
||||
fu_firmware_set_version_raw(firmware, version_raw);
|
||||
version =
|
||||
g_strdup_printf("%02x.%02x", (version_raw & 0xFF00U) >> 8, (version_raw & 0x00FFU));
|
||||
fu_firmware_set_version(firmware, version);
|
||||
|
||||
/* success */
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static GBytes *
|
||||
fu_genesys_usbhub_firmware_write(FuFirmware *firmware, GError **error)
|
||||
{
|
||||
FuGenesysUsbhubFirmware *self = FU_GENESYS_USBHUB_FIRMWARE(firmware);
|
||||
g_autoptr(GByteArray) buf = g_byte_array_new();
|
||||
guint16 code_size = 0x6000;
|
||||
guint16 checksum;
|
||||
const guint8 sign[] = {'X', 'R', 'O', 'M'};
|
||||
|
||||
/* fixed size */
|
||||
fu_byte_array_set_size(buf, code_size);
|
||||
|
||||
/* signature */
|
||||
if (!fu_memcpy_safe(buf->data,
|
||||
buf->len,
|
||||
0xfc, /* dst */
|
||||
sign,
|
||||
sizeof(sign),
|
||||
0x0, /* src */
|
||||
sizeof(sign),
|
||||
error))
|
||||
return NULL;
|
||||
|
||||
/* static tool string */
|
||||
if (!fu_memcpy_safe(buf->data,
|
||||
buf->len,
|
||||
0x221, /* dst */
|
||||
(const guint8 *)&self->static_ts,
|
||||
sizeof(self->static_ts),
|
||||
0x0, /* src */
|
||||
sizeof(self->static_ts),
|
||||
error))
|
||||
return NULL;
|
||||
|
||||
/* checksum */
|
||||
checksum = fu_common_sum16(buf->data, code_size - sizeof(checksum));
|
||||
if (!fu_common_write_uint16_safe(buf->data,
|
||||
buf->len,
|
||||
code_size - sizeof(guint16),
|
||||
checksum,
|
||||
G_BIG_ENDIAN,
|
||||
error))
|
||||
return NULL;
|
||||
|
||||
/* version */
|
||||
if (!fu_common_write_uint16_safe(buf->data,
|
||||
buf->len,
|
||||
0x10E,
|
||||
0x1234, // TODO: parse from firmware version string
|
||||
G_BIG_ENDIAN,
|
||||
error))
|
||||
return NULL;
|
||||
|
||||
/* success */
|
||||
return g_byte_array_free_to_bytes(g_steal_pointer(&buf));
|
||||
}
|
||||
|
||||
static gchar *
|
||||
fu_genesys_usbhub_firmware_get_project_ic_type_string(const gchar *tmp)
|
||||
{
|
||||
return g_strdup_printf("GL%c%c%c%c-%c%c", tmp[0], tmp[1], tmp[2], tmp[3], tmp[4], tmp[5]);
|
||||
}
|
||||
|
||||
static void
|
||||
fu_genesys_usbhub_firmware_export(FuFirmware *firmware,
|
||||
FuFirmwareExportFlags flags,
|
||||
XbBuilderNode *bn)
|
||||
{
|
||||
FuGenesysUsbhubFirmware *self = FU_GENESYS_USBHUB_FIRMWARE(firmware);
|
||||
g_autofree gchar *tool_string_version = NULL;
|
||||
g_autofree gchar *mask_project_code = NULL;
|
||||
g_autofree gchar *mask_project_hardware = NULL;
|
||||
g_autofree gchar *mask_project_firmware = NULL;
|
||||
g_autofree gchar *mask_project_ic_type = NULL;
|
||||
g_autofree gchar *running_project_code = NULL;
|
||||
g_autofree gchar *running_project_hardware = NULL;
|
||||
g_autofree gchar *running_project_firmware = NULL;
|
||||
g_autofree gchar *running_project_ic_type = NULL;
|
||||
|
||||
tool_string_version = fu_common_strsafe((const gchar *)&self->static_ts.tool_string_version,
|
||||
sizeof(self->static_ts.tool_string_version));
|
||||
fu_xmlb_builder_insert_kv(bn, "tool_string_version", tool_string_version);
|
||||
|
||||
mask_project_code = fu_common_strsafe((const gchar *)&self->static_ts.mask_project_code,
|
||||
sizeof(self->static_ts.mask_project_code));
|
||||
fu_xmlb_builder_insert_kv(bn, "mask_project_code", mask_project_code);
|
||||
|
||||
mask_project_hardware =
|
||||
fu_common_strsafe((const gchar *)&self->static_ts.mask_project_hardware,
|
||||
sizeof(self->static_ts.mask_project_hardware));
|
||||
if (mask_project_hardware != NULL)
|
||||
mask_project_hardware[0] += 0x10; /* '1' -> 'A'... */
|
||||
fu_xmlb_builder_insert_kv(bn, "mask_project_hardware", mask_project_hardware);
|
||||
|
||||
mask_project_firmware =
|
||||
fu_common_strsafe((const gchar *)&self->static_ts.mask_project_firmware,
|
||||
sizeof(self->static_ts.mask_project_firmware));
|
||||
fu_xmlb_builder_insert_kv(bn, "mask_project_firmware", mask_project_firmware);
|
||||
|
||||
mask_project_ic_type = fu_genesys_usbhub_firmware_get_project_ic_type_string(
|
||||
(const gchar *)self->static_ts.mask_project_ic_type);
|
||||
fu_xmlb_builder_insert_kv(bn, "mask_project_ic_type", mask_project_ic_type);
|
||||
|
||||
running_project_code =
|
||||
fu_common_strsafe((const gchar *)&self->static_ts.running_project_code,
|
||||
sizeof(self->static_ts.running_project_code));
|
||||
fu_xmlb_builder_insert_kv(bn, "running_project_code", running_project_code);
|
||||
|
||||
running_project_hardware =
|
||||
fu_common_strsafe((const gchar *)&self->static_ts.running_project_hardware,
|
||||
sizeof(self->static_ts.running_project_hardware));
|
||||
if (running_project_hardware != NULL)
|
||||
running_project_hardware[0] += 0x10; /* '1' -> 'A'... */
|
||||
fu_xmlb_builder_insert_kv(bn, "running_project_hardware", running_project_hardware);
|
||||
|
||||
running_project_firmware =
|
||||
fu_common_strsafe((const gchar *)&self->static_ts.running_project_firmware,
|
||||
sizeof(self->static_ts.running_project_firmware));
|
||||
fu_xmlb_builder_insert_kv(bn, "running_project_firmware", running_project_firmware);
|
||||
|
||||
running_project_ic_type = fu_genesys_usbhub_firmware_get_project_ic_type_string(
|
||||
(const gchar *)self->static_ts.running_project_ic_type);
|
||||
fu_xmlb_builder_insert_kv(bn, "running_project_ic_type", running_project_ic_type);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
fu_genesys_usbhub_firmware_build(FuFirmware *firmware, XbNode *n, GError **error)
|
||||
{
|
||||
FuGenesysUsbhubFirmware *self = FU_GENESYS_USBHUB_FIRMWARE(firmware);
|
||||
const gchar *tmp;
|
||||
guint64 tmp64;
|
||||
|
||||
/* optional properties */
|
||||
tmp64 = xb_node_query_text_as_uint(n, "tool_string_version", NULL);
|
||||
if (tmp64 != G_MAXUINT64) {
|
||||
if (tmp64 > G_MAXUINT8) {
|
||||
g_set_error_literal(error,
|
||||
G_IO_ERROR,
|
||||
G_IO_ERROR_INVALID_DATA,
|
||||
"invalid tool_string_version");
|
||||
return FALSE;
|
||||
}
|
||||
self->static_ts.tool_string_version = tmp64;
|
||||
}
|
||||
|
||||
/* mask_project_code */
|
||||
tmp = xb_node_query_text(n, "mask_project_code", NULL);
|
||||
if (tmp != NULL) {
|
||||
gsize len = strlen(tmp);
|
||||
if (len != 4) {
|
||||
g_set_error(error,
|
||||
G_IO_ERROR,
|
||||
G_IO_ERROR_INVALID_DATA,
|
||||
"invalid mask_project_code %s, got 0x%x length",
|
||||
tmp,
|
||||
(guint)len);
|
||||
return FALSE;
|
||||
}
|
||||
if (!fu_memcpy_safe((guint8 *)&self->static_ts.mask_project_code,
|
||||
sizeof(self->static_ts.mask_project_code),
|
||||
0x0, /* dst */
|
||||
(const guint8 *)tmp,
|
||||
len,
|
||||
0x0, /* src */
|
||||
len,
|
||||
error))
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* mask_project_ic_type */
|
||||
tmp = xb_node_query_text(n, "mask_project_ic_type", NULL);
|
||||
if (tmp != NULL) {
|
||||
gsize len = strlen(tmp);
|
||||
if (len != 6) {
|
||||
g_set_error(error,
|
||||
G_IO_ERROR,
|
||||
G_IO_ERROR_INVALID_DATA,
|
||||
"invalid mask_project_ic_type %s, got 0x%x length",
|
||||
tmp,
|
||||
(guint)len);
|
||||
return FALSE;
|
||||
}
|
||||
if (!fu_memcpy_safe((guint8 *)&self->static_ts.mask_project_ic_type,
|
||||
sizeof(self->static_ts.mask_project_ic_type),
|
||||
0x0, /* dst */
|
||||
(const guint8 *)tmp,
|
||||
len,
|
||||
0x0, /* src */
|
||||
len,
|
||||
error))
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* success */
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
fu_genesys_usbhub_firmware_init(FuGenesysUsbhubFirmware *self)
|
||||
{
|
||||
fu_firmware_add_flag(FU_FIRMWARE(self), FU_FIRMWARE_FLAG_HAS_CHECKSUM);
|
||||
}
|
||||
|
||||
static void
|
||||
fu_genesys_usbhub_firmware_class_init(FuGenesysUsbhubFirmwareClass *klass)
|
||||
{
|
||||
FuFirmwareClass *klass_firmware = FU_FIRMWARE_CLASS(klass);
|
||||
klass_firmware->parse = fu_genesys_usbhub_firmware_parse;
|
||||
klass_firmware->export = fu_genesys_usbhub_firmware_export;
|
||||
klass_firmware->build = fu_genesys_usbhub_firmware_build;
|
||||
klass_firmware->write = fu_genesys_usbhub_firmware_write;
|
||||
}
|
||||
|
||||
FuFirmware *
|
||||
fu_genesys_usbhub_firmware_new(void)
|
||||
{
|
||||
return FU_FIRMWARE(g_object_new(FU_TYPE_GENESYS_USBHUB_FIRMWARE, NULL));
|
||||
}
|
19
plugins/genesys/fu-genesys-usbhub-firmware.h
Normal file
19
plugins/genesys/fu-genesys-usbhub-firmware.h
Normal file
@ -0,0 +1,19 @@
|
||||
/*
|
||||
* Copyright (C) 2021 Gaël PORTAY <gael.portay@collabora.com>
|
||||
*
|
||||
* SPDX-License-Identifier: LGPL-2.1+
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <fwupdplugin.h>
|
||||
|
||||
#define FU_TYPE_GENESYS_USBHUB_FIRMWARE (fu_genesys_usbhub_firmware_get_type())
|
||||
G_DECLARE_FINAL_TYPE(FuGenesysUsbhubFirmware,
|
||||
fu_genesys_usbhub_firmware,
|
||||
FU,
|
||||
GENESYS_USBHUB_FIRMWARE,
|
||||
FuFirmware)
|
||||
|
||||
FuFirmware *
|
||||
fu_genesys_usbhub_firmware_new(void);
|
32
plugins/genesys/fu-plugin-genesys.c
Normal file
32
plugins/genesys/fu-plugin-genesys.c
Normal file
@ -0,0 +1,32 @@
|
||||
/*
|
||||
* Copyright (C) 2021 Ricardo Cañuelo <ricardo.canuelo@collabora.com>
|
||||
*
|
||||
* SPDX-License-Identifier: LGPL-2.1+
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <fwupdplugin.h>
|
||||
|
||||
#include "fu-genesys-scaler-firmware.h"
|
||||
#include "fu-genesys-usbhub-device.h"
|
||||
#include "fu-genesys-usbhub-firmware.h"
|
||||
|
||||
static void
|
||||
fu_plugin_genesys_init(FuPlugin *plugin)
|
||||
{
|
||||
FuContext *ctx = fu_plugin_get_context(plugin);
|
||||
fu_context_add_quirk_key(ctx, "GenesysScalerGpioOutputRegister");
|
||||
fu_context_add_quirk_key(ctx, "GenesysScalerGpioEnableRegister");
|
||||
fu_context_add_quirk_key(ctx, "GenesysScalerGpioValue");
|
||||
fu_plugin_add_device_gtype(plugin, FU_TYPE_GENESYS_USBHUB_DEVICE);
|
||||
fu_plugin_add_firmware_gtype(plugin, NULL, FU_TYPE_GENESYS_USBHUB_FIRMWARE);
|
||||
fu_plugin_add_firmware_gtype(plugin, NULL, FU_TYPE_GENESYS_SCALER_FIRMWARE);
|
||||
}
|
||||
|
||||
void
|
||||
fu_plugin_init_vfuncs(FuPluginVfuncs *vfuncs)
|
||||
{
|
||||
vfuncs->build_hash = FU_BUILD_HASH;
|
||||
vfuncs->init = fu_plugin_genesys_init;
|
||||
}
|
25
plugins/genesys/genesys.quirk
Normal file
25
plugins/genesys/genesys.quirk
Normal file
@ -0,0 +1,25 @@
|
||||
# M2xfd
|
||||
|
||||
# usbhub
|
||||
[USB\VID_03F0&PID_0610]
|
||||
Plugin = genesys
|
||||
Name = HP USB-C Controller
|
||||
Flags = has-mstar-scaler
|
||||
GenesysUsbhubSwitchRequest = 0xA1
|
||||
GenesysUsbhubReadRequest = 0xA2
|
||||
GenesysUsbhubWriteRequest = 0xA3
|
||||
|
||||
# scaler
|
||||
[GENESYS_SCALER\MSTAR_TSUM_G&PUBKEY_B335BDCE-7073-5D0E-9BD3-9B69C1A6899F]
|
||||
Name = HP M24fd USB-C Monitor
|
||||
Flags = use-i2c-ch0
|
||||
GenesysScalerGpioOutputRegister = 0x0426
|
||||
GenesysScalerGpioEnableRegister = 0x0428
|
||||
GenesysScalerGpioValue = 0x01
|
||||
|
||||
[GENESYS_SCALER\MSTAR_TSUM_G&PUBKEY_847A3650-8648-586B-83C8-8B53714F37E3]
|
||||
Name = HP M27fd USB-C Monitor
|
||||
Flags = use-i2c-ch0
|
||||
GenesysScalerGpioOutputRegister = 0x0426
|
||||
GenesysScalerGpioEnableRegister = 0x0428
|
||||
GenesysScalerGpioValue = 0x01
|
35
plugins/genesys/meson.build
Normal file
35
plugins/genesys/meson.build
Normal file
@ -0,0 +1,35 @@
|
||||
if get_option('gusb')
|
||||
cargs = ['-DG_LOG_DOMAIN="FuPluginGenesys"']
|
||||
|
||||
install_data([
|
||||
'genesys.quirk',
|
||||
],
|
||||
install_dir: join_paths(datadir, 'fwupd', 'quirks.d')
|
||||
)
|
||||
|
||||
shared_module('fu_plugin_genesys',
|
||||
fu_hash,
|
||||
sources : [
|
||||
'fu-genesys-scaler-firmware.c', # fuzzing
|
||||
'fu-genesys-usbhub-firmware.c', # fuzzing
|
||||
'fu-genesys-scaler-device.c',
|
||||
'fu-genesys-usbhub-device.c',
|
||||
'fu-plugin-genesys.c',
|
||||
],
|
||||
include_directories : [
|
||||
root_incdir,
|
||||
fwupd_incdir,
|
||||
fwupdplugin_incdir,
|
||||
],
|
||||
install : true,
|
||||
install_dir: plugin_dir,
|
||||
link_with : [
|
||||
fwupd,
|
||||
fwupdplugin,
|
||||
],
|
||||
c_args : cargs,
|
||||
dependencies : [
|
||||
plugin_deps,
|
||||
],
|
||||
)
|
||||
endif
|
1
plugins/genesys/tests/genesys-scaler.bin
Normal file
1
plugins/genesys/tests/genesys-scaler.bin
Normal file
@ -0,0 +1 @@
|
||||
hello worldmstarmstarmstarmstarmstarmstarmstarmstarmstarmstarmstarmstarmstarmstarmstarmstarmstarmstarmstarmstarmstarmstarmstarmstarmstarmstarmstarmstarmstarmstarmstarmstarmstarmstarmstarmstarmstarmstarmstarmstarmstarmstarmstarmstarmstarmstarmstarmstarmstarmstarmstarmstarmstarmstarmstarmstarmstarmstarmstarmstarmstarmstarmstarmstarmstarmstarmstarmstarmstarmstarmstarmstarmstarmstarmstarmstarmstarmstarmstarmstarmstarmstarmstarmstarmstarmstarmstarmstarmstarmstarmstarmstarmstarmstarmstarmstarmstarmstarmstarmstarmstarmstarmstarmstarmstarmstar '?> >2+)7,713rm2tarmstarmstarmstarmstarmstarmstarmstarmstarmstarmstarmstarmstarmstarmstarmstarmstarmstarmstarmstarmstarmstarmstarmstarmstarmstarmstarmstarmstarmstarmstarmstarmstarmstarmstarmstarmstarmstarmstarmstarmstarmstarmstarmstarmstarmstarmstarmstarm
|
4
plugins/genesys/tests/genesys-scaler.builder.xml
Normal file
4
plugins/genesys/tests/genesys-scaler.builder.xml
Normal file
@ -0,0 +1,4 @@
|
||||
<firmware gtype="FuGenesysScalerFirmware">
|
||||
<data>aGVsbG8gd29ybGQ=</data> <!-- base64 -->
|
||||
<model_name>A</model_name>
|
||||
</firmware>
|
BIN
plugins/genesys/tests/genesys-usbhub.bin
Normal file
BIN
plugins/genesys/tests/genesys-usbhub.bin
Normal file
Binary file not shown.
5
plugins/genesys/tests/genesys-usbhub.builder.xml
Normal file
5
plugins/genesys/tests/genesys-usbhub.builder.xml
Normal file
@ -0,0 +1,5 @@
|
||||
<firmware gtype="FuGenesysUsbhubFirmware">
|
||||
<data>aGVsbG8gd29ybGQ=</data> <!-- base64 -->
|
||||
<tool_string_version>1</tool_string_version>
|
||||
<mask_project_ic_type>352310</mask_project_ic_type>
|
||||
</firmware>
|
@ -24,6 +24,7 @@ subdir('ep963x')
|
||||
subdir('fastboot')
|
||||
subdir('flashrom')
|
||||
subdir('fresco-pd')
|
||||
subdir('genesys')
|
||||
subdir('goodix-moc')
|
||||
subdir('gpio')
|
||||
subdir('hailuck')
|
||||
|
Loading…
Reference in New Issue
Block a user