mirror of
https://git.proxmox.com/git/fwupd
synced 2025-07-25 06:11:22 +00:00
plugins: android-boot: new plugin
Add a plugin for supporting Android bootloaders which are used on all Qualcomm-based Android devices. These bootloaders are stored on their own partitions and the partition table cannot be altered on Qualcomm devices. This plugin supports any block device, but only exposes the ones defined in the quirk file as updatable.
This commit is contained in:
parent
92db5fc87a
commit
d0d4b17a7f
@ -432,6 +432,7 @@ done
|
||||
%{_libdir}/fwupd-plugins-%{fwupdplugin_version}/libfu_plugin_acpi_phat.so
|
||||
%{_libdir}/fwupd-plugins-%{fwupdplugin_version}/libfu_plugin_amt.so
|
||||
%{_libdir}/fwupd-plugins-%{fwupdplugin_version}/libfu_plugin_analogix.so
|
||||
%{_libdir}/fwupd-plugins-%{fwupdplugin_version}/libfu_plugin_android_boot.so
|
||||
%{_libdir}/fwupd-plugins-%{fwupdplugin_version}/libfu_plugin_ata.so
|
||||
%{_libdir}/fwupd-plugins-%{fwupdplugin_version}/libfu_plugin_bcm57xx.so
|
||||
%{_libdir}/fwupd-plugins-%{fwupdplugin_version}/libfu_plugin_cfu.so
|
||||
|
@ -18,6 +18,7 @@ option('lzma', type: 'feature', description : 'LZMA support', deprecated: {'true
|
||||
option('cbor', type: 'feature', description : 'CBOR support for coSWID and uSWID')
|
||||
option('plugin_amt', type : 'feature', description : 'Intel AMT support', deprecated: {'true': 'enabled', 'false': 'disabled'})
|
||||
option('plugin_acpi_phat', type : 'feature', description : 'ACPI PHAT support', deprecated: {'true': 'enabled', 'false': 'disabled'})
|
||||
option('plugin_android_boot', type : 'feature', description : 'Android Boot support')
|
||||
option('plugin_bcm57xx', type : 'feature', description : 'BCM57xx support', deprecated: {'true': 'enabled', 'false': 'disabled'})
|
||||
option('plugin_cfu', type : 'feature', description : 'CFU support', deprecated: {'true': 'enabled', 'false': 'disabled'})
|
||||
option('plugin_cpu', type : 'feature', description : 'CPU support', deprecated: {'true': 'enabled', 'false': 'disabled'})
|
||||
|
53
plugins/android-boot/README.md
Normal file
53
plugins/android-boot/README.md
Normal file
@ -0,0 +1,53 @@
|
||||
# Android Bootloaders
|
||||
|
||||
## Introduction
|
||||
|
||||
This plugin is used to update hardware that use partitions to store their firmware on.
|
||||
|
||||
## Firmware Format
|
||||
|
||||
The daemon will decompress the cabinet archive and extract a firmware blob as a Raw Disk File
|
||||
in the IMG format. The firmware blob will be flashed to the partition. Fastboot devices are similar
|
||||
but are flashed in fastboot mode using an external device. This plugin is similar but can be used
|
||||
to flash from the device itself rather than external device.
|
||||
|
||||
This plugin supports the following protocol ID:
|
||||
|
||||
* com.google.android_boot
|
||||
|
||||
## GUID Generation
|
||||
|
||||
The GUID is generated by combining the partition UUID of the block device, its label and optionally boot slot
|
||||
when using an Android A/B partitioning scheme, e.g.
|
||||
|
||||
* `DRIVE\UUID_c49183ed-aaec-9bf5-760a-66330fbcffc1&LABEL_label&SLOT_a`
|
||||
* `DRIVE\UUID_c49183ed-aaec-9bf5-760a-66330fbcffc1&LABEL_label`
|
||||
* `DRIVE\UUID_c49183ed-aaec-9bf5-760a-66330fbcffc1`
|
||||
|
||||
## Update Behavior
|
||||
|
||||
The block device is erased in chunks, written and then read back to verify.
|
||||
|
||||
## Quirk Use
|
||||
|
||||
This plugin uses the following plugin-specific quirk:
|
||||
|
||||
### AndroidBootVersionProperty
|
||||
|
||||
Property to parse from `/proc/cmdline` to retrieve the bootloader version.
|
||||
|
||||
Since: 1.8.5
|
||||
|
||||
### AndroidBootPartitionMaxSize
|
||||
|
||||
Maximum size the firmware may use of a partition.
|
||||
|
||||
Since: 1.8.5
|
||||
|
||||
## Vendor ID Security
|
||||
|
||||
The vendor ID is set through the `android-boot.quirk` file.
|
||||
|
||||
## External Interface Access
|
||||
|
||||
This plugin requires read/write access to `/dev/block`.
|
16
plugins/android-boot/android-boot.quirk
Normal file
16
plugins/android-boot/android-boot.quirk
Normal file
@ -0,0 +1,16 @@
|
||||
[BLOCK]
|
||||
Plugin = android_boot
|
||||
|
||||
# SHIFT6mq ABL A
|
||||
[DRIVE\UUID_c49183ed-aaec-9bf5-760a-66330fbcffc1&LABEL_abl-a]
|
||||
Flags = updatable,signed-payload
|
||||
Vendor = SHIFT GmbH
|
||||
VendorId = eco.shift
|
||||
AndroidBootVersionProperty = androidboot.abl.revision
|
||||
|
||||
# SHIFT6mq ABL B
|
||||
[DRIVE\UUID_3d7b21e8-048b-db0b-0c18-d07a9bb32f2d&LABEL_abl-b]
|
||||
Flags = updatable,signed-payload
|
||||
Vendor = SHIFT GmbH
|
||||
VendorId = eco.shift
|
||||
AndroidBootVersionProperty = androidboot.abl.revision
|
374
plugins/android-boot/fu-android-boot-device.c
Normal file
374
plugins/android-boot/fu-android-boot-device.c
Normal file
@ -0,0 +1,374 @@
|
||||
/*
|
||||
* Copyright (C) 2022 Dylan Van Assche <me@dylanvanassche.be>
|
||||
*
|
||||
* SPDX-License-Identifier: LGPL-2.1+
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <fwupdplugin.h>
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "fu-android-boot-device.h"
|
||||
|
||||
#define ANDROID_BOOT_UNKNOWN_VERSION "0.0.0"
|
||||
#define ANDROID_BOOT_SECTOR_SIZE 512
|
||||
|
||||
struct _FuAndroidBootDevice {
|
||||
FuUdevDevice parent_instance;
|
||||
const gchar *label;
|
||||
const gchar *uuid;
|
||||
gchar *boot_slot;
|
||||
guint64 max_size;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE(FuAndroidBootDevice, fu_android_boot_device, FU_TYPE_UDEV_DEVICE)
|
||||
|
||||
static void
|
||||
fu_android_boot_device_to_string(FuDevice *device, guint idt, GString *str)
|
||||
{
|
||||
FuAndroidBootDevice *self = FU_ANDROID_BOOT_DEVICE(device);
|
||||
|
||||
fu_string_append(str, idt, "BootSlot", self->boot_slot);
|
||||
fu_string_append(str, idt, "Label", self->label);
|
||||
fu_string_append(str, idt, "UUID", self->uuid);
|
||||
fu_string_append_kx(str, idt, "MaxSize", self->max_size);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
fu_android_boot_device_probe(FuDevice *device, GError **error)
|
||||
{
|
||||
FuAndroidBootDevice *self = FU_ANDROID_BOOT_DEVICE(device);
|
||||
GUdevDevice *udev_device = fu_udev_device_get_dev(FU_UDEV_DEVICE(device));
|
||||
g_autofree gchar *serial = NULL;
|
||||
guint64 sectors = 0;
|
||||
guint64 size = 0;
|
||||
g_autoptr(GHashTable) cmdline = NULL;
|
||||
|
||||
/* FuUdevDevice->probe */
|
||||
if (!FU_DEVICE_CLASS(fu_android_boot_device_parent_class)->probe(device, error))
|
||||
return FALSE;
|
||||
|
||||
/* get kernel cmdline */
|
||||
cmdline = fu_kernel_get_cmdline(error);
|
||||
if (cmdline == NULL)
|
||||
return FALSE;
|
||||
|
||||
/* set the physical ID */
|
||||
if (!fu_udev_device_set_physical_id(FU_UDEV_DEVICE(device), "block", error))
|
||||
return FALSE;
|
||||
|
||||
/* extract boot slot if available */
|
||||
self->boot_slot = g_strdup(g_hash_table_lookup(cmdline, "androidboot.slot_suffix"));
|
||||
|
||||
/* extract label and check if it matches boot slot*/
|
||||
if (g_udev_device_has_property(udev_device, "ID_PART_ENTRY_NAME")) {
|
||||
self->label = g_udev_device_get_property(udev_device, "ID_PART_ENTRY_NAME");
|
||||
|
||||
/* Use label as device name */
|
||||
fu_device_set_name(device, self->label);
|
||||
|
||||
/* If the device has A/B partitioning, compare boot slot to only expose partitions
|
||||
* in-use */
|
||||
if (self->boot_slot != NULL && !g_str_has_suffix(self->label, self->boot_slot)) {
|
||||
g_set_error_literal(error,
|
||||
FWUPD_ERROR,
|
||||
FWUPD_ERROR_NOT_SUPPORTED,
|
||||
"device is on a different bootslot");
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
/* set max firmware size, required to avoid writing firmware bigger than partition */
|
||||
if (!g_udev_device_has_property(udev_device, "ID_PART_ENTRY_SIZE")) {
|
||||
g_set_error_literal(error,
|
||||
FWUPD_ERROR,
|
||||
FWUPD_ERROR_NOT_SUPPORTED,
|
||||
"device does not expose its size");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
sectors = g_udev_device_get_property_as_uint64(udev_device, "ID_PART_ENTRY_SIZE");
|
||||
size = sectors * ANDROID_BOOT_SECTOR_SIZE;
|
||||
self->max_size = size;
|
||||
|
||||
/* extract partition UUID and require it for supporting a device */
|
||||
if (!g_udev_device_has_property(udev_device, "ID_PART_ENTRY_UUID")) {
|
||||
g_set_error_literal(error,
|
||||
FWUPD_ERROR,
|
||||
FWUPD_ERROR_NOT_SUPPORTED,
|
||||
"device does not have a UUID");
|
||||
return FALSE;
|
||||
}
|
||||
self->uuid = g_udev_device_get_property(udev_device, "ID_PART_ENTRY_UUID");
|
||||
|
||||
/* extract serial number and set it */
|
||||
serial = g_hash_table_lookup(cmdline, "androidboot.serialno");
|
||||
fu_device_set_serial(device, serial);
|
||||
|
||||
/*
|
||||
* Some devices don't have unique TYPE UUIDs, add the partition label to make them truly
|
||||
* unique Devices have a fixed partition scheme anyway because they originally have Android
|
||||
* which has such requirements.
|
||||
*/
|
||||
fu_device_add_instance_strsafe(device, "UUID", self->uuid);
|
||||
fu_device_add_instance_strsafe(device, "LABEL", self->label);
|
||||
fu_device_add_instance_strsafe(device, "SLOT", self->boot_slot);
|
||||
|
||||
/* GUID based on UUID / UUID, label / UUID, label, slot */
|
||||
fu_device_build_instance_id(device, error, "DRIVE", "UUID", NULL);
|
||||
fu_device_build_instance_id(device, error, "DRIVE", "UUID", "LABEL", NULL);
|
||||
fu_device_build_instance_id(device, error, "DRIVE", "UUID", "LABEL", "SLOT", NULL);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
fu_android_boot_device_setup(FuDevice *device, GError **error)
|
||||
{
|
||||
FuAndroidBootDevice *self = FU_ANDROID_BOOT_DEVICE(device);
|
||||
|
||||
/* set the firmware maximum size based on partition size or from quirk */
|
||||
fu_device_set_firmware_size_max(device, self->max_size);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
fu_android_boot_device_open(FuDevice *device, GError **error)
|
||||
{
|
||||
g_autoptr(GError) error_local = NULL;
|
||||
|
||||
/* FuUdevDevice->open */
|
||||
if (!FU_DEVICE_CLASS(fu_android_boot_device_parent_class)->open(device, &error_local)) {
|
||||
if (g_error_matches(error_local, G_IO_ERROR, G_IO_ERROR_PERMISSION_DENIED)) {
|
||||
g_set_error_literal(error,
|
||||
FWUPD_ERROR,
|
||||
FWUPD_ERROR_NOT_SUPPORTED,
|
||||
error_local->message);
|
||||
return FALSE;
|
||||
}
|
||||
g_propagate_error(error, g_steal_pointer(&error_local));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
fu_android_boot_device_write(FuAndroidBootDevice *self,
|
||||
GPtrArray *chunks,
|
||||
FuProgress *progress,
|
||||
GError **error)
|
||||
{
|
||||
fu_progress_set_id(progress, G_STRLOC);
|
||||
fu_progress_set_steps(progress, chunks->len);
|
||||
|
||||
/* rewind */
|
||||
if (!fu_udev_device_seek(FU_UDEV_DEVICE(self), 0x0, error)) {
|
||||
g_prefix_error(error, "failed to rewind: ");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* write each chunk */
|
||||
for (guint i = 0; i < chunks->len; i++) {
|
||||
FuChunk *chk = g_ptr_array_index(chunks, i);
|
||||
if (!fu_udev_device_pwrite(FU_UDEV_DEVICE(self),
|
||||
fu_chunk_get_address(chk),
|
||||
fu_chunk_get_data(chk),
|
||||
fu_chunk_get_data_sz(chk),
|
||||
error)) {
|
||||
g_prefix_error(error,
|
||||
"failed to write @0x%x: ",
|
||||
(guint)fu_chunk_get_address(chk));
|
||||
return FALSE;
|
||||
}
|
||||
fu_progress_step_done(progress);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
fu_android_boot_device_erase(FuAndroidBootDevice *self, FuProgress *progress, GError **error)
|
||||
{
|
||||
g_autoptr(GPtrArray) chunks = NULL;
|
||||
gsize bufsz = fu_device_get_firmware_size_max(FU_DEVICE(self));
|
||||
g_autofree guint8 *buf = g_malloc0(bufsz);
|
||||
|
||||
chunks = fu_chunk_array_new(buf, bufsz, 0x0, 0x0, 10 * 1024);
|
||||
|
||||
if (g_getenv("FWUPD_ANDROID_BOOT_VERBOSE") != NULL)
|
||||
fu_dump_raw(G_LOG_DOMAIN, "erase", buf, bufsz);
|
||||
|
||||
if (!fu_android_boot_device_write(self, chunks, progress, error))
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
fu_android_boot_device_verify(FuAndroidBootDevice *self,
|
||||
GPtrArray *chunks,
|
||||
FuProgress *progress,
|
||||
GError **error)
|
||||
{
|
||||
fu_progress_set_id(progress, G_STRLOC);
|
||||
fu_progress_set_steps(progress, chunks->len);
|
||||
|
||||
/* verify each chunk */
|
||||
for (guint i = 0; i < chunks->len; i++) {
|
||||
FuChunk *chk = g_ptr_array_index(chunks, i);
|
||||
g_autofree guint8 *buf = g_malloc0(fu_chunk_get_data_sz(chk));
|
||||
g_autoptr(GBytes) blob1 = fu_chunk_get_bytes(chk);
|
||||
g_autoptr(GBytes) blob2 = NULL;
|
||||
|
||||
if (!fu_udev_device_pread(FU_UDEV_DEVICE(self),
|
||||
fu_chunk_get_address(chk),
|
||||
buf,
|
||||
fu_chunk_get_data_sz(chk),
|
||||
error)) {
|
||||
g_prefix_error(error,
|
||||
"failed to read @0x%x: ",
|
||||
(guint)fu_chunk_get_address(chk));
|
||||
return FALSE;
|
||||
}
|
||||
blob2 = g_bytes_new_static(buf, fu_chunk_get_data_sz(chk));
|
||||
if (!fu_bytes_compare(blob1, blob2, error)) {
|
||||
g_prefix_error(error,
|
||||
"failed to verify @0x%x: ",
|
||||
(guint)fu_chunk_get_address(chk));
|
||||
return FALSE;
|
||||
}
|
||||
fu_progress_step_done(progress);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
fu_android_boot_device_write_firmware(FuDevice *device,
|
||||
FuFirmware *firmware,
|
||||
FuProgress *progress,
|
||||
FwupdInstallFlags flags,
|
||||
GError **error)
|
||||
{
|
||||
FuAndroidBootDevice *self = FU_ANDROID_BOOT_DEVICE(device);
|
||||
g_autoptr(GBytes) fw = NULL;
|
||||
g_autoptr(GPtrArray) chunks = NULL;
|
||||
|
||||
/* get data to write */
|
||||
fw = fu_firmware_get_bytes(firmware, error);
|
||||
if (fw == NULL)
|
||||
return FALSE;
|
||||
|
||||
if (g_getenv("FWUPD_ANDROID_BOOT_VERBOSE") != NULL)
|
||||
fu_dump_bytes(G_LOG_DOMAIN, "write", fw);
|
||||
|
||||
chunks = fu_chunk_array_new_from_bytes(fw, 0x0, 0x0, 10 * 1024);
|
||||
|
||||
fu_progress_set_id(progress, G_STRLOC);
|
||||
fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_ERASE, 72, NULL);
|
||||
fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_WRITE, 20, NULL);
|
||||
fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_VERIFY, 7, NULL);
|
||||
|
||||
/* erase, write, verify */
|
||||
if (!fu_android_boot_device_erase(self, fu_progress_get_child(progress), error))
|
||||
return FALSE;
|
||||
fu_progress_step_done(progress);
|
||||
|
||||
if (!fu_android_boot_device_write(self, chunks, fu_progress_get_child(progress), error))
|
||||
return FALSE;
|
||||
fu_progress_step_done(progress);
|
||||
|
||||
if (!fu_android_boot_device_verify(self, chunks, fu_progress_get_child(progress), error))
|
||||
return FALSE;
|
||||
fu_progress_step_done(progress);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
fu_android_boot_device_set_quirk_kv(FuDevice *device,
|
||||
const gchar *key,
|
||||
const gchar *value,
|
||||
GError **error)
|
||||
{
|
||||
FuAndroidBootDevice *self = FU_ANDROID_BOOT_DEVICE(device);
|
||||
|
||||
/* load from quirks */
|
||||
if (g_strcmp0(key, "AndroidBootVersionProperty") == 0) {
|
||||
g_autoptr(GHashTable) cmdline = NULL;
|
||||
const gchar *version = NULL;
|
||||
|
||||
cmdline = fu_kernel_get_cmdline(error);
|
||||
if (cmdline == NULL)
|
||||
return FALSE;
|
||||
|
||||
version = g_hash_table_lookup(cmdline, value);
|
||||
if (version != NULL)
|
||||
fu_device_set_version(device, version);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
if (g_strcmp0(key, "AndroidBootPartitionMaxSize") == 0) {
|
||||
guint64 size = 0;
|
||||
|
||||
if (!fu_strtoull(value, &size, 0, G_MAXUINT32, error))
|
||||
return FALSE;
|
||||
self->max_size = size;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* failed */
|
||||
g_set_error_literal(error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED, "quirk key not supported");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
fu_android_boot_device_finalize(GObject *obj)
|
||||
{
|
||||
FuAndroidBootDevice *self = FU_ANDROID_BOOT_DEVICE(obj);
|
||||
G_OBJECT_CLASS(fu_android_boot_device_parent_class)->finalize(obj);
|
||||
g_free(self->boot_slot);
|
||||
}
|
||||
|
||||
static void
|
||||
fu_android_boot_device_init(FuAndroidBootDevice *self)
|
||||
{
|
||||
fu_device_set_summary(FU_DEVICE(self), "Android Bootloader");
|
||||
fu_device_add_protocol(FU_DEVICE(self), "com.google.android_boot");
|
||||
fu_device_set_version_format(FU_DEVICE(self), FWUPD_VERSION_FORMAT_PLAIN);
|
||||
fu_device_add_flag(FU_DEVICE(self), FWUPD_DEVICE_FLAG_REQUIRE_AC);
|
||||
fu_device_add_flag(FU_DEVICE(self), FWUPD_DEVICE_FLAG_INTERNAL);
|
||||
fu_device_add_flag(FU_DEVICE(self), FWUPD_DEVICE_FLAG_NEEDS_REBOOT);
|
||||
fu_device_add_flag(FU_DEVICE(self), FWUPD_DEVICE_FLAG_CAN_VERIFY_IMAGE);
|
||||
fu_udev_device_set_flags(FU_UDEV_DEVICE(self),
|
||||
FU_UDEV_DEVICE_FLAG_OPEN_READ | FU_UDEV_DEVICE_FLAG_OPEN_WRITE |
|
||||
FU_UDEV_DEVICE_FLAG_OPEN_SYNC);
|
||||
fu_device_add_icon(FU_DEVICE(self), "computer");
|
||||
|
||||
/*
|
||||
* Fallback for ABL without version reporting, fwupd will always provide an upgrade in this
|
||||
* case. Once upgraded, the version reporting will be available and the update notification
|
||||
* will disappear. If version reporting is available, the reported version is set.
|
||||
*/
|
||||
fu_device_set_version(FU_DEVICE(self), ANDROID_BOOT_UNKNOWN_VERSION);
|
||||
}
|
||||
|
||||
static void
|
||||
fu_android_boot_device_class_init(FuAndroidBootDeviceClass *klass)
|
||||
{
|
||||
FuDeviceClass *klass_device = FU_DEVICE_CLASS(klass);
|
||||
GObjectClass *klass_object = G_OBJECT_CLASS(klass);
|
||||
|
||||
klass_object->finalize = fu_android_boot_device_finalize;
|
||||
klass_device->probe = fu_android_boot_device_probe;
|
||||
klass_device->setup = fu_android_boot_device_setup;
|
||||
klass_device->open = fu_android_boot_device_open;
|
||||
klass_device->write_firmware = fu_android_boot_device_write_firmware;
|
||||
klass_device->to_string = fu_android_boot_device_to_string;
|
||||
klass_device->set_quirk_kv = fu_android_boot_device_set_quirk_kv;
|
||||
}
|
17
plugins/android-boot/fu-android-boot-device.h
Normal file
17
plugins/android-boot/fu-android-boot-device.h
Normal file
@ -0,0 +1,17 @@
|
||||
/*
|
||||
* Copyright (C) 2022 Dylan Van Assche <me@dylanvanassche.be>
|
||||
*
|
||||
* SPDX-License-Identifier: LGPL-2.1+
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <fwupdplugin.h>
|
||||
|
||||
#define FU_TYPE_ANDROID_BOOT_DEVICE (fu_android_boot_device_get_type())
|
||||
|
||||
G_DECLARE_FINAL_TYPE(FuAndroidBootDevice,
|
||||
fu_android_boot_device,
|
||||
FU,
|
||||
ANDROID_BOOT_DEVICE,
|
||||
FuUdevDevice)
|
25
plugins/android-boot/fu-plugin-android-boot.c
Normal file
25
plugins/android-boot/fu-plugin-android-boot.c
Normal file
@ -0,0 +1,25 @@
|
||||
/*
|
||||
* Copyright (C) 2022 Dylan Van Assche <me@dylanvanassche.be>
|
||||
*
|
||||
* SPDX-License-Identifier: LGPL-2.1+
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <fwupdplugin.h>
|
||||
|
||||
#include "fu-android-boot-device.h"
|
||||
|
||||
static void
|
||||
fu_plugin_android_boot_init(FuPlugin *plugin)
|
||||
{
|
||||
fu_plugin_add_device_gtype(plugin, FU_TYPE_ANDROID_BOOT_DEVICE);
|
||||
fu_plugin_add_udev_subsystem(plugin, "block");
|
||||
}
|
||||
|
||||
void
|
||||
fu_plugin_init_vfuncs(FuPluginVfuncs *vfuncs)
|
||||
{
|
||||
vfuncs->build_hash = FU_BUILD_HASH;
|
||||
vfuncs->init = fu_plugin_android_boot_init;
|
||||
}
|
31
plugins/android-boot/meson.build
Normal file
31
plugins/android-boot/meson.build
Normal file
@ -0,0 +1,31 @@
|
||||
if get_option('plugin_android_boot').require(gudev.found(),
|
||||
error_message: 'gudev is needed for plugin_android_boot').allowed()
|
||||
cargs = ['-DG_LOG_DOMAIN="FuPluginAndroidBoot"']
|
||||
|
||||
install_data(['android-boot.quirk'],
|
||||
install_dir: join_paths(datadir, 'fwupd', 'quirks.d')
|
||||
)
|
||||
|
||||
shared_module('fu_plugin_android_boot',
|
||||
fu_hash,
|
||||
sources : [
|
||||
'fu-plugin-android-boot.c',
|
||||
'fu-android-boot-device.c',
|
||||
],
|
||||
include_directories : [
|
||||
root_incdir,
|
||||
fwupd_incdir,
|
||||
fwupdplugin_incdir,
|
||||
],
|
||||
install : true,
|
||||
install_dir: plugin_dir,
|
||||
link_with : [
|
||||
fwupd,
|
||||
fwupdplugin,
|
||||
],
|
||||
c_args : cargs,
|
||||
dependencies : [
|
||||
plugin_deps,
|
||||
],
|
||||
)
|
||||
endif
|
@ -18,6 +18,7 @@ subdir('acpi-ivrs')
|
||||
subdir('acpi-phat')
|
||||
subdir('amt')
|
||||
subdir('analogix')
|
||||
subdir('android-boot')
|
||||
subdir('ata')
|
||||
subdir('bcm57xx')
|
||||
subdir('bios')
|
||||
|
Loading…
Reference in New Issue
Block a user