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