diff --git a/configure.ac b/configure.ac index dc5671451..1f2993f52 100644 --- a/configure.ac +++ b/configure.ac @@ -122,9 +122,15 @@ PKG_CHECK_MODULES(GCAB, libgcab-1.0) PKG_CHECK_MODULES(APPSTREAM_GLIB, appstream-glib >= 0.3.5) PKG_CHECK_MODULES(GUSB, gusb >= 0.2.2) PKG_CHECK_MODULES(SQLITE, sqlite3) +PKG_CHECK_MODULES(ARCHIVE, libarchive) PKG_CHECK_MODULES(SOUP, libsoup-2.4 >= 2.42) AC_PATH_PROG(DOCBOOK2MAN, docbook2man) +AC_PATH_PROG(GCAB, [gcab], [no]) +if test x$GCAB = "xno" ; then + AC_MSG_ERROR([gcab program not found]) +fi + # ColorHug support AC_ARG_ENABLE(colorhug, AS_HELP_STRING([--enable-colorhug],[Enable ColorHug support]), enable_colorhug=$enableval, enable_colorhug=yes) @@ -187,6 +193,7 @@ libfwupd/Makefile data/Makefile data/pki/Makefile data/tests/Makefile +data/tests/rpiupdate/Makefile docs/Makefile docs/man/Makefile policy/Makefile diff --git a/contrib/fwupd.spec.in b/contrib/fwupd.spec.in index 90627413a..2ab28dc1a 100644 --- a/contrib/fwupd.spec.in +++ b/contrib/fwupd.spec.in @@ -20,8 +20,10 @@ BuildRequires: sqlite-devel BuildRequires: gpgme-devel BuildRequires: systemd BuildRequires: libsoup-devel +BuildRequires: libarchive-devel BuildRequires: gobject-introspection-devel BuildRequires: libappstream-glib-devel >= 0.3.6 +BuildRequires: gcab %ifarch x86_64 %{ix86} aarch64 BuildRequires: fwupdate-devel >= 0.4 diff --git a/data/tests/Makefile.am b/data/tests/Makefile.am index b10f9fc6d..1e60649f1 100644 --- a/data/tests/Makefile.am +++ b/data/tests/Makefile.am @@ -1,6 +1,10 @@ +SUBDIRS = \ + rpiupdate + test_files = \ colorhug-als-3.0.2.cab \ firmware.bin \ + rpiboot/start.elf \ pki/GPG-KEY-Linux-Vendor-Firmware-Service EXTRA_DIST = $(test_files) diff --git a/data/tests/rpiboot/start.elf b/data/tests/rpiboot/start.elf new file mode 100644 index 000000000..731bf3e43 Binary files /dev/null and b/data/tests/rpiboot/start.elf differ diff --git a/data/tests/rpiupdate/Makefile.am b/data/tests/rpiupdate/Makefile.am new file mode 100644 index 000000000..8e0d439cd --- /dev/null +++ b/data/tests/rpiupdate/Makefile.am @@ -0,0 +1,32 @@ +test_files = \ + firmware.bin \ + rpi-firmware-20150805.cab + +firmware.bin: $(srcdir)/*.elf $(srcdir)/overlays/* $(srcdir)/README + $(AM_V_GEN) tar -cf $@ \ + $(srcdir)/README \ + $(srcdir)/*.elf \ + $(srcdir)/overlays/*.dtb + +rpi-firmware-20150805.cab: firmware.bin firmware.inf firmware.metainfo.xml + $(AM_V_GEN) touch -c -m -d"2000-01-01T00:00:00" $?; \ + $(GCAB) --create --nopath $@ \ + $(builddir)/firmware.bin \ + $(srcdir)/firmware.metainfo.xml \ + $(srcdir)/firmware.inf + +BUILT_SOURCES = \ + firmware.bin \ + rpi-firmware-20150805.cab + +CLEANFILES = \ + $(BUILT_SOURCES) + +EXTRA_DIST = \ + $(test_files) \ + firmware.inf \ + firmware.metainfo.xml \ + overlays/test.dtb \ + start.elf + +-include $(top_srcdir)/git.mk diff --git a/data/tests/rpiupdate/README b/data/tests/rpiupdate/README new file mode 100644 index 000000000..e69de29bb diff --git a/data/tests/rpiupdate/firmware.inf b/data/tests/rpiupdate/firmware.inf new file mode 100644 index 000000000..9352063e0 --- /dev/null +++ b/data/tests/rpiupdate/firmware.inf @@ -0,0 +1,19 @@ +; Copyright (C) 2015 Richard Hughes + +[Version] +Class=Firmware +ClassGuid={f2e7dd72-6468-4e36-b6f1-6488f42c1b52} + +[Firmware_CopyFiles] +firmware.bin + +[Firmware_AddReg] +HKR,,FirmwareId,,{c77029fe-ffb2-3706-dc67-67af4a132afd} +HKR,,FirmwareVersion,%REG_DWORD%,0x0000000 +HKR,,FirmwareFilename,,firmware.bin + +[Strings] +Provider = "Raspberry Pi Foundation" +MfgName = "Raspberry Pi" +FirmwareDesc = "Raspberry Pi Firmware" +DiskName = "Firmware for the Raspberry Pi" diff --git a/data/tests/rpiupdate/firmware.metainfo.xml b/data/tests/rpiupdate/firmware.metainfo.xml new file mode 100644 index 000000000..9cdd02510 --- /dev/null +++ b/data/tests/rpiupdate/firmware.metainfo.xml @@ -0,0 +1,24 @@ + + + + c77029fe-ffb2-3706-dc67-67af4a132afd + Raspberry Pi Device Update + Firmware for the Raspberry Pi + + + Updating the firmware on your Raspberry Pi device improves + performance and fixes reported bugs. + + + https://www.raspberrypi.org/ + CC0-1.0 + proprietary + Raspberry Pi Foundation + + + + This release fixes device startup when running in FIXME mode. + + + + diff --git a/data/tests/rpiupdate/overlays/test.dtb b/data/tests/rpiupdate/overlays/test.dtb new file mode 100644 index 000000000..e69de29bb diff --git a/data/tests/rpiupdate/start.elf b/data/tests/rpiupdate/start.elf new file mode 100644 index 000000000..32577d8f0 Binary files /dev/null and b/data/tests/rpiupdate/start.elf differ diff --git a/src/Makefile.am b/src/Makefile.am index c1f437601..11b8c9349 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -14,6 +14,7 @@ AM_CPPFLAGS = \ $(UEFI_CFLAGS) \ $(GPGME_CFLAGS) \ $(SOUP_CFLAGS) \ + $(ARCHIVE_CFLAGS) \ -I$(top_srcdir) \ -I$(top_builddir) \ -I$(top_srcdir)/libfwupd \ @@ -98,6 +99,8 @@ fwupd_SOURCES = \ fu-pending.h \ fu-provider.c \ fu-provider.h \ + fu-provider-rpi.c \ + fu-provider-rpi.h \ fu-provider-udev.c \ fu-provider-udev.h \ fu-provider-usb.c \ @@ -131,6 +134,7 @@ fwupd_LDADD = \ $(POLKIT_LIBS) \ $(SQLITE_LIBS) \ $(GPGME_LIBS) \ + $(ARCHIVE_LIBS) \ $(UEFI_LIBS) fwupd_LDFLAGS = \ @@ -193,6 +197,8 @@ fu_self_test_SOURCES = \ fu-provider.h \ fu-provider-fake.c \ fu-provider-fake.h \ + fu-provider-rpi.c \ + fu-provider-rpi.h \ fu-rom.c \ fu-rom.h \ fu-self-test.c @@ -203,6 +209,7 @@ fu_self_test_LDADD = \ $(SQLITE_LIBS) \ $(GCAB_LIBS) \ $(GPGME_LIBS) \ + $(ARCHIVE_LIBS) \ $(GLIB_LIBS) fu_self_test_CFLAGS = \ diff --git a/src/fu-main.c b/src/fu-main.c index df0da4db0..5e5161e5f 100644 --- a/src/fu-main.c +++ b/src/fu-main.c @@ -40,6 +40,7 @@ #include "fu-keyring.h" #include "fu-pending.h" #include "fu-provider.h" +#include "fu-provider-rpi.h" #include "fu-provider-udev.h" #include "fu-provider-usb.h" #include "fu-resources.h" @@ -1537,6 +1538,7 @@ main (int argc, char *argv[]) if (g_key_file_get_boolean (config, "fwupd", "EnableOptionROM", NULL)) fu_main_add_provider (priv, fu_provider_udev_new ()); fu_main_add_provider (priv, fu_provider_usb_new ()); + fu_main_add_provider (priv, fu_provider_rpi_new ()); #ifdef HAVE_COLORHUG fu_main_add_provider (priv, fu_provider_chug_new ()); #endif diff --git a/src/fu-provider-rpi.c b/src/fu-provider-rpi.c new file mode 100644 index 000000000..c31c4e245 --- /dev/null +++ b/src/fu-provider-rpi.c @@ -0,0 +1,379 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- + * + * Copyright (C) 2015 Richard Hughes + * + * Licensed under the GNU General Public License Version 2 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include "config.h" + +#include +#include +#include +#include +#include +#include + +#include "fu-cleanup.h" +#include "fu-guid.h" +#include "fu-device.h" +#include "fu-provider-rpi.h" + +static void fu_provider_rpi_finalize (GObject *object); + +#define FU_PROVIDER_RPI_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), FU_TYPE_PROVIDER_RPI, FuProviderRpiPrivate)) + +#define FU_PROVIDER_RPI_FIRMWARE_FILENAME "start.elf" + +/** + * FuProviderRpiPrivate: + **/ +struct _FuProviderRpiPrivate +{ + gchar *fw_dir; +}; + +G_DEFINE_TYPE (FuProviderRpi, fu_provider_rpi, FU_TYPE_PROVIDER) + +/** + * fu_provider_rpi_get_name: + **/ +static const gchar * +fu_provider_rpi_get_name (FuProvider *provider) +{ + return "RaspberryPi"; +} + +/** + * fu_provider_rpi_strstr: + **/ +static gchar * +fu_provider_rpi_strstr (const guint8 *haystack, + gsize haystack_len, + const gchar *needle, + guint *offset) +{ + guint i; + guint needle_len; + + if (needle == NULL || needle[0] == '\0') + return NULL; + if (haystack == NULL || haystack_len == 0) + return NULL; + needle_len = strlen (needle); + if (needle_len > haystack_len) + return NULL; + for (i = 0; i < haystack_len - needle_len; i++) { + if (memcmp (haystack + i, needle, needle_len) == 0) { + if (offset != NULL) + *offset = i + needle_len; + return g_strdup ((const gchar *) &haystack[i + needle_len]); + } + } + return NULL; +} + +/** + * fu_provider_rpi_parse_firmware: + **/ +static gboolean +fu_provider_rpi_parse_firmware (FuDevice *device, const gchar *fn, GError **error) +{ + GDate *date; + gsize len = 0; + guint offset; + _cleanup_free_ gchar *fwver = NULL; + _cleanup_free_ gchar *platform = NULL; + _cleanup_free_ gchar *vc_date = NULL; + _cleanup_free_ gchar *vc_time = NULL; + _cleanup_free_ guint8 *data = NULL; + + /* read file -- things we can find are: + * + * VC_BUILD_ID_USER: dc4 + * VC_BUILD_ID_TIME: 14:58:37 + * VC_BUILD_ID_BRANCH: master + * VC_BUILD_ID_TIME: Aug 3 2015 + * VC_BUILD_ID_HOSTNAME: dc4-XPS13-9333 + * VC_BUILD_ID_PLATFORM: raspberrypi_linux + * VC_BUILD_ID_VERSION: 4b51d81eb0068a875b336f4cc2c468cbdd06d0c5 (clean) + */ + if (!g_file_get_contents (fn, (gchar **) &data, &len, error)) + return FALSE; + + /* check the platform matches */ + platform = fu_provider_rpi_strstr (data, len, + "VC_BUILD_ID_PLATFORM: ", + NULL); + if (g_strcmp0 (platform, "raspberrypi_linux") != 0) { + g_set_error (error, + FWUPD_ERROR, + FWUPD_ERROR_INVALID_FILE, + "not a RasberryPi, platform is %s", + platform); + return FALSE; + } + + /* find the VC_BUILD info which paradoxically is split into two + * string segments */ + vc_time = fu_provider_rpi_strstr (data, len, + "VC_BUILD_ID_TIME: ", &offset); + if (vc_time == NULL) { + g_set_error_literal (error, + FWUPD_ERROR, + FWUPD_ERROR_INVALID_FILE, + "Failed to get 1st VC_BUILD_ID_TIME"); + return FALSE; + } + vc_date = fu_provider_rpi_strstr (data + offset, len - offset, + "VC_BUILD_ID_TIME: ", NULL); + if (vc_date == NULL) { + g_set_error_literal (error, + FWUPD_ERROR, + FWUPD_ERROR_INVALID_FILE, + "Failed to get 2nd VC_BUILD_ID_TIME"); + return FALSE; + } + + /* parse the date */ + date = g_date_new (); + g_date_set_parse (date, vc_date); + if (!g_date_valid (date)) { + g_set_error (error, + FWUPD_ERROR, + FWUPD_ERROR_INVALID_FILE, + "Failed to parse date '%s'", + vc_date); + return FALSE; + } + + /* create a version number from the date and time */ + fwver = g_strdup_printf ("%04i%02i%02i", + g_date_get_year (date), + g_date_get_month (date), + g_date_get_day (date)); + fu_device_set_metadata (device, FU_DEVICE_KEY_VERSION, fwver); + + g_date_free (date); + return TRUE; +} + +/** + * fu_provider_rpi_explode_file: + **/ +static gboolean +fu_provider_rpi_explode_file (struct archive_entry *entry, const gchar *dir) +{ + const gchar *tmp; + _cleanup_free_ gchar *buf = NULL; + + /* no output file */ + if (archive_entry_pathname (entry) == NULL) + return FALSE; + + /* update output path */ + tmp = archive_entry_pathname (entry); + buf = g_build_filename (dir, tmp, NULL); + archive_entry_update_pathname_utf8 (entry, buf); + return TRUE; +} + +/** + * fu_provider_rpi_update: + **/ +static gboolean +fu_provider_rpi_update (FuProvider *provider, + FuDevice *device, + gint fd, + FuProviderFlags flags, + GError **error) +{ + FuProviderRpi *provider_rpi = FU_PROVIDER_RPI (provider); + gboolean ret = TRUE; + gboolean valid; + int r; + struct archive *arch = NULL; + struct archive_entry *entry; + _cleanup_free_ gchar *fwfn = NULL; + + /* decompress anything matching either glob */ + fu_provider_set_status (provider, FWUPD_STATUS_DECOMPRESSING); + arch = archive_read_new (); + archive_read_support_format_all (arch); + archive_read_support_filter_all (arch); + r = archive_read_open_fd (arch, fd, 1024 * 32); + if (r) { + ret = FALSE; + g_set_error (error, + FWUPD_ERROR, + FWUPD_ERROR_INTERNAL, + "Cannot open: %s", + archive_error_string (arch)); + goto out; + } + fu_provider_set_status (provider, FWUPD_STATUS_DEVICE_WRITE); + for (;;) { + _cleanup_free_ gchar *path = NULL; + r = archive_read_next_header (arch, &entry); + if (r == ARCHIVE_EOF) + break; + if (r != ARCHIVE_OK) { + ret = FALSE; + g_set_error (error, + FWUPD_ERROR, + FWUPD_ERROR_INTERNAL, + "Cannot read header: %s", + archive_error_string (arch)); + goto out; + } + + /* only extract if valid */ + valid = fu_provider_rpi_explode_file (entry, provider_rpi->priv->fw_dir); + if (!valid) + continue; + r = archive_read_extract (arch, entry, 0); + if (r != ARCHIVE_OK) { + ret = FALSE; + g_set_error (error, + FWUPD_ERROR, + FWUPD_ERROR_INTERNAL, + "Cannot extract: %s", + archive_error_string (arch)); + goto out; + } + } + + /* get the new VC build info */ + fu_provider_set_status (provider, FWUPD_STATUS_DEVICE_VERIFY); + fwfn = g_build_filename (provider_rpi->priv->fw_dir, + FU_PROVIDER_RPI_FIRMWARE_FILENAME, + NULL); + if (!fu_provider_rpi_parse_firmware (device, fwfn, error)) + return FALSE; +out: + if (arch != NULL) { + archive_read_close (arch); + archive_read_free (arch); + } + return ret; +} + +/** + * fu_provider_rpi_coldplug: + **/ +static gboolean +fu_provider_rpi_coldplug (FuProvider *provider, GError **error) +{ + FuProviderRpi *provider_rpi = FU_PROVIDER_RPI (provider); + _cleanup_free_ gchar *fwfn = NULL; + _cleanup_free_ gchar *fwver = NULL; + _cleanup_free_ gchar *guid = NULL; + _cleanup_object_unref_ FuDevice *device = NULL; + + /* anything interesting */ + fwfn = g_build_filename (provider_rpi->priv->fw_dir, + FU_PROVIDER_RPI_FIRMWARE_FILENAME, + NULL); + if (!g_file_test (fwfn, G_FILE_TEST_EXISTS)) + return TRUE; + + /* create fake device */ + device = fu_device_new (); + fu_device_set_id (device, "raspberry-pi"); + guid = fu_guid_generate_from_string ("raspberrypi"); + fu_device_set_guid (device, guid); + fu_device_set_display_name (device, "Raspberry Pi"); + fu_device_add_flag (device, FU_DEVICE_FLAG_INTERNAL); + fu_device_add_flag (device, FU_DEVICE_FLAG_ALLOW_OFFLINE); + fu_device_add_flag (device, FU_DEVICE_FLAG_ALLOW_ONLINE); + + /* get the VC build info */ + if (!fu_provider_rpi_parse_firmware (device, fwfn, error)) + return FALSE; + + fu_provider_device_add (provider, device); + return TRUE; +} + +/** + * fu_provider_rpi_class_init: + **/ +static void +fu_provider_rpi_class_init (FuProviderRpiClass *klass) +{ + FuProviderClass *provider_class = FU_PROVIDER_CLASS (klass); + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + provider_class->get_name = fu_provider_rpi_get_name; + provider_class->coldplug = fu_provider_rpi_coldplug; + provider_class->update_online = fu_provider_rpi_update; + object_class->finalize = fu_provider_rpi_finalize; + + g_type_class_add_private (klass, sizeof (FuProviderRpiPrivate)); +} + +/** + * fu_provider_rpi_init: + **/ +static void +fu_provider_rpi_init (FuProviderRpi *provider_rpi) +{ + const gchar *tmp; + provider_rpi->priv = FU_PROVIDER_RPI_GET_PRIVATE (provider_rpi); + + /* allow this to be overidden for testing */ + provider_rpi->priv->fw_dir = g_strdup ("/boot"); + tmp = g_getenv ("FWUPD_RPI_FW_DIR"); + if (tmp != NULL) + fu_provider_rpi_set_fw_dir (provider_rpi, tmp); +} + +/** + * fu_provider_rpi_set_fw_dir: + **/ +void +fu_provider_rpi_set_fw_dir (FuProviderRpi *provider_rpi, const gchar *fw_dir) +{ + g_free (provider_rpi->priv->fw_dir); + provider_rpi->priv->fw_dir = g_strdup (fw_dir); + g_mkdir_with_parents (fw_dir, 0700); +} + +/** + * fu_provider_rpi_finalize: + **/ +static void +fu_provider_rpi_finalize (GObject *object) +{ + FuProviderRpi *provider_rpi = FU_PROVIDER_RPI (object); + FuProviderRpiPrivate *priv = provider_rpi->priv; + + g_free (priv->fw_dir); + + G_OBJECT_CLASS (fu_provider_rpi_parent_class)->finalize (object); +} + +/** + * fu_provider_rpi_new: + **/ +FuProvider * +fu_provider_rpi_new (void) +{ + FuProviderRpi *provider; + provider = g_object_new (FU_TYPE_PROVIDER_RPI, NULL); + return FU_PROVIDER (provider); +} diff --git a/src/fu-provider-rpi.h b/src/fu-provider-rpi.h new file mode 100644 index 000000000..8e2483e89 --- /dev/null +++ b/src/fu-provider-rpi.h @@ -0,0 +1,58 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- + * + * Copyright (C) 2015 Richard Hughes + * + * Licensed under the GNU General Public License Version 2 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifndef __FU_PROVIDER_RPI_H +#define __FU_PROVIDER_RPI_H + +#include + +#include "fu-device.h" +#include "fu-provider.h" + +G_BEGIN_DECLS + +#define FU_TYPE_PROVIDER_RPI (fu_provider_rpi_get_type ()) +#define FU_PROVIDER_RPI(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), FU_TYPE_PROVIDER_RPI, FuProviderRpi)) +#define FU_IS_PROVIDER_RPI(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), FU_TYPE_PROVIDER_RPI)) + +typedef struct _FuProviderRpiPrivate FuProviderRpiPrivate; +typedef struct _FuProviderRpi FuProviderRpi; +typedef struct _FuProviderRpiClass FuProviderRpiClass; + +struct _FuProviderRpi +{ + FuProvider parent; + FuProviderRpiPrivate *priv; +}; + +struct _FuProviderRpiClass +{ + FuProviderClass parent_class; +}; + +GType fu_provider_rpi_get_type (void); +FuProvider *fu_provider_rpi_new (void); +void fu_provider_rpi_set_fw_dir (FuProviderRpi *provider_rpi, + const gchar *fw_dir); + +G_END_DECLS + +#endif /* __FU_PROVIDER_RPI_H */ diff --git a/src/fu-self-test.c b/src/fu-self-test.c index ba2452f51..35f59400c 100644 --- a/src/fu-self-test.c +++ b/src/fu-self-test.c @@ -24,6 +24,7 @@ #include #include #include +#include #include #include "fu-cab.h" @@ -32,6 +33,7 @@ #include "fu-keyring.h" #include "fu-pending.h" #include "fu-provider-fake.h" +#include "fu-provider-rpi.h" #include "fu-rom.h" /** @@ -354,6 +356,76 @@ fu_provider_func (void) g_unlink (pending_cap); } +static void +fu_provider_rpi_func (void) +{ + gboolean ret; + guint cnt = 0; + int fd; + _cleanup_error_free_ GError *error = NULL; + _cleanup_free_ gchar *path = NULL; + _cleanup_free_ gchar *pending_db = NULL; + _cleanup_free_ gchar *fwfile = NULL; + _cleanup_object_unref_ FuDevice *device = NULL; + _cleanup_object_unref_ FuProvider *provider = NULL; + _cleanup_object_unref_ GFile *file = NULL; + _cleanup_object_unref_ GInputStream *stream = NULL; + + /* test location */ + path = fu_test_get_filename ("rpiboot"); + g_assert (path != NULL); + + /* create a fake device */ + provider = fu_provider_rpi_new (); + fu_provider_rpi_set_fw_dir (FU_PROVIDER_RPI (provider), path); + g_signal_connect (provider, "device-added", + G_CALLBACK (_provider_device_added_cb), + &device); + g_signal_connect (provider, "status-changed", + G_CALLBACK (_provider_status_changed_cb), + &cnt); + ret = fu_provider_coldplug (provider, &error); + g_assert_no_error (error); + g_assert (ret); + + /* check we did the right thing */ + g_assert_cmpint (cnt, ==, 0); + g_assert (device != NULL); + g_assert_cmpstr (fu_device_get_id (device), ==, "raspberry-pi"); + g_assert_cmpstr (fu_device_get_guid (device), ==, + "c77029fe-ffb2-3706-dc67-67af4a132afd"); + g_assert_cmpstr (fu_device_get_metadata (device, FU_DEVICE_KEY_VERSION), ==, + "20150803"); + + /* ensure clean */ + g_unlink ("/tmp/rpiboot/start.elf"); + + /* do update */ + fu_provider_rpi_set_fw_dir (FU_PROVIDER_RPI (provider), "/tmp/rpiboot"); + fwfile = fu_test_get_filename ("rpiupdate/firmware.bin"); + g_assert (fwfile != NULL); + file = g_file_new_for_path (fwfile); + stream = G_INPUT_STREAM (g_file_read (file, NULL, &error)); + fd = g_file_descriptor_based_get_fd (G_FILE_DESCRIPTOR_BASED (stream)); + g_assert_no_error (error); + g_assert (stream != NULL); + ret = fu_provider_update (provider, device, NULL, fd, + FU_PROVIDER_UPDATE_FLAG_NONE, &error); + g_assert_no_error (error); + g_assert (ret); + g_assert_cmpint (cnt, ==, 3); + + /* check the file was exploded to the right place */ + g_assert (g_file_test ("/tmp/rpiboot/start.elf", G_FILE_TEST_EXISTS)); + g_assert (g_file_test ("/tmp/rpiboot/overlays/test.dtb", G_FILE_TEST_EXISTS)); + g_assert_cmpstr (fu_device_get_metadata (device, FU_DEVICE_KEY_VERSION), ==, + "20150805"); + + /* clean up */ + pending_db = g_build_filename (LOCALSTATEDIR, "lib", "fwupd", "pending.db", NULL); + g_unlink (pending_db); +} + static void fu_pending_func (void) { @@ -491,6 +563,7 @@ main (int argc, char **argv) g_test_add_func ("/fwupd/cab", fu_cab_func); g_test_add_func ("/fwupd/pending", fu_pending_func); g_test_add_func ("/fwupd/provider", fu_provider_func); + g_test_add_func ("/fwupd/provider{rpi}", fu_provider_rpi_func); g_test_add_func ("/fwupd/keyring", fu_keyring_func); return g_test_run (); } diff --git a/src/run-fwupd.sh b/src/run-fwupd.sh index 210c113cf..30210c803 100755 --- a/src/run-fwupd.sh +++ b/src/run-fwupd.sh @@ -1,2 +1,2 @@ #!/usr/bin/sh -sudo LIBFWUP_ESRT_DIR="../../fwupdate/linux/sys/firmware/efi/esrt/" ./fwupd --verbose +sudo LIBFWUP_ESRT_DIR="../../fwupdate/linux/sys/firmware/efi/esrt/" FWUPD_RPI_FW_DIR="../data/tests/rpiboot" ./fwupd --verbose
+ Updating the firmware on your Raspberry Pi device improves + performance and fixes reported bugs. +
This release fixes device startup when running in FIXME mode.