mirror of
https://git.proxmox.com/git/fwupd
synced 2025-11-02 16:06:17 +00:00
Add a GetReleases() D-Bus call to return all releases for a device
This allows us to downgrade firmware in the future.
This commit is contained in:
parent
fdce4f57a3
commit
e4a100cfee
@ -239,6 +239,28 @@ fwupd_client_parse_results_from_data (GVariant *devices)
|
||||
return results;
|
||||
}
|
||||
|
||||
static GPtrArray *
|
||||
fwupd_client_parse_releases_from_variant (GVariant *val)
|
||||
{
|
||||
FwupdRelease *release;
|
||||
GPtrArray *releases = NULL;
|
||||
gsize sz;
|
||||
guint i;
|
||||
g_autoptr(GVariant) untuple = NULL;
|
||||
|
||||
releases = g_ptr_array_new_with_free_func ((GDestroyNotify) g_object_unref);
|
||||
untuple = g_variant_get_child_value (val, 0);
|
||||
sz = g_variant_n_children (untuple);
|
||||
for (i = 0; i < sz; i++) {
|
||||
g_autoptr(GVariant) data = NULL;
|
||||
data = g_variant_get_child_value (untuple, i);
|
||||
release = fwupd_release_new_from_data (data);
|
||||
g_ptr_array_add (releases, release);
|
||||
}
|
||||
|
||||
return releases;
|
||||
}
|
||||
|
||||
static void
|
||||
fwupd_client_fixup_dbus_error (GError *error)
|
||||
{
|
||||
@ -351,6 +373,51 @@ fwupd_client_get_updates (FwupdClient *client, GCancellable *cancellable, GError
|
||||
return fwupd_client_parse_results_from_data (val);
|
||||
}
|
||||
|
||||
/**
|
||||
* fwupd_client_get_releases:
|
||||
* @client: A #FwupdClient
|
||||
* @device_id: the device ID
|
||||
* @cancellable: the #GCancellable, or %NULL
|
||||
* @error: the #GError, or %NULL
|
||||
*
|
||||
* Gets all the releases for a specific device
|
||||
*
|
||||
* Returns: (element-type FwupdRelease) (transfer container): results
|
||||
*
|
||||
* Since: 0.9.3
|
||||
**/
|
||||
GPtrArray *
|
||||
fwupd_client_get_releases (FwupdClient *client, const gchar *device_id,
|
||||
GCancellable *cancellable, GError **error)
|
||||
{
|
||||
FwupdClientPrivate *priv = GET_PRIVATE (client);
|
||||
g_autoptr(GVariant) val = NULL;
|
||||
|
||||
g_return_val_if_fail (FWUPD_IS_CLIENT (client), NULL);
|
||||
g_return_val_if_fail (device_id != NULL, NULL);
|
||||
g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), NULL);
|
||||
g_return_val_if_fail (error == NULL || *error == NULL, NULL);
|
||||
|
||||
/* connect */
|
||||
if (!fwupd_client_connect (client, cancellable, error))
|
||||
return NULL;
|
||||
|
||||
/* call into daemon */
|
||||
val = g_dbus_proxy_call_sync (priv->proxy,
|
||||
"GetReleases",
|
||||
g_variant_new ("(s)", device_id),
|
||||
G_DBUS_CALL_FLAGS_NONE,
|
||||
-1,
|
||||
cancellable,
|
||||
error);
|
||||
if (val == NULL) {
|
||||
if (error != NULL)
|
||||
fwupd_client_fixup_dbus_error (*error);
|
||||
return NULL;
|
||||
}
|
||||
return fwupd_client_parse_releases_from_variant (val);
|
||||
}
|
||||
|
||||
static void
|
||||
fwupd_client_proxy_call_cb (GObject *source, GAsyncResult *res, gpointer user_data)
|
||||
{
|
||||
|
||||
@ -63,6 +63,10 @@ GPtrArray *fwupd_client_get_devices (FwupdClient *client,
|
||||
GPtrArray *fwupd_client_get_updates (FwupdClient *client,
|
||||
GCancellable *cancellable,
|
||||
GError **error);
|
||||
GPtrArray *fwupd_client_get_releases (FwupdClient *client,
|
||||
const gchar *device_id,
|
||||
GCancellable *cancellable,
|
||||
GError **error);
|
||||
GPtrArray *fwupd_client_get_details_local (FwupdClient *client,
|
||||
const gchar *filename,
|
||||
GCancellable *cancellable,
|
||||
|
||||
@ -1585,6 +1585,54 @@ fu_main_get_updates (FuMainPrivate *priv, GError **error)
|
||||
return updates;
|
||||
}
|
||||
|
||||
/* find releases for a device */
|
||||
static GVariant *
|
||||
fu_main_get_releases_to_variant (FuMainPrivate *priv, FuDeviceItem *item, GError **error)
|
||||
{
|
||||
GPtrArray *device_guids;
|
||||
GVariantBuilder builder;
|
||||
g_autoptr(GPtrArray) results = NULL;
|
||||
|
||||
/* get all the results for the device */
|
||||
results = g_ptr_array_new_with_free_func ((GDestroyNotify) g_object_unref);
|
||||
device_guids = fu_device_get_guids (item->device);
|
||||
for (guint i = 0; i < device_guids->len; i++) {
|
||||
GPtrArray *releases;
|
||||
const gchar *guid = g_ptr_array_index (device_guids, i);
|
||||
AsApp *app = as_store_get_app_by_provide (priv->store,
|
||||
AS_PROVIDE_KIND_FIRMWARE_FLASHED,
|
||||
guid);
|
||||
if (app == NULL)
|
||||
continue;
|
||||
releases = as_app_get_releases (app);
|
||||
for (guint j = 0; j < releases->len; j++) {
|
||||
AsRelease *release = g_ptr_array_index (releases, j);
|
||||
FwupdRelease *rel = fwupd_release_new ();
|
||||
fu_main_set_release_from_item (rel, release);
|
||||
g_ptr_array_add (results, rel);
|
||||
}
|
||||
}
|
||||
|
||||
/* no devices */
|
||||
if (results->len == 0) {
|
||||
g_set_error_literal (error,
|
||||
FWUPD_ERROR,
|
||||
FWUPD_ERROR_NOTHING_TO_DO,
|
||||
"No releases for device");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* convert the objects to a variant */
|
||||
g_variant_builder_init (&builder, G_VARIANT_TYPE_ARRAY);
|
||||
for (guint i = 0; i < results->len; i++) {
|
||||
GVariant *tmp;
|
||||
FwupdRelease *rel = g_ptr_array_index (results, i);
|
||||
tmp = fwupd_release_to_data (rel, "a{sv}"); //FIXME?
|
||||
g_variant_builder_add_value (&builder, tmp);
|
||||
}
|
||||
return g_variant_new ("(aa{sv})", &builder);
|
||||
}
|
||||
|
||||
static AsStore *
|
||||
fu_main_get_store_from_fd (FuMainPrivate *priv, gint fd, GError **error)
|
||||
{
|
||||
@ -1840,6 +1888,40 @@ fu_main_daemon_method_call (GDBusConnection *connection, const gchar *sender,
|
||||
return;
|
||||
}
|
||||
|
||||
/* return variant */
|
||||
if (g_strcmp0 (method_name, "GetReleases") == 0) {
|
||||
FuDeviceItem *item;
|
||||
const gchar *device_id = NULL;
|
||||
g_autoptr(GPtrArray) releases = NULL;
|
||||
|
||||
g_variant_get (parameters, "(&s)", &device_id);
|
||||
g_debug ("Called %s(%s)", method_name, device_id);
|
||||
|
||||
/* find the device */
|
||||
item = fu_main_get_item_by_id (priv, device_id);
|
||||
if (item == NULL) {
|
||||
g_set_error (&error,
|
||||
FWUPD_ERROR,
|
||||
FWUPD_ERROR_INTERNAL,
|
||||
"no device with ID %s",
|
||||
device_id);
|
||||
fu_main_invocation_return_error (priv, invocation, error);
|
||||
return;
|
||||
}
|
||||
val = fu_main_get_releases_to_variant (priv, item, &error);
|
||||
if (val == NULL) {
|
||||
if (g_error_matches (error,
|
||||
FWUPD_ERROR,
|
||||
FWUPD_ERROR_NOTHING_TO_DO)) {
|
||||
g_prefix_error (&error, "No releases found: ");
|
||||
}
|
||||
fu_main_invocation_return_error (priv, invocation, error);
|
||||
return;
|
||||
}
|
||||
fu_main_invocation_return_value (priv, invocation, val);
|
||||
return;
|
||||
}
|
||||
|
||||
/* return '' */
|
||||
if (g_strcmp0 (method_name, "ClearResults") == 0) {
|
||||
FuDeviceItem *item = NULL;
|
||||
|
||||
123
src/fu-util.c
123
src/fu-util.c
@ -268,6 +268,27 @@ fu_util_client_notify_cb (GObject *object,
|
||||
fu_util_display_panel (priv);
|
||||
}
|
||||
|
||||
static void
|
||||
fu_util_print_data (const gchar *title, const gchar *msg)
|
||||
{
|
||||
gsize title_len;
|
||||
g_auto(GStrv) lines = NULL;
|
||||
|
||||
if (msg == NULL)
|
||||
return;
|
||||
g_print ("%s:", title);
|
||||
|
||||
/* pad */
|
||||
title_len = strlen (title) + 1;
|
||||
lines = g_strsplit (msg, "\n", -1);
|
||||
for (guint j = 0; lines[j] != NULL; j++) {
|
||||
for (gsize i = title_len; i < 25; i++)
|
||||
g_print (" ");
|
||||
g_print ("%s\n", lines[j]);
|
||||
title_len = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
fu_util_get_devices (FuUtilPrivate *priv, gchar **values, GError **error)
|
||||
{
|
||||
@ -806,6 +827,67 @@ fu_util_get_results (FuUtilPrivate *priv, gchar **values, GError **error)
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static const gchar *
|
||||
_g_checksum_type_to_string (GChecksumType checksum_type)
|
||||
{
|
||||
if (checksum_type == G_CHECKSUM_MD5)
|
||||
return "md5";
|
||||
if (checksum_type == G_CHECKSUM_SHA1)
|
||||
return "sha1";
|
||||
if (checksum_type == G_CHECKSUM_SHA256)
|
||||
return "sha256";
|
||||
if (checksum_type == G_CHECKSUM_SHA512)
|
||||
return "sha512";
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
fu_util_get_releases (FuUtilPrivate *priv, gchar **values, GError **error)
|
||||
{
|
||||
g_autoptr(GPtrArray) rels = NULL;
|
||||
if (g_strv_length (values) != 1) {
|
||||
g_set_error_literal (error,
|
||||
FWUPD_ERROR,
|
||||
FWUPD_ERROR_INVALID_ARGS,
|
||||
"Invalid arguments: expected 'DeviceID'");
|
||||
return FALSE;
|
||||
}
|
||||
rels = fwupd_client_get_releases (priv->client, values[0], NULL, error);
|
||||
if (rels == NULL)
|
||||
return FALSE;
|
||||
for (guint i = 0; i < rels->len; i++) {
|
||||
FwupdRelease *rel = g_ptr_array_index (rels, i);
|
||||
const gchar *tmp = fwupd_release_get_description (rel);
|
||||
|
||||
/* TRANSLATORS: section header for release version number */
|
||||
fu_util_print_data (_("Version"), fwupd_release_get_version (rel));
|
||||
|
||||
/* TRANSLATORS: section header for firmware URI */
|
||||
fu_util_print_data (_("URI"), fwupd_release_get_uri (rel));
|
||||
tmp = fwupd_release_get_description (rel);
|
||||
if (tmp != NULL) {
|
||||
g_autofree gchar *desc = NULL;
|
||||
desc = as_markup_convert_simple (tmp, NULL);
|
||||
/* TRANSLATORS: section header for firmware description */
|
||||
fu_util_print_data (_("Description"), desc);
|
||||
}
|
||||
|
||||
/* TRANSLATORS: section header for firmware checksum */
|
||||
fu_util_print_data (_("Checksum"), fwupd_release_get_checksum (rel));
|
||||
if (fwupd_release_get_checksum (rel) != NULL) {
|
||||
GChecksumType checksum_type = fwupd_release_get_checksum_kind (rel);
|
||||
tmp = _g_checksum_type_to_string (checksum_type);
|
||||
/* TRANSLATORS: section header for firmware checksum type */
|
||||
fu_util_print_data (_("Checksum Type"), tmp);
|
||||
}
|
||||
|
||||
/* new line between all but last entries */
|
||||
if (i != rels->len - 1)
|
||||
g_print ("\n");
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
fu_util_verify_all (FuUtilPrivate *priv, GError **error)
|
||||
{
|
||||
@ -865,41 +947,6 @@ fu_util_unlock (FuUtilPrivate *priv, gchar **values, GError **error)
|
||||
return fwupd_client_unlock (priv->client, values[0], NULL, error);
|
||||
}
|
||||
|
||||
static void
|
||||
fu_util_print_data (const gchar *title, const gchar *msg)
|
||||
{
|
||||
gsize title_len;
|
||||
g_auto(GStrv) lines = NULL;
|
||||
|
||||
if (msg == NULL)
|
||||
return;
|
||||
g_print ("%s:", title);
|
||||
|
||||
/* pad */
|
||||
title_len = strlen (title) + 1;
|
||||
lines = g_strsplit (msg, "\n", -1);
|
||||
for (guint j = 0; lines[j] != NULL; j++) {
|
||||
for (gsize i = title_len; i < 25; i++)
|
||||
g_print (" ");
|
||||
g_print ("%s\n", lines[j]);
|
||||
title_len = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static const gchar *
|
||||
_g_checksum_type_to_string (GChecksumType checksum_type)
|
||||
{
|
||||
if (checksum_type == G_CHECKSUM_MD5)
|
||||
return "md5";
|
||||
if (checksum_type == G_CHECKSUM_SHA1)
|
||||
return "sha1";
|
||||
if (checksum_type == G_CHECKSUM_SHA256)
|
||||
return "sha256";
|
||||
if (checksum_type == G_CHECKSUM_SHA512)
|
||||
return "sha512";
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
fu_util_get_updates (FuUtilPrivate *priv, gchar **values, GError **error)
|
||||
{
|
||||
@ -1308,6 +1355,12 @@ main (int argc, char *argv[])
|
||||
/* TRANSLATORS: command description */
|
||||
_("Gets the results from the last update"),
|
||||
fu_util_get_results);
|
||||
fu_util_add (priv->cmd_array,
|
||||
"get-releases",
|
||||
NULL,
|
||||
/* TRANSLATORS: command description */
|
||||
_("Gets the releases for a device"),
|
||||
fu_util_get_releases);
|
||||
fu_util_add (priv->cmd_array,
|
||||
"refresh",
|
||||
NULL,
|
||||
|
||||
@ -80,6 +80,36 @@
|
||||
</arg>
|
||||
</method>
|
||||
|
||||
<!--***********************************************************-->
|
||||
<method name='GetReleases'>
|
||||
<doc:doc>
|
||||
<doc:description>
|
||||
<doc:para>
|
||||
Gets a list of all the releases for a specific device.
|
||||
</doc:para>
|
||||
</doc:description>
|
||||
</doc:doc>
|
||||
<arg type='s' name='device_id' direction='in'>
|
||||
<doc:doc>
|
||||
<doc:summary>
|
||||
<doc:para>
|
||||
A device ID.
|
||||
</doc:para>
|
||||
</doc:summary>
|
||||
</doc:doc>
|
||||
</arg>
|
||||
<arg type='aa{sv}' name='releases' direction='out'>
|
||||
<doc:doc>
|
||||
<doc:summary>
|
||||
<doc:para>
|
||||
An array of releases (with the release number as the key),
|
||||
with any properties set on each.
|
||||
</doc:para>
|
||||
</doc:summary>
|
||||
</doc:doc>
|
||||
</arg>
|
||||
</method>
|
||||
|
||||
<!--***********************************************************-->
|
||||
<method name='GetDetails'>
|
||||
<doc:doc>
|
||||
|
||||
Loading…
Reference in New Issue
Block a user