From 86b79fb03915315c0fba6670989ea072be2e8a5e Mon Sep 17 00:00:00 2001 From: Richard Hughes Date: Wed, 14 Nov 2018 12:20:23 +0000 Subject: [PATCH] Speed up fwupd startup by loading less thunderbolt firmware We load the Thunderbolt controller firmware to see if the controller is in native mode, as this changes the GUID. If the controller is asleep the firmware is not cached by the kernel and it can take more than 4 seconds to read out 504kB of firmware. We only need the first two 64-byte chunks, so only read what is required. This speeds up fwupd starting substantially, and also means we don't have to allocate a giant chunk of heap memory just to inspect one byte. Fixes: https://github.com/hughsie/fwupd/issues/848 --- plugins/thunderbolt/fu-plugin-thunderbolt.c | 16 +++++++++++----- plugins/thunderbolt/fu-thunderbolt-image.c | 8 +++++--- plugins/thunderbolt/fu-thunderbolt-image.h | 4 ++++ 3 files changed, 20 insertions(+), 8 deletions(-) diff --git a/plugins/thunderbolt/fu-plugin-thunderbolt.c b/plugins/thunderbolt/fu-plugin-thunderbolt.c index 19e577dbf..d04e1ea68 100644 --- a/plugins/thunderbolt/fu-plugin-thunderbolt.c +++ b/plugins/thunderbolt/fu-plugin-thunderbolt.c @@ -193,19 +193,25 @@ fu_plugin_thunderbolt_udev_get_version (GUdevDevice *udevice) static gboolean fu_plugin_thunderbolt_is_native (GUdevDevice *udevice, gboolean *is_native, GError **error) { + gsize nr_chunks; g_autoptr(GFile) nvmem = NULL; g_autoptr(GBytes) controller_fw = NULL; - gchar *content; - gsize length; + g_autoptr(GInputStream) istr = NULL; nvmem = fu_plugin_thunderbolt_find_nvmem (udevice, TRUE, error); if (nvmem == NULL) return FALSE; - if (!g_file_load_contents (nvmem, NULL, &content, &length, NULL, error)) + /* read just enough bytes to read the status byte */ + nr_chunks = (FU_TBT_OFFSET_NATIVE + FU_TBT_CHUNK_SZ - 1) / FU_TBT_CHUNK_SZ; + istr = G_INPUT_STREAM (g_file_read (nvmem, NULL, error)); + if (istr == NULL) + return FALSE; + controller_fw = g_input_stream_read_bytes (istr, + nr_chunks * FU_TBT_CHUNK_SZ, + NULL, error); + if (controller_fw == NULL) return FALSE; - - controller_fw = g_bytes_new_take (content, length); return fu_thunderbolt_image_controller_is_native (controller_fw, is_native, diff --git a/plugins/thunderbolt/fu-thunderbolt-image.c b/plugins/thunderbolt/fu-thunderbolt-image.c index 40a5951ec..c88aed9b0 100644 --- a/plugins/thunderbolt/fu-thunderbolt-image.c +++ b/plugins/thunderbolt/fu-thunderbolt-image.c @@ -787,8 +787,10 @@ fu_thunderbolt_image_controller_is_native (GBytes *controller_fw, gsize fw_size; const guint8 *fw_data = g_bytes_get_data (controller_fw, &fw_size); const FuThunderboltFwObject controller = { fw_data, fw_size, controller_sections }; - - const FuThunderboltFwLocation location = { .offset = 0x7B, .len = 1, .description = "Native", .mask = 0x20 }; - + const FuThunderboltFwLocation location = { + .offset = FU_TBT_OFFSET_NATIVE, + .len = 1, + .description = "Native", + .mask = 0x20 }; return read_bool (&location, &controller, is_native, error); } diff --git a/plugins/thunderbolt/fu-thunderbolt-image.h b/plugins/thunderbolt/fu-thunderbolt-image.h index f00c42e19..ee7d000ce 100644 --- a/plugins/thunderbolt/fu-thunderbolt-image.h +++ b/plugins/thunderbolt/fu-thunderbolt-image.h @@ -15,6 +15,10 @@ typedef enum { UNKNOWN_DEVICE, } FuPluginValidation; +/* byte offsets in firmware image */ +#define FU_TBT_OFFSET_NATIVE 0x7B +#define FU_TBT_CHUNK_SZ 0x40 + FuPluginValidation fu_thunderbolt_image_validate (GBytes *controller_fw, GBytes *blob_fw, GError **error);