diff --git a/.lgtm.yml b/.lgtm.yml
index 3cf702194..a817b260a 100644
--- a/.lgtm.yml
+++ b/.lgtm.yml
@@ -14,8 +14,10 @@ extraction:
- "wget -O libxmlb.zip https://github.com/hughsie/libxmlb/archive/0.1.7.zip"
- "mkdir -p subprojects/libxmlb"
- "bsdtar --strip-components=1 -xvf libxmlb.zip -C subprojects/libxmlb"
+ - "wget -O flashrom.zip https://github.com/hughsie/flashrom/archive/wip/hughsie/fwupd.zip"
+ - "mkdir -p subprojects/flashrom"
+ - "bsdtar --strip-components=1 -xvf flashrom.zip -C subprojects/flashrom"
index:
build_command:
- "meson setup build"
- "ninja -C build"
-
diff --git a/contrib/PKGBUILD b/contrib/PKGBUILD
index 1de05f373..359ea8dd1 100644
--- a/contrib/PKGBUILD
+++ b/contrib/PKGBUILD
@@ -17,7 +17,7 @@ makedepends=('meson' 'valgrind' 'gobject-introspection' 'gtk-doc' 'python-pillow
build() {
cd ${pkgname}
if [ -n "$CI" ]; then
- export CI="--werror"
+ export CI="--werror --wrap-mode=default"
fi
arch-meson -D b_lto=false $CI ../build
diff --git a/contrib/ci/debian_s390x.sh b/contrib/ci/debian_s390x.sh
index c2ff250fa..9b277ff5f 100755
--- a/contrib/ci/debian_s390x.sh
+++ b/contrib/ci/debian_s390x.sh
@@ -16,6 +16,7 @@ cd build
meson .. \
--cross-file s390x_cross.txt \
--werror \
+ -Dplugin_flashrom=false \
-Dplugin_uefi=false \
-Dplugin_dell=false \
-Dplugin_modem_manager=false \
diff --git a/contrib/ci/dependencies.xml b/contrib/ci/dependencies.xml
index 463aaaedf..047f51810 100644
--- a/contrib/ci/dependencies.xml
+++ b/contrib/ci/dependencies.xml
@@ -142,6 +142,42 @@
+
+
+ libftdi
+
+
+ libftdi-devel
+
+
+ libftdi-devel
+
+
+
+
+
+
+
+
+
+
+
+ pciutils
+
+
+ pciutils-devel
+
+
+ pciutils-devel
+
+
+
+
+
+
+
+
+
noto-fonts
diff --git a/contrib/debian/rules b/contrib/debian/rules
index 2232148d3..52f315227 100755
--- a/contrib/debian/rules
+++ b/contrib/debian/rules
@@ -11,7 +11,7 @@ ifeq "$(DEB_HOST_ARCH_BITS)" "32"
endif
ifneq ($(CI),)
- export CI=--werror
+ export CI=--werror --wrap-mode=default
endif
SB_STYLE := debian
@@ -58,6 +58,9 @@ override_dh_install:
if [ -n "$CI" ] && [ -f debian/tmp/usr/lib/xb-tool ]; then \
dh_install -pfwupd usr/lib/xb-tool ;\
fi
+ if [ -n "$CI" ] && [ -f debian/tmp/usr/sbin/flashrom ]; then \
+ dh_install -pfwupd usr/sbin/flashrom ;\
+ fi
dh_missing -a --fail-missing
#this is placed in fwupd-tests
diff --git a/contrib/fwupd.spec.in b/contrib/fwupd.spec.in
index e47b0e059..ec48ddfb3 100644
--- a/contrib/fwupd.spec.in
+++ b/contrib/fwupd.spec.in
@@ -10,6 +10,7 @@
%global enable_ci 0
%global enable_tests 1
%global enable_dummy 1
+%global __meson_wrap_mode default
# fwupd.efi is only available on these arches
%ifarch x86_64 aarch64
@@ -151,6 +152,7 @@ Data files for installed tests.
%else
-Dplugin_dummy=false \
%endif
+ -Dplugin_flashrom=true \
-Dplugin_thunderbolt=true \
%if 0%{?have_redfish}
-Dplugin_redfish=true \
@@ -202,6 +204,12 @@ Data files for installed tests.
mkdir -p --mode=0700 $RPM_BUILD_ROOT%{_localstatedir}/lib/fwupd/gnupg
+# delete most files from the subproject
+rm ${RPM_BUILD_ROOT}%{_includedir}/libflashrom.h
+rm ${RPM_BUILD_ROOT}%{_libdir}/libflashrom.so
+rm ${RPM_BUILD_ROOT}%{_libdir}/pkgconfig/libflashrom.pc
+rm ${RPM_BUILD_ROOT}%{_sbindir}/flashrom
+
%find_lang %{name}
%post
@@ -327,6 +335,9 @@ mkdir -p --mode=0700 $RPM_BUILD_ROOT%{_localstatedir}/lib/fwupd/gnupg
%{_datadir}/locale/*/LC_IMAGES/fwupd*
%endif
+# eww, but just until the Fedora package ships these...
+%{_libdir}/libflashrom.so.1*
+
%files devel
%{_datadir}/gir-1.0/Fwupd-2.0.gir
%{_datadir}/gtk-doc/html/libfwupd
diff --git a/meson.build b/meson.build
index b9aea3d74..1364e3b0b 100644
--- a/meson.build
+++ b/meson.build
@@ -278,6 +278,10 @@ if get_option('plugin_thunderbolt')
conf.set('HAVE_THUNDERBOLT', '1')
endif
+if get_option('plugin_flashrom')
+ libflashrom = dependency('flashrom', fallback : ['flashrom', 'flashrom_dep'])
+endif
+
if get_option('systemd')
systemd = dependency('systemd', version : '>= 211')
conf.set('HAVE_SYSTEMD' , '1')
diff --git a/meson_options.txt b/meson_options.txt
index 5d4163e85..d6520cf39 100644
--- a/meson_options.txt
+++ b/meson_options.txt
@@ -18,6 +18,7 @@ option('plugin_redfish', type : 'boolean', value : true, description : 'enable R
option('plugin_uefi', type : 'boolean', value : true, description : 'enable UEFI support')
option('plugin_nvme', type : 'boolean', value : true, description : 'enable NVMe support')
option('plugin_modem_manager', type : 'boolean', value : false, description : 'enable ModemManager support')
+option('plugin_flashrom', type : 'boolean', value : true, description : 'enable libflashrom support')
option('systemd', type : 'boolean', value : true, description : 'enable systemd support')
option('systemdunitdir', type: 'string', value: '', description: 'Directory for systemd units')
option('elogind', type : 'boolean', value : false, description : 'enable elogind support')
diff --git a/plugins/flashrom/flashrom.quirk b/plugins/flashrom/flashrom.quirk
index a5d833f49..aeb0d0e68 100644
--- a/plugins/flashrom/flashrom.quirk
+++ b/plugins/flashrom/flashrom.quirk
@@ -1,3 +1,8 @@
# Purism
[HwId=a0ce5085-2dea-5086-ae72-45810a186ad0]
DeviceId=librem15v3
+
+# Libretrend
+[HwId=52b68c34-6b31-5ecc-8a5c-de37e666ccd5]
+DeviceId=LT1000
+VersionFormat=quad
diff --git a/plugins/flashrom/fu-plugin-flashrom.c b/plugins/flashrom/fu-plugin-flashrom.c
index adf41e3ca..3a1241a45 100644
--- a/plugins/flashrom/fu-plugin-flashrom.c
+++ b/plugins/flashrom/fu-plugin-flashrom.c
@@ -24,9 +24,15 @@
#include
#include "fu-plugin-vfuncs.h"
+#include "libflashrom.h"
+
+#define SELFCHECK_TRUE 1
struct FuPluginData {
- gchar *flashrom_fn;
+ gsize flash_size;
+ struct flashrom_flashctx *flashctx;
+ struct flashrom_layout *layout;
+ struct flashrom_programmer *flashprog;
};
void
@@ -41,21 +47,72 @@ void
fu_plugin_destroy (FuPlugin *plugin)
{
FuPluginData *data = fu_plugin_get_data (plugin);
- g_free (data->flashrom_fn);
+ flashrom_layout_release (data->layout);
+ flashrom_programmer_shutdown (data->flashprog);
+ flashrom_flash_release (data->flashctx);
+}
+
+static int
+fu_plugin_flashrom_debug_cb (enum flashrom_log_level lvl, const char *fmt, va_list args)
+{
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wformat-nonliteral"
+ g_autofree gchar *tmp = g_strdup_vprintf (fmt, args);
+#pragma clang diagnostic pop
+ switch (lvl) {
+ case FLASHROM_MSG_ERROR:
+ case FLASHROM_MSG_WARN:
+ g_warning ("%s", tmp);
+ break;
+ case FLASHROM_MSG_INFO:
+ case FLASHROM_MSG_DEBUG:
+ case FLASHROM_MSG_DEBUG2:
+ g_debug ("%s", tmp);
+ break;
+ case FLASHROM_MSG_SPEW:
+ break;
+ default:
+ break;
+ }
+ return 0;
}
gboolean
fu_plugin_startup (FuPlugin *plugin, GError **error)
{
FuPluginData *data = fu_plugin_get_data (plugin);
- GPtrArray *hwids;
- g_autoptr(GError) error_local = NULL;
- /* we need flashrom from the host system */
- data->flashrom_fn = fu_common_find_program_in_path ("flashrom", &error_local);
+ /* probe hardware */
+ if (flashrom_init (SELFCHECK_TRUE)) {
+ g_set_error_literal (error,
+ FWUPD_ERROR,
+ FWUPD_ERROR_NOT_SUPPORTED,
+ "flashrom initialization error");
+ return FALSE;
+ }
+ flashrom_set_log_callback (fu_plugin_flashrom_debug_cb);
+ if (flashrom_programmer_init (&data->flashprog, "internal", NULL)) {
+ g_set_error_literal (error,
+ FWUPD_ERROR,
+ FWUPD_ERROR_NOT_SUPPORTED,
+ "programmer initialization failed");
+ return FALSE;
+ }
+ if (flashrom_flash_probe (&data->flashctx, data->flashprog, NULL)) {
+ g_set_error_literal (error,
+ FWUPD_ERROR,
+ FWUPD_ERROR_NOT_SUPPORTED,
+ "flash probe failed");
+ return FALSE;
+ }
+ data->flash_size = flashrom_flash_getsize (data->flashctx);
+ return TRUE;
+}
- /* search for devices */
- hwids = fu_plugin_get_hwids (plugin);
+gboolean
+fu_plugin_coldplug (FuPlugin *plugin, GError **error)
+{
+ GPtrArray *hwids = fu_plugin_get_hwids (plugin);
for (guint i = 0; i < hwids->len; i++) {
const gchar *guid = g_ptr_array_index (hwids, i);
const gchar *quirk_str;
@@ -70,11 +127,7 @@ fu_plugin_startup (FuPlugin *plugin, GError **error)
fu_device_set_id (dev, device_id);
fu_device_set_quirks (dev, fu_plugin_get_quirks (plugin));
fu_device_add_flag (dev, FWUPD_DEVICE_FLAG_INTERNAL);
- if (data->flashrom_fn != NULL) {
- fu_device_add_flag (dev, FWUPD_DEVICE_FLAG_UPDATABLE);
- } else {
- fu_device_set_update_error (dev, error_local->message);
- }
+ fu_device_add_flag (dev, FWUPD_DEVICE_FLAG_UPDATABLE);
fu_device_add_guid (dev, guid);
fu_device_set_name (dev, fu_plugin_get_dmi_value (plugin, FU_HWIDS_KEY_PRODUCT_NAME));
fu_device_set_vendor (dev, fu_plugin_get_dmi_value (plugin, FU_HWIDS_KEY_MANUFACTURER));
@@ -89,44 +142,6 @@ fu_plugin_startup (FuPlugin *plugin, GError **error)
return TRUE;
}
-static guint
-fu_plugin_flashrom_parse_percentage (const gchar *lines_verbose)
-{
- const guint64 addr_highest = 0x800000;
- guint64 addr_best = 0x0;
- g_auto(GStrv) chunks = NULL;
-
- /* parse 0x000000-0x000fff:S, 0x001000-0x001fff:S */
- chunks = g_strsplit_set (lines_verbose, "x-:S, \n\r", -1);
- for (guint i = 0; chunks[i] != NULL; i++) {
- guint64 addr_tmp;
- if (strlen (chunks[i]) != 6)
- continue;
- addr_tmp = g_ascii_strtoull (chunks[i], NULL, 16);
- if (addr_tmp > addr_best)
- addr_best = addr_tmp;
- }
- return (addr_best * 100) / addr_highest;
-}
-
-static void
-fu_plugin_flashrom_read_cb (const gchar *line, gpointer user_data)
-{
- FuDevice *device = FU_DEVICE (user_data);
- if (g_strcmp0 (line, "Reading flash...") == 0)
- fu_device_set_status (device, FWUPD_STATUS_DEVICE_VERIFY);
- fu_device_set_progress (device, fu_plugin_flashrom_parse_percentage (line));
-}
-
-static void
-fu_plugin_flashrom_write_cb (const gchar *line, gpointer user_data)
-{
- FuDevice *device = FU_DEVICE (user_data);
- if (g_strcmp0 (line, "Writing flash...") == 0)
- fu_device_set_status (device, FWUPD_STATUS_DEVICE_WRITE);
- fu_device_set_progress (device, fu_plugin_flashrom_parse_percentage (line));
-}
-
gboolean
fu_plugin_update_prepare (FuPlugin *plugin,
FwupdInstallFlags flags,
@@ -148,17 +163,20 @@ fu_plugin_update_prepare (FuPlugin *plugin,
if (!fu_common_mkdir_parent (firmware_orig, error))
return FALSE;
if (!g_file_test (firmware_orig, G_FILE_TEST_EXISTS)) {
- const gchar *argv[] = {
- data->flashrom_fn,
- "--programmer", "internal:laptop=force_I_want_a_brick",
- "--read", firmware_orig,
- "--verbose", NULL };
- if (!fu_common_spawn_sync ((const gchar * const *) argv,
- fu_plugin_flashrom_read_cb, device,
- 0, NULL, error)) {
- g_prefix_error (error, "failed to get original firmware: ");
+ g_autofree guint8 *newcontents = g_malloc0 (data->flash_size);
+ g_autoptr(GBytes) buf = NULL;
+
+ fu_device_set_status (device, FWUPD_STATUS_DEVICE_READ);
+ if (flashrom_image_read (data->flashctx, newcontents, data->flash_size)) {
+ g_set_error_literal (error,
+ FWUPD_ERROR,
+ FWUPD_ERROR_READ,
+ "failed to back up original firmware");
return FALSE;
}
+ buf = g_bytes_new_static (newcontents, data->flash_size);
+ if (!fu_common_set_contents_bytes (firmware_orig, buf, error))
+ return FALSE;
}
return TRUE;
@@ -172,34 +190,56 @@ fu_plugin_update (FuPlugin *plugin,
GError **error)
{
FuPluginData *data = fu_plugin_get_data (plugin);
- g_autofree gchar *firmware_fn = NULL;
- g_autofree gchar *tmpdir = NULL;
- const gchar *argv[] = {
- data->flashrom_fn,
- "--programmer", "internal:laptop=force_I_want_a_brick",
- "--write", "xxx",
- "--verbose", NULL };
+ gsize sz = 0;
+ gint rc;
+ const guint8 *buf = g_bytes_get_data (blob_fw, &sz);
- /* write blob to temp location */
- tmpdir = g_dir_make_tmp ("fwupd-XXXXXX", error);
- if (tmpdir == NULL)
- return FALSE;
- firmware_fn = g_build_filename (tmpdir, "flashrom-firmware.bin", NULL);
- if (!fu_common_set_contents_bytes (firmware_fn, blob_fw, error))
- return FALSE;
-
- /* use flashrom to write image */
- argv[4] = firmware_fn;
- if (!fu_common_spawn_sync ((const gchar * const *) argv,
- fu_plugin_flashrom_write_cb, device,
- 0, NULL, error)) {
- g_prefix_error (error, "failed to write firmware: ");
+ if (flashrom_layout_read_from_ifd (&data->layout, data->flashctx, NULL, 0)) {
+ g_set_error_literal (error,
+ FWUPD_ERROR,
+ FWUPD_ERROR_READ,
+ "failed to read layout from Intel ICH descriptor");
return FALSE;
}
- /* delete temp location */
- if (!fu_common_rmtree (tmpdir, error))
+ /* include bios region for safety reasons */
+ if (flashrom_layout_include_region (data->layout, "bios")) {
+ g_set_error_literal (error,
+ FWUPD_ERROR,
+ FWUPD_ERROR_NOT_SUPPORTED,
+ "invalid region name");
return FALSE;
+ }
+
+ /* write region */
+ flashrom_layout_set (data->flashctx, data->layout);
+ if (sz != data->flash_size) {
+ g_set_error (error,
+ FWUPD_ERROR,
+ FWUPD_ERROR_NOT_SUPPORTED,
+ "invalid image size 0x%x, expected 0x%x",
+ (guint) sz, (guint) data->flash_size);
+ return FALSE;
+ }
+
+ fu_device_set_status (device, FWUPD_STATUS_DEVICE_WRITE);
+ rc = flashrom_image_write (data->flashctx, (void *) buf, sz, NULL /* refbuffer */);
+ if (rc != 0) {
+ g_set_error (error,
+ FWUPD_ERROR,
+ FWUPD_ERROR_WRITE,
+ "image write failed, err=%i", rc);
+ return FALSE;
+ }
+
+ fu_device_set_status (device, FWUPD_STATUS_DEVICE_VERIFY);
+ if (flashrom_image_verify (data->flashctx, (void *) buf, sz)) {
+ g_set_error (error,
+ FWUPD_ERROR,
+ FWUPD_ERROR_WRITE,
+ "image verify failed");
+ return FALSE;
+ }
/* success */
return TRUE;
diff --git a/plugins/flashrom/meson.build b/plugins/flashrom/meson.build
index 222b5f88f..1e5a60647 100644
--- a/plugins/flashrom/meson.build
+++ b/plugins/flashrom/meson.build
@@ -25,5 +25,6 @@ shared_module('fu_plugin_flashrom',
],
dependencies : [
plugin_deps,
+ libflashrom,
],
)
diff --git a/plugins/meson.build b/plugins/meson.build
index 80b4f9ba3..b45621f1f 100644
--- a/plugins/meson.build
+++ b/plugins/meson.build
@@ -3,7 +3,6 @@ subdir('dfu')
subdir('colorhug')
subdir('ebitdo')
subdir('fastboot')
-subdir('flashrom')
subdir('steelseries')
subdir('dell-dock')
subdir('nitrokey')
@@ -58,3 +57,7 @@ endif
if get_option('plugin_uefi')
subdir('uefi')
endif
+
+if get_option('plugin_flashrom')
+subdir('flashrom')
+endif
diff --git a/snap/snapcraft.yaml b/snap/snapcraft.yaml
index 701a26ee6..047383101 100644
--- a/snap/snapcraft.yaml
+++ b/snap/snapcraft.yaml
@@ -264,11 +264,13 @@ parts:
- libarchive-dev
- libcairo-dev
- libelf-dev
+ - libftdi1-dev
- libgcab-dev
- libglib2.0-dev
- libgpgme11-dev
- libjson-glib-dev
- libpango1.0-dev
+ - libpci-dev
- libpolkit-gobject-1-dev
- libsoup2.4-dev
- libsqlite3-dev
diff --git a/subprojects/.gitignore b/subprojects/.gitignore
index d8d6c81a5..99292448a 100644
--- a/subprojects/.gitignore
+++ b/subprojects/.gitignore
@@ -1 +1,2 @@
+flashrom
libxmlb
diff --git a/subprojects/flashrom.wrap b/subprojects/flashrom.wrap
new file mode 100644
index 000000000..1039a40ff
--- /dev/null
+++ b/subprojects/flashrom.wrap
@@ -0,0 +1,4 @@
+[wrap-git]
+directory = flashrom
+url = https://github.com/hughsie/flashrom.git
+revision = wip/hughsie/fwupd