blob: fe63a70044db8aa5b889bfd710d3a3b56f3699af [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;
106 struct pldm_package_iter iter;
107 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);
122 rc = decode_pldm_firmware_update_package(package, in, &pin, &hdr,
123 &iter);
124 if (rc < 0) {
125 warnx("Failed to parse PLDM package: %s\n",
126 strerrorname_np(-rc));
127 status = EXIT_FAILURE;
128 goto cleanup_package;
129 }
130
131 printf("Package header\n");
132 pd_print_bytes("\tIdentifier: 0x [ ", hdr.package_header_identifier,
133 sizeof(hdr.package_header_identifier), " ]\n");
134 printf("\tFormat revision: %" PRIu8 "\n",
135 hdr.package_header_format_revision);
136 fwrite("\n", 1, 1, stdout);
137
138 foreach_pldm_package_firmware_device_id_record(iter, fdrec, rc)
139 {
140 struct pldm_descriptor desc;
141
142 printf("Firmware device ID record: %zu\n", nr_fdrecs++);
143 printf("\tDevice update option flags: %#.8" PRIx32 "\n",
144 fdrec.device_update_option_flags.value);
145 pd_print_typed_string(
146 "\tComponent image set version: ",
147 fdrec.component_image_set_version_string_type,
148 &fdrec.component_image_set_version_string, "\n");
149 pd_print_bytes("\tApplicable components: 0x [ ",
150 fdrec.applicable_components.bitmap.ptr,
151 fdrec.applicable_components.bitmap.length,
152 " ]\n");
153
154 printf("\tDescriptors:\n");
155 foreach_pldm_package_firmware_device_id_record_descriptor(
156 iter, fdrec, desc, rc)
157 {
158 pd_print_descriptor("\t\t", &desc, "\n");
159 }
160 if (rc) {
161 warnx("Failed parsing firmware device ID record descriptors: %s\n",
162 strerrorname_np(-rc));
163 status = EXIT_FAILURE;
164 goto cleanup_package;
165 }
166 fwrite("\n", 1, 1, stdout);
167 }
168 if (rc) {
169 warnx("Failed parsing firmware device ID records: %s\n",
170 strerrorname_np(-rc));
171 status = EXIT_FAILURE;
172 goto cleanup_package;
173 }
174
175 foreach_pldm_package_downstream_device_id_record(iter, ddrec, rc)
176 {
177 struct pldm_descriptor desc;
178
179 printf("Downstream device ID record: %zu\n", nr_ddrecs++);
180 printf("\tDevice update option flags: %#.4" PRIx32 "\n",
181 ddrec.update_option_flags.value);
182 pd_print_typed_string(
183 "\tSelf-contained activation min version: ",
184 ddrec.self_contained_activation_min_version_string_type,
185 &ddrec.self_contained_activation_min_version_string,
186 "\n");
187 pd_print_bytes("\tApplicable components: 0x [ ",
188 ddrec.applicable_components.bitmap.ptr,
189 ddrec.applicable_components.bitmap.length,
190 " ]\n");
191 printf("\tDescriptors:\n");
192 foreach_pldm_package_downstream_device_id_record_descriptor(
193 iter, ddrec, desc, rc)
194 {
195 pd_print_descriptor("\t\t", &desc, "\n");
196 }
197 if (rc) {
198 warnx("Failed parsing downstream device ID record descriptors: %s\n",
199 strerrorname_np(-rc));
200 status = EXIT_FAILURE;
201 goto cleanup_package;
202 }
203 fwrite("\n", 1, 1, stdout);
204 }
205 if (rc) {
206 warnx("Failed parsing downstream device ID records: %s\n",
207 strerrorname_np(-rc));
208 status = EXIT_FAILURE;
209 goto cleanup_package;
210 }
211
212 foreach_pldm_package_component_image_information(iter, info, rc)
213 {
214 printf("Component image info: %zu\n", nr_infos++);
215 printf("\tComponent classification: %" PRIu16 "\n",
216 info.component_classification);
217 printf("\tComponent identifier: %" PRIu16 "\n",
218 info.component_identifier);
219 printf("\tComponent comparison stamp: %" PRIu32 "\n",
220 info.component_comparison_stamp);
221 printf("\tComponent options: %#.4" PRIx16 "\n",
222 info.component_options.value);
223 printf("\tRequested activation method: %#.4" PRIx16 "\n",
224 info.requested_component_activation_method.value);
225 printf("\tComponent image: %p (%zu)\n",
226 (void *)info.component_image.ptr,
227 info.component_image.length);
228 pd_print_typed_string("\tComponent version: ",
229 info.component_version_string_type,
230 &info.component_version_string, "\n");
231 fwrite("\n", 1, 1, stdout);
232 }
233 if (rc) {
234 warnx("Failed parsing component image information: %s\n",
235 strerrorname_np(-rc));
236 status = EXIT_FAILURE;
237 goto cleanup_package;
238 }
239
240cleanup_package:
241 free(package);
242
243 exit(status);
244}