blob: d88cea287de5cdb2c6742791276a9ab2c4cff5bb [file] [log] [blame]
Andrew Jefferyf363bda2025-03-12 12:49:31 +00001/* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */
2/* Copyright 2025 Code Construct */
3
4/*
5 * `grep 'p.*l.*d.*m' /usr/share/dict/words` found 'palladium', which has
6 * element symbol Pd.
7 */
8
9#include <assert.h>
10#include <err.h>
11#include <inttypes.h>
12#include <libpldm/firmware_update.h>
13#include <stdio.h>
14#include <stdlib.h>
15#include <string.h>
16
17#define PD_PACKAGE_BUFFER (1ul * 1024ul * 1024ul)
18
19static void pd_print_bytes(const char *head, const void *_buf, size_t len,
20 const char *tail)
21{
22 const uint8_t *buf = _buf;
23
24 if (head) {
25 printf("%s", head);
26 }
27
28 while (len-- > 1) {
29 printf("%02" PRIx8 " ", *buf++);
30 }
31
32 printf("%02" PRIx8, *buf++);
33
34 if (tail) {
35 printf("%s", tail);
36 }
37}
38
39static void pd_print_variable_field(const char *head,
40 const struct variable_field *field,
41 const char *tail)
42{
43 if (head) {
44 printf("%s", head);
45 }
46
47 if (field && field->ptr) {
48 fwrite(field->ptr, 1, field->length, stdout);
49 }
50
51 if (tail) {
52 printf("%s", tail);
53 }
54}
55
56static void pd_print_typed_string(const char *head, size_t type,
57 const struct variable_field *string,
58 const char *tail)
59{
60 switch (type) {
61 case 1:
62 pd_print_variable_field(head, string, tail);
63 break;
64 default:
65 printf("Unsupported string type: %zu\n", type);
66 break;
67 }
68}
69
70static void pd_print_descriptor(const char *head,
71 const struct pldm_descriptor *desc,
72 const char *tail)
73{
74 if (head) {
75 printf("%s", head);
76 }
77
78 assert(desc);
79 switch (desc->descriptor_type) {
80 case 1: {
81 uint32_t pen;
82
83 memcpy(&pen, desc->descriptor_data, sizeof(pen));
84 pen = le32toh(pen);
85 printf("IANA PEN: %" PRIu32, pen);
86 break;
87 }
88 default:
89 printf("Unsupported descriptor type: %" PRIu16,
90 desc->descriptor_type);
91 break;
92 }
93
94 if (tail) {
95 printf("%s", tail);
96 }
97}
98
99int main(void)
100{
101 struct pldm_package_downstream_device_id_record ddrec;
102 struct pldm_package_component_image_information info;
103 struct pldm_package_firmware_device_id_record fdrec;
104 DEFINE_PLDM_PACKAGE_FORMAT_PIN_FR02H(pin);
105 pldm_package_header_information_pad hdr;
Andrew Jefferyc53c6fe2025-08-11 07:44:38 +0000106 struct pldm_package pkg = { 0 };
Andrew Jefferyf363bda2025-03-12 12:49:31 +0000107 size_t nr_fdrecs = 0;
108 size_t nr_ddrecs = 0;
109 size_t nr_infos = 0;
110 void *package;
111 int status;
112 size_t in;
113 int rc;
114
115 status = EXIT_SUCCESS;
116 package = calloc(PD_PACKAGE_BUFFER, 1);
117 if (!package) {
118 err(EXIT_FAILURE, "malloc");
119 }
120
121 in = fread(package, 1, PD_PACKAGE_BUFFER, stdin);
Andrew Jefferyc53c6fe2025-08-11 07:44:38 +0000122 rc = decode_pldm_firmware_update_package(package, in, &pin, &hdr, &pkg);
Andrew Jefferyf363bda2025-03-12 12:49:31 +0000123 if (rc < 0) {
124 warnx("Failed to parse PLDM package: %s\n",
125 strerrorname_np(-rc));
126 status = EXIT_FAILURE;
127 goto cleanup_package;
128 }
129
130 printf("Package header\n");
131 pd_print_bytes("\tIdentifier: 0x [ ", hdr.package_header_identifier,
132 sizeof(hdr.package_header_identifier), " ]\n");
133 printf("\tFormat revision: %" PRIu8 "\n",
134 hdr.package_header_format_revision);
135 fwrite("\n", 1, 1, stdout);
136
Andrew Jefferyc53c6fe2025-08-11 07:44:38 +0000137 foreach_pldm_package_firmware_device_id_record(pkg, fdrec, rc)
Andrew Jefferyf363bda2025-03-12 12:49:31 +0000138 {
139 struct pldm_descriptor desc;
140
141 printf("Firmware device ID record: %zu\n", nr_fdrecs++);
142 printf("\tDevice update option flags: %#.8" PRIx32 "\n",
143 fdrec.device_update_option_flags.value);
144 pd_print_typed_string(
145 "\tComponent image set version: ",
146 fdrec.component_image_set_version_string_type,
147 &fdrec.component_image_set_version_string, "\n");
148 pd_print_bytes("\tApplicable components: 0x [ ",
149 fdrec.applicable_components.bitmap.ptr,
150 fdrec.applicable_components.bitmap.length,
151 " ]\n");
152
153 printf("\tDescriptors:\n");
154 foreach_pldm_package_firmware_device_id_record_descriptor(
Andrew Jefferyc53c6fe2025-08-11 07:44:38 +0000155 pkg, fdrec, desc, rc)
Andrew Jefferyf363bda2025-03-12 12:49:31 +0000156 {
157 pd_print_descriptor("\t\t", &desc, "\n");
158 }
159 if (rc) {
160 warnx("Failed parsing firmware device ID record descriptors: %s\n",
161 strerrorname_np(-rc));
162 status = EXIT_FAILURE;
163 goto cleanup_package;
164 }
165 fwrite("\n", 1, 1, stdout);
166 }
167 if (rc) {
168 warnx("Failed parsing firmware device ID records: %s\n",
169 strerrorname_np(-rc));
170 status = EXIT_FAILURE;
171 goto cleanup_package;
172 }
173
Andrew Jefferyc53c6fe2025-08-11 07:44:38 +0000174 foreach_pldm_package_downstream_device_id_record(pkg, ddrec, rc)
Andrew Jefferyf363bda2025-03-12 12:49:31 +0000175 {
176 struct pldm_descriptor desc;
177
178 printf("Downstream device ID record: %zu\n", nr_ddrecs++);
179 printf("\tDevice update option flags: %#.4" PRIx32 "\n",
180 ddrec.update_option_flags.value);
181 pd_print_typed_string(
182 "\tSelf-contained activation min version: ",
183 ddrec.self_contained_activation_min_version_string_type,
184 &ddrec.self_contained_activation_min_version_string,
185 "\n");
186 pd_print_bytes("\tApplicable components: 0x [ ",
187 ddrec.applicable_components.bitmap.ptr,
188 ddrec.applicable_components.bitmap.length,
189 " ]\n");
190 printf("\tDescriptors:\n");
191 foreach_pldm_package_downstream_device_id_record_descriptor(
Andrew Jefferyc53c6fe2025-08-11 07:44:38 +0000192 pkg, ddrec, desc, rc)
Andrew Jefferyf363bda2025-03-12 12:49:31 +0000193 {
194 pd_print_descriptor("\t\t", &desc, "\n");
195 }
196 if (rc) {
197 warnx("Failed parsing downstream device ID record descriptors: %s\n",
198 strerrorname_np(-rc));
199 status = EXIT_FAILURE;
200 goto cleanup_package;
201 }
202 fwrite("\n", 1, 1, stdout);
203 }
204 if (rc) {
205 warnx("Failed parsing downstream device ID records: %s\n",
206 strerrorname_np(-rc));
207 status = EXIT_FAILURE;
208 goto cleanup_package;
209 }
210
Andrew Jefferyc53c6fe2025-08-11 07:44:38 +0000211 foreach_pldm_package_component_image_information(pkg, info, rc)
Andrew Jefferyf363bda2025-03-12 12:49:31 +0000212 {
213 printf("Component image info: %zu\n", nr_infos++);
214 printf("\tComponent classification: %" PRIu16 "\n",
215 info.component_classification);
216 printf("\tComponent identifier: %" PRIu16 "\n",
217 info.component_identifier);
218 printf("\tComponent comparison stamp: %" PRIu32 "\n",
219 info.component_comparison_stamp);
220 printf("\tComponent options: %#.4" PRIx16 "\n",
221 info.component_options.value);
222 printf("\tRequested activation method: %#.4" PRIx16 "\n",
223 info.requested_component_activation_method.value);
224 printf("\tComponent image: %p (%zu)\n",
225 (void *)info.component_image.ptr,
226 info.component_image.length);
227 pd_print_typed_string("\tComponent version: ",
228 info.component_version_string_type,
229 &info.component_version_string, "\n");
230 fwrite("\n", 1, 1, stdout);
231 }
232 if (rc) {
233 warnx("Failed parsing component image information: %s\n",
234 strerrorname_np(-rc));
235 status = EXIT_FAILURE;
236 goto cleanup_package;
237 }
238
239cleanup_package:
240 free(package);
241
242 exit(status);
243}