fwupd/plugins/test/fu-plugin-test.c
Richard Hughes af14073522 Allow applying all releases to get to a target version
Some hardware does not handle upgrading from version 1.2.2 to 1.2.4 and instead
needs to be upgraded from 1.2.2->1.2.3->1.2.4 so that on-device metadata can be
migrated correctly.

Add a new per-device flag `install-all-releases` which causes the daemon to not
skip directly to the newest release. This is designed to be set from a quirk
file.

This can obviously only be used for devices that can apply firmware "live" and
thus do not need a reboot or system shutdown to actually apply the firmware.
This also needs the cabinet archive to ship multiple versions of the firmware,
and for the metainfo.xml file to refer to multiple release objects.
2020-01-07 15:33:12 +00:00

255 lines
7.7 KiB
C

/*
* Copyright (C) 2016 Richard Hughes <richard@hughsie.com>
*
* SPDX-License-Identifier: LGPL-2.1+
*/
#include "config.h"
#include "fu-plugin-vfuncs.h"
#include "fu-hash.h"
struct FuPluginData {
GMutex mutex;
};
void
fu_plugin_init (FuPlugin *plugin)
{
fu_plugin_set_build_hash (plugin, FU_BUILD_HASH);
fu_plugin_alloc_data (plugin, sizeof (FuPluginData));
g_debug ("init");
}
void
fu_plugin_destroy (FuPlugin *plugin)
{
//FuPluginData *data = fu_plugin_get_data (plugin);
g_debug ("destroy");
}
gboolean
fu_plugin_coldplug (FuPlugin *plugin, GError **error)
{
g_autoptr(FuDevice) device = NULL;
device = fu_device_new ();
fu_device_set_id (device, "FakeDevice");
fu_device_add_guid (device, "b585990a-003e-5270-89d5-3705a17f9a43");
fu_device_set_name (device, "Integrated_Webcam(TM)");
fu_device_add_icon (device, "preferences-desktop-keyboard");
fu_device_add_flag (device, FWUPD_DEVICE_FLAG_UPDATABLE);
fu_device_add_flag (device, FWUPD_DEVICE_FLAG_CAN_VERIFY);
fu_device_set_protocol (device, "com.acme.test");
fu_device_set_summary (device, "A fake webcam");
fu_device_set_vendor (device, "ACME Corp.");
fu_device_set_vendor_id (device, "USB:0x046D");
fu_device_set_version_bootloader (device, "0.1.2");
fu_device_set_version (device, "1.2.2", FWUPD_VERSION_FORMAT_TRIPLET);
fu_device_set_version_lowest (device, "1.2.0");
if (g_strcmp0 (g_getenv ("FWUPD_PLUGIN_TEST"), "registration") == 0) {
fu_plugin_device_register (plugin, device);
if (fu_device_get_metadata (device, "BestDevice") == NULL) {
g_set_error (error,
FWUPD_ERROR,
FWUPD_ERROR_NOT_FOUND,
"Device not set by another plugin");
return FALSE;
}
}
fu_plugin_device_add (plugin, device);
if (g_strcmp0 (g_getenv ("FWUPD_PLUGIN_TEST"), "composite") == 0) {
g_autoptr(FuDevice) child1 = NULL;
g_autoptr(FuDevice) child2 = NULL;
child1 = fu_device_new ();
fu_device_set_vendor_id (child1, "USB:FFFF");
fu_device_set_protocol (child1, "com.acme");
fu_device_set_physical_id (child1, "fake");
fu_device_set_logical_id (child1, "child1");
fu_device_add_guid (child1, "7fddead7-12b5-4fb9-9fa0-6d30305df755");
fu_device_set_name (child1, "Module1");
fu_device_set_version (child1, "1", FWUPD_VERSION_FORMAT_PLAIN);
fu_device_add_parent_guid (child1, "b585990a-003e-5270-89d5-3705a17f9a43");
fu_device_add_flag (child1, FWUPD_DEVICE_FLAG_UPDATABLE);
fu_plugin_device_add (plugin, child1);
child2 = fu_device_new ();
fu_device_set_vendor_id (child2, "USB:FFFF");
fu_device_set_protocol (child2, "com.acme");
fu_device_set_physical_id (child2, "fake");
fu_device_set_logical_id (child2, "child2");
fu_device_add_guid (child2, "b8fe6b45-8702-4bcd-8120-ef236caac76f");
fu_device_set_name (child2, "Module2");
fu_device_set_version (child2, "10", FWUPD_VERSION_FORMAT_PLAIN);
fu_device_add_parent_guid (child2, "b585990a-003e-5270-89d5-3705a17f9a43");
fu_device_add_flag (child2, FWUPD_DEVICE_FLAG_UPDATABLE);
fu_plugin_device_add (plugin, child2);
}
return TRUE;
}
void
fu_plugin_device_registered (FuPlugin *plugin, FuDevice *device)
{
fu_device_set_metadata (device, "BestDevice", "/dev/urandom");
}
gboolean
fu_plugin_verify (FuPlugin *plugin,
FuDevice *device,
FuPluginVerifyFlags flags,
GError **error)
{
if (g_strcmp0 (fu_device_get_version (device), "1.2.2") == 0) {
fu_device_add_checksum (device, "90d0ad436d21e0687998cd2127b2411135e1f730");
fu_device_add_checksum (device, "921631916a60b295605dbae6a0309f9b64e2401b3de8e8506e109fc82c586e3a");
return TRUE;
}
if (g_strcmp0 (fu_device_get_version (device), "1.2.3") == 0) {
fu_device_add_checksum (device, "7998cd212721e068b2411135e1f90d0ad436d730");
fu_device_add_checksum (device, "dbae6a0309b3de8e850921631916a60b2956056e109fc82c586e3f9b64e2401a");
return TRUE;
}
if (g_strcmp0 (fu_device_get_version (device), "1.2.4") == 0) {
fu_device_add_checksum (device, "2b8546ba805ad10bf8a2e5ad539d53f303812ba5");
fu_device_add_checksum (device, "b546c241029ce4e16c99eb6bfd77b86e4490aa3826ba71b8a4114e96a2d69bcd");
return TRUE;
}
g_set_error (error,
FWUPD_ERROR,
FWUPD_ERROR_NOT_SUPPORTED,
"no checksum for %s", fu_device_get_version (device));
return FALSE;
}
static gchar *
fu_plugin_test_get_version (GBytes *blob_fw)
{
const gchar *str = g_bytes_get_data (blob_fw, NULL);
guint64 val = 0;
if (str == NULL)
return NULL;
val = fu_common_strtoull (str);
if (val == 0x0)
return NULL;
return fu_common_version_from_uint32 (val, FWUPD_VERSION_FORMAT_TRIPLET);
}
gboolean
fu_plugin_update (FuPlugin *plugin,
FuDevice *device,
GBytes *blob_fw,
FwupdInstallFlags flags,
GError **error)
{
const gchar *test = g_getenv ("FWUPD_PLUGIN_TEST");
gboolean requires_activation = g_strcmp0 (test, "requires-activation") == 0;
if (g_strcmp0 (test, "fail") == 0) {
g_set_error_literal (error,
FWUPD_ERROR,
FWUPD_ERROR_NOT_SUPPORTED,
"device was not in supported mode");
return FALSE;
}
fu_device_set_status (device, FWUPD_STATUS_DECOMPRESSING);
for (guint i = 1; i <= 100; i++) {
g_usleep (1000);
fu_device_set_progress (device, i);
}
fu_device_set_status (device, FWUPD_STATUS_DEVICE_WRITE);
for (guint i = 1; i <= 100; i++) {
g_usleep (1000);
fu_device_set_progress (device, i);
}
fu_device_set_status (device, FWUPD_STATUS_DEVICE_VERIFY);
for (guint i = 1; i <= 100; i++) {
g_usleep (1000);
fu_device_set_progress (device, i);
}
/* composite test, upgrade composite devices */
if (g_strcmp0 (test, "composite") == 0) {
if (g_strcmp0 (fu_device_get_logical_id (device), "child1") == 0) {
fu_device_set_version (device, "2", FWUPD_VERSION_FORMAT_PLAIN);
return TRUE;
} else if (g_strcmp0 (fu_device_get_logical_id (device), "child2") == 0) {
fu_device_set_version (device, "11", FWUPD_VERSION_FORMAT_PLAIN);
return TRUE;
}
}
/* upgrade, or downgrade */
if (requires_activation) {
fu_device_add_flag (device, FWUPD_DEVICE_FLAG_NEEDS_ACTIVATION);
} else {
g_autofree gchar *ver = fu_plugin_test_get_version (blob_fw);
if (ver != NULL) {
fu_device_set_version (device, ver, FWUPD_VERSION_FORMAT_TRIPLET);
} else {
if (flags & FWUPD_INSTALL_FLAG_ALLOW_OLDER) {
fu_device_set_version (device, "1.2.2", FWUPD_VERSION_FORMAT_TRIPLET);
} else {
fu_device_set_version (device, "1.2.3", FWUPD_VERSION_FORMAT_TRIPLET);
}
}
}
/* do this all over again */
if (g_strcmp0 (test, "another-write-required") == 0) {
g_unsetenv ("FWUPD_PLUGIN_TEST");
fu_device_add_flag (device, FWUPD_DEVICE_FLAG_ANOTHER_WRITE_REQUIRED);
}
/* for the self tests only */
fu_device_set_metadata_integer (device, "nr-update",
fu_device_get_metadata_integer (device, "nr-update") + 1);
return TRUE;
}
gboolean
fu_plugin_activate (FuPlugin *plugin, FuDevice *device, GError **error)
{
fu_device_set_version (device, "1.2.3", FWUPD_VERSION_FORMAT_TRIPLET);
return TRUE;
}
gboolean
fu_plugin_get_results (FuPlugin *plugin, FuDevice *device, GError **error)
{
fu_device_set_update_state (device, FWUPD_UPDATE_STATE_SUCCESS);
fu_device_set_update_error (device, NULL);
return TRUE;
}
gboolean
fu_plugin_composite_prepare (FuPlugin *plugin,
GPtrArray *devices,
GError **error)
{
if (g_strcmp0 (g_getenv ("FWUPD_PLUGIN_TEST"), "composite") == 0) {
for (guint i = 0; i < devices->len; i++) {
FuDevice *device = g_ptr_array_index (devices, i);
fu_device_set_metadata (device, "frimbulator", "1");
}
}
return TRUE;
}
gboolean
fu_plugin_composite_cleanup (FuPlugin *plugin,
GPtrArray *devices,
GError **error)
{
if (g_strcmp0 (g_getenv ("FWUPD_PLUGIN_TEST"), "composite") == 0) {
for (guint i = 0; i < devices->len; i++) {
FuDevice *device = g_ptr_array_index (devices, i);
fu_device_set_metadata (device, "frombulator", "1");
}
}
return TRUE;
}