diff --git a/libfwupdplugin/fu-common.c b/libfwupdplugin/fu-common.c index 4a5e1a81e..eb1508765 100644 --- a/libfwupdplugin/fu-common.c +++ b/libfwupdplugin/fu-common.c @@ -2249,6 +2249,7 @@ fu_common_get_volumes_by_kind (const gchar *kind, GError **error) for (guint i = 0; i < devices->len; i++) { GDBusProxy *proxy_blk = g_ptr_array_index (devices, i); const gchar *type_str; + g_autoptr(FuVolume) vol = NULL; g_autoptr(GDBusProxy) proxy_part = NULL; g_autoptr(GDBusProxy) proxy_fs = NULL; g_autoptr(GVariant) val = NULL; @@ -2269,10 +2270,6 @@ fu_common_get_volumes_by_kind (const gchar *kind, GError **error) continue; g_variant_get (val, "&s", &type_str); - g_debug ("device %s, type: %s", - g_dbus_proxy_get_object_path (proxy_blk), type_str); - if (g_strcmp0 (type_str, kind) != 0) - continue; proxy_fs = g_dbus_proxy_new_sync (g_dbus_proxy_get_connection (proxy_blk), G_DBUS_PROXY_FLAGS_NONE, NULL, UDISKS_DBUS_SERVICE, @@ -2284,11 +2281,17 @@ fu_common_get_volumes_by_kind (const gchar *kind, GError **error) g_dbus_proxy_get_object_path (proxy_blk)); return NULL; } - g_ptr_array_add (volumes, - g_object_new (FU_TYPE_VOLUME, - "proxy-block", proxy_blk, - "proxy-filesystem", proxy_fs, - NULL)); + vol = g_object_new (FU_TYPE_VOLUME, + "proxy-block", proxy_blk, + "proxy-filesystem", proxy_fs, + NULL); + g_debug ("device %s, type: %s, internal: %d, fs: %s", + g_dbus_proxy_get_object_path (proxy_blk), type_str, + fu_volume_is_internal (vol), + fu_volume_get_id_type (vol)); + if (g_strcmp0 (type_str, kind) != 0) + continue; + g_ptr_array_add (volumes, g_steal_pointer (&vol)); } if (volumes->len == 0) { g_set_error (error, @@ -2400,18 +2403,44 @@ fu_common_get_esp_default (GError **error) const gchar *path_tmp; g_autoptr(GPtrArray) volumes_fstab = g_ptr_array_new (); g_autoptr(GPtrArray) volumes_mtab = g_ptr_array_new (); + g_autoptr(GPtrArray) volumes_vfat = g_ptr_array_new (); g_autoptr(GPtrArray) volumes = NULL; + g_autoptr(GError) error_local = NULL; /* for the test suite use local directory for ESP */ path_tmp = g_getenv ("FWUPD_UEFI_ESP_PATH"); if (path_tmp != NULL) return fu_volume_new_from_mount_path (path_tmp); - volumes = fu_common_get_volumes_by_kind (FU_VOLUME_KIND_ESP, error); - if (volumes == NULL) - return NULL; + volumes = fu_common_get_volumes_by_kind (FU_VOLUME_KIND_ESP, &error_local); + if (volumes == NULL) { + g_debug ("%s, falling back to %s", error_local->message, FU_VOLUME_KIND_BDP); + volumes = fu_common_get_volumes_by_kind (FU_VOLUME_KIND_BDP, error); + if (volumes == NULL) { + g_prefix_error (error, "%s: ", error_local->message); + return NULL; + } + } + /* only add in internal vfat partitions */ for (guint i = 0; i < volumes->len; i++) { FuVolume *vol = g_ptr_array_index (volumes, i); + g_autofree gchar *type = fu_volume_get_id_type (vol); + if (type == NULL) + continue; + if (!fu_volume_is_internal (vol)) + continue; + if (g_strcmp0 (type, "vfat") == 0) + g_ptr_array_add (volumes_vfat, vol); + } + if (volumes_vfat->len == 0) { + g_set_error (error, + G_IO_ERROR, + G_IO_ERROR_INVALID_FILENAME, + "No ESP found"); + return NULL; + } + for (guint i = 0; i < volumes_vfat->len; i++) { + FuVolume *vol = g_ptr_array_index (volumes_vfat, i); g_ptr_array_add (fu_volume_is_mounted (vol) ? volumes_mtab : volumes_fstab, vol); } if (volumes_mtab->len == 1) { diff --git a/libfwupdplugin/fu-volume.c b/libfwupdplugin/fu-volume.c index 55ef98762..ce91b570c 100644 --- a/libfwupdplugin/fu-volume.c +++ b/libfwupdplugin/fu-volume.c @@ -307,6 +307,53 @@ fu_volume_mount (FuVolume *self, GError **error) return TRUE; } +/** + * fu_volume_is_internal: + * @self: a @FuVolume + * + * Guesses if the drive is internal to the system + * + * Returns: %TRUE for success + * + * Since: 1.5.2 + **/ +gboolean +fu_volume_is_internal (FuVolume *self) +{ + g_autoptr(GVariant) val_system = NULL; + g_return_val_if_fail (FU_IS_VOLUME (self), FALSE); + + val_system = g_dbus_proxy_get_cached_property (self->proxy_blk, "HintSystem"); + if (val_system == NULL) + return FALSE; + + return g_variant_get_boolean (val_system); +} + +/** + * fu_volume_get_id_type: + * @self: a @FuVolume + * + * Return the IdType of the volume + * + * Returns: string for type or NULL + * + * Since: 1.5.2 + **/ +gchar * +fu_volume_get_id_type (FuVolume *self) +{ + g_autoptr(GVariant) val = NULL; + g_return_val_if_fail (FU_IS_VOLUME (self), NULL); + + val = g_dbus_proxy_get_cached_property (self->proxy_blk, "IdType"); + if (val == NULL) + return NULL; + + return g_strdup (g_variant_get_string (val, NULL)); +} + + /** * fu_volume_unmount: * @self: a @FuVolume diff --git a/libfwupdplugin/fu-volume.h b/libfwupdplugin/fu-volume.h index 0f12edf9c..69bb73b7d 100644 --- a/libfwupdplugin/fu-volume.h +++ b/libfwupdplugin/fu-volume.h @@ -16,6 +16,7 @@ G_DECLARE_FINAL_TYPE (FuVolume, fu_volume, FU, VOLUME, GObject) #define FU_VOLUME_KIND_ESP "c12a7328-f81f-11d2-ba4b-00a0c93ec93b" +#define FU_VOLUME_KIND_BDP "ebd0a0a2-b9e5-4433-87c0-68b6b72699c7" const gchar *fu_volume_get_id (FuVolume *self); gboolean fu_volume_check_free_space (FuVolume *self, @@ -30,3 +31,5 @@ gboolean fu_volume_unmount (FuVolume *self, GError **error); FuDeviceLocker *fu_volume_locker (FuVolume *self, GError **error); +gboolean fu_volume_is_internal (FuVolume *self); +gchar *fu_volume_get_id_type (FuVolume *self); diff --git a/libfwupdplugin/fwupdplugin.map b/libfwupdplugin/fwupdplugin.map index 288d1ad10..2d5213472 100644 --- a/libfwupdplugin/fwupdplugin.map +++ b/libfwupdplugin/fwupdplugin.map @@ -683,5 +683,7 @@ LIBFWUPDPLUGIN_1.5.1 { LIBFWUPDPLUGIN_1.5.2 { global: fu_hid_device_add_flag; + fu_volume_get_id_type; + fu_volume_is_internal; local: *; } LIBFWUPDPLUGIN_1.5.1; diff --git a/src/fu-tool.c b/src/fu-tool.c index 3c242b223..f35847492 100644 --- a/src/fu-tool.c +++ b/src/fu-tool.c @@ -2373,13 +2373,32 @@ fu_util_prompt_for_volume (GError **error) FuVolume *volume; guint idx; g_autoptr(GPtrArray) volumes = NULL; + g_autoptr(GPtrArray) volumes_vfat = g_ptr_array_new (); + g_autoptr(GError) error_local = NULL; /* exactly one */ - volumes = fu_common_get_volumes_by_kind (FU_VOLUME_KIND_ESP, error); - if (volumes == NULL) - return NULL; - if (volumes->len == 1) { - volume = g_ptr_array_index (volumes, 0); + volumes = fu_common_get_volumes_by_kind (FU_VOLUME_KIND_ESP, &error_local); + if (volumes == NULL) { + g_debug ("%s, falling back to %s", error_local->message, FU_VOLUME_KIND_BDP); + volumes = fu_common_get_volumes_by_kind (FU_VOLUME_KIND_BDP, error); + if (volumes == NULL) { + g_prefix_error (error, "%s: ", error_local->message); + return NULL; + } + } + /* only add internal vfat partitions */ + for (guint i = 0; i < volumes->len; i++) { + FuVolume *vol = g_ptr_array_index (volumes, i); + g_autofree gchar *type = fu_volume_get_id_type (vol); + if (type == NULL) + continue; + if (!fu_volume_is_internal (vol)) + continue; + if (g_strcmp0 (type, "vfat") == 0) + g_ptr_array_add (volumes_vfat, vol); + } + if (volumes_vfat->len == 1) { + volume = g_ptr_array_index (volumes_vfat, 0); /* TRANSLATORS: Volume has been chosen by the user */ g_print ("%s: %s\n", _("Selected volume"), fu_volume_get_id (volume)); return g_object_ref (volume); @@ -2389,11 +2408,11 @@ fu_util_prompt_for_volume (GError **error) g_print ("%s\n", _("Choose a volume:")); /* TRANSLATORS: this is to abort the interactive prompt */ g_print ("0.\t%s\n", _("Cancel")); - for (guint i = 0; i < volumes->len; i++) { - volume = g_ptr_array_index (volumes, i); + for (guint i = 0; i < volumes_vfat->len; i++) { + volume = g_ptr_array_index (volumes_vfat, i); g_print ("%u.\t%s\n", i + 1, fu_volume_get_id (volume)); } - idx = fu_util_prompt_for_number (volumes->len); + idx = fu_util_prompt_for_number (volumes_vfat->len); if (idx == 0) { g_set_error_literal (error, FWUPD_ERROR, @@ -2401,7 +2420,7 @@ fu_util_prompt_for_volume (GError **error) "Request canceled"); return NULL; } - volume = g_ptr_array_index (volumes, idx - 1); + volume = g_ptr_array_index (volumes_vfat, idx - 1); return g_object_ref (volume); }