Coverage Report

Created: 2025-06-22 06:29

/src/fwupd/libfwupdplugin/fu-ifd-image.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Copyright 2021 Richard Hughes <richard@hughsie.com>
3
 *
4
 * SPDX-License-Identifier: LGPL-2.1-or-later
5
 */
6
7
#include "config.h"
8
9
#include "fu-byte-array.h"
10
#include "fu-common.h"
11
#include "fu-ifd-image.h"
12
13
/**
14
 * FuIfdImage:
15
 *
16
 * An Intel Flash Descriptor image, e.g. BIOS.
17
 *
18
 * See also: [class@FuFirmware]
19
 */
20
21
typedef struct {
22
  FuIfdAccess access[FU_IFD_REGION_MAX];
23
} FuIfdImagePrivate;
24
25
G_DEFINE_TYPE_WITH_PRIVATE(FuIfdImage, fu_ifd_image, FU_TYPE_FIRMWARE)
26
21.4k
#define GET_PRIVATE(o) (fu_ifd_image_get_instance_private(o))
27
28
static void
29
fu_ifd_image_export(FuFirmware *firmware, FuFirmwareExportFlags flags, XbBuilderNode *bn)
30
0
{
31
0
  FuIfdImage *self = FU_IFD_IMAGE(firmware);
32
0
  FuIfdImagePrivate *priv = GET_PRIVATE(self);
33
0
  for (guint i = 0; i < FU_IFD_REGION_MAX; i++) {
34
0
    if (priv->access[i] == FU_IFD_ACCESS_NONE)
35
0
      continue;
36
0
    xb_builder_node_insert_text(bn,
37
0
              "access",
38
0
              fu_ifd_access_to_string(priv->access[i]),
39
0
              "region",
40
0
              fu_ifd_region_to_string(i),
41
0
              NULL);
42
0
  }
43
0
}
44
45
/**
46
 * fu_ifd_image_set_access:
47
 * @self: a #FuIfdImage
48
 * @region: a #FuIfdRegion, e.g. %FU_IFD_REGION_BIOS
49
 * @access: a #FuIfdAccess, e.g. %FU_IFD_ACCESS_NONE
50
 *
51
 * Sets the access control for a specific reason.
52
 *
53
 * Since: 1.6.2
54
 **/
55
void
56
fu_ifd_image_set_access(FuIfdImage *self, FuIfdRegion region, FuIfdAccess access)
57
21.4k
{
58
21.4k
  FuIfdImagePrivate *priv = GET_PRIVATE(self);
59
21.4k
  g_return_if_fail(FU_IS_IFD_IMAGE(self));
60
21.4k
  g_return_if_fail(region < FU_IFD_REGION_MAX);
61
21.4k
  priv->access[region] = access;
62
21.4k
}
63
64
/**
65
 * fu_ifd_image_get_access:
66
 * @self: a #FuIfdImage
67
 * @region: a #FuIfdRegion, e.g. %FU_IFD_REGION_BIOS
68
 *
69
 * Gets the access control for a specific reason.
70
 *
71
 * Returns: a #FuIfdAccess, e.g. %FU_IFD_ACCESS_NONE
72
 *
73
 * Since: 1.6.2
74
 **/
75
FuIfdAccess
76
fu_ifd_image_get_access(FuIfdImage *self, FuIfdRegion region)
77
0
{
78
0
  FuIfdImagePrivate *priv = GET_PRIVATE(self);
79
0
  g_return_val_if_fail(FU_IS_IFD_IMAGE(self), FU_IFD_ACCESS_NONE);
80
0
  g_return_val_if_fail(region < FU_IFD_REGION_MAX, FU_IFD_ACCESS_NONE);
81
0
  return priv->access[region];
82
0
}
83
84
static GByteArray *
85
fu_ifd_image_write(FuFirmware *firmware, GError **error)
86
774
{
87
774
  g_autoptr(GByteArray) buf = g_byte_array_new();
88
774
  g_autoptr(GPtrArray) images = fu_firmware_get_images(firmware);
89
90
  /* sanity check */
91
774
  if (fu_firmware_get_alignment(firmware) > FU_FIRMWARE_ALIGNMENT_1M) {
92
0
    g_set_error(error,
93
0
          FWUPD_ERROR,
94
0
          FWUPD_ERROR_INVALID_FILE,
95
0
          "alignment invalid, got 0x%02x",
96
0
          fu_firmware_get_alignment(firmware));
97
0
    return NULL;
98
0
  }
99
100
  /* add each volume */
101
774
  if (images->len > 0) {
102
2.32k
    for (guint i = 0; i < images->len; i++) {
103
2.16k
      FuFirmware *img = g_ptr_array_index(images, i);
104
2.16k
      g_autoptr(GBytes) bytes = fu_firmware_write(img, error);
105
2.16k
      if (bytes == NULL)
106
106
        return NULL;
107
2.05k
      fu_byte_array_append_bytes(buf, bytes);
108
2.05k
    }
109
500
  } else {
110
500
    g_autoptr(GBytes) bytes = NULL;
111
500
    bytes = fu_firmware_get_bytes_with_patches(firmware, error);
112
500
    if (bytes == NULL)
113
500
      return NULL;
114
0
    fu_byte_array_append_bytes(buf, bytes);
115
0
  }
116
117
  /* align up */
118
168
  fu_byte_array_set_size(buf,
119
168
             fu_common_align_up(buf->len, fu_firmware_get_alignment(firmware)),
120
168
             0x00);
121
122
  /* success */
123
168
  return g_steal_pointer(&buf);
124
774
}
125
126
static void
127
fu_ifd_image_init(FuIfdImage *self)
128
7.46k
{
129
7.46k
  fu_firmware_set_alignment(FU_FIRMWARE(self), FU_FIRMWARE_ALIGNMENT_4K);
130
7.46k
}
131
132
static void
133
fu_ifd_image_class_init(FuIfdImageClass *klass)
134
1
{
135
1
  FuFirmwareClass *firmware_class = FU_FIRMWARE_CLASS(klass);
136
1
  firmware_class->export = fu_ifd_image_export;
137
1
  firmware_class->write = fu_ifd_image_write;
138
1
}
139
140
/**
141
 * fu_ifd_image_new:
142
 *
143
 * Creates a new #FuFirmware
144
 *
145
 * Since: 1.6.2
146
 **/
147
FuFirmware *
148
fu_ifd_image_new(void)
149
5.71k
{
150
5.71k
  return FU_FIRMWARE(g_object_new(FU_TYPE_IFD_IMAGE, NULL));
151
5.71k
}