Coverage Report

Created: 2026-06-15 06:54

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/fwupd/libfwupd/fwupd-bios-setting.c
Line
Count
Source
1
/*
2
 * Copyright 2022 Mario Limonciello <mario.limonciello@amd.com>
3
 *
4
 * SPDX-License-Identifier: LGPL-2.1-or-later
5
 */
6
7
#include "config.h"
8
9
#include "fwupd-bios-setting.h"
10
#include "fwupd-codec.h"
11
#include "fwupd-enums-private.h"
12
#include "fwupd-error.h"
13
#include "fwupd-json-array.h"
14
#include "fwupd-json-object.h"
15
#include "fwupd-variant.h"
16
17
/**
18
 * FwupdBiosSetting:
19
 *
20
 * A BIOS setting that represents a setting in the firmware.
21
 */
22
23
static void
24
fwupd_bios_setting_finalize(GObject *object);
25
26
typedef struct {
27
  FwupdBiosSettingKind kind;
28
  gchar *id;
29
  gchar *name;
30
  gchar *description;
31
  gchar *path;
32
  gchar *value_filename;
33
  gchar *current_value;
34
  guint64 lower_bound;
35
  guint64 upper_bound;
36
  guint64 scalar_increment;
37
  gboolean read_only;
38
  GPtrArray *possible_values;
39
} FwupdBiosSettingPrivate;
40
41
static void
42
fwupd_bios_setting_codec_iface_init(FwupdCodecInterface *iface);
43
44
0
G_DEFINE_TYPE_EXTENDED(FwupdBiosSetting,
45
0
           fwupd_bios_setting,
46
0
           G_TYPE_OBJECT,
47
0
           0,
48
0
           G_ADD_PRIVATE(FwupdBiosSetting)
49
0
         G_IMPLEMENT_INTERFACE(FWUPD_TYPE_CODEC,
50
0
             fwupd_bios_setting_codec_iface_init));
51
0
52
0
#define GET_PRIVATE(o) (fwupd_bios_setting_get_instance_private(o))
53
54
/**
55
 * fwupd_bios_setting_get_id
56
 * @self: a #FwupdBiosSetting
57
 *
58
 * Gets the unique attribute identifier for this attribute/driver
59
 *
60
 * Returns: attribute ID if set otherwise NULL
61
 *
62
 * Since: 1.8.4
63
 **/
64
const gchar *
65
fwupd_bios_setting_get_id(FwupdBiosSetting *self)
66
0
{
67
0
  FwupdBiosSettingPrivate *priv = GET_PRIVATE(self);
68
0
  g_return_val_if_fail(FWUPD_IS_BIOS_SETTING(self), NULL);
69
0
  return priv->id;
70
0
}
71
72
/**
73
 * fwupd_bios_setting_set_id
74
 * @self: a #FwupdBiosSetting
75
 *
76
 * Sets the unique attribute identifier for this attribute
77
 *
78
 * Since: 1.8.4
79
 **/
80
void
81
fwupd_bios_setting_set_id(FwupdBiosSetting *self, const gchar *id)
82
0
{
83
0
  FwupdBiosSettingPrivate *priv = GET_PRIVATE(self);
84
0
  g_return_if_fail(FWUPD_IS_BIOS_SETTING(self));
85
86
  /* not changed */
87
0
  if (g_strcmp0(priv->id, id) == 0)
88
0
    return;
89
90
0
  g_free(priv->id);
91
0
  priv->id = g_strdup(id);
92
0
}
93
94
/**
95
 * fwupd_bios_setting_get_read_only:
96
 * @self: a #FwupdBiosSetting
97
 *
98
 * Determines if a BIOS setting is read only
99
 *
100
 * Returns: gboolean
101
 *
102
 * Since: 1.8.4
103
 **/
104
gboolean
105
fwupd_bios_setting_get_read_only(FwupdBiosSetting *self)
106
0
{
107
0
  FwupdBiosSettingPrivate *priv = GET_PRIVATE(self);
108
0
  g_return_val_if_fail(FWUPD_IS_BIOS_SETTING(self), FALSE);
109
0
  return priv->read_only;
110
0
}
111
112
/**
113
 * fwupd_bios_setting_set_read_only:
114
 * @self: a #FwupdBiosSetting
115
 *
116
 * Configures whether an attribute is read only
117
 * maximum length for string attributes.
118
 *
119
 *
120
 * Since: 1.8.4
121
 **/
122
void
123
fwupd_bios_setting_set_read_only(FwupdBiosSetting *self, gboolean val)
124
0
{
125
0
  FwupdBiosSettingPrivate *priv = GET_PRIVATE(self);
126
0
  g_return_if_fail(FWUPD_IS_BIOS_SETTING(self));
127
0
  priv->read_only = val;
128
0
}
129
130
/**
131
 * fwupd_bios_setting_get_filename:
132
 * @self: a #FwupdBiosSetting
133
 *
134
 * Gets the filename within @path where values are read/written.
135
 *
136
 * Returns: the value filename or NULL if not set
137
 *
138
 * Since: 2.1.1
139
 **/
140
const gchar *
141
fwupd_bios_setting_get_filename(FwupdBiosSetting *self)
142
0
{
143
0
  FwupdBiosSettingPrivate *priv = GET_PRIVATE(self);
144
0
  g_return_val_if_fail(FWUPD_IS_BIOS_SETTING(self), NULL);
145
0
  return priv->value_filename;
146
0
}
147
148
/**
149
 * fwupd_bios_setting_set_filename:
150
 * @self: a #FwupdBiosSetting
151
 * @filename: the filename within @path for value operations
152
 *
153
 * Sets the filename within @path where values are read/written.
154
 * If not set, defaults to "current_value".
155
 *
156
 * Since: 2.1.1
157
 **/
158
void
159
fwupd_bios_setting_set_filename(FwupdBiosSetting *self, const gchar *filename)
160
0
{
161
0
  FwupdBiosSettingPrivate *priv = GET_PRIVATE(self);
162
0
  g_return_if_fail(FWUPD_IS_BIOS_SETTING(self));
163
164
  /* not changed */
165
0
  if (g_strcmp0(priv->value_filename, filename) == 0)
166
0
    return;
167
168
0
  g_free(priv->value_filename);
169
0
  priv->value_filename = g_strdup(filename);
170
0
}
171
172
/**
173
 * fwupd_bios_setting_get_lower_bound:
174
 * @self: a #FwupdBiosSetting
175
 *
176
 * Gets the lower bound for integer attributes or
177
 * minimum length for string attributes.
178
 *
179
 * Returns: guint64
180
 *
181
 * Since: 1.8.4
182
 **/
183
guint64
184
fwupd_bios_setting_get_lower_bound(FwupdBiosSetting *self)
185
0
{
186
0
  FwupdBiosSettingPrivate *priv = GET_PRIVATE(self);
187
0
  g_return_val_if_fail(FWUPD_IS_BIOS_SETTING(self), 0);
188
0
  return priv->lower_bound;
189
0
}
190
191
/**
192
 * fwupd_bios_setting_get_upper_bound:
193
 * @self: a #FwupdBiosSetting
194
 *
195
 * Gets the upper bound for integer attributes or
196
 * maximum length for string attributes.
197
 *
198
 * Returns: guint64
199
 *
200
 * Since: 1.8.4
201
 **/
202
guint64
203
fwupd_bios_setting_get_upper_bound(FwupdBiosSetting *self)
204
0
{
205
0
  FwupdBiosSettingPrivate *priv = GET_PRIVATE(self);
206
0
  g_return_val_if_fail(FWUPD_IS_BIOS_SETTING(self), 0);
207
0
  return priv->upper_bound;
208
0
}
209
210
/**
211
 * fwupd_bios_setting_get_scalar_increment:
212
 * @self: a #FwupdBiosSetting
213
 *
214
 * Gets the scalar increment used for integer attributes.
215
 *
216
 * Returns: guint64
217
 *
218
 * Since: 1.8.4
219
 **/
220
guint64
221
fwupd_bios_setting_get_scalar_increment(FwupdBiosSetting *self)
222
0
{
223
0
  FwupdBiosSettingPrivate *priv = GET_PRIVATE(self);
224
0
  g_return_val_if_fail(FWUPD_IS_BIOS_SETTING(self), 0);
225
0
  return priv->scalar_increment;
226
0
}
227
228
/**
229
 * fwupd_bios_setting_set_upper_bound:
230
 * @self: a #FwupdBiosSetting
231
 * @val: a guint64 value to set bound to
232
 *
233
 * Sets the upper bound used for BIOS integer attributes or max
234
 * length for string attributes.
235
 *
236
 * Since: 1.8.4
237
 **/
238
void
239
fwupd_bios_setting_set_upper_bound(FwupdBiosSetting *self, guint64 val)
240
0
{
241
0
  FwupdBiosSettingPrivate *priv = GET_PRIVATE(self);
242
0
  g_return_if_fail(FWUPD_IS_BIOS_SETTING(self));
243
0
  priv->upper_bound = val;
244
0
}
245
246
/**
247
 * fwupd_bios_setting_set_lower_bound:
248
 * @self: a #FwupdBiosSetting
249
 * @val: a guint64 value to set bound to
250
 *
251
 * Sets the lower bound used for BIOS integer attributes or max
252
 * length for string attributes.
253
 *
254
 * Since: 1.8.4
255
 **/
256
void
257
fwupd_bios_setting_set_lower_bound(FwupdBiosSetting *self, guint64 val)
258
0
{
259
0
  FwupdBiosSettingPrivate *priv = GET_PRIVATE(self);
260
0
  g_return_if_fail(FWUPD_IS_BIOS_SETTING(self));
261
0
  priv->lower_bound = val;
262
0
}
263
264
/**
265
 * fwupd_bios_setting_set_scalar_increment:
266
 * @self: a #FwupdBiosSetting
267
 * @val: a guint64 value to set increment to
268
 *
269
 * Sets the scalar increment used for BIOS integer attributes.
270
 *
271
 * Since: 1.8.4
272
 **/
273
void
274
fwupd_bios_setting_set_scalar_increment(FwupdBiosSetting *self, guint64 val)
275
0
{
276
0
  FwupdBiosSettingPrivate *priv = GET_PRIVATE(self);
277
0
  g_return_if_fail(FWUPD_IS_BIOS_SETTING(self));
278
0
  priv->scalar_increment = val;
279
0
}
280
281
/**
282
 * fwupd_bios_setting_get_kind:
283
 * @self: a #FwupdBiosSetting
284
 *
285
 * Gets the BIOS setting type used by the kernel interface.
286
 *
287
 * Returns: the bios setting type, or %FWUPD_BIOS_SETTING_KIND_UNKNOWN if unset.
288
 *
289
 * Since: 1.8.4
290
 **/
291
FwupdBiosSettingKind
292
fwupd_bios_setting_get_kind(FwupdBiosSetting *self)
293
0
{
294
0
  FwupdBiosSettingPrivate *priv = GET_PRIVATE(self);
295
0
  g_return_val_if_fail(FWUPD_IS_BIOS_SETTING(self), 0);
296
0
  return priv->kind;
297
0
}
298
299
/**
300
 * fwupd_bios_setting_set_kind:
301
 * @self: a #FwupdBiosSetting
302
 * @type: a bios setting type, e.g. %FWUPD_BIOS_SETTING_KIND_ENUMERATION
303
 *
304
 * Sets the BIOS setting type used by the kernel interface.
305
 *
306
 * Since: 1.8.4
307
 **/
308
void
309
fwupd_bios_setting_set_kind(FwupdBiosSetting *self, FwupdBiosSettingKind type)
310
0
{
311
0
  FwupdBiosSettingPrivate *priv = GET_PRIVATE(self);
312
0
  g_return_if_fail(FWUPD_IS_BIOS_SETTING(self));
313
0
  priv->kind = type;
314
0
}
315
316
/**
317
 * fwupd_bios_setting_set_name:
318
 * @self: a #FwupdBiosSetting
319
 * @name: (nullable): the attribute name
320
 *
321
 * Sets the attribute name provided by a kernel driver.
322
 *
323
 * Since: 1.8.4
324
 **/
325
void
326
fwupd_bios_setting_set_name(FwupdBiosSetting *self, const gchar *name)
327
0
{
328
0
  FwupdBiosSettingPrivate *priv = GET_PRIVATE(self);
329
0
  g_return_if_fail(FWUPD_IS_BIOS_SETTING(self));
330
331
  /* not changed */
332
0
  if (g_strcmp0(priv->name, name) == 0)
333
0
    return;
334
335
0
  g_free(priv->name);
336
0
  priv->name = g_strdup(name);
337
0
}
338
339
/**
340
 * fwupd_bios_setting_set_path:
341
 * @self: a #FwupdBiosSetting
342
 * @path: (nullable): the path the driver providing the attribute uses
343
 *
344
 * Sets path to the attribute.
345
 *
346
 * Since: 1.8.4
347
 **/
348
void
349
fwupd_bios_setting_set_path(FwupdBiosSetting *self, const gchar *path)
350
0
{
351
0
  FwupdBiosSettingPrivate *priv = GET_PRIVATE(self);
352
0
  g_return_if_fail(FWUPD_IS_BIOS_SETTING(self));
353
354
  /* not changed */
355
0
  if (g_strcmp0(priv->path, path) == 0)
356
0
    return;
357
358
0
  g_free(priv->path);
359
0
  priv->path = g_strdup(path);
360
0
}
361
362
/**
363
 * fwupd_bios_setting_set_description:
364
 * @self: a #FwupdBiosSetting
365
 * @description: (nullable): the attribute description
366
 *
367
 * Sets the attribute description.
368
 *
369
 * Since: 1.8.4
370
 **/
371
void
372
fwupd_bios_setting_set_description(FwupdBiosSetting *self, const gchar *description)
373
0
{
374
0
  FwupdBiosSettingPrivate *priv = GET_PRIVATE(self);
375
0
  g_return_if_fail(FWUPD_IS_BIOS_SETTING(self));
376
377
  /* not changed */
378
0
  if (g_strcmp0(priv->description, description) == 0)
379
0
    return;
380
381
0
  g_free(priv->description);
382
0
  priv->description = g_strdup(description);
383
0
}
384
385
/* determine if key is supposed to be positive */
386
static gboolean
387
fwupd_bios_setting_key_is_positive(const gchar *key)
388
0
{
389
0
  if (g_strrstr(key, "enable"))
390
0
    return TRUE;
391
0
  if (g_strcmp0(key, "true") == 0)
392
0
    return TRUE;
393
0
  if (g_strcmp0(key, "1") == 0)
394
0
    return TRUE;
395
0
  if (g_strcmp0(key, "on") == 0)
396
0
    return TRUE;
397
0
  return FALSE;
398
0
}
399
400
/* determine if key is supposed to be negative */
401
static gboolean
402
fwupd_bios_setting_key_is_negative(const gchar *key)
403
0
{
404
0
  if (g_strrstr(key, "disable"))
405
0
    return TRUE;
406
0
  if (g_strcmp0(key, "false") == 0)
407
0
    return TRUE;
408
0
  if (g_strcmp0(key, "0") == 0)
409
0
    return TRUE;
410
0
  if (g_strcmp0(key, "off") == 0)
411
0
    return TRUE;
412
0
  return FALSE;
413
0
}
414
415
/**
416
 * fwupd_bios_setting_map_possible_value:
417
 * @self: a #FwupdBiosSetting
418
 * @key: the string to try to map
419
 * @error: (nullable): optional return location for an error
420
 *
421
 * Attempts to map a user provided string into strings that a #FwupdBiosSetting can
422
 * support.  The following heuristics are used:
423
 * - Ignore case sensitivity
424
 * - Map obviously "positive" phrases into a value that turns on the #FwupdBiosSetting
425
 * - Map obviously "negative" phrases into a value that turns off the #FwupdBiosSetting
426
 *
427
 * Returns: (transfer none): the possible value that maps or NULL if none if found
428
 *
429
 * Since: 1.8.4
430
 **/
431
const gchar *
432
fwupd_bios_setting_map_possible_value(FwupdBiosSetting *self, const gchar *key, GError **error)
433
0
{
434
0
  FwupdBiosSettingPrivate *priv = GET_PRIVATE(self);
435
0
  gboolean positive_key = FALSE;
436
0
  gboolean negative_key = FALSE;
437
0
  g_autofree gchar *lower_key = NULL;
438
439
0
  g_return_val_if_fail(FWUPD_IS_BIOS_SETTING(self), NULL);
440
0
  g_return_val_if_fail(priv->kind == FWUPD_BIOS_SETTING_KIND_ENUMERATION, NULL);
441
442
0
  if (priv->possible_values->len == 0) {
443
0
    g_set_error(error,
444
0
          FWUPD_ERROR,
445
0
          FWUPD_ERROR_NOT_SUPPORTED,
446
0
          "%s doesn't contain any possible values",
447
0
          priv->name);
448
0
    return NULL;
449
0
  }
450
451
0
  lower_key = g_utf8_strdown(key, -1);
452
0
  positive_key = fwupd_bios_setting_key_is_positive(lower_key);
453
0
  negative_key = fwupd_bios_setting_key_is_negative(lower_key);
454
0
  for (guint i = 0; i < priv->possible_values->len; i++) {
455
0
    const gchar *possible = g_ptr_array_index(priv->possible_values, i);
456
0
    g_autofree gchar *lower_possible = g_utf8_strdown(possible, -1);
457
0
    gboolean positive_possible;
458
0
    gboolean negative_possible;
459
460
    /* perfect match */
461
0
    if (g_strcmp0(lower_possible, lower_key) == 0)
462
0
      return possible;
463
    /* fuzzy match */
464
0
    positive_possible = fwupd_bios_setting_key_is_positive(lower_possible);
465
0
    negative_possible = fwupd_bios_setting_key_is_negative(lower_possible);
466
0
    if ((positive_possible && positive_key) || (negative_possible && negative_key))
467
0
      return possible;
468
0
  }
469
0
  g_set_error(error,
470
0
        FWUPD_ERROR,
471
0
        FWUPD_ERROR_NOT_SUPPORTED,
472
0
        "%s doesn't map to any possible values for %s",
473
0
        key,
474
0
        priv->name);
475
0
  return NULL;
476
0
}
477
478
/**
479
 * fwupd_bios_setting_has_possible_value:
480
 * @self: a #FwupdBiosSetting
481
 * @val: the possible value string
482
 *
483
 * Finds out if a specific possible value was added to the attribute.
484
 *
485
 * Returns: %TRUE if the self matches.
486
 *
487
 * Since: 1.8.4
488
 **/
489
gboolean
490
fwupd_bios_setting_has_possible_value(FwupdBiosSetting *self, const gchar *val)
491
0
{
492
0
  FwupdBiosSettingPrivate *priv = GET_PRIVATE(self);
493
0
  g_return_val_if_fail(FWUPD_IS_BIOS_SETTING(self), FALSE);
494
0
  g_return_val_if_fail(val != NULL, FALSE);
495
496
0
  if (priv->possible_values->len == 0)
497
0
    return TRUE;
498
499
0
  for (guint i = 0; i < priv->possible_values->len; i++) {
500
0
    const gchar *tmp = g_ptr_array_index(priv->possible_values, i);
501
0
    if (g_strcmp0(tmp, val) == 0)
502
0
      return TRUE;
503
0
  }
504
0
  return FALSE;
505
0
}
506
507
/**
508
 * fwupd_bios_setting_add_possible_value:
509
 * @self: a #FwupdBiosSetting
510
 * @possible_value: the possible
511
 *
512
 * Adds a possible value to the attribute.  This indicates one of the values the
513
 * kernel driver will accept from userspace.
514
 *
515
 * Since: 1.8.4
516
 **/
517
void
518
fwupd_bios_setting_add_possible_value(FwupdBiosSetting *self, const gchar *possible_value)
519
0
{
520
0
  FwupdBiosSettingPrivate *priv = GET_PRIVATE(self);
521
0
  g_return_if_fail(FWUPD_IS_BIOS_SETTING(self));
522
0
  if (priv->possible_values->len > 0 &&
523
0
      fwupd_bios_setting_has_possible_value(self, possible_value))
524
0
    return;
525
0
  g_ptr_array_add(priv->possible_values, g_strdup(possible_value));
526
0
}
527
528
/**
529
 * fwupd_bios_setting_get_possible_values:
530
 * @self: a #FwupdBiosSetting
531
 *
532
 * Find all possible values for an enumeration attribute.
533
 *
534
 * Returns: (transfer container) (element-type gchar*): all possible values.
535
 *
536
 * Since: 1.8.4
537
 **/
538
GPtrArray *
539
fwupd_bios_setting_get_possible_values(FwupdBiosSetting *self)
540
0
{
541
0
  FwupdBiosSettingPrivate *priv = GET_PRIVATE(self);
542
0
  g_return_val_if_fail(FWUPD_IS_BIOS_SETTING(self), NULL);
543
0
  g_return_val_if_fail(priv->kind == FWUPD_BIOS_SETTING_KIND_ENUMERATION, NULL);
544
0
  return priv->possible_values;
545
0
}
546
547
/**
548
 * fwupd_bios_setting_get_name:
549
 * @self: a #FwupdBiosSetting
550
 *
551
 * Gets the attribute name.
552
 *
553
 * Returns: the attribute name, or %NULL if unset.
554
 *
555
 * Since: 1.8.4
556
 **/
557
const gchar *
558
fwupd_bios_setting_get_name(FwupdBiosSetting *self)
559
0
{
560
0
  FwupdBiosSettingPrivate *priv = GET_PRIVATE(self);
561
0
  g_return_val_if_fail(FWUPD_IS_BIOS_SETTING(self), NULL);
562
0
  return priv->name;
563
0
}
564
565
/**
566
 * fwupd_bios_setting_get_path:
567
 * @self: a #FwupdBiosSetting
568
 *
569
 * Gets the path for the driver providing the attribute.
570
 *
571
 * Returns: (nullable): the driver, or %NULL if unfound.
572
 *
573
 * Since: 1.8.4
574
 **/
575
const gchar *
576
fwupd_bios_setting_get_path(FwupdBiosSetting *self)
577
0
{
578
0
  FwupdBiosSettingPrivate *priv = GET_PRIVATE(self);
579
0
  g_return_val_if_fail(FWUPD_IS_BIOS_SETTING(self), NULL);
580
0
  return priv->path;
581
0
}
582
583
/**
584
 * fwupd_bios_setting_get_description:
585
 * @self: a #FwupdBiosSetting
586
 *
587
 * Gets the attribute description which is provided by some drivers to explain
588
 * what they change.
589
 *
590
 * Returns: the attribute description, or %NULL if unset.
591
 *
592
 * Since: 1.8.4
593
 **/
594
const gchar *
595
fwupd_bios_setting_get_description(FwupdBiosSetting *self)
596
0
{
597
0
  FwupdBiosSettingPrivate *priv = GET_PRIVATE(self);
598
0
  g_return_val_if_fail(FWUPD_IS_BIOS_SETTING(self), NULL);
599
0
  return priv->description;
600
0
}
601
602
/**
603
 * fwupd_bios_setting_get_current_value:
604
 * @self: a #FwupdBiosSetting
605
 *
606
 * Gets the string representation of the current_value stored in an attribute
607
 * from the kernel.  This value is cached; so changing it outside of fwupd may
608
 * may put it out of sync.
609
 *
610
 * Returns: the current value of the attribute.
611
 *
612
 * Since: 1.8.4
613
 **/
614
const gchar *
615
fwupd_bios_setting_get_current_value(FwupdBiosSetting *self)
616
0
{
617
0
  FwupdBiosSettingPrivate *priv = GET_PRIVATE(self);
618
0
  g_return_val_if_fail(FWUPD_IS_BIOS_SETTING(self), NULL);
619
0
  return priv->current_value;
620
0
}
621
622
/**
623
 * fwupd_bios_setting_set_current_value:
624
 * @self: a #FwupdBiosSetting
625
 * @value: (nullable): The string to set an attribute to
626
 *
627
 * Sets the string stored in an attribute.
628
 * This doesn't change the representation in the kernel.
629
 *
630
 * Since: 1.8.4
631
 **/
632
void
633
fwupd_bios_setting_set_current_value(FwupdBiosSetting *self, const gchar *value)
634
0
{
635
0
  FwupdBiosSettingPrivate *priv = GET_PRIVATE(self);
636
637
  /* not changed */
638
0
  if (g_strcmp0(priv->current_value, value) == 0)
639
0
    return;
640
641
0
  g_free(priv->current_value);
642
0
  priv->current_value = g_strdup(value);
643
0
}
644
645
static gboolean
646
_fu_strtoull_simple(const gchar *str, guint64 *value, GError **error)
647
0
{
648
0
  gchar *endptr = NULL;
649
0
  guint base = 10;
650
651
  /* convert */
652
0
  if (g_str_has_prefix(str, "0x")) {
653
0
    str += 2;
654
0
    base = 16;
655
0
  }
656
0
  *value = g_ascii_strtoull(str, &endptr, base); /* nocheck:blocked */
657
0
  if ((gsize)(endptr - str) != strlen(str) && *endptr != '\n') {
658
0
    g_set_error(error, FWUPD_ERROR, FWUPD_ERROR_INVALID_DATA, "cannot parse %s", str);
659
0
    return FALSE;
660
0
  }
661
0
  return TRUE;
662
0
}
663
664
static gboolean
665
fwupd_bios_setting_validate_value(FwupdBiosSetting *self, const gchar *value, GError **error)
666
0
{
667
0
  FwupdBiosSettingPrivate *priv = GET_PRIVATE(self);
668
669
0
  if (priv->kind == FWUPD_BIOS_SETTING_KIND_INTEGER) {
670
0
    guint64 tmp = 0;
671
0
    if (!_fu_strtoull_simple(value, &tmp, error))
672
0
      return FALSE;
673
0
    if (tmp < priv->lower_bound) {
674
0
      g_set_error(error, /* nocheck:error */
675
0
            FWUPD_ERROR,
676
0
            FWUPD_ERROR_NOT_SUPPORTED,
677
0
            "%s is too small (%" G_GUINT64_FORMAT
678
0
            ") expected at least %" G_GUINT64_FORMAT,
679
0
            value,
680
0
            tmp,
681
0
            priv->lower_bound);
682
0
      return FALSE;
683
0
    }
684
0
    if (tmp > priv->upper_bound) {
685
0
      g_set_error(error, /* nocheck:error */
686
0
            FWUPD_ERROR,
687
0
            FWUPD_ERROR_NOT_SUPPORTED,
688
0
            "%s is too big (%" G_GUINT64_FORMAT
689
0
            ") expected no more than %" G_GUINT64_FORMAT,
690
0
            value,
691
0
            tmp,
692
0
            priv->upper_bound);
693
0
      return FALSE;
694
0
    }
695
0
    return TRUE;
696
0
  }
697
0
  if (priv->kind == FWUPD_BIOS_SETTING_KIND_STRING) {
698
0
    gsize tmp = strlen(value);
699
0
    if (tmp < priv->lower_bound) {
700
0
      g_set_error(error, /* nocheck:error */
701
0
            FWUPD_ERROR,
702
0
            FWUPD_ERROR_NOT_SUPPORTED,
703
0
            "%s is too short (%" G_GSIZE_FORMAT
704
0
            ") expected at least %" G_GUINT64_FORMAT,
705
0
            value,
706
0
            tmp,
707
0
            priv->lower_bound);
708
0
      return FALSE;
709
0
    }
710
0
    if (tmp > priv->upper_bound) {
711
0
      g_set_error(error, /* nocheck:error */
712
0
            FWUPD_ERROR,
713
0
            FWUPD_ERROR_NOT_SUPPORTED,
714
0
            "%s is too long (%" G_GSIZE_FORMAT
715
0
            ") expected no more than %" G_GUINT64_FORMAT,
716
0
            value,
717
0
            tmp,
718
0
            priv->upper_bound);
719
0
      return FALSE;
720
0
    }
721
0
    return TRUE;
722
0
  }
723
0
  if (priv->kind == FWUPD_BIOS_SETTING_KIND_ENUMERATION)
724
0
    return TRUE;
725
726
  /* not supported */
727
0
  g_set_error_literal(error,
728
0
          FWUPD_ERROR,
729
0
          FWUPD_ERROR_NOT_SUPPORTED,
730
0
          "unknown attribute type");
731
0
  return FALSE;
732
0
}
733
734
/**
735
 * fwupd_bios_setting_write_value:
736
 * @self: a #FwupdBiosSetting
737
 * @value: (not nullable): The string to write
738
 * @error: (nullable): optional return location for an error
739
 *
740
 * Writes a new value into the setting if it is different from the current value.
741
 *
742
 * NOTE: A subclass should handle the `->write_value()` vfunc and actually write the value to the
743
 * firmware.
744
 *
745
 * Returns: %TRUE for success
746
 *
747
 * Since: 1.9.4
748
 **/
749
gboolean
750
fwupd_bios_setting_write_value(FwupdBiosSetting *self, const gchar *value, GError **error)
751
0
{
752
0
  FwupdBiosSettingPrivate *priv = GET_PRIVATE(self);
753
0
  FwupdBiosSettingClass *klass = FWUPD_BIOS_SETTING_GET_CLASS(self);
754
755
0
  g_return_val_if_fail(FWUPD_IS_BIOS_SETTING(self), FALSE);
756
0
  g_return_val_if_fail(value != NULL, FALSE);
757
0
  g_return_val_if_fail(error == NULL || *error == NULL, FALSE);
758
759
  /* not changed */
760
0
  if (g_strcmp0(priv->current_value, value) == 0) {
761
0
    g_set_error(error,
762
0
          FWUPD_ERROR,
763
0
          FWUPD_ERROR_NOTHING_TO_DO,
764
0
          "%s is already set to %s",
765
0
          priv->id,
766
0
          value);
767
0
    return FALSE;
768
0
  }
769
770
  /* sanity check */
771
0
  if (fwupd_bios_setting_get_read_only(self)) {
772
0
    g_set_error(error,
773
0
          FWUPD_ERROR,
774
0
          FWUPD_ERROR_NOT_SUPPORTED,
775
0
          "%s is read only",
776
0
          priv->name);
777
0
    return FALSE;
778
0
  }
779
780
  /* convert the value */
781
0
  if (priv->kind == FWUPD_BIOS_SETTING_KIND_ENUMERATION) {
782
0
    value = fwupd_bios_setting_map_possible_value(self, value, error);
783
0
    if (value == NULL)
784
0
      return FALSE;
785
0
  }
786
787
  /* also done by the kernel or firmware, doing it here too allows for better errors */
788
0
  if (!fwupd_bios_setting_validate_value(self, value, error))
789
0
    return FALSE;
790
791
  /* not implemented */
792
0
  if (klass->write_value == NULL) {
793
0
    g_set_error_literal(error, FWUPD_ERROR, FWUPD_ERROR_NOT_SUPPORTED, "not supported");
794
0
    return FALSE;
795
0
  }
796
797
  /* proxy */
798
0
  return klass->write_value(self, value, error);
799
0
}
800
801
static gboolean
802
fwupd_bios_setting_trusted(FwupdBiosSetting *self, gboolean trusted)
803
0
{
804
0
  g_return_val_if_fail(FWUPD_IS_BIOS_SETTING(self), FALSE);
805
806
0
  if (trusted)
807
0
    return TRUE;
808
0
  if (g_strcmp0(fwupd_bios_setting_get_name(self), "pending_reboot") == 0)
809
0
    return TRUE;
810
0
  return FALSE;
811
0
}
812
813
static void
814
fwupd_bios_setting_add_variant(FwupdCodec *codec, GVariantBuilder *builder, FwupdCodecFlags flags)
815
0
{
816
0
  FwupdBiosSetting *self = FWUPD_BIOS_SETTING(codec);
817
0
  FwupdBiosSettingPrivate *priv = GET_PRIVATE(self);
818
819
0
  g_variant_builder_add(builder,
820
0
            "{sv}",
821
0
            FWUPD_RESULT_KEY_BIOS_SETTING_TYPE,
822
0
            g_variant_new_uint64(priv->kind));
823
0
  if (priv->id != NULL) {
824
0
    g_variant_builder_add(builder,
825
0
              "{sv}",
826
0
              FWUPD_RESULT_KEY_BIOS_SETTING_ID,
827
0
              g_variant_new_string(priv->id));
828
0
  }
829
0
  if (priv->name != NULL) {
830
0
    g_variant_builder_add(builder,
831
0
              "{sv}",
832
0
              FWUPD_RESULT_KEY_NAME,
833
0
              g_variant_new_string(priv->name));
834
0
  }
835
0
  if (priv->path != NULL) {
836
0
    g_variant_builder_add(builder,
837
0
              "{sv}",
838
0
              FWUPD_RESULT_KEY_FILENAME,
839
0
              g_variant_new_string(priv->path));
840
0
  }
841
0
  if (priv->description != NULL) {
842
0
    g_variant_builder_add(builder,
843
0
              "{sv}",
844
0
              FWUPD_RESULT_KEY_DESCRIPTION,
845
0
              g_variant_new_string(priv->description));
846
0
  }
847
0
  if (priv->value_filename != NULL) {
848
0
    g_variant_builder_add(builder,
849
0
              "{sv}",
850
0
              FWUPD_RESULT_KEY_BIOS_SETTING_FILENAME,
851
0
              g_variant_new_string(priv->value_filename));
852
0
  }
853
0
  g_variant_builder_add(builder,
854
0
            "{sv}",
855
0
            FWUPD_RESULT_KEY_BIOS_SETTING_READ_ONLY,
856
0
            g_variant_new_boolean(priv->read_only));
857
0
  if (priv->current_value != NULL &&
858
0
      fwupd_bios_setting_trusted(self, flags & FWUPD_CODEC_FLAG_TRUSTED)) {
859
0
    g_variant_builder_add(builder,
860
0
              "{sv}",
861
0
              FWUPD_RESULT_KEY_BIOS_SETTING_CURRENT_VALUE,
862
0
              g_variant_new_string(priv->current_value));
863
0
  }
864
0
  if (priv->kind == FWUPD_BIOS_SETTING_KIND_INTEGER ||
865
0
      priv->kind == FWUPD_BIOS_SETTING_KIND_STRING) {
866
0
    g_variant_builder_add(builder,
867
0
              "{sv}",
868
0
              FWUPD_RESULT_KEY_BIOS_SETTING_LOWER_BOUND,
869
0
              g_variant_new_uint64(priv->lower_bound));
870
0
    g_variant_builder_add(builder,
871
0
              "{sv}",
872
0
              FWUPD_RESULT_KEY_BIOS_SETTING_UPPER_BOUND,
873
0
              g_variant_new_uint64(priv->upper_bound));
874
0
    if (priv->kind == FWUPD_BIOS_SETTING_KIND_INTEGER) {
875
0
      g_variant_builder_add(builder,
876
0
                "{sv}",
877
0
                FWUPD_RESULT_KEY_BIOS_SETTING_SCALAR_INCREMENT,
878
0
                g_variant_new_uint64(priv->scalar_increment));
879
0
    }
880
0
  } else if (priv->kind == FWUPD_BIOS_SETTING_KIND_ENUMERATION) {
881
0
    if (priv->possible_values->len > 0) {
882
0
      g_autofree const gchar **strv =
883
0
          g_new0(const gchar *, priv->possible_values->len + 1);
884
0
      for (guint i = 0; i < priv->possible_values->len; i++)
885
0
        strv[i] =
886
0
            (const gchar *)g_ptr_array_index(priv->possible_values, i);
887
0
      g_variant_builder_add(builder,
888
0
                "{sv}",
889
0
                FWUPD_RESULT_KEY_BIOS_SETTING_POSSIBLE_VALUES,
890
0
                g_variant_new_strv(strv, -1));
891
0
    }
892
0
  }
893
0
}
894
895
static void
896
fwupd_bios_setting_from_key_value(FwupdBiosSetting *self, const gchar *key, GVariant *value)
897
0
{
898
0
  if (g_strcmp0(key, FWUPD_RESULT_KEY_BIOS_SETTING_TYPE) == 0) {
899
0
    fwupd_bios_setting_set_kind(self, fwupd_variant_get_uint64(value));
900
0
    return;
901
0
  }
902
0
  if (g_strcmp0(key, FWUPD_RESULT_KEY_BIOS_SETTING_ID) == 0) {
903
0
    fwupd_bios_setting_set_id(self, fwupd_variant_get_string(value));
904
0
    return;
905
0
  }
906
0
  if (g_strcmp0(key, FWUPD_RESULT_KEY_NAME) == 0) {
907
0
    fwupd_bios_setting_set_name(self, fwupd_variant_get_string(value));
908
0
    return;
909
0
  }
910
0
  if (g_strcmp0(key, FWUPD_RESULT_KEY_FILENAME) == 0) {
911
0
    fwupd_bios_setting_set_path(self, fwupd_variant_get_string(value));
912
0
    return;
913
0
  }
914
0
  if (g_strcmp0(key, FWUPD_RESULT_KEY_BIOS_SETTING_CURRENT_VALUE) == 0) {
915
0
    fwupd_bios_setting_set_current_value(self, fwupd_variant_get_string(value));
916
0
    return;
917
0
  }
918
0
  if (g_strcmp0(key, FWUPD_RESULT_KEY_BIOS_SETTING_FILENAME) == 0) {
919
0
    fwupd_bios_setting_set_filename(self, fwupd_variant_get_string(value));
920
0
    return;
921
0
  }
922
0
  if (g_strcmp0(key, FWUPD_RESULT_KEY_DESCRIPTION) == 0) {
923
0
    fwupd_bios_setting_set_description(self, fwupd_variant_get_string(value));
924
0
    return;
925
0
  }
926
0
  if (g_strcmp0(key, FWUPD_RESULT_KEY_BIOS_SETTING_POSSIBLE_VALUES) == 0) {
927
0
    g_autofree const gchar **strv = fwupd_variant_get_strv(value);
928
0
    for (guint i = 0; strv != NULL && strv[i] != NULL; i++)
929
0
      fwupd_bios_setting_add_possible_value(self, strv[i]);
930
0
    return;
931
0
  }
932
0
  if (g_strcmp0(key, FWUPD_RESULT_KEY_BIOS_SETTING_LOWER_BOUND) == 0) {
933
0
    fwupd_bios_setting_set_lower_bound(self, fwupd_variant_get_uint64(value));
934
0
    return;
935
0
  }
936
0
  if (g_strcmp0(key, FWUPD_RESULT_KEY_BIOS_SETTING_UPPER_BOUND) == 0) {
937
0
    fwupd_bios_setting_set_upper_bound(self, fwupd_variant_get_uint64(value));
938
0
    return;
939
0
  }
940
0
  if (g_strcmp0(key, FWUPD_RESULT_KEY_BIOS_SETTING_SCALAR_INCREMENT) == 0) {
941
0
    fwupd_bios_setting_set_scalar_increment(self, fwupd_variant_get_uint64(value));
942
0
    return;
943
0
  }
944
0
  if (g_strcmp0(key, FWUPD_RESULT_KEY_BIOS_SETTING_READ_ONLY) == 0) {
945
0
    fwupd_bios_setting_set_read_only(self, fwupd_variant_get_boolean(value));
946
0
    return;
947
0
  }
948
0
}
949
950
static gboolean
951
fwupd_bios_setting_from_json(FwupdCodec *codec, FwupdJsonObject *json_obj, GError **error)
952
0
{
953
0
  FwupdBiosSetting *self = FWUPD_BIOS_SETTING(codec);
954
0
  gboolean tmpb = FALSE;
955
0
  gint64 tmpi = 0;
956
0
  g_autoptr(FwupdJsonArray) json_arr = NULL;
957
958
0
  if (!fwupd_json_object_get_integer_with_default(json_obj,
959
0
              FWUPD_RESULT_KEY_BIOS_SETTING_TYPE,
960
0
              &tmpi,
961
0
              0,
962
0
              error))
963
0
    return FALSE;
964
0
  fwupd_bios_setting_set_kind(self, tmpi);
965
0
  fwupd_bios_setting_set_id(
966
0
      self,
967
0
      fwupd_json_object_get_string(json_obj, FWUPD_RESULT_KEY_BIOS_SETTING_ID, NULL));
968
969
0
  fwupd_bios_setting_set_name(
970
0
      self,
971
0
      fwupd_json_object_get_string(json_obj, FWUPD_RESULT_KEY_NAME, NULL));
972
0
  fwupd_bios_setting_set_description(
973
0
      self,
974
0
      fwupd_json_object_get_string(json_obj, FWUPD_RESULT_KEY_DESCRIPTION, NULL));
975
0
  fwupd_bios_setting_set_path(
976
0
      self,
977
0
      fwupd_json_object_get_string(json_obj, FWUPD_RESULT_KEY_FILENAME, NULL));
978
0
  fwupd_bios_setting_set_current_value(
979
0
      self,
980
0
      fwupd_json_object_get_string(json_obj,
981
0
           FWUPD_RESULT_KEY_BIOS_SETTING_CURRENT_VALUE,
982
0
           NULL));
983
0
  fwupd_bios_setting_set_filename(
984
0
      self,
985
0
      fwupd_json_object_get_string(json_obj, FWUPD_RESULT_KEY_BIOS_SETTING_FILENAME, NULL));
986
0
  json_arr = fwupd_json_object_get_array(json_obj,
987
0
                 FWUPD_RESULT_KEY_BIOS_SETTING_POSSIBLE_VALUES,
988
0
                 NULL);
989
0
  if (json_arr != NULL) {
990
0
    for (guint i = 0; i < fwupd_json_array_get_size(json_arr); i++) {
991
0
      const gchar *tmp = fwupd_json_array_get_string(json_arr, i, NULL);
992
0
      fwupd_bios_setting_add_possible_value(self, tmp);
993
0
    }
994
0
  }
995
0
  if (!fwupd_json_object_get_integer_with_default(json_obj,
996
0
              FWUPD_RESULT_KEY_BIOS_SETTING_LOWER_BOUND,
997
0
              &tmpi,
998
0
              0,
999
0
              error))
1000
0
    return FALSE;
1001
0
  fwupd_bios_setting_set_lower_bound(self, tmpi);
1002
0
  if (!fwupd_json_object_get_integer_with_default(json_obj,
1003
0
              FWUPD_RESULT_KEY_BIOS_SETTING_UPPER_BOUND,
1004
0
              &tmpi,
1005
0
              0,
1006
0
              error))
1007
0
    return FALSE;
1008
0
  fwupd_bios_setting_set_upper_bound(self, tmpi);
1009
0
  if (!fwupd_json_object_get_integer_with_default(
1010
0
    json_obj,
1011
0
    FWUPD_RESULT_KEY_BIOS_SETTING_SCALAR_INCREMENT,
1012
0
    &tmpi,
1013
0
    0,
1014
0
    error))
1015
0
    return FALSE;
1016
0
  fwupd_bios_setting_set_scalar_increment(self, tmpi);
1017
0
  if (!fwupd_json_object_get_boolean_with_default(json_obj,
1018
0
              FWUPD_RESULT_KEY_BIOS_SETTING_READ_ONLY,
1019
0
              &tmpb,
1020
0
              FALSE,
1021
0
              error))
1022
0
    return FALSE;
1023
0
  fwupd_bios_setting_set_read_only(self, tmpb);
1024
  /* success */
1025
0
  return TRUE;
1026
0
}
1027
1028
static void
1029
fwupd_bios_setting_add_json(FwupdCodec *codec, FwupdJsonObject *json_obj, FwupdCodecFlags flags)
1030
0
{
1031
0
  FwupdBiosSetting *self = FWUPD_BIOS_SETTING(codec);
1032
0
  FwupdBiosSettingPrivate *priv = GET_PRIVATE(self);
1033
1034
0
  if (priv->name != NULL)
1035
0
    fwupd_json_object_add_string(json_obj, FWUPD_RESULT_KEY_NAME, priv->name);
1036
0
  if (priv->description != NULL)
1037
0
    fwupd_json_object_add_string(json_obj,
1038
0
               FWUPD_RESULT_KEY_DESCRIPTION,
1039
0
               priv->description);
1040
0
  if (priv->path != NULL)
1041
0
    fwupd_json_object_add_string(json_obj, FWUPD_RESULT_KEY_FILENAME, priv->path);
1042
0
  if (priv->id != NULL)
1043
0
    fwupd_json_object_add_string(json_obj, FWUPD_RESULT_KEY_BIOS_SETTING_ID, priv->id);
1044
0
  if (priv->current_value != NULL) {
1045
0
    fwupd_json_object_add_string(json_obj,
1046
0
               FWUPD_RESULT_KEY_BIOS_SETTING_CURRENT_VALUE,
1047
0
               priv->current_value);
1048
0
  }
1049
0
  if (priv->value_filename != NULL) {
1050
0
    fwupd_json_object_add_string(json_obj,
1051
0
               FWUPD_RESULT_KEY_BIOS_SETTING_FILENAME,
1052
0
               priv->value_filename);
1053
0
  }
1054
0
  fwupd_json_object_add_boolean(json_obj,
1055
0
              FWUPD_RESULT_KEY_BIOS_SETTING_READ_ONLY,
1056
0
              priv->read_only);
1057
0
  fwupd_json_object_add_integer(json_obj, FWUPD_RESULT_KEY_BIOS_SETTING_TYPE, priv->kind);
1058
0
  if (priv->kind == FWUPD_BIOS_SETTING_KIND_ENUMERATION) {
1059
0
    if (priv->possible_values->len > 0) {
1060
0
      g_autoptr(FwupdJsonArray) json_arr = fwupd_json_array_new();
1061
0
      for (guint i = 0; i < priv->possible_values->len; i++) {
1062
0
        const gchar *tmp = g_ptr_array_index(priv->possible_values, i);
1063
0
        fwupd_json_array_add_string(json_arr, tmp);
1064
0
      }
1065
0
      fwupd_json_object_add_array(json_obj,
1066
0
                FWUPD_RESULT_KEY_BIOS_SETTING_POSSIBLE_VALUES,
1067
0
                json_arr);
1068
0
    }
1069
0
  }
1070
0
  if (priv->kind == FWUPD_BIOS_SETTING_KIND_INTEGER ||
1071
0
      priv->kind == FWUPD_BIOS_SETTING_KIND_STRING) {
1072
0
    fwupd_json_object_add_integer(json_obj,
1073
0
                FWUPD_RESULT_KEY_BIOS_SETTING_LOWER_BOUND,
1074
0
                priv->lower_bound);
1075
0
    fwupd_json_object_add_integer(json_obj,
1076
0
                FWUPD_RESULT_KEY_BIOS_SETTING_UPPER_BOUND,
1077
0
                priv->upper_bound);
1078
0
    if (priv->kind == FWUPD_BIOS_SETTING_KIND_INTEGER) {
1079
0
      fwupd_json_object_add_integer(
1080
0
          json_obj,
1081
0
          FWUPD_RESULT_KEY_BIOS_SETTING_SCALAR_INCREMENT,
1082
0
          priv->scalar_increment);
1083
0
    }
1084
0
  }
1085
0
}
1086
1087
static void
1088
fwupd_bios_setting_add_string(FwupdCodec *codec, guint idt, GString *str)
1089
0
{
1090
0
  FwupdBiosSetting *self = FWUPD_BIOS_SETTING(codec);
1091
0
  FwupdBiosSettingPrivate *priv = GET_PRIVATE(self);
1092
1093
0
  fwupd_codec_string_append(str, idt, FWUPD_RESULT_KEY_NAME, priv->name);
1094
0
  fwupd_codec_string_append(str, idt, FWUPD_RESULT_KEY_BIOS_SETTING_ID, priv->id);
1095
0
  fwupd_codec_string_append(str, idt, FWUPD_RESULT_KEY_DESCRIPTION, priv->description);
1096
0
  fwupd_codec_string_append(str, idt, FWUPD_RESULT_KEY_FILENAME, priv->path);
1097
0
  fwupd_codec_string_append_int(str, idt, FWUPD_RESULT_KEY_BIOS_SETTING_TYPE, priv->kind);
1098
0
  fwupd_codec_string_append(str,
1099
0
          idt,
1100
0
          FWUPD_RESULT_KEY_BIOS_SETTING_CURRENT_VALUE,
1101
0
          priv->current_value);
1102
0
  fwupd_codec_string_append(str,
1103
0
          idt,
1104
0
          FWUPD_RESULT_KEY_BIOS_SETTING_FILENAME,
1105
0
          priv->value_filename);
1106
0
  fwupd_codec_string_append(str,
1107
0
          idt,
1108
0
          FWUPD_RESULT_KEY_BIOS_SETTING_READ_ONLY,
1109
0
          priv->read_only ? "True" : "False");
1110
0
  if (priv->kind == FWUPD_BIOS_SETTING_KIND_ENUMERATION) {
1111
0
    for (guint i = 0; i < priv->possible_values->len; i++) {
1112
0
      const gchar *tmp = g_ptr_array_index(priv->possible_values, i);
1113
0
      fwupd_codec_string_append(str,
1114
0
              idt,
1115
0
              FWUPD_RESULT_KEY_BIOS_SETTING_POSSIBLE_VALUES,
1116
0
              tmp);
1117
0
    }
1118
0
  }
1119
0
  if (priv->kind == FWUPD_BIOS_SETTING_KIND_INTEGER ||
1120
0
      priv->kind == FWUPD_BIOS_SETTING_KIND_STRING) {
1121
0
    fwupd_codec_string_append_int(str,
1122
0
                idt,
1123
0
                FWUPD_RESULT_KEY_BIOS_SETTING_LOWER_BOUND,
1124
0
                priv->lower_bound);
1125
0
    fwupd_codec_string_append_int(str,
1126
0
                idt,
1127
0
                FWUPD_RESULT_KEY_BIOS_SETTING_UPPER_BOUND,
1128
0
                priv->upper_bound);
1129
0
    if (priv->kind == FWUPD_BIOS_SETTING_KIND_INTEGER) {
1130
0
      fwupd_codec_string_append_int(
1131
0
          str,
1132
0
          idt,
1133
0
          FWUPD_RESULT_KEY_BIOS_SETTING_SCALAR_INCREMENT,
1134
0
          priv->scalar_increment);
1135
0
    }
1136
0
  }
1137
0
}
1138
1139
static void
1140
fwupd_bios_setting_class_init(FwupdBiosSettingClass *klass)
1141
0
{
1142
0
  GObjectClass *object_class = G_OBJECT_CLASS(klass);
1143
0
  object_class->finalize = fwupd_bios_setting_finalize;
1144
0
}
1145
1146
static void
1147
fwupd_bios_setting_init(FwupdBiosSetting *self)
1148
0
{
1149
0
  FwupdBiosSettingPrivate *priv = GET_PRIVATE(self);
1150
0
  priv->possible_values = g_ptr_array_new_with_free_func(g_free);
1151
0
}
1152
1153
static void
1154
fwupd_bios_setting_finalize(GObject *object)
1155
0
{
1156
0
  FwupdBiosSetting *self = FWUPD_BIOS_SETTING(object);
1157
0
  FwupdBiosSettingPrivate *priv = GET_PRIVATE(self);
1158
1159
0
  g_free(priv->current_value);
1160
0
  g_free(priv->id);
1161
0
  g_free(priv->name);
1162
0
  g_free(priv->description);
1163
0
  g_free(priv->path);
1164
0
  g_free(priv->value_filename);
1165
0
  g_ptr_array_unref(priv->possible_values);
1166
1167
0
  G_OBJECT_CLASS(fwupd_bios_setting_parent_class)->finalize(object);
1168
0
}
1169
1170
static void
1171
fwupd_bios_setting_from_variant_iter(FwupdCodec *codec, GVariantIter *iter)
1172
0
{
1173
0
  FwupdBiosSetting *self = FWUPD_BIOS_SETTING(codec);
1174
0
  GVariant *value;
1175
0
  const gchar *key;
1176
0
  while (g_variant_iter_next(iter, "{&sv}", &key, &value)) {
1177
0
    fwupd_bios_setting_from_key_value(self, key, value);
1178
0
    g_variant_unref(value);
1179
0
  }
1180
0
}
1181
1182
static void
1183
fwupd_bios_setting_codec_iface_init(FwupdCodecInterface *iface)
1184
0
{
1185
0
  iface->add_string = fwupd_bios_setting_add_string;
1186
0
  iface->add_json = fwupd_bios_setting_add_json;
1187
0
  iface->from_json = fwupd_bios_setting_from_json;
1188
0
  iface->add_variant = fwupd_bios_setting_add_variant;
1189
0
  iface->from_variant_iter = fwupd_bios_setting_from_variant_iter;
1190
0
}
1191
1192
/**
1193
 * fwupd_bios_setting_new:
1194
 * @name: (nullable): the attribute name
1195
 * @path: (nullable): the path the driver providing this attribute uses
1196
 *
1197
 * Creates a new bios setting.
1198
 *
1199
 * Returns: a new #FwupdBiosSetting.
1200
 *
1201
 * Since: 1.8.4
1202
 **/
1203
FwupdBiosSetting *
1204
fwupd_bios_setting_new(const gchar *name, const gchar *path)
1205
0
{
1206
0
  FwupdBiosSetting *self;
1207
1208
0
  self = g_object_new(FWUPD_TYPE_BIOS_SETTING, NULL);
1209
0
  if (name != NULL)
1210
0
    fwupd_bios_setting_set_name(self, name);
1211
0
  if (path != NULL)
1212
0
    fwupd_bios_setting_set_path(self, path);
1213
1214
0
  return FWUPD_BIOS_SETTING(self);
1215
0
}