Coverage Report

Created: 2025-08-24 07:10

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