Coverage Report

Created: 2026-06-15 06:54

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/fwupd/libfwupdplugin/fu-efi-common.c
Line
Count
Source
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-common.h"
10
#include "fu-efi-common.h"
11
#include "fu-efi-section.h"
12
#include "fu-input-stream.h"
13
#include "fu-partial-input-stream.h"
14
15
/**
16
 * fu_efi_guid_to_name:
17
 * @guid: A lowercase GUID string, e.g. `8c8ce578-8a3d-4f1c-9935-896185c32dd3`
18
 *
19
 * Converts a GUID to the known nice name.
20
 *
21
 * Returns: identifier string, or %NULL if unknown
22
 *
23
 * Since: 1.6.2
24
 **/
25
const gchar *
26
fu_efi_guid_to_name(const gchar *guid)
27
17.6k
{
28
17.6k
  if (g_strcmp0(guid, FU_EFI_VOLUME_GUID_FFS1) == 0)
29
0
    return "Volume:Ffs1";
30
17.6k
  if (g_strcmp0(guid, FU_EFI_VOLUME_GUID_FFS2) == 0)
31
1.15k
    return "Volume:Ffs2";
32
16.4k
  if (g_strcmp0(guid, FU_EFI_VOLUME_GUID_FFS3) == 0)
33
0
    return "Volume:Ffs3";
34
16.4k
  if (g_strcmp0(guid, FU_EFI_VOLUME_GUID_NVRAM_EVSA) == 0)
35
11.4k
    return "Volume:NvramEvsa";
36
5.00k
  if (g_strcmp0(guid, FU_EFI_VOLUME_GUID_NVRAM_NVAR) == 0)
37
0
    return "Volume:NvramNvar";
38
5.00k
  if (g_strcmp0(guid, FU_EFI_VOLUME_GUID_NVRAM_EVSA2) == 0)
39
0
    return "Volume:NvramEvsa2";
40
5.00k
  if (g_strcmp0(guid, FU_EFI_VOLUME_GUID_APPLE_BOOT) == 0)
41
0
    return "Volume:AppleBoot";
42
5.00k
  if (g_strcmp0(guid, FU_EFI_VOLUME_GUID_PFH1) == 0)
43
0
    return "Volume:Pfh1";
44
5.00k
  if (g_strcmp0(guid, FU_EFI_VOLUME_GUID_PFH2) == 0)
45
0
    return "Volume:Pfh2";
46
5.00k
  if (g_strcmp0(guid, FU_EFI_VOLUME_GUID_HP_FS) == 0)
47
0
    return "Volume:HpFs";
48
5.00k
  if (g_strcmp0(guid, FU_EFI_FILE_GUID_FV_IMAGE) == 0)
49
0
    return "File:FvImage";
50
5.00k
  if (g_strcmp0(guid, FU_EFI_FILE_GUID_MICROCODE) == 0)
51
0
    return "File:Microcode";
52
5.00k
  if (g_strcmp0(guid, FU_EFI_FILE_GUID_BIOS_GUARD) == 0)
53
0
    return "File:BiosGuard";
54
5.00k
  if (g_strcmp0(guid, FU_EFI_SECTION_GUID_LZMA_COMPRESS) == 0)
55
0
    return "Section:LzmaCompress";
56
5.00k
  if (g_strcmp0(guid, FU_EFI_SECTION_GUID_TIANO_COMPRESS) == 0)
57
0
    return "Section:TianoCompress";
58
5.00k
  if (g_strcmp0(guid, FU_EFI_SECTION_GUID_SMBIOS_TABLE) == 0)
59
0
    return "Section:SmbiosTable";
60
5.00k
  if (g_strcmp0(guid, FU_EFI_SECTION_GUID_ESRT_TABLE) == 0)
61
0
    return "Section:EsrtTable";
62
5.00k
  if (g_strcmp0(guid, FU_EFI_SECTION_GUID_ACPI1_TABLE) == 0)
63
0
    return "Section:Acpi1Table";
64
5.00k
  if (g_strcmp0(guid, FU_EFI_SECTION_GUID_ACPI2_TABLE) == 0)
65
0
    return "Section:Acpi2Table";
66
5.00k
  return NULL;
67
5.00k
}
68
69
/**
70
 * fu_efi_parse_sections:
71
 * @firmware: #FuFirmware
72
 * @stream: a #GInputStream
73
 * @flags: #FuFirmwareParseFlags
74
 * @error: (nullable): optional return location for an error
75
 *
76
 * Parses a UEFI section.
77
 *
78
 * Returns: %TRUE for success
79
 *
80
 * Since: 2.0.0
81
 **/
82
gboolean
83
fu_efi_parse_sections(FuFirmware *firmware,
84
          GInputStream *stream,
85
          gsize offset,
86
          FuFirmwareParseFlags flags,
87
          GError **error)
88
9.55k
{
89
9.55k
  gsize streamsz = 0;
90
91
9.55k
  if (!fu_input_stream_size(stream, &streamsz, error))
92
0
    return FALSE;
93
44.9k
  while (offset < streamsz) {
94
39.2k
    g_autoptr(FuFirmware) img = fu_efi_section_new();
95
39.2k
    g_autoptr(GInputStream) partial_stream = NULL;
96
97
    /* parse maximum payload */
98
39.2k
    partial_stream =
99
39.2k
        fu_partial_input_stream_new(stream, offset, streamsz - offset, error);
100
39.2k
    if (partial_stream == NULL) {
101
0
      g_prefix_error_literal(error, "failed to cut payload: ");
102
0
      return FALSE;
103
0
    }
104
39.2k
    if (!fu_firmware_parse_stream(img,
105
39.2k
                partial_stream,
106
39.2k
                0x0,
107
39.2k
                flags | FU_FIRMWARE_PARSE_FLAG_NO_SEARCH,
108
39.2k
                error)) {
109
3.77k
      g_prefix_error(error,
110
3.77k
               "failed to parse section of size 0x%x: ",
111
3.77k
               (guint)streamsz);
112
3.77k
      return FALSE;
113
3.77k
    }
114
115
    /* invalid */
116
35.4k
    if (fu_firmware_get_size(img) == 0) {
117
0
      g_set_error_literal(error,
118
0
              FWUPD_ERROR,
119
0
              FWUPD_ERROR_INVALID_DATA,
120
0
              "section had zero size");
121
0
      return FALSE;
122
0
    }
123
124
35.4k
    fu_firmware_set_offset(img, offset);
125
35.4k
    if (!fu_firmware_add_image(firmware, img, error))
126
13
      return FALSE;
127
128
    /* next! */
129
35.4k
    if (!fu_size_checked_inc(
130
35.4k
      &offset,
131
35.4k
      fu_common_align_up(fu_firmware_get_size(img), FU_FIRMWARE_ALIGNMENT_4),
132
35.4k
      error))
133
0
      return FALSE;
134
35.4k
  }
135
136
  /* success */
137
5.76k
  return TRUE;
138
9.55k
}
139
140
/**
141
 * fu_efi_timestamp_export:
142
 * @st: a #FuStructEfiTime
143
 * @bn: a #XbBuilderNode
144
 *
145
 * Exports an `EFI_TIME` to XML.
146
 *
147
 * Since: 2.0.17
148
 **/
149
void
150
fu_efi_timestamp_export(FuStructEfiTime *st, XbBuilderNode *bn)
151
0
{
152
0
  if (fu_struct_efi_time_get_year(st) != 0)
153
0
    fu_xmlb_builder_insert_kx(bn, "year", fu_struct_efi_time_get_year(st));
154
0
  if (fu_struct_efi_time_get_month(st) != 0)
155
0
    fu_xmlb_builder_insert_kx(bn, "month", fu_struct_efi_time_get_month(st));
156
0
  if (fu_struct_efi_time_get_day(st) != 0)
157
0
    fu_xmlb_builder_insert_kx(bn, "day", fu_struct_efi_time_get_day(st));
158
0
  if (fu_struct_efi_time_get_hour(st) != 0)
159
0
    fu_xmlb_builder_insert_kx(bn, "hour", fu_struct_efi_time_get_hour(st));
160
0
  if (fu_struct_efi_time_get_minute(st) != 0)
161
0
    fu_xmlb_builder_insert_kx(bn, "minute", fu_struct_efi_time_get_minute(st));
162
0
  if (fu_struct_efi_time_get_second(st) != 0)
163
0
    fu_xmlb_builder_insert_kx(bn, "second", fu_struct_efi_time_get_second(st));
164
0
}
165
166
/**
167
 * fu_efi_timestamp_build:
168
 * @st: a #FuStructEfiTime
169
 * @n: a #XbNode
170
 *
171
 * Imports an `EFI_TIME` from XML.
172
 *
173
 * Since: 2.0.17
174
 **/
175
void
176
fu_efi_timestamp_build(FuStructEfiTime *st, XbNode *n)
177
0
{
178
0
  guint64 tmp;
179
180
0
  tmp = xb_node_query_text_as_uint(n, "year", NULL);
181
0
  if (tmp != G_MAXUINT64)
182
0
    fu_struct_efi_time_set_year(st, tmp);
183
0
  tmp = xb_node_query_text_as_uint(n, "month", NULL);
184
0
  if (tmp != G_MAXUINT64)
185
0
    fu_struct_efi_time_set_month(st, tmp);
186
0
  tmp = xb_node_query_text_as_uint(n, "day", NULL);
187
0
  if (tmp != G_MAXUINT64)
188
0
    fu_struct_efi_time_set_day(st, tmp);
189
0
  tmp = xb_node_query_text_as_uint(n, "hour", NULL);
190
0
  if (tmp != G_MAXUINT64)
191
0
    fu_struct_efi_time_set_hour(st, tmp);
192
0
  tmp = xb_node_query_text_as_uint(n, "minute", NULL);
193
0
  if (tmp != G_MAXUINT64)
194
0
    fu_struct_efi_time_set_minute(st, tmp);
195
0
  tmp = xb_node_query_text_as_uint(n, "second", NULL);
196
0
  if (tmp != G_MAXUINT64)
197
0
    fu_struct_efi_time_set_second(st, tmp);
198
0
}