static gboolean fu_provider_uefi_update (FuProvider *provider, FuDevice *device, GBytes *blob_fw, FwupdInstallFlags flags, GError **error) { g_autoptr(GError) error_local = NULL; fwup_resource *re = NULL; guint64 hardware_instance = 0; /* FIXME */ int rc; g_autoptr(fwup_resource_iter) iter = NULL; /* get the hardware we're referencing */ fwup_resource_iter_create (&iter); re = fu_provider_uefi_find (iter, fu_device_get_guid_default (device), error); if (re == NULL) return FALSE; /* perform the update */ g_debug ("Performing UEFI capsule update"); fu_provider_set_status (provider, FWUPD_STATUS_SCHEDULING); rc = fwup_set_up_update_with_buf (re, hardware_instance, g_bytes_get_data (blob_fw, NULL), g_bytes_get_size (blob_fw)); if (rc < 0) { g_set_error (error, FWUPD_ERROR, FWUPD_ERROR_NOT_SUPPORTED, "UEFI firmware update failed: %s", strerror (rc)); return FALSE; } return TRUE; }
/** * fu_provider_schedule_update: **/ static gboolean fu_provider_schedule_update (FuProvider *provider, FuDevice *device, GBytes *blob_cab, GError **error) { gchar tmpname[] = {"XXXXXX.cap"}; guint i; g_autofree gchar *dirname = NULL; g_autofree gchar *filename = NULL; g_autoptr(FuDevice) device_tmp = NULL; g_autoptr(FuPending) pending = NULL; g_autoptr(GFile) file = NULL; /* id already exists */ pending = fu_pending_new (); device_tmp = fu_pending_get_device (pending, fu_device_get_id (device), NULL); if (device_tmp != NULL) { g_set_error (error, FWUPD_ERROR, FWUPD_ERROR_ALREADY_PENDING, "%s is already scheduled to be updated", fu_device_get_id (device)); return FALSE; } /* create directory */ dirname = g_build_filename (LOCALSTATEDIR, "lib", "fwupd", NULL); file = g_file_new_for_path (dirname); if (!g_file_query_exists (file, NULL)) { if (!g_file_make_directory_with_parents (file, NULL, error)) return FALSE; } /* get a random filename */ for (i = 0; i < 6; i++) tmpname[i] = g_random_int_range ('A', 'Z'); filename = g_build_filename (dirname, tmpname, NULL); /* just copy to the temp file */ fu_provider_set_status (provider, FWUPD_STATUS_SCHEDULING); if (!g_file_set_contents (filename, g_bytes_get_data (blob_cab, NULL), g_bytes_get_size (blob_cab), error)) return FALSE; /* schedule for next boot */ g_debug ("schedule %s to be installed to %s on next boot", filename, fu_device_get_id (device)); fu_device_set_metadata (device, FU_DEVICE_KEY_FILENAME_CAB, filename); /* add to database */ if (!fu_pending_add_device (pending, device, error)) return FALSE; /* next boot we run offline */ return fu_provider_offline_setup (error); }
static gboolean fu_provider_chug_verify (FuProvider *provider, FuDevice *device, FuProviderVerifyFlags flags, GError **error) { FuProviderChug *provider_chug = FU_PROVIDER_CHUG (provider); FuProviderChugPrivate *priv = GET_PRIVATE (provider_chug); FuProviderChugItem *item; GChecksumType checksum_type; gsize len; g_autoptr(GError) error_local = NULL; g_autofree gchar *hash = NULL; g_autofree guint8 *data = NULL; /* find item */ item = g_hash_table_lookup (priv->devices, fu_device_get_id (device)); if (item == NULL) { g_set_error (error, FWUPD_ERROR, FWUPD_ERROR_NOT_FOUND, "cannot find: %s", fu_device_get_id (device)); return FALSE; } /* open */ if (!fu_provider_chug_open (item, error)) return FALSE; /* get the firmware from the device */ g_debug ("ColorHug: Verifying firmware"); ch_device_queue_read_firmware (priv->device_queue, item->usb_device, &data, &len); fu_provider_set_status (provider, FWUPD_STATUS_DEVICE_VERIFY); if (!ch_device_queue_process (priv->device_queue, CH_DEVICE_QUEUE_PROCESS_FLAGS_NONE, NULL, &error_local)) { g_set_error (error, FWUPD_ERROR, FWUPD_ERROR_WRITE, "failed to dump firmware: %s", error_local->message); g_usb_device_close (item->usb_device, NULL); return FALSE; } /* get the checksum */ checksum_type = fu_provider_get_checksum_type (flags); hash = g_compute_checksum_for_data (checksum_type, (guchar *) data, len); fu_device_set_checksum (device, hash); fu_device_set_checksum_kind (device, checksum_type); /* we're done here */ if (!g_usb_device_close (item->usb_device, &error_local)) g_debug ("Failed to close: %s", error_local->message); return TRUE; }
/** * fu_provider_fake_update: **/ static gboolean fu_provider_fake_update (FuProvider *provider, FuDevice *device, GBytes *blob_fw, FuProviderFlags flags, GError **error) { if (flags & FU_PROVIDER_UPDATE_FLAG_OFFLINE) { g_set_error_literal (error, FWUPD_ERROR, FWUPD_ERROR_INTERNAL, "cannot handle offline"); } fu_provider_set_status (provider, FWUPD_STATUS_DECOMPRESSING); fu_provider_set_status (provider, FWUPD_STATUS_DEVICE_WRITE); return TRUE; }
/** * fu_provider_schedule_update: **/ static gboolean fu_provider_schedule_update (FuProvider *provider, FuDevice *device, GInputStream *stream, GError **error) { gchar tmpname[] = {"XXXXXX.cap"}; guint i; _cleanup_bytes_unref_ GBytes *fwbin = NULL; _cleanup_free_ gchar *dirname = NULL; _cleanup_free_ gchar *filename = NULL; _cleanup_object_unref_ FuDevice *device_tmp = NULL; _cleanup_object_unref_ FuPending *pending = NULL; _cleanup_object_unref_ GFile *file = NULL; /* id already exists */ pending = fu_pending_new (); device_tmp = fu_pending_get_device (pending, fu_device_get_id (device), NULL); if (device_tmp != NULL) { g_set_error (error, FWUPD_ERROR, FWUPD_ERROR_ALREADY_PENDING, "%s is already scheduled to be updated", fu_device_get_id (device)); return FALSE; } /* create directory */ dirname = g_build_filename (LOCALSTATEDIR, "lib", "fwupd", NULL); file = g_file_new_for_path (dirname); if (!g_file_query_exists (file, NULL)) { if (!g_file_make_directory_with_parents (file, NULL, error)) return FALSE; } /* get a random filename */ for (i = 0; i < 6; i++) tmpname[i] = g_random_int_range ('A', 'Z'); filename = g_build_filename (dirname, tmpname, NULL); /* just copy to the temp file */ fu_provider_set_status (provider, FWUPD_STATUS_SCHEDULING); if (!g_seekable_seek (G_SEEKABLE (stream), 0, G_SEEK_SET, NULL, error)) return FALSE; fwbin = g_input_stream_read_bytes (stream, FU_PROVIDER_FIRMWARE_MAX, NULL, error); if (fwbin == NULL) return FALSE; if (!g_file_set_contents (filename, g_bytes_get_data (fwbin, NULL), g_bytes_get_size (fwbin), error)) return FALSE; /* schedule for next boot */ g_debug ("schedule %s to be installed to %s on next boot", filename, fu_device_get_id (device)); fu_device_set_metadata (device, FU_DEVICE_KEY_FILENAME_CAB, filename); /* add to database */ if (!fu_pending_add_device (pending, device, error)) return FALSE; /* next boot we run offline */ return fu_provider_offline_setup (error); }
static gboolean fu_provider_chug_update (FuProvider *provider, FuDevice *device, GBytes *blob_fw, FwupdInstallFlags flags, GError **error) { FuProviderChug *provider_chug = FU_PROVIDER_CHUG (provider); FuProviderChugPrivate *priv = GET_PRIVATE (provider_chug); FuProviderChugItem *item; g_autoptr(GError) error_local = NULL; /* find item */ item = g_hash_table_lookup (priv->devices, fu_device_get_id (device)); if (item == NULL) { g_set_error (error, FWUPD_ERROR, FWUPD_ERROR_NOT_FOUND, "cannot find: %s", fu_device_get_id (device)); return FALSE; } /* this file is so small, just slurp it all in one go */ item->fw_bin = g_bytes_ref (blob_fw); /* check this firmware is actually for this device */ if (!ch_device_check_firmware (item->usb_device, g_bytes_get_data (item->fw_bin, NULL), g_bytes_get_size (item->fw_bin), &error_local)) { g_set_error (error, FWUPD_ERROR, FWUPD_ERROR_NOT_SUPPORTED, "firmware is not suitable: %s", error_local->message); return FALSE; } /* switch to bootloader mode */ if (!item->is_bootloader) { g_debug ("ColorHug: Switching to bootloader mode"); if (!fu_provider_chug_open (item, error)) return FALSE; ch_device_queue_reset (priv->device_queue, item->usb_device); fu_provider_set_status (provider, FWUPD_STATUS_DEVICE_RESTART); if (!ch_device_queue_process (priv->device_queue, CH_DEVICE_QUEUE_PROCESS_FLAGS_NONE, NULL, &error_local)) { g_set_error (error, FWUPD_ERROR, FWUPD_ERROR_WRITE, "failed to reset device: %s", error_local->message); g_usb_device_close (item->usb_device, NULL); return FALSE; } /* this device has just gone away, no error possible */ g_usb_device_close (item->usb_device, NULL); /* wait for reconnection */ g_debug ("ColorHug: Waiting for bootloader"); if (!fu_provider_chug_wait_for_connect (provider_chug, item, error)) return FALSE; } /* open the device, which is now in bootloader mode */ if (!fu_provider_chug_open (item, error)) return FALSE; /* write firmware */ g_debug ("ColorHug: Writing firmware"); ch_device_queue_write_firmware (priv->device_queue, item->usb_device, g_bytes_get_data (item->fw_bin, NULL), g_bytes_get_size (item->fw_bin)); fu_provider_set_status (provider, FWUPD_STATUS_DEVICE_WRITE); if (!ch_device_queue_process (priv->device_queue, CH_DEVICE_QUEUE_PROCESS_FLAGS_NONE, NULL, &error_local)) { g_set_error (error, FWUPD_ERROR, FWUPD_ERROR_WRITE, "failed to write firmware: %s", error_local->message); g_usb_device_close (item->usb_device, NULL); return FALSE; } /* verify firmware */ g_debug ("ColorHug: Veifying firmware"); ch_device_queue_verify_firmware (priv->device_queue, item->usb_device, g_bytes_get_data (item->fw_bin, NULL), g_bytes_get_size (item->fw_bin)); fu_provider_set_status (provider, FWUPD_STATUS_DEVICE_VERIFY); if (!ch_device_queue_process (priv->device_queue, CH_DEVICE_QUEUE_PROCESS_FLAGS_NONE, NULL, &error_local)) { g_set_error (error, FWUPD_ERROR, FWUPD_ERROR_WRITE, "failed to verify firmware: %s", error_local->message); g_usb_device_close (item->usb_device, NULL); return FALSE; } /* boot into the new firmware */ g_debug ("ColorHug: Booting new firmware"); ch_device_queue_boot_flash (priv->device_queue, item->usb_device); fu_provider_set_status (provider, FWUPD_STATUS_DEVICE_RESTART); if (!ch_device_queue_process (priv->device_queue, CH_DEVICE_QUEUE_PROCESS_FLAGS_NONE, NULL, &error_local)) { g_set_error (error, FWUPD_ERROR, FWUPD_ERROR_WRITE, "failed to boot flash: %s", error_local->message); g_usb_device_close (item->usb_device, NULL); return FALSE; } /* this device has just gone away, no error possible */ g_usb_device_close (item->usb_device, NULL); /* wait for firmware mode */ if (!fu_provider_chug_wait_for_connect (provider_chug, item, error)) return FALSE; if (!fu_provider_chug_open (item, error)) return FALSE; /* set flash success */ g_debug ("ColorHug: Setting flash success"); ch_device_queue_set_flash_success (priv->device_queue, item->usb_device, 1); if (!ch_device_queue_process (priv->device_queue, CH_DEVICE_QUEUE_PROCESS_FLAGS_NONE, NULL, &error_local)) { g_set_error (error, FWUPD_ERROR, FWUPD_ERROR_WRITE, "failed to set flash success: %s", error_local->message); g_usb_device_close (item->usb_device, NULL); return FALSE; } /* close, orderly */ if (!g_usb_device_close (item->usb_device, &error_local)) { g_set_error (error, FWUPD_ERROR, FWUPD_ERROR_WRITE, "failed to close device: %s", error_local->message); g_usb_device_close (item->usb_device, NULL); return FALSE; } /* get the new firmware version */ g_debug ("ColorHug: Getting new firmware version"); item->got_version = FALSE; fu_provider_chug_get_firmware_version (item); if (item->got_version) g_debug ("ColorHug: DONE!"); return TRUE; }