fwupd/libfwupd/fwupd-bios-setting.c
2022-12-15 17:27:22 +00:00

1069 lines
29 KiB
C

/*
* Copyright (C) 2022 Mario Limonciello <mario.limonciello@amd.com>
*
* SPDX-License-Identifier: LGPL-2.1+
*/
#include "config.h"
#include "fwupd-bios-setting-private.h"
#include "fwupd-common-private.h"
#include "fwupd-enums-private.h"
#include "fwupd-error.h"
/**
* FwupdBiosSetting:
*
* A BIOS setting that represents a setting in the firmware.
*/
static void
fwupd_bios_setting_finalize(GObject *object);
typedef struct {
FwupdBiosSettingKind kind;
gchar *id;
gchar *name;
gchar *description;
gchar *path;
gchar *current_value;
guint64 lower_bound;
guint64 upper_bound;
guint64 scalar_increment;
gboolean read_only;
GPtrArray *possible_values;
} FwupdBiosSettingPrivate;
G_DEFINE_TYPE_WITH_PRIVATE(FwupdBiosSetting, fwupd_bios_setting, G_TYPE_OBJECT)
#define GET_PRIVATE(o) (fwupd_bios_setting_get_instance_private(o))
/**
* fwupd_bios_setting_get_id
* @self: a #FwupdBiosSetting
*
* Gets the unique attribute identifier for this attribute/driver
*
* Returns: attribute ID if set otherwise NULL
*
* Since: 1.8.4
**/
const gchar *
fwupd_bios_setting_get_id(FwupdBiosSetting *self)
{
FwupdBiosSettingPrivate *priv = GET_PRIVATE(self);
g_return_val_if_fail(FWUPD_IS_BIOS_SETTING(self), NULL);
return priv->id;
}
/**
* fwupd_bios_setting_set_id
* @self: a #FwupdBiosSetting
*
* Sets the unique attribute identifier for this attribute
*
* Since: 1.8.4
**/
void
fwupd_bios_setting_set_id(FwupdBiosSetting *self, const gchar *id)
{
FwupdBiosSettingPrivate *priv = GET_PRIVATE(self);
g_return_if_fail(FWUPD_IS_BIOS_SETTING(self));
/* not changed */
if (g_strcmp0(priv->id, id) == 0)
return;
g_free(priv->id);
priv->id = g_strdup(id);
}
/**
* fwupd_bios_setting_get_read_only:
* @self: a #FwupdBiosSetting
*
* Determines if a BIOS setting is read only
*
* Returns: gboolean
*
* Since: 1.8.4
**/
gboolean
fwupd_bios_setting_get_read_only(FwupdBiosSetting *self)
{
FwupdBiosSettingPrivate *priv = GET_PRIVATE(self);
g_return_val_if_fail(FWUPD_IS_BIOS_SETTING(self), FALSE);
return priv->read_only;
}
/**
* fwupd_bios_setting_set_read_only:
* @self: a #FwupdBiosSetting
*
* Configures whether an attribute is read only
* maximum length for string attributes.
*
*
* Since: 1.8.4
**/
void
fwupd_bios_setting_set_read_only(FwupdBiosSetting *self, gboolean val)
{
FwupdBiosSettingPrivate *priv = GET_PRIVATE(self);
g_return_if_fail(FWUPD_IS_BIOS_SETTING(self));
priv->read_only = val;
}
/**
* fwupd_bios_setting_get_lower_bound:
* @self: a #FwupdBiosSetting
*
* Gets the lower bound for integer attributes or
* minimum length for string attributes.
*
* Returns: guint64
*
* Since: 1.8.4
**/
guint64
fwupd_bios_setting_get_lower_bound(FwupdBiosSetting *self)
{
FwupdBiosSettingPrivate *priv = GET_PRIVATE(self);
g_return_val_if_fail(FWUPD_IS_BIOS_SETTING(self), 0);
return priv->lower_bound;
}
/**
* fwupd_bios_setting_get_upper_bound:
* @self: a #FwupdBiosSetting
*
* Gets the upper bound for integer attributes or
* maximum length for string attributes.
*
* Returns: guint64
*
* Since: 1.8.4
**/
guint64
fwupd_bios_setting_get_upper_bound(FwupdBiosSetting *self)
{
FwupdBiosSettingPrivate *priv = GET_PRIVATE(self);
g_return_val_if_fail(FWUPD_IS_BIOS_SETTING(self), 0);
return priv->upper_bound;
}
/**
* fwupd_bios_setting_get_scalar_increment:
* @self: a #FwupdBiosSetting
*
* Gets the scalar increment used for integer attributes.
*
* Returns: guint64
*
* Since: 1.8.4
**/
guint64
fwupd_bios_setting_get_scalar_increment(FwupdBiosSetting *self)
{
FwupdBiosSettingPrivate *priv = GET_PRIVATE(self);
g_return_val_if_fail(FWUPD_IS_BIOS_SETTING(self), 0);
return priv->scalar_increment;
}
/**
* fwupd_bios_setting_set_upper_bound:
* @self: a #FwupdBiosSetting
* @val: a guint64 value to set bound to
*
* Sets the upper bound used for BIOS integer attributes or max
* length for string attributes.
*
* Since: 1.8.4
**/
void
fwupd_bios_setting_set_upper_bound(FwupdBiosSetting *self, guint64 val)
{
FwupdBiosSettingPrivate *priv = GET_PRIVATE(self);
g_return_if_fail(FWUPD_IS_BIOS_SETTING(self));
priv->upper_bound = val;
}
/**
* fwupd_bios_setting_set_lower_bound:
* @self: a #FwupdBiosSetting
* @val: a guint64 value to set bound to
*
* Sets the lower bound used for BIOS integer attributes or max
* length for string attributes.
*
* Since: 1.8.4
**/
void
fwupd_bios_setting_set_lower_bound(FwupdBiosSetting *self, guint64 val)
{
FwupdBiosSettingPrivate *priv = GET_PRIVATE(self);
g_return_if_fail(FWUPD_IS_BIOS_SETTING(self));
priv->lower_bound = val;
}
/**
* fwupd_bios_setting_set_scalar_increment:
* @self: a #FwupdBiosSetting
* @val: a guint64 value to set increment to
*
* Sets the scalar increment used for BIOS integer attributes.
*
* Since: 1.8.4
**/
void
fwupd_bios_setting_set_scalar_increment(FwupdBiosSetting *self, guint64 val)
{
FwupdBiosSettingPrivate *priv = GET_PRIVATE(self);
g_return_if_fail(FWUPD_IS_BIOS_SETTING(self));
priv->scalar_increment = val;
}
/**
* fwupd_bios_setting_get_kind:
* @self: a #FwupdBiosSetting
*
* Gets the BIOS setting type used by the kernel interface.
*
* Returns: the bios setting type, or %FWUPD_BIOS_SETTING_KIND_UNKNOWN if unset.
*
* Since: 1.8.4
**/
FwupdBiosSettingKind
fwupd_bios_setting_get_kind(FwupdBiosSetting *self)
{
FwupdBiosSettingPrivate *priv = GET_PRIVATE(self);
g_return_val_if_fail(FWUPD_IS_BIOS_SETTING(self), 0);
return priv->kind;
}
/**
* fwupd_bios_setting_set_kind:
* @self: a #FwupdBiosSetting
* @type: a bios setting type, e.g. %FWUPD_BIOS_SETTING_KIND_ENUMERATION
*
* Sets the BIOS setting type used by the kernel interface.
*
* Since: 1.8.4
**/
void
fwupd_bios_setting_set_kind(FwupdBiosSetting *self, FwupdBiosSettingKind type)
{
FwupdBiosSettingPrivate *priv = GET_PRIVATE(self);
g_return_if_fail(FWUPD_IS_BIOS_SETTING(self));
priv->kind = type;
}
/**
* fwupd_bios_setting_set_name:
* @self: a #FwupdBiosSetting
* @name: (nullable): the attribute name
*
* Sets the attribute name provided by a kernel driver.
*
* Since: 1.8.4
**/
void
fwupd_bios_setting_set_name(FwupdBiosSetting *self, const gchar *name)
{
FwupdBiosSettingPrivate *priv = GET_PRIVATE(self);
g_return_if_fail(FWUPD_IS_BIOS_SETTING(self));
/* not changed */
if (g_strcmp0(priv->name, name) == 0)
return;
g_free(priv->name);
priv->name = g_strdup(name);
}
/**
* fwupd_bios_setting_set_path:
* @self: a #FwupdBiosSetting
* @path: (nullable): the path the driver providing the attribute uses
*
* Sets path to the attribute.
*
* Since: 1.8.4
**/
void
fwupd_bios_setting_set_path(FwupdBiosSetting *self, const gchar *path)
{
FwupdBiosSettingPrivate *priv = GET_PRIVATE(self);
g_return_if_fail(FWUPD_IS_BIOS_SETTING(self));
/* not changed */
if (g_strcmp0(priv->path, path) == 0)
return;
g_free(priv->path);
priv->path = g_strdup(path);
}
/**
* fwupd_bios_setting_set_description:
* @self: a #FwupdBiosSetting
* @description: (nullable): the attribute description
*
* Sets the attribute description.
*
* Since: 1.8.4
**/
void
fwupd_bios_setting_set_description(FwupdBiosSetting *self, const gchar *description)
{
FwupdBiosSettingPrivate *priv = GET_PRIVATE(self);
g_return_if_fail(FWUPD_IS_BIOS_SETTING(self));
/* not changed */
if (g_strcmp0(priv->description, description) == 0)
return;
g_free(priv->description);
priv->description = g_strdup(description);
}
/* determine if key is supposed to be positive */
static gboolean
fu_bios_setting_key_is_positive(const gchar *key)
{
if (g_strrstr(key, "enable"))
return TRUE;
if (g_strcmp0(key, "true") == 0)
return TRUE;
if (g_strcmp0(key, "1") == 0)
return TRUE;
if (g_strcmp0(key, "on") == 0)
return TRUE;
return FALSE;
}
/* determine if key is supposed to be negative */
static gboolean
fu_bios_setting_key_is_negative(const gchar *key)
{
if (g_strrstr(key, "disable"))
return TRUE;
if (g_strcmp0(key, "false") == 0)
return TRUE;
if (g_strcmp0(key, "0") == 0)
return TRUE;
if (g_strcmp0(key, "off") == 0)
return TRUE;
return FALSE;
}
/**
* fwupd_bios_setting_map_possible_value:
* @self: a #FwupdBiosSetting
* @key: the string to try to map
* @error: (nullable): optional return location for an error
*
* Attempts to map a user provided string into strings that a #FwupdBiosSetting can
* support. The following heuristics are used:
* - Ignore case sensitivity
* - Map obviously "positive" phrases into a value that turns on the #FwupdBiosSetting
* - Map obviously "negative" phrases into a value that turns off the #FwupdBiosSetting
*
* Returns: (transfer none): the possible value that maps or NULL if none if found
*
* Since: 1.8.4
**/
const gchar *
fwupd_bios_setting_map_possible_value(FwupdBiosSetting *self, const gchar *key, GError **error)
{
FwupdBiosSettingPrivate *priv = GET_PRIVATE(self);
gboolean positive_key = FALSE;
gboolean negative_key = FALSE;
g_autofree gchar *lower_key = NULL;
g_return_val_if_fail(FWUPD_IS_BIOS_SETTING(self), NULL);
g_return_val_if_fail(priv->kind == FWUPD_BIOS_SETTING_KIND_ENUMERATION, NULL);
if (priv->possible_values->len == 0) {
g_set_error(error,
FWUPD_ERROR,
FWUPD_ERROR_NOT_SUPPORTED,
"%s doesn't contain any possible values",
priv->name);
return NULL;
}
lower_key = g_utf8_strdown(key, -1);
positive_key = fu_bios_setting_key_is_positive(lower_key);
negative_key = fu_bios_setting_key_is_negative(lower_key);
for (guint i = 0; i < priv->possible_values->len; i++) {
const gchar *possible = g_ptr_array_index(priv->possible_values, i);
g_autofree gchar *lower_possible = g_utf8_strdown(possible, -1);
gboolean positive_possible;
gboolean negative_possible;
/* perfect match */
if (g_strcmp0(lower_possible, lower_key) == 0)
return possible;
/* fuzzy match */
positive_possible = fu_bios_setting_key_is_positive(lower_possible);
negative_possible = fu_bios_setting_key_is_negative(lower_possible);
if ((positive_possible && positive_key) || (negative_possible && negative_key))
return possible;
}
g_set_error(error,
FWUPD_ERROR,
FWUPD_ERROR_NOT_SUPPORTED,
"%s doesn't map to any possible values for %s",
key,
priv->name);
return NULL;
}
/**
* fwupd_bios_setting_has_possible_value:
* @self: a #FwupdBiosSetting
* @val: the possible value string
*
* Finds out if a specific possible value was added to the attribute.
*
* Returns: %TRUE if the self matches.
*
* Since: 1.8.4
**/
gboolean
fwupd_bios_setting_has_possible_value(FwupdBiosSetting *self, const gchar *val)
{
FwupdBiosSettingPrivate *priv = GET_PRIVATE(self);
g_return_val_if_fail(FWUPD_IS_BIOS_SETTING(self), FALSE);
g_return_val_if_fail(val != NULL, FALSE);
if (priv->possible_values->len == 0)
return TRUE;
for (guint i = 0; i < priv->possible_values->len; i++) {
const gchar *tmp = g_ptr_array_index(priv->possible_values, i);
if (g_strcmp0(tmp, val) == 0)
return TRUE;
}
return FALSE;
}
/**
* fwupd_bios_setting_add_possible_value:
* @self: a #FwupdBiosSetting
* @possible_value: the possible
*
* Adds a possible value to the attribute. This indicates one of the values the
* kernel driver will accept from userspace.
*
* Since: 1.8.4
**/
void
fwupd_bios_setting_add_possible_value(FwupdBiosSetting *self, const gchar *possible_value)
{
FwupdBiosSettingPrivate *priv = GET_PRIVATE(self);
g_return_if_fail(FWUPD_IS_BIOS_SETTING(self));
if (priv->possible_values->len > 0 &&
fwupd_bios_setting_has_possible_value(self, possible_value))
return;
g_ptr_array_add(priv->possible_values, g_strdup(possible_value));
}
/**
* fwupd_bios_setting_get_possible_values:
* @self: a #FwupdBiosSetting
*
* Find all possible values for an enumeration attribute.
*
* Returns: (transfer container) (element-type gchar*): all possible values.
*
* Since: 1.8.4
**/
GPtrArray *
fwupd_bios_setting_get_possible_values(FwupdBiosSetting *self)
{
FwupdBiosSettingPrivate *priv = GET_PRIVATE(self);
g_return_val_if_fail(FWUPD_IS_BIOS_SETTING(self), NULL);
g_return_val_if_fail(priv->kind == FWUPD_BIOS_SETTING_KIND_ENUMERATION, NULL);
return priv->possible_values;
}
/**
* fwupd_bios_setting_get_name:
* @self: a #FwupdBiosSetting
*
* Gets the attribute name.
*
* Returns: the attribute name, or %NULL if unset.
*
* Since: 1.8.4
**/
const gchar *
fwupd_bios_setting_get_name(FwupdBiosSetting *self)
{
FwupdBiosSettingPrivate *priv = GET_PRIVATE(self);
g_return_val_if_fail(FWUPD_IS_BIOS_SETTING(self), NULL);
return priv->name;
}
/**
* fwupd_bios_setting_get_path:
* @self: a #FwupdBiosSetting
*
* Gets the path for the driver providing the attribute.
*
* Returns: (nullable): the driver, or %NULL if unfound.
*
* Since: 1.8.4
**/
const gchar *
fwupd_bios_setting_get_path(FwupdBiosSetting *self)
{
FwupdBiosSettingPrivate *priv = GET_PRIVATE(self);
g_return_val_if_fail(FWUPD_IS_BIOS_SETTING(self), NULL);
return priv->path;
}
/**
* fwupd_bios_setting_get_description:
* @self: a #FwupdBiosSetting
*
* Gets the attribute description which is provided by some drivers to explain
* what they change.
*
* Returns: the attribute description, or %NULL if unset.
*
* Since: 1.8.4
**/
const gchar *
fwupd_bios_setting_get_description(FwupdBiosSetting *self)
{
FwupdBiosSettingPrivate *priv = GET_PRIVATE(self);
g_return_val_if_fail(FWUPD_IS_BIOS_SETTING(self), NULL);
return priv->description;
}
/**
* fwupd_bios_setting_get_current_value:
* @self: a #FwupdBiosSetting
*
* Gets the string representation of the current_value stored in an attribute
* from the kernel. This value is cached; so changing it outside of fwupd may
* may put it out of sync.
*
* Returns: the current value of the attribute.
*
* Since: 1.8.4
**/
const gchar *
fwupd_bios_setting_get_current_value(FwupdBiosSetting *self)
{
FwupdBiosSettingPrivate *priv = GET_PRIVATE(self);
g_return_val_if_fail(FWUPD_IS_BIOS_SETTING(self), NULL);
return priv->current_value;
}
/**
* fwupd_bios_setting_set_current_value:
* @self: a #FwupdBiosSetting
* @value: (nullable): The string to set an attribute to
*
* Sets the string stored in an attribute.
* This doesn't change the representation in the kernel.
*
* Since: 1.8.4
**/
void
fwupd_bios_setting_set_current_value(FwupdBiosSetting *self, const gchar *value)
{
FwupdBiosSettingPrivate *priv = GET_PRIVATE(self);
/* not changed */
if (g_strcmp0(priv->current_value, value) == 0)
return;
g_free(priv->current_value);
priv->current_value = g_strdup(value);
}
static gboolean
fwupd_bios_setting_trusted(FwupdBiosSetting *self, gboolean trusted)
{
g_return_val_if_fail(FWUPD_IS_BIOS_SETTING(self), FALSE);
if (trusted)
return TRUE;
if (g_strcmp0(fwupd_bios_setting_get_name(self), "pending_reboot") == 0)
return TRUE;
return FALSE;
}
/**
* fwupd_bios_setting_to_variant:
* @self: a #FwupdBiosSetting
* @trusted: whether the caller should receive trusted values
*
* Serialize the bios setting.
*
* Returns: the serialized data, or %NULL for error.
*
* Since: 1.8.4
**/
GVariant *
fwupd_bios_setting_to_variant(FwupdBiosSetting *self, gboolean trusted)
{
FwupdBiosSettingPrivate *priv = GET_PRIVATE(self);
GVariantBuilder builder;
g_return_val_if_fail(FWUPD_IS_BIOS_SETTING(self), NULL);
g_variant_builder_init(&builder, G_VARIANT_TYPE_VARDICT);
g_variant_builder_add(&builder,
"{sv}",
FWUPD_RESULT_KEY_BIOS_SETTING_TYPE,
g_variant_new_uint64(priv->kind));
if (priv->id != NULL) {
g_variant_builder_add(&builder,
"{sv}",
FWUPD_RESULT_KEY_BIOS_SETTING_ID,
g_variant_new_string(priv->id));
}
if (priv->name != NULL) {
g_variant_builder_add(&builder,
"{sv}",
FWUPD_RESULT_KEY_NAME,
g_variant_new_string(priv->name));
}
if (priv->path != NULL) {
g_variant_builder_add(&builder,
"{sv}",
FWUPD_RESULT_KEY_FILENAME,
g_variant_new_string(priv->path));
}
if (priv->description != NULL) {
g_variant_builder_add(&builder,
"{sv}",
FWUPD_RESULT_KEY_DESCRIPTION,
g_variant_new_string(priv->description));
}
g_variant_builder_add(&builder,
"{sv}",
FWUPD_RESULT_KEY_BIOS_SETTING_READ_ONLY,
g_variant_new_boolean(priv->read_only));
if (fwupd_bios_setting_trusted(self, trusted)) {
g_variant_builder_add(&builder,
"{sv}",
FWUPD_RESULT_KEY_BIOS_SETTING_CURRENT_VALUE,
g_variant_new_string(priv->current_value));
}
if (priv->kind == FWUPD_BIOS_SETTING_KIND_INTEGER ||
priv->kind == FWUPD_BIOS_SETTING_KIND_STRING) {
g_variant_builder_add(&builder,
"{sv}",
FWUPD_RESULT_KEY_BIOS_SETTING_LOWER_BOUND,
g_variant_new_uint64(priv->lower_bound));
g_variant_builder_add(&builder,
"{sv}",
FWUPD_RESULT_KEY_BIOS_SETTING_UPPER_BOUND,
g_variant_new_uint64(priv->upper_bound));
if (priv->kind == FWUPD_BIOS_SETTING_KIND_INTEGER) {
g_variant_builder_add(&builder,
"{sv}",
FWUPD_RESULT_KEY_BIOS_SETTING_SCALAR_INCREMENT,
g_variant_new_uint64(priv->scalar_increment));
}
} else if (priv->kind == FWUPD_BIOS_SETTING_KIND_ENUMERATION) {
if (priv->possible_values->len > 0) {
g_autofree const gchar **strv =
g_new0(const gchar *, priv->possible_values->len + 1);
for (guint i = 0; i < priv->possible_values->len; i++)
strv[i] =
(const gchar *)g_ptr_array_index(priv->possible_values, i);
g_variant_builder_add(&builder,
"{sv}",
FWUPD_RESULT_KEY_BIOS_SETTING_POSSIBLE_VALUES,
g_variant_new_strv(strv, -1));
}
}
return g_variant_new("a{sv}", &builder);
}
static void
fwupd_bios_setting_from_key_value(FwupdBiosSetting *self, const gchar *key, GVariant *value)
{
if (g_strcmp0(key, FWUPD_RESULT_KEY_BIOS_SETTING_TYPE) == 0) {
fwupd_bios_setting_set_kind(self, g_variant_get_uint64(value));
return;
}
if (g_strcmp0(key, FWUPD_RESULT_KEY_BIOS_SETTING_ID) == 0) {
fwupd_bios_setting_set_id(self, g_variant_get_string(value, NULL));
return;
}
if (g_strcmp0(key, FWUPD_RESULT_KEY_NAME) == 0) {
fwupd_bios_setting_set_name(self, g_variant_get_string(value, NULL));
return;
}
if (g_strcmp0(key, FWUPD_RESULT_KEY_FILENAME) == 0) {
fwupd_bios_setting_set_path(self, g_variant_get_string(value, NULL));
return;
}
if (g_strcmp0(key, FWUPD_RESULT_KEY_BIOS_SETTING_CURRENT_VALUE) == 0) {
fwupd_bios_setting_set_current_value(self, g_variant_get_string(value, NULL));
return;
}
if (g_strcmp0(key, FWUPD_RESULT_KEY_DESCRIPTION) == 0) {
fwupd_bios_setting_set_description(self, g_variant_get_string(value, NULL));
return;
}
if (g_strcmp0(key, FWUPD_RESULT_KEY_BIOS_SETTING_POSSIBLE_VALUES) == 0) {
g_autofree const gchar **strv = g_variant_get_strv(value, NULL);
for (guint i = 0; strv[i] != NULL; i++)
fwupd_bios_setting_add_possible_value(self, strv[i]);
return;
}
if (g_strcmp0(key, FWUPD_RESULT_KEY_BIOS_SETTING_LOWER_BOUND) == 0) {
fwupd_bios_setting_set_lower_bound(self, g_variant_get_uint64(value));
return;
}
if (g_strcmp0(key, FWUPD_RESULT_KEY_BIOS_SETTING_UPPER_BOUND) == 0) {
fwupd_bios_setting_set_upper_bound(self, g_variant_get_uint64(value));
return;
}
if (g_strcmp0(key, FWUPD_RESULT_KEY_BIOS_SETTING_SCALAR_INCREMENT) == 0) {
fwupd_bios_setting_set_scalar_increment(self, g_variant_get_uint64(value));
return;
}
if (g_strcmp0(key, FWUPD_RESULT_KEY_BIOS_SETTING_READ_ONLY) == 0) {
fwupd_bios_setting_set_read_only(self, g_variant_get_boolean(value));
return;
}
}
/**
* fwupd_bios_setting_from_json:
* @self: a #FwupdBiosSetting
* @json_node: a JSON node
* @error: (nullable): optional return location for an error
*
* Loads a fwupd bios setting from a JSON node.
*
* Returns: %TRUE for success
*
* Since: 1.8.4
**/
gboolean
fwupd_bios_setting_from_json(FwupdBiosSetting *self, JsonNode *json_node, GError **error)
{
#if JSON_CHECK_VERSION(1, 6, 0)
JsonObject *obj;
/* sanity check */
if (!JSON_NODE_HOLDS_OBJECT(json_node)) {
g_set_error_literal(error, G_IO_ERROR, G_IO_ERROR_INVALID_DATA, "not JSON object");
return FALSE;
}
obj = json_node_get_object(json_node);
fwupd_bios_setting_set_kind(
self,
json_object_get_int_member_with_default(obj, FWUPD_RESULT_KEY_BIOS_SETTING_TYPE, 0));
fwupd_bios_setting_set_id(
self,
json_object_get_string_member_with_default(obj,
FWUPD_RESULT_KEY_BIOS_SETTING_ID,
NULL));
fwupd_bios_setting_set_name(
self,
json_object_get_string_member_with_default(obj, FWUPD_RESULT_KEY_NAME, NULL));
fwupd_bios_setting_set_description(
self,
json_object_get_string_member_with_default(obj, FWUPD_RESULT_KEY_DESCRIPTION, NULL));
fwupd_bios_setting_set_path(
self,
json_object_get_string_member_with_default(obj, FWUPD_RESULT_KEY_FILENAME, NULL));
fwupd_bios_setting_set_current_value(
self,
json_object_get_string_member_with_default(obj,
FWUPD_RESULT_KEY_BIOS_SETTING_CURRENT_VALUE,
NULL));
if (json_object_has_member(obj, FWUPD_RESULT_KEY_BIOS_SETTING_POSSIBLE_VALUES)) {
JsonArray *array =
json_object_get_array_member(obj,
FWUPD_RESULT_KEY_BIOS_SETTING_POSSIBLE_VALUES);
for (guint i = 0; i < json_array_get_length(array); i++) {
const gchar *tmp = json_array_get_string_element(array, i);
fwupd_bios_setting_add_possible_value(self, tmp);
}
}
fwupd_bios_setting_set_lower_bound(
self,
json_object_get_int_member_with_default(obj,
FWUPD_RESULT_KEY_BIOS_SETTING_LOWER_BOUND,
0));
fwupd_bios_setting_set_upper_bound(
self,
json_object_get_int_member_with_default(obj,
FWUPD_RESULT_KEY_BIOS_SETTING_UPPER_BOUND,
0));
fwupd_bios_setting_set_scalar_increment(
self,
json_object_get_int_member_with_default(obj,
FWUPD_RESULT_KEY_BIOS_SETTING_SCALAR_INCREMENT,
0));
fwupd_bios_setting_set_read_only(
self,
json_object_get_boolean_member_with_default(obj,
FWUPD_RESULT_KEY_BIOS_SETTING_READ_ONLY,
FALSE));
/* success */
return TRUE;
#else
g_set_error_literal(error,
FWUPD_ERROR,
FWUPD_ERROR_NOT_SUPPORTED,
"json-glib version too old");
return FALSE;
#endif
}
/**
* fwupd_bios_setting_to_json:
* @self: a #FwupdBiosSetting
* @builder: a JSON builder
*
* Adds a fwupd bios setting to a JSON builder.
*
* Since: 1.8.4
**/
void
fwupd_bios_setting_to_json(FwupdBiosSetting *self, JsonBuilder *builder)
{
FwupdBiosSettingPrivate *priv = GET_PRIVATE(self);
g_return_if_fail(FWUPD_IS_BIOS_SETTING(self));
g_return_if_fail(builder != NULL);
fwupd_common_json_add_string(builder, FWUPD_RESULT_KEY_NAME, priv->name);
fwupd_common_json_add_string(builder, FWUPD_RESULT_KEY_DESCRIPTION, priv->description);
fwupd_common_json_add_string(builder, FWUPD_RESULT_KEY_FILENAME, priv->path);
fwupd_common_json_add_string(builder, FWUPD_RESULT_KEY_BIOS_SETTING_ID, priv->id);
fwupd_common_json_add_string(builder,
FWUPD_RESULT_KEY_BIOS_SETTING_CURRENT_VALUE,
priv->current_value);
fwupd_common_json_add_boolean(builder,
FWUPD_RESULT_KEY_BIOS_SETTING_READ_ONLY,
priv->read_only);
fwupd_common_json_add_int(builder, FWUPD_RESULT_KEY_BIOS_SETTING_TYPE, priv->kind);
if (priv->kind == FWUPD_BIOS_SETTING_KIND_ENUMERATION) {
if (priv->possible_values->len > 0) {
json_builder_set_member_name(builder,
FWUPD_RESULT_KEY_BIOS_SETTING_POSSIBLE_VALUES);
json_builder_begin_array(builder);
for (guint i = 0; i < priv->possible_values->len; i++) {
const gchar *tmp = g_ptr_array_index(priv->possible_values, i);
json_builder_add_string_value(builder, tmp);
}
json_builder_end_array(builder);
}
}
if (priv->kind == FWUPD_BIOS_SETTING_KIND_INTEGER ||
priv->kind == FWUPD_BIOS_SETTING_KIND_STRING) {
fwupd_common_json_add_int(builder,
FWUPD_RESULT_KEY_BIOS_SETTING_LOWER_BOUND,
priv->lower_bound);
fwupd_common_json_add_int(builder,
FWUPD_RESULT_KEY_BIOS_SETTING_UPPER_BOUND,
priv->upper_bound);
if (priv->kind == FWUPD_BIOS_SETTING_KIND_INTEGER) {
fwupd_common_json_add_int(builder,
FWUPD_RESULT_KEY_BIOS_SETTING_SCALAR_INCREMENT,
priv->scalar_increment);
}
}
}
/**
* fwupd_bios_setting_to_string:
* @self: a #FwupdBiosSetting
*
* Builds a text representation of the object.
*
* Returns: text, or %NULL for invalid
*
* Since: 1.8.4
**/
gchar *
fwupd_bios_setting_to_string(FwupdBiosSetting *self)
{
FwupdBiosSettingPrivate *priv = GET_PRIVATE(self);
GString *str;
g_return_val_if_fail(FWUPD_IS_BIOS_SETTING(self), NULL);
str = g_string_new(NULL);
fwupd_pad_kv_str(str, FWUPD_RESULT_KEY_NAME, priv->name);
fwupd_pad_kv_str(str, FWUPD_RESULT_KEY_BIOS_SETTING_ID, priv->id);
fwupd_pad_kv_str(str, FWUPD_RESULT_KEY_DESCRIPTION, priv->description);
fwupd_pad_kv_str(str, FWUPD_RESULT_KEY_FILENAME, priv->path);
fwupd_pad_kv_int(str, FWUPD_RESULT_KEY_BIOS_SETTING_TYPE, priv->kind);
fwupd_pad_kv_str(str, FWUPD_RESULT_KEY_BIOS_SETTING_CURRENT_VALUE, priv->current_value);
fwupd_pad_kv_str(str,
FWUPD_RESULT_KEY_BIOS_SETTING_READ_ONLY,
priv->read_only ? "True" : "False");
if (priv->kind == FWUPD_BIOS_SETTING_KIND_ENUMERATION) {
for (guint i = 0; i < priv->possible_values->len; i++) {
const gchar *tmp = g_ptr_array_index(priv->possible_values, i);
fwupd_pad_kv_str(str, FWUPD_RESULT_KEY_BIOS_SETTING_POSSIBLE_VALUES, tmp);
}
}
if (priv->kind == FWUPD_BIOS_SETTING_KIND_INTEGER ||
priv->kind == FWUPD_BIOS_SETTING_KIND_STRING) {
fwupd_pad_kv_int(str, FWUPD_RESULT_KEY_BIOS_SETTING_LOWER_BOUND, priv->lower_bound);
fwupd_pad_kv_int(str, FWUPD_RESULT_KEY_BIOS_SETTING_UPPER_BOUND, priv->upper_bound);
if (priv->kind == FWUPD_BIOS_SETTING_KIND_INTEGER) {
fwupd_pad_kv_int(str,
FWUPD_RESULT_KEY_BIOS_SETTING_SCALAR_INCREMENT,
priv->scalar_increment);
}
}
return g_string_free(str, FALSE);
}
static void
fwupd_bios_setting_class_init(FwupdBiosSettingClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS(klass);
object_class->finalize = fwupd_bios_setting_finalize;
}
static void
fwupd_bios_setting_init(FwupdBiosSetting *self)
{
FwupdBiosSettingPrivate *priv = GET_PRIVATE(self);
priv->possible_values = g_ptr_array_new_with_free_func(g_free);
}
static void
fwupd_bios_setting_finalize(GObject *object)
{
FwupdBiosSetting *self = FWUPD_BIOS_SETTING(object);
FwupdBiosSettingPrivate *priv = GET_PRIVATE(self);
g_free(priv->current_value);
g_free(priv->id);
g_free(priv->name);
g_free(priv->description);
g_free(priv->path);
g_ptr_array_unref(priv->possible_values);
G_OBJECT_CLASS(fwupd_bios_setting_parent_class)->finalize(object);
}
static void
fwupd_bios_setting_set_from_variant_iter(FwupdBiosSetting *self, GVariantIter *iter)
{
GVariant *value;
const gchar *key;
while (g_variant_iter_next(iter, "{&sv}", &key, &value)) {
fwupd_bios_setting_from_key_value(self, key, value);
g_variant_unref(value);
}
}
/**
* fwupd_bios_setting_from_variant:
* @value: (not nullable): the serialized data
*
* Creates a new bios setting using serialized data.
*
* Returns: (transfer full): a new #FwupdBiosSetting, or %NULL if @value was invalid.
*
* Since: 1.8.4
**/
FwupdBiosSetting *
fwupd_bios_setting_from_variant(GVariant *value)
{
FwupdBiosSetting *rel = NULL;
const gchar *type_string;
g_autoptr(GVariantIter) iter = NULL;
g_return_val_if_fail(value != NULL, NULL);
type_string = g_variant_get_type_string(value);
if (g_strcmp0(type_string, "(a{sv})") == 0) {
rel = g_object_new(FWUPD_TYPE_BIOS_SETTING, NULL);
g_variant_get(value, "(a{sv})", &iter);
fwupd_bios_setting_set_from_variant_iter(rel, iter);
} else if (g_strcmp0(type_string, "a{sv}") == 0) {
rel = g_object_new(FWUPD_TYPE_BIOS_SETTING, NULL);
g_variant_get(value, "a{sv}", &iter);
fwupd_bios_setting_set_from_variant_iter(rel, iter);
} else {
g_warning("type %s not known", type_string);
}
return rel;
}
/**
* fwupd_bios_setting_array_from_variant:
* @value: (not nullable): the serialized data
*
* Creates an array of new bios settings using serialized data.
*
* Returns: (transfer container) (element-type FwupdBiosSetting): attributes,
* or %NULL if @value was invalid.
*
* Since: 1.8.4
**/
GPtrArray *
fwupd_bios_setting_array_from_variant(GVariant *value)
{
GPtrArray *array = NULL;
gsize sz;
g_autoptr(GVariant) untuple = NULL;
g_return_val_if_fail(value != NULL, NULL);
array = g_ptr_array_new_with_free_func((GDestroyNotify)g_object_unref);
untuple = g_variant_get_child_value(value, 0);
sz = g_variant_n_children(untuple);
for (guint i = 0; i < sz; i++) {
FwupdBiosSetting *rel;
g_autoptr(GVariant) data = NULL;
data = g_variant_get_child_value(untuple, i);
rel = fwupd_bios_setting_from_variant(data);
if (rel == NULL)
continue;
g_ptr_array_add(array, rel);
}
return array;
}
/**
* fwupd_bios_setting_new:
* @name: (nullable): the attribute name
* @path: (nullable): the path the driver providing this attribute uses
*
* Creates a new bios setting.
*
* Returns: a new #FwupdBiosSetting.
*
* Since: 1.8.4
**/
FwupdBiosSetting *
fwupd_bios_setting_new(const gchar *name, const gchar *path)
{
FwupdBiosSetting *self;
self = g_object_new(FWUPD_TYPE_BIOS_SETTING, NULL);
if (name != NULL)
fwupd_bios_setting_set_name(self, name);
if (path != NULL)
fwupd_bios_setting_set_path(self, path);
return FWUPD_BIOS_SETTING(self);
}