mirror of
https://git.proxmox.com/git/fwupd
synced 2025-06-12 00:54:23 +00:00

This is needed because multiple plugins will soon be consuming the system FDT, and we don't want to either parse this multiple times, or duplicate the loading logic.
138 lines
3.3 KiB
C
138 lines
3.3 KiB
C
/*
|
|
* Copyright (C) 2022 Richard Hughes <richard@hughsie.com>
|
|
* Copyright (C) 2022 Google LLC
|
|
* Written by Simon Glass <sjg@chromium.org>
|
|
*
|
|
* SPDX-License-Identifier: LGPL-2.1+
|
|
*/
|
|
|
|
#include "config.h"
|
|
|
|
#include "fu-vbe-plugin.h"
|
|
#include "fu-vbe-simple-device.h"
|
|
|
|
struct _FuVbePlugin {
|
|
FuPlugin parent_instance;
|
|
};
|
|
|
|
G_DEFINE_TYPE(FuVbePlugin, fu_vbe_plugin, FU_TYPE_PLUGIN)
|
|
|
|
static gboolean
|
|
fu_vbe_plugin_coldplug_img(FuPlugin *plugin,
|
|
FuFdtImage *fdt_root,
|
|
FuFdtImage *fdt_node,
|
|
GError **error)
|
|
{
|
|
GType device_gtype = G_TYPE_INVALID;
|
|
g_autofree gchar *compatible = NULL;
|
|
g_auto(GStrv) split = NULL;
|
|
g_autoptr(FuDevice) dev = NULL;
|
|
|
|
/* we expect 'fwupd,vbe-<driver>' */
|
|
if (!fu_fdt_image_get_attr_str(fdt_node,
|
|
FU_FIT_FIRMWARE_ATTR_COMPATIBLE,
|
|
&compatible,
|
|
error)) {
|
|
g_prefix_error(error, "missing update mechanism: ");
|
|
return FALSE;
|
|
}
|
|
split = g_strsplit(compatible, ",", 2);
|
|
if (g_strv_length(split) != 2) {
|
|
g_set_error(error,
|
|
FWUPD_ERROR,
|
|
FWUPD_ERROR_INVALID_FILE,
|
|
"update mechanism is invalid: %s",
|
|
compatible);
|
|
return FALSE;
|
|
}
|
|
if (g_strcmp0(split[0], "fwupd") != 0) {
|
|
g_set_error(error,
|
|
FWUPD_ERROR,
|
|
FWUPD_ERROR_INVALID_FILE,
|
|
"update mechanism should have manufacturer of fwupd: %s",
|
|
split[0]);
|
|
return FALSE;
|
|
}
|
|
|
|
/* skip past 'vbe-' */
|
|
if (!g_str_has_prefix(split[1], "vbe-")) {
|
|
g_set_error(error,
|
|
FWUPD_ERROR,
|
|
FWUPD_ERROR_INVALID_FILE,
|
|
"update mechanism is missing vbe prefix: %s",
|
|
split[1]);
|
|
return FALSE;
|
|
}
|
|
if (g_strcmp0(split[1], "vbe-simple") == 0) {
|
|
device_gtype = FU_TYPE_VBE_SIMPLE_DEVICE;
|
|
} else {
|
|
g_set_error(error,
|
|
FWUPD_ERROR,
|
|
FWUPD_ERROR_INVALID_FILE,
|
|
"no driver for VBE method '%s'",
|
|
split[1]);
|
|
return FALSE;
|
|
}
|
|
|
|
/* success */
|
|
dev = g_object_new(device_gtype,
|
|
"context",
|
|
fu_plugin_get_context(plugin),
|
|
"fdt-root",
|
|
fdt_root,
|
|
"fdt-node",
|
|
fdt_node,
|
|
NULL);
|
|
fu_plugin_device_add(plugin, dev);
|
|
return TRUE;
|
|
}
|
|
|
|
static gboolean
|
|
fu_vbe_plugin_coldplug(FuPlugin *plugin, FuProgress *progress, GError **error)
|
|
{
|
|
g_autoptr(FuFirmware) fdt = NULL;
|
|
g_autoptr(FuFdtImage) fdt_root = NULL;
|
|
g_autoptr(GPtrArray) fdt_imgs = NULL;
|
|
|
|
/* get compatible from root node */
|
|
fdt = fu_context_get_fdt(fu_plugin_get_context(plugin), error);
|
|
if (fdt == NULL)
|
|
return FALSE;
|
|
fdt_root = fu_fdt_firmware_get_image_by_path(FU_FDT_FIRMWARE(fdt), "/chosen/fwupd", error);
|
|
if (fdt_root == NULL)
|
|
return FALSE;
|
|
fdt_imgs = fu_firmware_get_images(FU_FIRMWARE(fdt_root));
|
|
for (guint i = 0; i < fdt_imgs->len; i++) {
|
|
FuFdtImage *fdt_node = g_ptr_array_index(fdt_imgs, i);
|
|
g_autoptr(GError) error_local = NULL;
|
|
if (!fu_vbe_plugin_coldplug_img(plugin, fdt_root, fdt_node, &error_local)) {
|
|
g_warning("%s", error_local->message);
|
|
continue;
|
|
}
|
|
}
|
|
|
|
/* nothing found? */
|
|
if (fu_plugin_get_devices(plugin)->len == 0) {
|
|
g_set_error(error,
|
|
FWUPD_ERROR,
|
|
FWUPD_ERROR_NOT_SUPPORTED,
|
|
"no valid VBE update mechanism found");
|
|
return FALSE;
|
|
}
|
|
|
|
/* success */
|
|
return TRUE;
|
|
}
|
|
|
|
static void
|
|
fu_vbe_plugin_init(FuVbePlugin *self)
|
|
{
|
|
}
|
|
|
|
static void
|
|
fu_vbe_plugin_class_init(FuVbePluginClass *klass)
|
|
{
|
|
FuPluginClass *plugin_class = FU_PLUGIN_CLASS(klass);
|
|
plugin_class->coldplug = fu_vbe_plugin_coldplug;
|
|
}
|