/src/fwupd/plugins/acpi-phat/fu-acpi-phat-version-record.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-acpi-phat-struct.h" |
10 | | #include "fu-acpi-phat-version-element.h" |
11 | | #include "fu-acpi-phat-version-record.h" |
12 | | #include "fu-acpi-phat.h" |
13 | | |
14 | | struct _FuAcpiPhatVersionRecord { |
15 | | FuFirmware parent_instance; |
16 | | }; |
17 | | |
18 | | G_DEFINE_TYPE(FuAcpiPhatVersionRecord, fu_acpi_phat_version_record, FU_TYPE_FIRMWARE) |
19 | | |
20 | | static gboolean |
21 | | fu_acpi_phat_version_record_parse(FuFirmware *firmware, |
22 | | GInputStream *stream, |
23 | | FuFirmwareParseFlags flags, |
24 | | GError **error) |
25 | 23.2k | { |
26 | 23.2k | gsize offset = 0; |
27 | 23.2k | guint32 record_count = 0; |
28 | 23.2k | g_autoptr(GByteArray) st = NULL; |
29 | | |
30 | 23.2k | st = fu_struct_acpi_phat_version_record_parse_stream(stream, offset, error); |
31 | 23.2k | if (st == NULL) |
32 | 50 | return FALSE; |
33 | 23.1k | record_count = fu_struct_acpi_phat_version_record_get_record_count(st); |
34 | 55.0k | for (guint32 i = 0; i < record_count; i++) { |
35 | 32.1k | g_autoptr(FuFirmware) firmware_tmp = fu_acpi_phat_version_element_new(); |
36 | 32.1k | g_autoptr(GInputStream) stream_tmp = NULL; |
37 | 32.1k | stream_tmp = fu_partial_input_stream_new(stream, |
38 | 32.1k | offset + st->len, |
39 | 32.1k | FU_STRUCT_ACPI_PHAT_VERSION_ELEMENT_SIZE, |
40 | 32.1k | error); |
41 | 32.1k | if (stream_tmp == NULL) |
42 | 293 | return FALSE; |
43 | 31.8k | fu_firmware_set_offset(firmware_tmp, offset + st->len); |
44 | 31.8k | if (!fu_firmware_parse_stream(firmware_tmp, |
45 | 31.8k | stream_tmp, |
46 | 31.8k | 0x0, |
47 | 31.8k | flags | FU_FIRMWARE_PARSE_FLAG_NO_SEARCH, |
48 | 31.8k | error)) |
49 | 0 | return FALSE; |
50 | 31.8k | if (!fu_firmware_add_image_full(firmware, firmware_tmp, error)) |
51 | 7 | return FALSE; |
52 | 31.8k | offset += fu_firmware_get_size(firmware_tmp); |
53 | 31.8k | } |
54 | 22.8k | return TRUE; |
55 | 23.1k | } |
56 | | |
57 | | static GByteArray * |
58 | | fu_acpi_phat_version_record_write(FuFirmware *firmware, GError **error) |
59 | 7.67k | { |
60 | 7.67k | g_autoptr(GByteArray) buf2 = g_byte_array_new(); |
61 | 7.67k | g_autoptr(GByteArray) st = fu_struct_acpi_phat_version_record_new(); |
62 | 7.67k | g_autoptr(GPtrArray) images = fu_firmware_get_images(firmware); |
63 | | |
64 | | /* write each element so we get the image size */ |
65 | 14.7k | for (guint i = 0; i < images->len; i++) { |
66 | 7.04k | FuFirmware *img = g_ptr_array_index(images, i); |
67 | 7.04k | g_autoptr(GBytes) blob = fu_firmware_write(img, error); |
68 | 7.04k | if (blob == NULL) |
69 | 0 | return NULL; |
70 | 7.04k | fu_byte_array_append_bytes(buf2, blob); |
71 | 7.04k | } |
72 | | |
73 | | /* data record */ |
74 | 7.67k | fu_struct_acpi_phat_version_record_set_rcdlen(st, st->len + buf2->len); |
75 | 7.67k | fu_struct_acpi_phat_version_record_set_version(st, fu_firmware_get_version_raw(firmware)); |
76 | 7.67k | fu_struct_acpi_phat_version_record_set_record_count(st, images->len); |
77 | | |
78 | | /* element data */ |
79 | 7.67k | g_byte_array_append(st, buf2->data, buf2->len); |
80 | 7.67k | return g_steal_pointer(&st); |
81 | 7.67k | } |
82 | | |
83 | | static void |
84 | | fu_acpi_phat_version_record_init(FuAcpiPhatVersionRecord *self) |
85 | 23.2k | { |
86 | 23.2k | fu_firmware_set_images_max(FU_FIRMWARE(self), 2000); |
87 | 23.2k | fu_firmware_add_flag(FU_FIRMWARE(self), FU_FIRMWARE_FLAG_NO_AUTO_DETECTION); |
88 | 23.2k | g_type_ensure(FU_TYPE_ACPI_PHAT_VERSION_ELEMENT); |
89 | 23.2k | } |
90 | | |
91 | | static void |
92 | | fu_acpi_phat_version_record_class_init(FuAcpiPhatVersionRecordClass *klass) |
93 | 1 | { |
94 | 1 | FuFirmwareClass *firmware_class = FU_FIRMWARE_CLASS(klass); |
95 | 1 | firmware_class->parse = fu_acpi_phat_version_record_parse; |
96 | 1 | firmware_class->write = fu_acpi_phat_version_record_write; |
97 | 1 | } |
98 | | |
99 | | FuFirmware * |
100 | | fu_acpi_phat_version_record_new(void) |
101 | 23.2k | { |
102 | 23.2k | return FU_FIRMWARE(g_object_new(FU_TYPE_ACPI_PHAT_VERSION_RECORD, NULL)); |
103 | 23.2k | } |