Coverage Report

Created: 2026-01-17 07:04

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.5k
{
28
17.5k
  if (g_strcmp0(guid, FU_EFI_VOLUME_GUID_FFS1) == 0)
29
0
    return "Volume:Ffs1";
30
17.5k
  if (g_strcmp0(guid, FU_EFI_VOLUME_GUID_FFS2) == 0)
31
63
    return "Volume:Ffs2";
32
17.4k
  if (g_strcmp0(guid, FU_EFI_VOLUME_GUID_FFS3) == 0)
33
0
    return "Volume:Ffs3";
34
17.4k
  if (g_strcmp0(guid, FU_EFI_VOLUME_GUID_NVRAM_EVSA) == 0)
35
11.0k
    return "Volume:NvramEvsa";
36
6.39k
  if (g_strcmp0(guid, FU_EFI_VOLUME_GUID_NVRAM_NVAR) == 0)
37
0
    return "Volume:NvramNvar";
38
6.39k
  if (g_strcmp0(guid, FU_EFI_VOLUME_GUID_NVRAM_EVSA2) == 0)
39
0
    return "Volume:NvramEvsa2";
40
6.39k
  if (g_strcmp0(guid, FU_EFI_VOLUME_GUID_APPLE_BOOT) == 0)
41
0
    return "Volume:AppleBoot";
42
6.39k
  if (g_strcmp0(guid, FU_EFI_VOLUME_GUID_PFH1) == 0)
43
0
    return "Volume:Pfh1";
44
6.39k
  if (g_strcmp0(guid, FU_EFI_VOLUME_GUID_PFH2) == 0)
45
0
    return "Volume:Pfh2";
46
6.39k
  if (g_strcmp0(guid, FU_EFI_VOLUME_GUID_HP_FS) == 0)
47
0
    return "Volume:HpFs";
48
6.39k
  if (g_strcmp0(guid, FU_EFI_FILE_GUID_FV_IMAGE) == 0)
49
0
    return "File:FvImage";
50
6.39k
  if (g_strcmp0(guid, FU_EFI_FILE_GUID_MICROCODE) == 0)
51
0
    return "File:Microcode";
52
6.39k
  if (g_strcmp0(guid, FU_EFI_FILE_GUID_BIOS_GUARD) == 0)
53
0
    return "File:BiosGuard";
54
6.39k
  if (g_strcmp0(guid, FU_EFI_SECTION_GUID_LZMA_COMPRESS) == 0)
55
0
    return "Section:LzmaCompress";
56
6.39k
  if (g_strcmp0(guid, FU_EFI_SECTION_GUID_TIANO_COMPRESS) == 0)
57
0
    return "Section:TianoCompress";
58
6.39k
  if (g_strcmp0(guid, FU_EFI_SECTION_GUID_SMBIOS_TABLE) == 0)
59
0
    return "Section:SmbiosTable";
60
6.39k
  if (g_strcmp0(guid, FU_EFI_SECTION_GUID_ESRT_TABLE) == 0)
61
0
    return "Section:EsrtTable";
62
6.39k
  if (g_strcmp0(guid, FU_EFI_SECTION_GUID_ACPI1_TABLE) == 0)
63
0
    return "Section:Acpi1Table";
64
6.39k
  if (g_strcmp0(guid, FU_EFI_SECTION_GUID_ACPI2_TABLE) == 0)
65
0
    return "Section:Acpi2Table";
66
6.39k
  return NULL;
67
6.39k
}
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
8.20k
{
89
8.20k
  gsize streamsz = 0;
90
91
8.20k
  if (!fu_input_stream_size(stream, &streamsz, error))
92
0
    return FALSE;
93
30.5k
  while (offset < streamsz) {
94
25.2k
    g_autoptr(FuFirmware) img = fu_efi_section_new();
95
25.2k
    g_autoptr(GInputStream) partial_stream = NULL;
96
97
    /* parse maximum payload */
98
25.2k
    partial_stream =
99
25.2k
        fu_partial_input_stream_new(stream, offset, streamsz - offset, error);
100
25.2k
    if (partial_stream == NULL) {
101
0
      g_prefix_error_literal(error, "failed to cut payload: ");
102
0
      return FALSE;
103
0
    }
104
25.2k
    if (!fu_firmware_parse_stream(img,
105
25.2k
                partial_stream,
106
25.2k
                0x0,
107
25.2k
                flags | FU_FIRMWARE_PARSE_FLAG_NO_SEARCH,
108
25.2k
                error)) {
109
2.88k
      g_prefix_error(error,
110
2.88k
               "failed to parse section of size 0x%x: ",
111
2.88k
               (guint)streamsz);
112
2.88k
      return FALSE;
113
2.88k
    }
114
115
    /* invalid */
116
22.3k
    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
22.3k
    fu_firmware_set_offset(img, offset);
125
22.3k
    if (!fu_firmware_add_image(firmware, img, error))
126
71
      return FALSE;
127
128
    /* next! */
129
22.3k
    offset += fu_common_align_up(fu_firmware_get_size(img), FU_FIRMWARE_ALIGNMENT_4);
130
22.3k
  }
131
132
  /* success */
133
5.25k
  return TRUE;
134
8.20k
}
135
136
/**
137
 * fu_efi_timestamp_export:
138
 * @st: a #FuStructEfiTime
139
 * @bn: a #XbBuilderNode
140
 *
141
 * Exports an `EFI_TIME` to XML.
142
 *
143
 * Since: 2.0.17
144
 **/
145
void
146
fu_efi_timestamp_export(FuStructEfiTime *st, XbBuilderNode *bn)
147
0
{
148
0
  if (fu_struct_efi_time_get_year(st) != 0)
149
0
    fu_xmlb_builder_insert_kx(bn, "year", fu_struct_efi_time_get_year(st));
150
0
  if (fu_struct_efi_time_get_month(st) != 0)
151
0
    fu_xmlb_builder_insert_kx(bn, "month", fu_struct_efi_time_get_month(st));
152
0
  if (fu_struct_efi_time_get_day(st) != 0)
153
0
    fu_xmlb_builder_insert_kx(bn, "day", fu_struct_efi_time_get_day(st));
154
0
  if (fu_struct_efi_time_get_hour(st) != 0)
155
0
    fu_xmlb_builder_insert_kx(bn, "hour", fu_struct_efi_time_get_hour(st));
156
0
  if (fu_struct_efi_time_get_minute(st) != 0)
157
0
    fu_xmlb_builder_insert_kx(bn, "minute", fu_struct_efi_time_get_minute(st));
158
0
  if (fu_struct_efi_time_get_second(st) != 0)
159
0
    fu_xmlb_builder_insert_kx(bn, "second", fu_struct_efi_time_get_second(st));
160
0
}
161
162
/**
163
 * fu_efi_timestamp_build:
164
 * @st: a #FuStructEfiTime
165
 * @n: a #XbNode
166
 *
167
 * Imports an `EFI_TIME` from XML.
168
 *
169
 * Since: 2.0.17
170
 **/
171
void
172
fu_efi_timestamp_build(FuStructEfiTime *st, XbNode *n)
173
0
{
174
0
  guint64 tmp;
175
176
0
  tmp = xb_node_query_text_as_uint(n, "year", NULL);
177
0
  if (tmp != G_MAXUINT64)
178
0
    fu_struct_efi_time_set_year(st, tmp);
179
0
  tmp = xb_node_query_text_as_uint(n, "month", NULL);
180
0
  if (tmp != G_MAXUINT64)
181
0
    fu_struct_efi_time_set_month(st, tmp);
182
0
  tmp = xb_node_query_text_as_uint(n, "day", NULL);
183
0
  if (tmp != G_MAXUINT64)
184
0
    fu_struct_efi_time_set_day(st, tmp);
185
0
  tmp = xb_node_query_text_as_uint(n, "hour", NULL);
186
0
  if (tmp != G_MAXUINT64)
187
0
    fu_struct_efi_time_set_hour(st, tmp);
188
0
  tmp = xb_node_query_text_as_uint(n, "minute", NULL);
189
0
  if (tmp != G_MAXUINT64)
190
0
    fu_struct_efi_time_set_minute(st, tmp);
191
0
  tmp = xb_node_query_text_as_uint(n, "second", NULL);
192
0
  if (tmp != G_MAXUINT64)
193
0
    fu_struct_efi_time_set_second(st, tmp);
194
0
}