mirror of
https://git.proxmox.com/git/fwupd
synced 2025-08-03 06:09:51 +00:00
flashrom: Use libflashrom
This also means we now include a flashrom subproject as no distro currently has a flashrom new enough to build the plugin. Signed-off-by: Richard Hughes <richard@hughsie.com> Signed-off-by: Artur Raglis <artur.raglis@3mdeb.com> Signed-off-by: Maciej Pijanowski <maciej.pijanowski@3mdeb.com>
This commit is contained in:
parent
749b50f3d1
commit
13fd21d806
@ -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"
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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 \
|
||||
|
@ -142,6 +142,42 @@
|
||||
<package variant="x86_64" />
|
||||
</distro>
|
||||
</dependency>
|
||||
<dependency type="build" id="libftdi1-dev">
|
||||
<distro id="arch">
|
||||
<package>libftdi</package>
|
||||
</distro>
|
||||
<distro id="centos">
|
||||
<package>libftdi-devel</package>
|
||||
</distro>
|
||||
<distro id="fedora">
|
||||
<package>libftdi-devel</package>
|
||||
</distro>
|
||||
<distro id="debian">
|
||||
<package variant="x86_64" />
|
||||
<package variant="i386" />
|
||||
</distro>
|
||||
<distro id="ubuntu">
|
||||
<package variant="x86_64" />
|
||||
</distro>
|
||||
</dependency>
|
||||
<dependency type="build" id="libpci-dev">
|
||||
<distro id="arch">
|
||||
<package>pciutils</package>
|
||||
</distro>
|
||||
<distro id="centos">
|
||||
<package>pciutils-devel</package>
|
||||
</distro>
|
||||
<distro id="fedora">
|
||||
<package>pciutils-devel</package>
|
||||
</distro>
|
||||
<distro id="debian">
|
||||
<package variant="x86_64" />
|
||||
<package variant="i386" />
|
||||
</distro>
|
||||
<distro id="ubuntu">
|
||||
<package variant="x86_64" />
|
||||
</distro>
|
||||
</dependency>
|
||||
<dependency type="build" id="fonts-noto">
|
||||
<distro id="arch">
|
||||
<package>noto-fonts</package>
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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')
|
||||
|
@ -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')
|
||||
|
@ -1,3 +1,8 @@
|
||||
# Purism
|
||||
[HwId=a0ce5085-2dea-5086-ae72-45810a186ad0]
|
||||
DeviceId=librem15v3
|
||||
|
||||
# Libretrend
|
||||
[HwId=52b68c34-6b31-5ecc-8a5c-de37e666ccd5]
|
||||
DeviceId=LT1000
|
||||
VersionFormat=quad
|
||||
|
@ -24,9 +24,15 @@
|
||||
#include <string.h>
|
||||
|
||||
#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;
|
||||
|
@ -25,5 +25,6 @@ shared_module('fu_plugin_flashrom',
|
||||
],
|
||||
dependencies : [
|
||||
plugin_deps,
|
||||
libflashrom,
|
||||
],
|
||||
)
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
1
subprojects/.gitignore
vendored
1
subprojects/.gitignore
vendored
@ -1 +1,2 @@
|
||||
flashrom
|
||||
libxmlb
|
||||
|
4
subprojects/flashrom.wrap
Normal file
4
subprojects/flashrom.wrap
Normal file
@ -0,0 +1,4 @@
|
||||
[wrap-git]
|
||||
directory = flashrom
|
||||
url = https://github.com/hughsie/flashrom.git
|
||||
revision = wip/hughsie/fwupd
|
Loading…
Reference in New Issue
Block a user