fwupd/plugins/uefi/fu-uefi-udisks.c
Mario Limonciello 44b9e46d37 uefi: rework ESP path detection and lifecycle
This makes the daemon less destructive at startup, especially if the ESP
is not mounted.

It's stored in 3 different places right now, so move it into one point of truth.

Now the ESP is detected when needed including all point of time safety checks and
dynamically mounted and unmounted if necessary.
2019-10-24 15:22:01 -05:00

191 lines
5.0 KiB
C

/*
* Copyright (C) 2019 Mario Limonciello <mario.limonciello@dell.com>
*
* SPDX-License-Identifier: LGPL-2.1+
*/
#include "config.h"
#include <gio/gio.h>
#include "fu-uefi-udisks.h"
#include "fwupd-common.h"
#include "fwupd-error.h"
#define UDISKS_DBUS_SERVICE "org.freedesktop.UDisks2"
#define UDISKS_DBUS_PATH "/org/freedesktop/UDisks2/Manager"
#define UDISKS_DBUS_MANAGER_INTERFACE "org.freedesktop.UDisks2.Manager"
#define UDISKS_DBUS_PART_INTERFACE "org.freedesktop.UDisks2.Partition"
#define UDISKS_DBUS_FILE_INTERFACE "org.freedesktop.UDisks2.Filesystem"
#define ESP_DISK_TYPE "c12a7328-f81f-11d2-ba4b-00a0c93ec93b"
gboolean
fu_uefi_udisks_objpath (const gchar *path)
{
return g_str_has_prefix (path, "/org/freedesktop/UDisks2/");
}
static GDBusProxy *
fu_uefi_udisks_get_dbus_proxy (const gchar *path, const gchar *interface,
GError **error)
{
g_autoptr(GDBusConnection) connection = NULL;
g_autoptr(GDBusProxy) proxy = NULL;
connection = g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, error);
if (connection == NULL) {
g_prefix_error (error, "failed to get bus: ");
return NULL;
}
proxy = g_dbus_proxy_new_sync (connection,
G_DBUS_PROXY_FLAGS_NONE, NULL,
UDISKS_DBUS_SERVICE,
path,
interface,
NULL, error);
if (proxy == NULL) {
g_prefix_error (error, "failed to find %s: ", UDISKS_DBUS_SERVICE);
return NULL;
}
return g_steal_pointer (&proxy);
}
GPtrArray *
fu_uefi_udisks_get_block_devices (GError **error)
{
g_autoptr(GVariant) output = NULL;
g_autoptr(GDBusProxy) proxy = NULL;
g_autoptr(GPtrArray) devices = NULL;
g_autoptr(GVariantIter) iter = NULL;
GVariant *input;
GVariantBuilder builder;
const gchar *obj;
proxy = fu_uefi_udisks_get_dbus_proxy (UDISKS_DBUS_PATH,
UDISKS_DBUS_MANAGER_INTERFACE,
error);
if (proxy == NULL)
return NULL;
g_variant_builder_init (&builder, G_VARIANT_TYPE_VARDICT);
input = g_variant_new ("(a{sv})", &builder);
output = g_dbus_proxy_call_sync (proxy,
"GetBlockDevices", g_variant_ref (input),
G_DBUS_CALL_FLAGS_NONE,
-1, NULL, error);
if (output == NULL)
return FALSE;
devices = g_ptr_array_new_with_free_func (g_free);
g_variant_get (output, "(ao)", &iter);
while (g_variant_iter_next (iter, "o", &obj))
g_ptr_array_add (devices, g_strdup (obj));
return g_steal_pointer (&devices);
}
gboolean
fu_uefi_udisks_objpath_is_esp (const gchar *obj)
{
g_autoptr(GDBusProxy) proxy = NULL;
g_autoptr(GError) error_local = NULL;
g_autoptr(GVariant) val = NULL;
const gchar *str;
proxy = fu_uefi_udisks_get_dbus_proxy (obj,
UDISKS_DBUS_PART_INTERFACE,
&error_local);
if (proxy == NULL) {
g_warning ("Failed to initialize d-bus proxy: %s",
error_local->message);
return FALSE;
}
val = g_dbus_proxy_get_cached_property (proxy, "Type");
if (val == NULL)
return FALSE;
g_variant_get (val, "s", &str);
return g_strcmp0 (str, ESP_DISK_TYPE) == 0;
}
gboolean
fu_uefi_udisks_objpath_umount (const gchar *path, GError **error)
{
GVariant *input;
GVariantBuilder builder;
g_autoptr(GDBusProxy) proxy = NULL;
g_autoptr(GVariant) val = NULL;
g_return_val_if_fail (fu_uefi_udisks_objpath (path), FALSE);
proxy = fu_uefi_udisks_get_dbus_proxy (path,
UDISKS_DBUS_FILE_INTERFACE,
error);
if (proxy == NULL)
return FALSE;
g_variant_builder_init (&builder, G_VARIANT_TYPE_VARDICT);
input = g_variant_new ("(a{sv})", &builder);
val = g_dbus_proxy_call_sync (proxy,
"Unmount", input,
G_DBUS_CALL_FLAGS_NONE,
-1, NULL, error);
if (val == NULL)
return FALSE;
return TRUE;
}
gchar *
fu_uefi_udisks_objpath_mount (const gchar *path, GError **error)
{
GVariant *input;
GVariantBuilder builder;
const gchar *str;
g_autoptr(GDBusProxy) proxy = NULL;
g_autoptr(GVariant) val = NULL;
g_return_val_if_fail (fu_uefi_udisks_objpath (path), NULL);
proxy = fu_uefi_udisks_get_dbus_proxy (path,
UDISKS_DBUS_FILE_INTERFACE,
error);
if (proxy == NULL)
return NULL;
g_variant_builder_init (&builder, G_VARIANT_TYPE_VARDICT);
input = g_variant_new ("(a{sv})", &builder);
val = g_dbus_proxy_call_sync (proxy,
"Mount", input,
G_DBUS_CALL_FLAGS_NONE,
-1, NULL, error);
if (val == NULL)
return NULL;
g_variant_get (val, "(s)", &str);
return g_strdup (str);
}
gchar *
fu_uefi_udisks_objpath_is_mounted (const gchar *path)
{
const gchar **mountpoints = NULL;
g_autoptr(GDBusProxy) proxy = NULL;
g_autoptr(GVariant) val = NULL;
g_autoptr(GError) error_local = NULL;
g_return_val_if_fail (fu_uefi_udisks_objpath (path), NULL);
proxy = fu_uefi_udisks_get_dbus_proxy (path,
UDISKS_DBUS_FILE_INTERFACE,
&error_local);
if (proxy == NULL) {
g_warning ("%s", error_local->message);
return NULL;
}
val = g_dbus_proxy_get_cached_property (proxy, "MountPoints");
if (val == NULL)
return NULL;
mountpoints = g_variant_get_bytestring_array (val, NULL);
return g_strdup (mountpoints[0]);
}