TODO drsuapi compressed
[wireshark-sm.git] / epan / dissectors / packet-pldm.c
blob481148ea2eed238f74136e687c55069df5e7ad1c
1 /* packet-pldm.c
2 * Routines for Platform Level Data Model(PLDM) packet
3 * disassembly
4 * https://www.dmtf.org/sites/default/files/standards/documents/DSP0240_1.1.0.pdf
5 * https://www.dmtf.org/sites/default/files/standards/documents/DSP0248_1.2.0.pdf
6 * Copyright 2023, Riya Dixit <riyadixitagra@gmail.com>
8 * Wireshark - Network traffic analyzer
9 * By Gerald Combs <gerald@wireshark.org>
10 * Copyright 1998 Gerald Combs
12 * SPDX-License-Identifier: GPL-2.0-or-later
16 #include "config.h"
17 #include <epan/packet.h>
19 #define PLDM_MIN_LENGTH 4
20 #define PLDM_MAX_TYPES 8
23 static int proto_pldm;
24 static int ett_pldm;
26 static wmem_map_t* pldmTypeMap;
27 static wmem_allocator_t *addr_resolv_scope;
29 static int hf_pldm_msg_direction;
30 static int hf_pldm_instance_id;
31 static int hf_pldm_header_version;
32 static int hf_pldm_type;
33 static int hf_pldm_reserved;
34 static int hf_pldm_base_commands;
35 static int hf_pldm_BIOS_commands;
36 static int hf_pldm_FRU_commands;
37 static int hf_pldm_platform_commands;
38 static int hf_pldm_base_typeVersion;
39 static int hf_pldm_base_PLDMtype;
40 static int hf_pldm_base_typesSupported;
41 static int hf_pldm_base_transferOperationFlag;
42 static int hf_pldm_base_nextDataTransferHandle;
43 static int hf_pldm_base_transferFlag;
44 static int hf_pldm_base_dataTransferHandle;
45 static int hf_pldm_base_TID;
46 static int hf_pldm_completion_code;
48 /*platform*/
50 static int hf_pldm_platform_completion_code;
51 /* Set Event Receiver */
52 static int hf_event_message_global;
53 static int hf_transport_protocol_type;
54 static int hf_event_receiver_addr_info;
55 static int hf_heartbeat_timer;
57 /* Event messages */
58 static int hf_pldm_platform_format_version;
59 static int hf_event_class;
60 static int hf_sensor_id;
61 static int hf_sensor_event_class;
62 static int hf_sensor_offset;
63 static int hf_event_state;
64 static int hf_event_prev_state;
65 static int hf_sensor_data_size;
66 static int hf_sensor_value_u8;
67 static int hf_sensor_value_s8;
68 static int hf_sensor_value_u16;
69 static int hf_sensor_value_s16;
70 static int hf_sensor_value_u32;
71 static int hf_sensor_value_s32;
72 static int hf_sensor_present_op_state;
73 static int hf_sensor_prev_op_state;
74 static int hf_heartbeat_format_ver;
75 static int hf_heartbeat_sequence_num;
76 static int hf_pdr_data_format;
77 static int hf_pdr_num_change_recs;
78 static int hf_pdr_repo_change_event_data_op;
79 static int hf_pdr_repo_change_rec_num_change_entries;
80 static int hf_pdr_repo_change_event_record_pdr_type;
81 static int hf_pdr_repo_change_event_record_pdr_record_handle;
82 static int hf_result_status;
84 /* GetStateSensorReadings */
85 static int hf_sensor_rearm;
86 static int hf_sensor_composite_count;
87 static int hf_sensor_event_state;
88 static int hf_sensor_present_event_state;
89 static int hf_sensor_prev_event_state;
90 static int hf_pldm_sensor_reserved;
91 static int hf_sensor_rearm_none;
93 /* GetSensorReading */
94 static int hf_event_rearm;
95 static int hf_sensor_event_msg_enable;
97 /* SetNumericEffecterValue */
98 static int hf_effecter_id;
99 static int hf_effecter_count;
100 static int hf_effecter_datasize;
101 static int hf_effecter_value_u8;
102 static int hf_effecter_value_s8;
103 static int hf_effecter_value_u16;
104 static int hf_effecter_value_s16;
105 static int hf_effecter_value_u32;
106 static int hf_effecter_value_s32;
108 /* GetNumericEffecterValue */
109 static int hf_effecter_op_state;
110 static int hf_effecter_value_pnd_u8;
111 static int hf_effecter_value_pnd_s8;
112 static int hf_effecter_value_pnd_u16;
113 static int hf_effecter_value_pnd_s16;
114 static int hf_effecter_value_pnd_u32;
115 static int hf_effecter_value_pnd_s32;
116 static int hf_effecter_value_pres_u8;
117 static int hf_effecter_value_pres_s8;
118 static int hf_effecter_value_pres_u16;
119 static int hf_effecter_value_pres_s16;
120 static int hf_effecter_value_pres_u32;
121 static int hf_effecter_value_pres_s32;
123 /* SetStateEffecterStates */
124 static int hf_effecter_set_request;
125 static int hf_effecter_state;
127 /* GetPDR */
128 static int hf_pdr_record_handle;
129 static int hf_pdr_data_handle;
130 static int hf_pdr_transfer_op_flag;
131 static int hf_pdr_req_count;
132 static int hf_pdr_record_change_num;
133 static int hf_pdr_next_record_handle;
134 static int hf_pdr_next_data_handle;
135 static int hf_pdr_transfer_flag;
136 static int hf_pdr_response_count;
137 static int hf_transfer_crc;
138 static int hf_pdr_record_data;
140 /* FRU definitions */
141 /* FRU specific completion code */
142 static int hf_fru_completion_code;
143 static int hf_fru_major_ver;
144 static int hf_fru_minor_ver;
145 static int hf_fru_table_max_size;
146 static int hf_fru_table_length;
147 static int hf_fru_num_record_identifiers;
148 static int hf_fru_num_records;
149 static int hf_fru_table_crc;
151 static int hf_fru_data_handle;
152 static int hf_fru_transfer_op_flag;
153 static int hf_fru_next_data_handle;
154 static int hf_fru_transfer_flag;
156 // FRU Record fields
157 static int hf_fru_record_id;
158 static int hf_fru_record_type;
159 static int hf_fru_record_num_fields;
160 static int hf_fru_record_encoding;
161 static int hf_fru_record_field_type;
162 static int hf_fru_record_field_len;
163 static int hf_fru_record_field_value;
164 static int hf_fru_record_field_value_uint16;
165 static int hf_fru_record_field_value_string;
166 static int hf_fru_record_crc;
167 static int hf_fru_table_handle;
169 static const value_string directions[] = {
170 {0, "response"},
171 {1, "reserved"},
172 {2, "request"},
173 {3, "async/unack"},
174 {0, NULL}
177 static const value_string pldm_types[] = {
178 {0, "PLDM Messaging and Discovery"},
179 {1, "PLDM for SMBIOS"},
180 {2, "PLDM Platform Monitoring and Control"},
181 {3, "PLDM for BIOS Control and Configuration"},
182 {4, "PLDM for FRU Data"},
183 {5, "PLDM for Firmware Update"},
184 {6, "PLDM for Redfish Device Enablement"},
185 {63, "OEM Specific"},
186 {0, NULL}
189 static const value_string pldmBaseCmd[] = {
190 {1, "Set TID"},
191 {2, "Get TID"},
192 {3, "Get PLDM Version"},
193 {4, "Get PLDM Types"},
194 {5, "GetPLDMCommands"},
195 {6, "SelectPLDMVersion"},
196 {7, "NegotiateTransferParameters"},
197 {8, "Multipart Send"},
198 {9, "Multipart Receive"},
199 {0, NULL}
202 static const value_string pldmPlatformCmds[] = {
203 {4, "SetEventReceiver"},
204 {10, "PlatformEventMessage"},
205 {17, "GetSensorReading"},
206 {33, "GetStateSensorReadings"},
207 {49, "SetNumericEffecterValue"},
208 {50, "GetNumericEffecterValue"},
209 {57, "SetStateEffecterStates"},
210 {81, "GetPDR"},
211 {0, NULL}
214 static const value_string pldmFruCmds[] = {
215 {1, "GetFRURecordTableMetadata"},
216 {2, "GetFRURecordTable"},
217 {3, "SetFRURecordTable"},
218 {4, "GetFRURecordByOption"},
219 {0, NULL}
222 static const value_string pldmBIOScmd[] = {
223 {1, "GetBIOSTable"},
224 {2, "SetBIOSTable"},
225 {7, "SetBIOSAttributeCurrentValue"},
226 {8, "GetBIOSAttributeCurrentValueByHandle"},
227 {12, "GetDateTime"},
228 {13, "SetDateTime"},
229 {0, NULL}
232 static const value_string transferOperationFlags[] = {
233 {0, "GetNextPart"},
234 {1, "GetFirstPart"},
235 {0, NULL}
238 static const value_string transferFlags[] = {
239 {1, "Start"},
240 {2, "Middle"},
241 {4, "End"},
242 {5, "StartAndEnd"},
243 {0, NULL}
246 static const value_string completion_codes[] = {
247 {0x0, "Success"},
248 {0x1, "Error"},
249 {0x2, "Invalid Data"},
250 {0x3, "Invalid Length"},
251 {0x4, "Not Ready"},
252 {0x5, "Unsupported PLDM command"},
253 {0x20, "Invalid PLDM type"},
254 {0, NULL}
257 static const value_string platform_completion_codes[] = {
258 {0x0, "Success"},
259 {0x1, "Error"},
260 {0x2, "Invalid Data"},
261 {0x3, "Invalid Length"},
262 {0x4, "Not Ready"},
263 {0x5, "Unsupported PLDM command"},
264 {0x20, "Invalid PLDM type"},
265 {0x80, "PLDM Platform Invalid ID/Data Handle/Protocol Type"},
266 {0x81, "Unsupported Event Format Version"},
267 {0x82, "PLDM Platform Invalid Record Handle"},
268 {0x83, "PLDM Platform Invalid Record Change Number"},
269 {0x84, "PLDM Platform PDR Transfer Timeout"},
270 {0x85, "Repository update in progress"},
271 {0, NULL}
275 /* platform */
277 static const value_string event_message_global_enable[] = {
278 {0, "Disable"},
279 {1, "Enable Async"},
280 {2, "Enable Polling"},
281 {3, "Enable Async Keep Alive"},
282 {0, NULL}
285 static const value_string transport_protocols[] = {
286 {0, "MCTP"},
287 {1, "NC-SI/RBT"},
288 {2, "Vendor Specific"},
289 {0, NULL}
292 static const value_string platform_event_message_classes[] = {
293 {0, "Sensor Event"},
294 {1, "Effecter Event"},
295 {2, "Redfish Task Event"},
296 {3, "Redfish Message Event"},
297 {4, "Pldm PDR Repository Change Event"},
298 {5, "Pldm Message Poll Event"},
299 {6, "Heartbeat Timer Elapsed Event"},
300 {0, NULL}
303 static const value_string sensor_data_size[] = {
304 {0, "uint8"},
305 {1, "sint8"},
306 {2, "uint16"},
307 {3, "sint16"},
308 {4, "uint32"},
309 {5, "sint32"},
310 {0, NULL}
313 static const value_string pldm_pdr_repository_chg_event_data_format[] = {
314 {0, "Refresh Entire Repository"},
315 {1, "Format is PDR Types"},
316 {2, "Format is PDR Handles"},
317 {0, NULL}
320 static const value_string sensor_platform_event_message_classes[] = {
321 {0, "Sensor Operational"},
322 {1, "State Sensor State"},
323 {2, "Numeric Sensor State"},
324 {0, NULL}
327 static const value_string platform_sensor_operational_state[] = {
328 {0, "PLDM Sensor Enabled"},
329 {1, "PLDM Sensor Disabled"},
330 {2, "PLDM Sensor Unavailable"},
331 {3, "PLDM Sensor Status Unknown"},
332 {4, "PLDM Sensor Failed"},
333 {5, "PLDM Sensor Initializing"},
334 {6, "PLDM Sensor SHUTTING DOWN"},
335 {7, "PLDM Sensor Intest"},
336 {0, NULL}
339 static const value_string pdr_repo_chg_event_data_operation[] = {
340 {0, "PLDM Refresh all Records"},
341 {1, "PLDM Records Deleted"},
342 {2, "PLDM Records Added"},
343 {3, "PLDM Records Modified"},
344 {0, NULL}
347 static const value_string platform_pdr_type[] = {
348 {1, "PLDM Terminus Locator PDR"},
349 {2, "PLDM Numeric Sensor PDR"},
350 {3, "PLDM Numeric Sensor Initialization PDR"},
351 {4, "PLDM State Sensor PDR"},
352 {5, "PLDM State Sensor Initialization PDR"},
353 {6, "PLDM Sensor Auxiliary Names PDR"},
354 {7, "PLDM OEM Unit PDR"},
355 {8, "PLDM OEM State Set PDR"},
356 {9, "PLDM Numeric Effecter PDR"},
357 {10, "PLDM Numeric Effecter Initialization PDR"},
358 {11, "PLDM State Effecter PDR"},
359 {12, "PLDM State Effecter Initialization PDR"},
360 {13, "PLDM Effecter Auxiliary Names PDR"},
361 {14, "PLDM Effecter OEM Semantic PDR"},
362 {15, "PLDM PDR Entity Association"},
363 {16, "PLDM Entity Auxiliary Names PDR"},
364 {17, "PLDM OEM Entity ID PDR"},
365 {18, "PLDM Interrupt Association PDR"},
366 {19, "PLDM Event Log PDR"},
367 {20, "PLDM PDR FRU Record Set"},
368 {21, "PLDM Compact Numeric Sensor PDR"},
369 {126, "PLDM OEM Device PDR"},
370 {127, "PLDM OEM PDR"},
371 {0, NULL}
374 static const value_string pldm_sensor_event_states[] = {
375 {0, "PLDM Sensor Unknown"},
376 {1, "PLDM Sensor Normal"},
377 {2, "PLDM Sensor Warning"},
378 {3, "PLDM Sensor Critical"},
379 {4, "PLDM Sensor Fatal"},
380 {5, "PLDM Sensor Lower Warning"},
381 {6, "PLDM Sensor Lower Critical"},
382 {7, "PLDM Sensor Lower Fatal"},
383 {8, "PLDM Sensor Upper Warning"},
384 {9, "PLDM Sensor Upper Critical"},
385 {10, "PLDM Sensor Upper fatal"},
386 {0, NULL}
389 static const value_string pldm_sensor_event_message_enable[] = {
390 {0, "PLDM NO Event Generation"},
391 {1, "PLDM Events Disabled"},
392 {2, "PLDM Events Enabled"},
393 {3, "PLDM Operation Events Only Enabled"},
394 {4, "PLDM State Events Only Enabled"},
395 {0, NULL}
398 static const value_string pldm_effecter_oper_state[] = {
399 {0, "Effecter Operational State Enabled Update Pending"},
400 {1, "Effecter Operational State Enabled No Update Pending"},
401 {2, "Effecter Operational State Disabled"},
402 {3, "Effecter Operational State Unavailable"},
403 {4, "Effecter Operational State Status Unknown"},
404 {5, "Effecter Operational State Failed"},
405 {6, "Effecter Operational State Initializing"},
406 {7, "Effecter Operational State Shutting Down"},
407 {8, "Effecter Operational State Intest"},
408 {0, NULL}
411 static const value_string transfer_op_flags[] = {
412 {0, "Get Next Part"},
413 {1, "Get First Part"},
414 {0, NULL}
417 static const value_string pldm_effecter_state_set_request[] = {
418 {0, "No Change"},
419 {1, "Request Set"},
420 {0, NULL}
423 static const value_string pdr_transfer_flags[] = {
424 {0, "Start"},
425 {1, "Middle"},
426 {4, "End"},
427 {5, "Start and End"},
428 {0, NULL}
431 static const value_string sensor_bool8[] = {
432 {0x01, "True"},
433 {0x00, "False"},
434 {0, NULL}
437 static const value_string result_status[] = {
438 {0, "No Logging"},
439 {1, "Logging Disabled"},
440 {2, "Log Full"},
441 {3, "Accepted for Logging"},
442 {4, "Logged"},
443 {5, "Logging Rejected"},
444 {0, NULL}
447 /* FRU */
448 static const value_string FRU_completion_code[] = {
449 {0x80, "Invalid data transfer handle"},
450 {0x81, "Invalid transfer operation flag"},
451 {0x82, "Invalid transfer flag"},
452 {0x83, "No FRU table metadata"},
453 {0x84, "Invalid data integrity check"},
454 {0x85, "Fru data table unavailable"},
455 {0, NULL}
458 static const value_string record_encoding[] = {
459 {1, "ASCII"},
460 {2, "UTF8"},
461 {3, "UTF16"},
462 {4, "UTF16-LE"},
463 {5, "UTF16-BE"},
464 {0, NULL}
467 static const value_string record_types[] = {
468 {1, "General FRU Record"},
469 {254, "OEM FRU Record"},
470 {0, NULL}
473 static const value_string field_types_general[] = {
474 {0x0, "Reserved"},
475 {0x1, "Chassis Type"},
476 {0x2, "Model"},
477 {0x3, "Part Number"},
478 {0x4, "Serial Number"},
479 {0x5, "Manufacturer"},
480 {0x6, "Manufacture Date"},
481 {0x7, "Vendor"},
482 {0x8, "Name"},
483 {0x9, "SKU"},
484 {0xa, "Version"},
485 {0xb, "Asset Tag"},
486 {0xc, "Description"},
487 {0xd, "Engineering Change Level"},
488 {0xe, "Other Information"},
489 {0xf, "Vendor IANA"},
490 {0, NULL}
493 /* Some details of frame seen passed info functions handling packet types.
494 Not stored as per-packet data in frame... */
495 typedef struct pldm_packet_data {
496 uint8_t direction;
497 uint8_t instance_id;
498 } pldm_packet_data;
501 /* Return number of characters written */
502 static int print_version_field(uint8_t bcd, char *buffer, size_t buffer_size)
504 int v;
505 if (bcd == 0xff)
506 // No value to write
507 return 0;
508 if (((bcd) & 0xf0) == 0xf0) {
509 // First nibble all set, so get value from 2nd nibble - show as bcd
510 v = (bcd) & 0x0f;
511 return snprintf(buffer, buffer_size, "%d", v);
513 // Get one char from each nibble by printing as 2-digit number
514 v = (((bcd) >> 4) * 10) + ((bcd) & 0x0f);
515 return snprintf(buffer, buffer_size, "%02d", v);
518 static char* ver2str(tvbuff_t *tvb, int offset)
520 #define VER_BUF_LEN 12
521 static char buffer[VER_BUF_LEN+1];
522 char* buf_ptr = &buffer[0];
524 uint8_t major = tvb_get_uint8(tvb, offset);
525 uint8_t minor = tvb_get_uint8(tvb, offset+1);
526 uint8_t update = tvb_get_uint8(tvb, offset+2);
527 uint8_t alpha = tvb_get_uint8(tvb, offset+3);
529 // major, minor and update fields are all BCD encoded
530 uint8_t c_offset = 0;
532 // Major
533 if (major != 0xff) {
534 c_offset += print_version_field(major, buf_ptr+c_offset, VER_BUF_LEN-c_offset);
535 c_offset += snprintf(buf_ptr+c_offset, VER_BUF_LEN-c_offset, ".");
536 } else {
537 c_offset += snprintf(buf_ptr+c_offset, VER_BUF_LEN-c_offset, "-");
539 // Minor
540 if (minor != 0xff) {
541 c_offset += print_version_field(minor, buf_ptr+c_offset, VER_BUF_LEN-c_offset);
542 } else {
543 c_offset += snprintf(buf_ptr+c_offset, VER_BUF_LEN-c_offset, "-");
545 // Update
546 if (update != 0xff) {
547 c_offset += snprintf(buf_ptr+c_offset, VER_BUF_LEN-c_offset, ".");
548 c_offset += print_version_field(update, buf_ptr+c_offset, VER_BUF_LEN-c_offset);
549 } else {
550 c_offset += snprintf(buf_ptr+c_offset, VER_BUF_LEN-c_offset, "-");
552 // Alpha
553 if (alpha != 0x00) {
554 /*c_offset += */snprintf(buf_ptr+c_offset, VER_BUF_LEN-c_offset, "%c", alpha);
555 } else {
556 c_offset += snprintf(buf_ptr+c_offset, VER_BUF_LEN-c_offset, ".");
557 snprintf(buf_ptr+c_offset, VER_BUF_LEN-c_offset, "-");
560 return buf_ptr;
564 static
565 int dissect_base(tvbuff_t *tvb, packet_info *pinfo, proto_tree *p_tree, const pldm_packet_data *data)
567 static uint8_t pldmT = -1;
568 uint8_t instID = data->instance_id;
569 uint8_t request = data->direction;
570 int offset = 0;
571 uint32_t pldm_cmd, completion_code;
572 proto_tree_add_item_ret_uint(p_tree, hf_pldm_base_commands, tvb, offset, 1, ENC_LITTLE_ENDIAN, &pldm_cmd);
573 offset += 1;
574 if (!request) { //completion code in response only
575 proto_tree_add_item_ret_uint(p_tree, hf_pldm_completion_code, tvb, offset, 1, ENC_LITTLE_ENDIAN, &completion_code);
576 if (completion_code)
577 return tvb_captured_length(tvb);
578 offset += 1;
580 switch (pldm_cmd) {
581 case 01: // SetTID
582 if (request) {
583 proto_tree_add_item(p_tree, hf_pldm_base_TID, tvb, offset, 1, ENC_LITTLE_ENDIAN);
585 break;
586 case 02: // GetTID
587 if (!request) {
588 proto_tree_add_item(p_tree, hf_pldm_base_TID, tvb, offset, 1, ENC_LITTLE_ENDIAN);
590 break;
591 case 03: // GetPLDMVersion
592 if (request) {
593 proto_tree_add_item(p_tree, hf_pldm_base_dataTransferHandle, tvb, offset, 4, ENC_LITTLE_ENDIAN);
594 offset += 4;
595 proto_tree_add_item(p_tree, hf_pldm_base_transferOperationFlag, tvb, offset, 1, ENC_LITTLE_ENDIAN);
596 offset += 1;
597 proto_tree_add_item(p_tree, hf_pldm_base_PLDMtype, tvb, offset, 1, ENC_LITTLE_ENDIAN);
598 } else {
599 proto_tree_add_item(p_tree, hf_pldm_base_nextDataTransferHandle, tvb, offset, 4, ENC_LITTLE_ENDIAN);
600 offset += 4;
601 proto_tree_add_item(p_tree, hf_pldm_base_transferFlag, tvb, offset, 1, ENC_LITTLE_ENDIAN);
602 offset += 1;
603 const char *version_string = ver2str(tvb, offset);
604 proto_tree_add_string_format_value(p_tree, hf_pldm_base_typeVersion, tvb, offset, 4,
605 version_string, "%s", version_string);
606 // possibly more than one entry
608 break;
609 case 04: // GetPLDMTypes
610 if (!request) {
611 uint8_t flag_bit, curr_byte;
612 int byte, bit;
613 for (byte=0; byte<8; byte++, offset+=1) { // loop for iterating over last 8 bytes
614 curr_byte = tvb_get_uint8(tvb, offset);
615 flag_bit = 1; // bit within current byte
616 for (bit=0; bit<8; bit++, flag_bit <<=1) {
617 if (curr_byte & flag_bit) { // type is supported
618 // Add bit position as value
619 proto_tree_add_uint(p_tree, hf_pldm_base_typesSupported, tvb, offset, 1, (byte*8)+bit);
624 break;
625 case 05: // GetPLDMCommand
626 if (request) {
627 pldmT = tvb_get_uint8(tvb, offset); // response depends on this
628 if (pldmT == 63)
629 pldmT = 7; // for oem-specific inorder to avoid array of size 64
630 if (instID > 31 || pldmT > 7) {
631 col_append_str(pinfo->cinfo, COL_INFO, "Invalid PLDM Inst ID or Type");
632 break;
633 } else {
634 pldmTypeMap = wmem_map_new(addr_resolv_scope, g_direct_hash, g_direct_equal);
635 wmem_map_insert(pldmTypeMap, GUINT_TO_POINTER(instID), GUINT_TO_POINTER(pldmT));
637 proto_tree_add_item(p_tree, hf_pldm_base_PLDMtype, tvb, offset, 1, ENC_LITTLE_ENDIAN);
638 offset += 1;
639 const char *version_string = ver2str(tvb, offset);
640 proto_tree_add_string_format_value(p_tree, hf_pldm_base_typeVersion, tvb, offset, 4,
641 version_string, "%s", version_string);
642 } else if (!request) {
643 int pldmTypeReceived = GPOINTER_TO_UINT(wmem_map_lookup(pldmTypeMap, GUINT_TO_POINTER(instID)));
644 switch (pldmTypeReceived) {
645 case 0:
647 uint8_t byte = tvb_get_uint8(tvb, offset);
648 uint8_t flag_bit = 1;
649 for (int i = 0; i < 8; i++, flag_bit <<= 1) {
650 if (byte & flag_bit) {
651 proto_tree_add_uint(p_tree, hf_pldm_base_commands, tvb, offset, 1, i);
655 break;
656 case 2:
658 uint64_t byt[4];
659 byt[0] = tvb_get_letoh64(tvb, offset);
660 byt[1] = tvb_get_letoh64(tvb, offset + 8);
661 byt[2] = tvb_get_letoh64(tvb, offset + 16);
662 byt[3] = tvb_get_letoh64(tvb, offset + 24);
663 uint64_t flag_bit = 1;
664 for (int i = 0; i < 88; i++, flag_bit <<= 1) {
665 if (i == 64) {
666 flag_bit = 1;
668 int j = i / 64;
669 if (i > 7 && i % 8 == 0)
670 offset += 1;
671 uint64_t byte = byt[j];
672 if (byte & flag_bit) {
673 proto_tree_add_uint(p_tree, hf_pldm_platform_commands, tvb, offset, 1, i);
677 break;
678 case 3:
680 uint16_t byte = tvb_get_letohs(tvb, offset);
681 uint16_t flag_bit = 1;
682 for (int i = 0; i < 16; i++, flag_bit <<= 1) {
683 if (i > 7 && i % 8 == 0)
684 offset += 1;
685 if (byte & flag_bit) {
686 proto_tree_add_uint(p_tree, hf_pldm_BIOS_commands, tvb, offset, 1, i);
690 break;
691 case 4:
693 uint64_t byte = tvb_get_letoh64(tvb, offset);
694 uint64_t flag_bit = 1;
695 for (int i = 0; i < 64; i++, flag_bit <<= 1) {
696 if (i > 7 && i % 8 == 0)
697 offset += 1;
698 if (byte & flag_bit) {
699 proto_tree_add_uint(p_tree, hf_pldm_FRU_commands, tvb, offset, 1, i);
703 break;
704 default:
705 col_append_str(pinfo->cinfo, COL_INFO, "Invalid PLDM Command Request");
708 break;
709 default:
710 col_append_str(pinfo->cinfo, COL_INFO, "Invalid PLDM command");
711 break;
713 return tvb_captured_length(tvb);
717 static
718 int dissect_platform(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *p_tree, const pldm_packet_data *data)
720 uint8_t request = data->direction;
721 int offset = 0;
722 uint32_t pldm_cmd, completion_code;
723 proto_tree_add_item_ret_uint(p_tree, hf_pldm_platform_commands, tvb, offset, 1, ENC_LITTLE_ENDIAN, &pldm_cmd);
724 offset += 1;
725 if (!request) { //completion code in response only
726 proto_tree_add_item_ret_uint(p_tree, hf_pldm_platform_completion_code, tvb, offset, 1, ENC_LITTLE_ENDIAN, &completion_code);
727 if (completion_code)
728 return tvb_captured_length(tvb);
729 offset += 1;
731 switch (pldm_cmd) {
732 case 0x04: // Set Event Receiver command
733 if (request) {
734 uint32_t transport_protocol, event_message_global;
735 proto_item *event_msg_global_response = proto_tree_add_item_ret_uint(
736 p_tree, hf_event_message_global, tvb, offset, 1, ENC_LITTLE_ENDIAN, &event_message_global);
737 offset += 1;
738 proto_item *transport_protocol_response = proto_tree_add_item_ret_uint(
739 p_tree, hf_transport_protocol_type, tvb, offset, 1, ENC_LITTLE_ENDIAN, &transport_protocol);
740 offset += 1;
741 if (transport_protocol_response != NULL && transport_protocol == 0) { // MCTP
742 proto_tree_add_item(p_tree, hf_event_receiver_addr_info, tvb, offset, 1, ENC_LITTLE_ENDIAN);
744 if (event_msg_global_response != NULL && event_message_global == 3) {
745 offset += 1;
746 proto_tree_add_item(p_tree, hf_heartbeat_timer, tvb, offset, 2, ENC_LITTLE_ENDIAN);
749 break;
750 case 0x0a: // Platform Event Message command
751 if (request) {
752 proto_tree_add_item(p_tree, hf_pldm_platform_format_version, tvb, offset, 1, ENC_LITTLE_ENDIAN);
753 offset += 1;
754 proto_tree_add_item(p_tree, hf_pldm_base_TID, tvb, offset, 1, ENC_LITTLE_ENDIAN);
755 offset += 1;
756 uint32_t platform_event_message_class;
757 proto_tree_add_item_ret_uint(p_tree, hf_event_class, tvb, offset, 1, ENC_LITTLE_ENDIAN, &platform_event_message_class);
758 offset += 1;
759 uint32_t sensor_event_class;
760 /* Event Data */
761 switch (platform_event_message_class) {
762 case 0x0: // SensorEvent(0x00)
763 proto_tree_add_item(p_tree, hf_sensor_id, tvb, offset, 2, ENC_LITTLE_ENDIAN);
764 offset += 2;
765 proto_tree_add_item_ret_uint(p_tree, hf_sensor_event_class, tvb, offset, 1, ENC_LITTLE_ENDIAN, &sensor_event_class);
766 offset += 1;
767 /* Sensor Event Class */
768 switch (sensor_event_class) {
769 case 0x0: // Sensor Operational State
770 proto_tree_add_item(p_tree, hf_sensor_present_op_state, tvb, offset, 1, ENC_LITTLE_ENDIAN);
771 offset += 1;
772 proto_tree_add_item(p_tree, hf_sensor_prev_op_state, tvb, offset, 1, ENC_LITTLE_ENDIAN);
773 break;
774 case 0x1: // State Sensor State
775 proto_tree_add_item(p_tree, hf_sensor_offset, tvb, offset, 1, ENC_LITTLE_ENDIAN);
776 offset += 1;
777 proto_tree_add_item(p_tree, hf_event_state, tvb, offset, 1, ENC_LITTLE_ENDIAN);
778 offset += 1;
779 proto_tree_add_item(p_tree, hf_event_prev_state, tvb, offset, 1, ENC_LITTLE_ENDIAN);
780 break;
781 case 0x2: // Numeric Sensor State
782 proto_tree_add_item(p_tree, hf_event_state, tvb, offset, 1, ENC_LITTLE_ENDIAN);
783 offset += 1;
784 proto_tree_add_item(p_tree, hf_event_prev_state, tvb, offset, 1, ENC_LITTLE_ENDIAN);
785 offset += 1;
786 uint32_t size;
787 proto_tree_add_item_ret_uint(p_tree, hf_sensor_data_size, tvb, offset, 1, ENC_LITTLE_ENDIAN, &size);
788 offset += 1;
789 switch (size) {
790 case 0:
791 proto_tree_add_item(p_tree, hf_sensor_value_u8, tvb, offset, 1, ENC_LITTLE_ENDIAN);
792 break;
793 case 1:
794 proto_tree_add_item(p_tree, hf_sensor_value_s8, tvb, offset, 1, ENC_LITTLE_ENDIAN);
795 break;
796 case 2:
797 proto_tree_add_item(p_tree, hf_sensor_value_u16, tvb, offset, 2, ENC_LITTLE_ENDIAN);
798 break;
799 case 3:
800 proto_tree_add_item(p_tree, hf_sensor_value_s16, tvb, offset, 2, ENC_LITTLE_ENDIAN);
801 break;
802 case 4:
803 proto_tree_add_item(p_tree, hf_sensor_value_u32, tvb, offset, 4, ENC_LITTLE_ENDIAN);
804 break;
805 case 5:
806 proto_tree_add_item(p_tree, hf_sensor_value_s32, tvb, offset, 4, ENC_LITTLE_ENDIAN);
807 break;
808 default: // Invalid
809 col_append_str(pinfo->cinfo, COL_INFO, "Invalid byte");
811 break;
812 default:
813 col_append_str(pinfo->cinfo, COL_INFO, "Invalid sensor event class");
814 break;
816 break;
817 case 0x4: // PLDM PDR Repository Change Event
818 if (request) {
819 uint32_t pdr_data_format, num_change_record;
820 proto_tree_add_item_ret_uint(p_tree, hf_pdr_data_format, tvb, offset, 1, ENC_LITTLE_ENDIAN, &pdr_data_format);
821 offset += 1;
822 proto_tree_add_item_ret_uint(p_tree, hf_pdr_num_change_recs, tvb, offset, 1, ENC_LITTLE_ENDIAN, &num_change_record);
823 if (num_change_record>0) { // if pdr_data_format is refresh entire repo then num-change-record shall be 0
824 offset +=1;
825 for (uint32_t i = 0; i < num_change_record; i++) {
826 proto_tree_add_item(p_tree, hf_pdr_repo_change_event_data_op, tvb, offset, 1, ENC_LITTLE_ENDIAN);
827 offset +=1;
828 uint32_t num_change_entries;
829 proto_tree_add_item_ret_uint(p_tree, hf_pdr_repo_change_rec_num_change_entries, tvb, offset, 1, ENC_LITTLE_ENDIAN, &num_change_entries);
830 offset +=1;
831 for (uint32_t j = 0; j < num_change_entries; j++) {
832 if (pdr_data_format == 1) { // pdr type enumeration
833 proto_tree_add_item(p_tree, hf_pdr_repo_change_event_record_pdr_type, tvb, offset, 4, ENC_LITTLE_ENDIAN);
835 else if (pdr_data_format == 2) { // pdr Record handle enumeration
836 proto_tree_add_item(p_tree, hf_pdr_repo_change_event_record_pdr_record_handle, tvb, offset, 4, ENC_LITTLE_ENDIAN);
838 offset+=4;
843 break;
844 case 0x6: // Heartbeat elapsed
845 if (request) {
846 proto_tree_add_item(p_tree, hf_heartbeat_format_ver, tvb, offset, 1, ENC_LITTLE_ENDIAN);
847 offset += 1;
848 proto_tree_add_item(p_tree, hf_heartbeat_sequence_num, tvb, offset, 1, ENC_LITTLE_ENDIAN);
850 break;
851 default:
852 col_append_str(pinfo->cinfo, COL_INFO, "Invalid platform message type");
855 else {
856 proto_tree_add_item(p_tree, hf_result_status, tvb, offset, 1, ENC_LITTLE_ENDIAN);
858 break;
859 case 0x21: // GetStateSensorReadings(33)
860 if (request) {
861 proto_tree_add_item(p_tree, hf_sensor_id, tvb, offset, 2, ENC_LITTLE_ENDIAN);
862 offset += 2;
863 uint8_t sensor_rearm = tvb_get_uint8(tvb, offset);
864 uint8_t flag_bit = 1;
865 int cnt = 0;
866 for (int i = 0; i < 8; i++, flag_bit <<= 1) {
867 if (sensor_rearm & flag_bit) {
868 cnt++;
869 proto_tree_add_uint(p_tree, hf_sensor_rearm, tvb, offset, 1, i);
872 if (cnt == 0) {
873 proto_tree_add_item(p_tree, hf_sensor_rearm_none, tvb, offset, 1, ENC_LITTLE_ENDIAN);
875 offset +=1;
876 proto_tree_add_item(p_tree, hf_pldm_sensor_reserved, tvb, offset, 1, ENC_LITTLE_ENDIAN);
877 } else {
878 uint32_t sensor_comp_count;
879 proto_tree_add_item_ret_uint(p_tree, hf_sensor_composite_count, tvb, offset, 1, ENC_LITTLE_ENDIAN, &sensor_comp_count);
880 for (uint32_t i=0; i<sensor_comp_count; i++) { // statefield
881 offset += 1;
882 proto_tree_add_item(p_tree, hf_sensor_present_op_state, tvb, offset, 1, ENC_LITTLE_ENDIAN);
883 offset += 1;
884 proto_tree_add_item(p_tree, hf_sensor_present_event_state, tvb, offset, 1, ENC_LITTLE_ENDIAN);
885 offset += 1;
886 proto_tree_add_item(p_tree, hf_sensor_prev_event_state, tvb, offset, 1, ENC_LITTLE_ENDIAN);
887 offset += 1;
888 proto_tree_add_item(p_tree, hf_sensor_event_state, tvb, offset, 1, ENC_LITTLE_ENDIAN);
891 break;
892 case 0x11: // GetSensorReading(17)
893 if (request) {
894 proto_tree_add_item(p_tree, hf_sensor_id, tvb, offset, 2, ENC_LITTLE_ENDIAN);
895 offset += 2;
896 proto_tree_add_item(p_tree, hf_event_rearm, tvb, offset, 1, ENC_LITTLE_ENDIAN);
898 else {
899 uint32_t size;
900 proto_tree_add_item_ret_uint(p_tree, hf_sensor_data_size, tvb, offset, 1, ENC_LITTLE_ENDIAN, &size);
901 offset += 1;
902 proto_tree_add_item(p_tree, hf_sensor_present_op_state, tvb, offset, 1, ENC_LITTLE_ENDIAN);
903 offset += 1;
904 proto_tree_add_item(p_tree, hf_sensor_event_msg_enable, tvb, offset, 1, ENC_LITTLE_ENDIAN);
905 offset += 1;
906 proto_tree_add_item(p_tree, hf_sensor_present_event_state, tvb, offset, 1, ENC_LITTLE_ENDIAN);
907 offset += 1;
908 proto_tree_add_item(p_tree, hf_sensor_prev_event_state, tvb, offset, 1, ENC_LITTLE_ENDIAN);
909 offset += 1;
910 proto_tree_add_item(p_tree, hf_sensor_event_state, tvb, offset, 1, ENC_LITTLE_ENDIAN);
911 offset += 1;
912 switch (size) {
913 case 0:
914 proto_tree_add_item(p_tree, hf_sensor_value_u8, tvb, offset, 1, ENC_LITTLE_ENDIAN);
915 break;
916 case 1:
917 proto_tree_add_item(p_tree, hf_sensor_value_s8, tvb, offset, 1, ENC_LITTLE_ENDIAN);
918 break;
919 case 2:
920 proto_tree_add_item(p_tree, hf_sensor_value_u16, tvb, offset, 2, ENC_LITTLE_ENDIAN);
921 break;
922 case 3:
923 proto_tree_add_item(p_tree, hf_sensor_value_s16, tvb, offset, 2, ENC_LITTLE_ENDIAN);
924 break;
925 case 4:
926 proto_tree_add_item(p_tree, hf_sensor_value_u32, tvb, offset, 4, ENC_LITTLE_ENDIAN);
927 break;
928 case 5:
929 proto_tree_add_item(p_tree, hf_sensor_value_s32, tvb, offset, 4, ENC_LITTLE_ENDIAN);
930 break;
931 default: // Invalid
932 col_append_str(pinfo->cinfo, COL_INFO, "Invalid byte");
935 break;
936 case 0x31: // SetNumericEffecterValue(49)
937 if (request) {
938 proto_tree_add_item(p_tree, hf_effecter_id, tvb, offset, 2, ENC_LITTLE_ENDIAN);
939 offset += 2;
940 uint32_t size;
941 proto_tree_add_item_ret_uint(p_tree, hf_effecter_datasize, tvb, offset, 1, ENC_LITTLE_ENDIAN, &size);
942 offset += 1;
943 switch (size) {
944 case 0:
945 proto_tree_add_item(p_tree, hf_effecter_value_u8, tvb, offset, 1, ENC_LITTLE_ENDIAN);
946 break;
947 case 1:
948 proto_tree_add_item(p_tree, hf_effecter_value_s8, tvb, offset, 1, ENC_LITTLE_ENDIAN);
949 break;
950 case 2:
951 proto_tree_add_item(p_tree, hf_effecter_value_u16, tvb, offset, 2, ENC_LITTLE_ENDIAN);
952 break;
953 case 3:
954 proto_tree_add_item(p_tree, hf_effecter_value_s16, tvb, offset, 2, ENC_LITTLE_ENDIAN);
955 break;
956 case 4:
957 proto_tree_add_item(p_tree, hf_effecter_value_u32, tvb, offset, 4, ENC_LITTLE_ENDIAN);
958 break;
959 case 5:
960 proto_tree_add_item(p_tree, hf_effecter_value_s32, tvb, offset, 4, ENC_LITTLE_ENDIAN);
961 break;
962 default: // Invalid
963 col_append_str(pinfo->cinfo, COL_INFO, "Invalid byte");
966 break;
967 case 0x32: // GetNumericEffecterValue(50)
968 if (request) {
969 proto_tree_add_item(p_tree, hf_effecter_id, tvb, offset, 2, ENC_LITTLE_ENDIAN);
970 } else {
971 uint32_t size;
972 proto_tree_add_item_ret_uint(p_tree, hf_effecter_datasize, tvb, offset, 1, ENC_LITTLE_ENDIAN, &size);
973 offset += 1;
974 proto_tree_add_item(p_tree, hf_effecter_op_state, tvb, offset, 1, ENC_LITTLE_ENDIAN);
975 offset += 1;
976 switch (size) {
977 case 0:
978 proto_tree_add_item(p_tree, hf_effecter_value_pnd_u8, tvb, offset, 1, ENC_LITTLE_ENDIAN);
979 offset += 1;
980 proto_tree_add_item(p_tree, hf_effecter_value_pres_u8, tvb, offset, 1, ENC_LITTLE_ENDIAN);
981 break;
982 case 1:
983 proto_tree_add_item(p_tree, hf_effecter_value_pnd_s8, tvb, offset, 1, ENC_LITTLE_ENDIAN);
984 offset += 1;
985 proto_tree_add_item(p_tree, hf_effecter_value_pres_s8, tvb, offset, 1, ENC_LITTLE_ENDIAN);
986 break;
987 case 2:
988 proto_tree_add_item(p_tree, hf_effecter_value_pnd_u16, tvb, offset, 2, ENC_LITTLE_ENDIAN);
989 offset += 2;
990 proto_tree_add_item(p_tree, hf_effecter_value_pres_u16, tvb, offset, 2, ENC_LITTLE_ENDIAN);
991 break;
992 case 3:
993 proto_tree_add_item(p_tree, hf_effecter_value_pnd_s16, tvb, offset, 2, ENC_LITTLE_ENDIAN);
994 offset += 2;
995 proto_tree_add_item(p_tree, hf_effecter_value_pres_s16, tvb, offset, 2, ENC_LITTLE_ENDIAN);
996 break;
997 case 4:
998 proto_tree_add_item(p_tree, hf_effecter_value_pnd_u32, tvb, offset, 4, ENC_LITTLE_ENDIAN);
999 offset += 4;
1000 proto_tree_add_item(p_tree, hf_effecter_value_pres_u32, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1001 break;
1002 case 5:
1003 proto_tree_add_item(p_tree, hf_effecter_value_pnd_s32, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1004 offset += 4;
1005 proto_tree_add_item(p_tree, hf_effecter_value_pres_s32, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1006 break;
1007 default: // Invalid
1008 col_append_str(pinfo->cinfo, COL_INFO, "Invalid byte");
1012 break;
1013 case 0x39: // SetStateEffecterStates(57)
1014 if (request) {
1015 proto_tree_add_item(p_tree, hf_effecter_id, tvb, offset, 2, ENC_LITTLE_ENDIAN);
1016 offset += 2;
1017 uint32_t effecter_comp_count;
1018 proto_tree_add_item_ret_uint(p_tree, hf_effecter_count, tvb, offset, 1, ENC_LITTLE_ENDIAN, &effecter_comp_count);
1019 for (uint32_t i=0; i < effecter_comp_count; i++) { // statefield
1020 offset += 1;
1021 proto_tree_add_item(p_tree, hf_effecter_set_request, tvb, offset, 1, ENC_LITTLE_ENDIAN);
1022 offset += 1;
1023 proto_tree_add_item(p_tree, hf_effecter_state, tvb, offset, 1, ENC_LITTLE_ENDIAN);
1026 break;
1027 case 0x51: // GetPDR
1028 if (request) {
1029 proto_tree_add_item(p_tree, hf_pdr_record_handle, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1030 offset += 4;
1031 proto_tree_add_item(p_tree, hf_pdr_data_handle, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1032 offset += 4;
1033 proto_tree_add_item(p_tree, hf_pdr_transfer_op_flag, tvb, offset, 1, ENC_LITTLE_ENDIAN);
1034 offset += 1;
1035 proto_tree_add_item(p_tree, hf_pdr_req_count, tvb, offset, 2, ENC_LITTLE_ENDIAN);
1036 offset += 2;
1037 proto_tree_add_item(p_tree, hf_pdr_record_change_num, tvb, offset, 2, ENC_LITTLE_ENDIAN);
1039 } else {
1040 proto_tree_add_item(p_tree, hf_pdr_next_record_handle, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1041 offset += 4;
1042 proto_tree_add_item(p_tree, hf_pdr_next_data_handle, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1043 offset += 4;
1044 uint32_t transfer_flag;
1045 proto_tree_add_item_ret_uint(p_tree, hf_pdr_transfer_flag, tvb, offset, 1, ENC_LITTLE_ENDIAN, &transfer_flag);
1046 offset += 1;
1047 uint32_t response_cnt;
1048 proto_tree_add_item_ret_uint(p_tree, hf_pdr_response_count, tvb, offset, 2, ENC_LITTLE_ENDIAN, &response_cnt);
1049 offset += 2;
1050 uint16_t pdr_length = tvb_reported_length_remaining(tvb, offset);
1051 if (response_cnt) {
1052 if (pdr_length != response_cnt) {
1053 col_append_str(pinfo->cinfo, COL_INFO, "Corrupt PDR Record data");
1054 break;
1056 while (response_cnt > 0) {
1057 proto_tree_add_item(p_tree, hf_pdr_record_data, tvb, offset, 1, ENC_LITTLE_ENDIAN );
1058 offset += 1;
1059 response_cnt -= 1;
1062 if (transfer_flag == 0x4) {
1063 // CRC only present if flag == end
1064 proto_tree_add_item(p_tree, hf_transfer_crc, tvb, offset, 1, ENC_LITTLE_ENDIAN);
1067 break;
1068 default:
1069 col_append_fstr(pinfo->cinfo, COL_INFO, "Unsupported or Invalid PLDM command %x ", pldm_cmd);
1070 break;
1072 return tvb_captured_length(tvb);
1075 static
1076 uint16_t parse_fru_record_table(tvbuff_t *tvb, const packet_info *pinfo,
1077 proto_tree *p_tree, uint16_t offset)
1079 uint32_t min_size = 8, field_len = 0, num_fields = 0, encoding = 0, record_type;
1080 uint16_t bytes_left = tvb_reported_length(tvb) - offset;
1081 while (bytes_left >= min_size) {
1082 // parse a FRU Record Data
1083 proto_tree_add_item(p_tree, hf_fru_record_id, tvb, offset, 2, ENC_LITTLE_ENDIAN);
1084 offset += 2;
1085 proto_tree_add_item_ret_uint(p_tree, hf_fru_record_type, tvb, offset, 1, ENC_LITTLE_ENDIAN, &record_type);
1086 offset += 1;
1087 proto_tree_add_item_ret_uint(p_tree, hf_fru_record_num_fields, tvb, offset, 1, ENC_LITTLE_ENDIAN, &num_fields);
1088 offset += 1;
1089 proto_tree_add_item_ret_uint(p_tree, hf_fru_record_encoding, tvb, offset, 1, ENC_LITTLE_ENDIAN, &encoding);
1090 offset += 1;
1092 for (uint8_t i = 0; i < num_fields; i++) {
1093 if (record_type == 1) { // General
1094 proto_tree_add_item(p_tree, hf_fru_record_field_type, tvb, offset, 1, ENC_LITTLE_ENDIAN);
1095 offset += 1;
1096 proto_tree_add_item_ret_uint(p_tree, hf_fru_record_field_len, tvb, offset, 1, ENC_LITTLE_ENDIAN, &field_len);
1097 offset += 1;
1098 switch (encoding) {
1099 case 0x1:
1100 proto_tree_add_item(p_tree, hf_fru_record_field_value_string, tvb, offset, field_len, ENC_ASCII);
1101 break;
1102 case 0x2:
1103 proto_tree_add_item(p_tree, hf_fru_record_field_value, tvb, offset, field_len, ENC_UTF_8);
1104 break;
1105 case 0x3:
1106 proto_tree_add_item(p_tree, hf_fru_record_field_value_uint16, tvb, offset, field_len, ENC_UTF_16);
1107 break;
1108 case 0x4:
1109 proto_tree_add_item(p_tree, hf_fru_record_field_value_uint16, tvb,
1110 offset, field_len, ENC_UTF_16 | ENC_LITTLE_ENDIAN);
1111 break;
1112 case 0x5:
1113 proto_tree_add_item(p_tree, hf_fru_record_field_value_uint16, tvb,
1114 offset, field_len, ENC_UTF_16 | ENC_BIG_ENDIAN);
1115 break;
1116 default:
1117 col_append_str(pinfo->cinfo, COL_INFO, "Unsupported or invalid FRU record encoding");
1118 break;
1120 offset += field_len;
1121 } else {
1122 col_append_str(pinfo->cinfo, COL_INFO, "Unsupported or OEM FRU record type");
1125 bytes_left = tvb_reported_length(tvb) - offset;
1127 return offset;
1130 static
1131 int dissect_FRU(tvbuff_t *tvb, packet_info *pinfo, proto_tree *p_tree, const pldm_packet_data *data)
1133 uint8_t request = data->direction;
1134 uint16_t offset = 0;
1135 uint32_t pldm_cmd;
1136 uint8_t padding = 0;
1137 proto_tree_add_item_ret_uint(p_tree, hf_pldm_FRU_commands, tvb, offset, 1, ENC_LITTLE_ENDIAN, &pldm_cmd);
1138 offset += 1;
1139 if (!request) {
1140 uint8_t completion_code = tvb_get_uint8(tvb, offset);
1141 switch (completion_code) {
1142 case 0x80:
1143 case 0x81:
1144 case 0x82:
1145 case 0x83:
1146 case 0x84:
1147 case 0x85:
1148 proto_tree_add_item(p_tree, hf_fru_completion_code, tvb, offset, 1, ENC_LITTLE_ENDIAN);
1149 break;
1150 default:
1151 proto_tree_add_item(p_tree, hf_pldm_completion_code, tvb, offset, 1, ENC_LITTLE_ENDIAN);
1154 if (completion_code)
1155 return tvb_captured_length(tvb);
1156 offset += 1;
1158 switch (pldm_cmd) {
1159 case 0x01: // Get Fru record table metadata
1160 if (!request) {
1161 proto_tree_add_item(p_tree, hf_fru_major_ver, tvb, offset, 1, ENC_LITTLE_ENDIAN);
1162 offset += 1;
1163 proto_tree_add_item(p_tree, hf_fru_minor_ver, tvb, offset, 1, ENC_LITTLE_ENDIAN);
1164 offset += 1;
1165 proto_tree_add_item(p_tree, hf_fru_table_max_size, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1166 offset += 4;
1167 proto_tree_add_item(p_tree, hf_fru_table_length, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1168 offset += 4;
1169 proto_tree_add_item(p_tree, hf_fru_num_record_identifiers, tvb, offset, 2, ENC_LITTLE_ENDIAN);
1170 offset += 2;
1171 proto_tree_add_item(p_tree, hf_fru_num_records, tvb, offset, 2, ENC_LITTLE_ENDIAN);
1172 offset += 2;
1173 proto_tree_add_item(p_tree, hf_fru_table_crc, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1175 break;
1176 case 0x02: // Get Fru record table
1177 if (request) {
1178 proto_tree_add_item(p_tree, hf_fru_data_handle, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1179 offset += 4;
1180 proto_tree_add_item(p_tree, hf_fru_transfer_op_flag, tvb, offset, 1, ENC_LITTLE_ENDIAN);
1181 } else {
1182 proto_tree_add_item(p_tree, hf_fru_next_data_handle, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1183 offset += 4;
1184 proto_tree_add_item(p_tree, hf_fru_transfer_flag, tvb, offset, 1, ENC_LITTLE_ENDIAN);
1185 offset += 1;
1186 offset = parse_fru_record_table(tvb, pinfo, p_tree, offset);//check
1187 if (tvb_captured_length(tvb) != offset)
1188 col_append_str(pinfo->cinfo, COL_INFO, "Unexpected bytes at end of FRU table");
1190 break;
1191 case 0x03: // Set Fru record table
1192 if (request) {
1193 proto_tree_add_item(p_tree, hf_fru_data_handle, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1194 offset += 4;
1195 proto_tree_add_item(p_tree, hf_pldm_base_transferFlag, tvb, offset, 1, ENC_LITTLE_ENDIAN);
1196 offset += 1;
1197 offset = parse_fru_record_table(tvb, pinfo, p_tree, offset);//check
1198 if (tvb_captured_length(tvb) != offset) {
1199 padding = tvb_captured_length(tvb) - offset - 4;
1200 offset += padding;
1201 proto_tree_add_item(p_tree, hf_fru_record_crc, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1203 } else {
1204 proto_tree_add_item(p_tree, hf_fru_next_data_handle, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1206 break;
1207 case 0x04: // GetFruRecordByOption
1208 if (request) {
1209 proto_tree_add_item(p_tree, hf_fru_data_handle, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1210 offset += 4;
1211 proto_tree_add_item(p_tree, hf_fru_table_handle, tvb, offset, 2, ENC_LITTLE_ENDIAN);
1212 offset += 2;
1213 proto_tree_add_item(p_tree, hf_fru_record_id, tvb, offset, 2, ENC_LITTLE_ENDIAN);
1214 offset += 2;
1215 proto_tree_add_item(p_tree, hf_fru_record_type, tvb, offset, 1, ENC_LITTLE_ENDIAN);
1216 offset += 1;
1217 proto_tree_add_item(p_tree, hf_fru_record_field_type, tvb, offset, 1, ENC_LITTLE_ENDIAN);
1218 offset +=1;
1219 proto_tree_add_item(p_tree, hf_fru_transfer_op_flag, tvb, offset, 1, ENC_LITTLE_ENDIAN);
1220 } else {
1221 proto_tree_add_item(p_tree, hf_fru_next_data_handle, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1222 offset += 4;
1223 proto_tree_add_item(p_tree, hf_pldm_base_transferFlag, tvb, offset, 1, ENC_LITTLE_ENDIAN);
1224 offset += 1;
1225 offset = parse_fru_record_table(tvb, pinfo, p_tree, offset); // check
1226 if (tvb_captured_length(tvb) != offset) {
1227 padding = tvb_captured_length(tvb) - offset - 4;
1228 offset += padding;
1229 proto_tree_add_item(p_tree, hf_fru_record_crc, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1232 break;
1233 default:
1234 col_append_str(pinfo->cinfo, COL_INFO, "Unsupported or Invalid PLDM command");
1235 break;
1238 return tvb_captured_length(tvb);
1241 static int dissect_pldm(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
1242 void *data _U_)
1244 col_set_str(pinfo->cinfo, COL_PROTOCOL, "PLDM");
1245 col_clear(pinfo->cinfo, COL_INFO);
1247 tvbuff_t *next_tvb;
1248 unsigned len;
1249 uint32_t direction;
1250 uint32_t instID, pldm_type, offset;
1251 int reported_length;
1252 len = tvb_reported_length(tvb);
1253 if (len < PLDM_MIN_LENGTH) {
1254 col_add_fstr(pinfo->cinfo, COL_INFO, "Packet length %u, minimum %u", len, PLDM_MIN_LENGTH);
1255 return tvb_captured_length(tvb);
1257 if (tree) {
1258 /* First byte is the MCTP msg type, it is 01 for PLDM over MCTP */
1259 offset = 1;
1260 proto_item *ti = proto_tree_add_item(tree, proto_pldm, tvb, offset, -1, ENC_NA);
1261 proto_tree *pldm_tree = proto_item_add_subtree(ti, ett_pldm);
1263 proto_tree_add_item_ret_uint(pldm_tree, hf_pldm_msg_direction, tvb, offset, 1, ENC_LITTLE_ENDIAN, &direction);
1264 proto_tree_add_item(pldm_tree, hf_pldm_reserved, tvb, offset, 1, ENC_LITTLE_ENDIAN);
1265 proto_tree_add_item_ret_uint(pldm_tree, hf_pldm_instance_id, tvb, offset, 1, ENC_LITTLE_ENDIAN, &instID);
1266 offset += 1;
1267 proto_tree_add_item(pldm_tree, hf_pldm_header_version, tvb, offset, 1, ENC_LITTLE_ENDIAN);
1268 proto_tree_add_item_ret_uint(pldm_tree, hf_pldm_type, tvb, offset, 1, ENC_LITTLE_ENDIAN, &pldm_type);
1269 offset += 1;
1270 next_tvb = tvb_new_subset_remaining(tvb, offset);
1271 reported_length = tvb_reported_length_remaining(tvb, offset);
1273 /* Handle specific packet type */
1274 pldm_packet_data d = {direction, instID};
1275 if (reported_length >= 1) {
1276 switch (pldm_type) {
1277 case 0:
1278 dissect_base(next_tvb, pinfo, pldm_tree, &d);
1279 break;
1280 case 2:
1281 dissect_platform(next_tvb, pinfo, pldm_tree, &d);
1282 break;
1283 case 4:
1284 dissect_FRU(next_tvb, pinfo, pldm_tree, &d);
1288 return tvb_captured_length(tvb);
1291 void proto_register_pldm(void)
1293 static hf_register_info hf[] = {
1294 {&hf_pldm_msg_direction,
1295 {"PLDM Message Direction", "pldm.direction", FT_UINT8, BASE_DEC, VALS(directions),
1296 0xc0, NULL, HFILL}},
1297 {&hf_pldm_reserved,
1298 {"PLDM Reserved Bit", "pldm.reservedBit", FT_UINT8, BASE_DEC, NULL,
1299 0x20, NULL, HFILL}},
1300 {&hf_pldm_instance_id,
1301 {"PLDM Instance Id", "pldm.instanceID", FT_UINT8, BASE_DEC, NULL,
1302 0x1F, NULL, HFILL}},
1303 {&hf_pldm_header_version,
1304 {"PLDM Header Version", "pldm.headerVersion", FT_UINT8, BASE_DEC, NULL,
1305 0xC0, NULL, HFILL}},
1306 {&hf_pldm_type,
1307 {"PLDM Type", "pldm.type", FT_UINT8, BASE_HEX, VALS(pldm_types),
1308 0x3f, "PLDM Specification Type", HFILL}},
1309 {&hf_pldm_base_TID,
1310 {"TID Value", "pldm.base.TID", FT_UINT8, BASE_DEC, NULL,
1311 0x0, "Terminus ID", HFILL}},
1312 {&hf_pldm_base_dataTransferHandle,
1313 {"Data Transfer Handle", "pldm.base.dataTransferHandle", FT_UINT32, BASE_DEC, NULL,
1314 0x0, NULL, HFILL}},
1315 {&hf_pldm_base_transferOperationFlag,
1316 {"Transfer Operation Flag", "pldm.base.transferOperationFlag", FT_UINT8, BASE_HEX, VALS(transferOperationFlags),
1317 0x0, NULL, HFILL}},
1318 {&hf_pldm_base_nextDataTransferHandle,
1319 {"Next Data Transfer Handle", "pldm.base.nextDataTransferHandle", FT_UINT32, BASE_DEC, NULL,
1320 0x0, NULL, HFILL}},
1321 {&hf_pldm_base_transferFlag,
1322 {"Transfer Flag", "pldm.base.transferFlag", FT_UINT8, BASE_HEX, VALS(transferFlags),
1323 0x0, NULL, HFILL}},
1324 {&hf_pldm_base_PLDMtype,
1325 {"PLDM Type Requested", "pldm.base.pldmType", FT_UINT8, BASE_HEX, VALS(pldm_types),
1326 0x0, "Requested PLDM Specification Type", HFILL}},
1327 {&hf_pldm_base_typeVersion,
1328 {"PLDM Type Version", "pldm.base.pldmTypeVersion", FT_STRING, BASE_NONE, NULL,
1329 0x0, NULL, HFILL}},
1330 {&hf_pldm_base_typesSupported,
1331 {"PLDM Type Supported", "pldm.base.typeSupported", FT_UINT8, BASE_HEX, VALS(pldm_types),
1332 0x0, NULL, HFILL}},
1333 {&hf_pldm_BIOS_commands,
1334 {"BIOS Command", "pldm.biosCommands", FT_UINT8, BASE_HEX, VALS(pldmBIOScmd),
1335 0x0, "BIOS Command Supported", HFILL}},
1336 {&hf_pldm_FRU_commands,
1337 {"FRU Command", "pldm.fruCommands", FT_UINT8, BASE_HEX, VALS(pldmFruCmds),
1338 0x0, "FRU Command Supported", HFILL}},
1339 {&hf_pldm_platform_commands,
1340 {"Platform Command", "pldm.platformCommands", FT_UINT8, BASE_HEX, VALS(pldmPlatformCmds),
1341 0x0, "Platform Command Supported", HFILL}},
1342 {&hf_pldm_base_commands,
1343 {"PLDM Base Command", "pldm.baseCommands", FT_UINT8, BASE_HEX, VALS(pldmBaseCmd),
1344 0x0, "PLDM Messaging and Discovery Command Supported", HFILL}},
1345 {&hf_pldm_completion_code,
1346 {"Completion Code", "pldm.completionCode", FT_UINT8, BASE_DEC, VALS(completion_codes),
1347 0x0, NULL, HFILL}},
1348 /*platform*/
1349 {&hf_pldm_platform_completion_code,
1350 {"Completion Code", "pldm.completionCode", FT_UINT8, BASE_DEC, VALS(platform_completion_codes),
1351 0x0, NULL, HFILL}},
1352 {&hf_event_message_global,
1353 {"Event message global enable", "pldm.platform.receiver.enable", FT_UINT8, BASE_DEC, VALS(event_message_global_enable),
1354 0x0, NULL, HFILL}},
1355 {&hf_result_status,
1356 {"Completion Code", "pldm.status", FT_UINT8, BASE_DEC, VALS(result_status),
1357 0x0, NULL, HFILL}},
1358 {&hf_transport_protocol_type,
1359 {"Transport protocol", "pldm.platform.receiver.transport", FT_UINT8, BASE_DEC, VALS(transport_protocols),
1360 0x0, NULL, HFILL}},
1361 {&hf_event_receiver_addr_info,
1362 {"Event receiver address info", "pldm.platform.receiver.addr_info", FT_UINT8, BASE_DEC, NULL,
1363 0x0, NULL, HFILL}},
1364 {&hf_heartbeat_timer,
1365 {"Heartbeat timer", "pldm.platform.receiver.timer", FT_UINT16, BASE_DEC, NULL,
1366 0x0, NULL, HFILL}},
1367 {&hf_event_class,
1368 {"Event Class", "pldm.platform.event.class", FT_UINT8, BASE_DEC, VALS(platform_event_message_classes),
1369 0x0, NULL, HFILL}},
1370 {&hf_sensor_id,
1371 {"Sensor ID", "pldm.platform.event.sensor_id", FT_UINT16, BASE_DEC, NULL,
1372 0x0, NULL, HFILL}},
1373 {&hf_sensor_event_class,
1374 {"Sensor event class", "pldm.platform.event.sensor_event_class", FT_UINT8, BASE_DEC, VALS(sensor_platform_event_message_classes),
1375 0x0, NULL, HFILL}},
1376 {&hf_pldm_platform_format_version,
1377 {"Format Version", "pldm.platform.event_format_version", FT_UINT8, BASE_DEC, NULL,
1378 0x0, NULL, HFILL}},
1379 {&hf_sensor_present_op_state,
1380 {"Sensor present operational state", "pldm.platform.event.sensor.op_state", FT_UINT8, BASE_DEC, VALS(platform_sensor_operational_state),
1381 0x0,NULL, HFILL}},
1382 {&hf_sensor_prev_op_state,
1383 {"Sensor previous operational state", "pldm.platform.event.sensor.prev_op_state", FT_UINT8, BASE_DEC, VALS(platform_sensor_operational_state),
1384 0x0, NULL, HFILL}},
1385 {&hf_sensor_offset,
1386 {"Sensor offset", "pldm.platform.event.sensor_offset", FT_UINT8, BASE_DEC, NULL,
1387 0x0, NULL, HFILL}},
1388 {&hf_event_state,
1389 {"Event state", "pldm.platform.event.state", FT_UINT8, BASE_DEC, VALS(pldm_sensor_event_states),
1390 0x0, NULL, HFILL}},
1391 {&hf_event_prev_state,
1392 {"Event previous state", "pldm.platform.event.prev_state", FT_UINT8, BASE_DEC, VALS(pldm_sensor_event_states),
1393 0x0, NULL, HFILL}},
1394 {&hf_sensor_data_size,
1395 {"Sensor data size", "pldm.platform.sensor.data_size", FT_UINT8, BASE_DEC, VALS(sensor_data_size),
1396 0x0, NULL, HFILL}},
1397 {&hf_sensor_value_u8,
1398 {"Sensor reading", "pldm.platform.event.sensor.data_u8", FT_UINT8, BASE_DEC, NULL,
1399 0x0, NULL, HFILL}},
1400 {&hf_sensor_value_s8,
1401 {"Sensor reading", "pldm.platform.event.sensor.data_s8", FT_INT8, BASE_DEC, NULL,
1402 0x0, NULL, HFILL}},
1403 {&hf_sensor_value_u16,
1404 {"Sensor reading", "pldm.platform.event.sensor.data_u16", FT_UINT16, BASE_DEC, NULL,
1405 0x0, NULL, HFILL}},
1406 {&hf_sensor_value_s16,
1407 {"Sensor reading", "pldm.platform.event.sensor.data_s16", FT_INT16, BASE_DEC, NULL,
1408 0x0, NULL, HFILL}},
1409 {&hf_sensor_value_u32,
1410 {"Sensor reading", "pldm.platform.event.sensor.data_u32", FT_UINT32, BASE_DEC, NULL,
1411 0x0, NULL, HFILL}},
1412 {&hf_sensor_value_s32,
1413 {"Sensor reading", "pldm.platform.event.sensor.data_s32", FT_INT32, BASE_DEC, NULL,
1414 0x0, NULL, HFILL}},
1415 {&hf_effecter_value_pnd_u8,
1416 {"Pending Effecter Value in uint8", "pldm.platform.effecter.pnd_val_u8", FT_UINT8, BASE_DEC, NULL,
1417 0x0, NULL, HFILL}},
1418 {&hf_effecter_value_pnd_s8,
1419 {"Pending Effecter Value in sint8", "pldm.platform.effecter.pnd_val_s8", FT_INT8, BASE_DEC, NULL,
1420 0x0, NULL, HFILL}},
1421 {&hf_effecter_value_pnd_u16,
1422 {"Pending Effecter Value in uint16", "pldm.platform.effecter.pnd_val_u16", FT_UINT16, BASE_DEC, NULL,
1423 0x0, NULL, HFILL}},
1424 {&hf_effecter_value_pnd_s16,
1425 {"Pending Effecter Value in sint16", "pldm.platform.effecter.pnd_val_s16", FT_INT16, BASE_DEC, NULL,
1426 0x0, NULL, HFILL}},
1427 {&hf_effecter_value_pnd_u32,
1428 {"Pending Effecter Value in uint32", "pldm.platform.effecter.pnd_val_u32", FT_UINT32, BASE_DEC, NULL,
1429 0x0, NULL, HFILL}},
1430 {&hf_effecter_value_pnd_s32,
1431 {"Pending Effecter Value in sint32", "pldm.platform.effecter.pnd_val_s32", FT_INT32, BASE_DEC, NULL,
1432 0x0, NULL, HFILL}},
1433 {&hf_effecter_value_pres_u8,
1434 {"Present Effecter Value in uint8", "pldm.platform.effecter.pres_val_u8", FT_UINT8, BASE_DEC, NULL,
1435 0x0, NULL, HFILL}},
1436 {&hf_effecter_value_pres_s8,
1437 {"Present Effecter Value in sint8", "pldm.platform.effecter.pres_val_s8", FT_INT8, BASE_DEC, NULL,
1438 0x0, NULL, HFILL}},
1439 {&hf_effecter_value_pres_u16,
1440 {"Present Effecter Value in uint16", "pldm.platform.effecter.pres_val_u16", FT_UINT16, BASE_DEC, NULL,
1441 0x0, NULL, HFILL}},
1442 {&hf_effecter_value_pres_s16,
1443 {"Present Effecter Value in sint16", "pldm.platform.effecter.pres_val_s16", FT_INT16, BASE_DEC, NULL,
1444 0x0, NULL, HFILL}},
1445 {&hf_effecter_value_pres_u32,
1446 {"Present Effecter Value in uint32", "pldm.platform.effecter.pres_val_u32", FT_UINT32, BASE_DEC, NULL,
1447 0x0, NULL, HFILL}},
1448 {&hf_effecter_value_pres_s32,
1449 {"Present Effecter Value in sint32", "pldm.platform.effecter.pres_val_s32", FT_INT32, BASE_DEC, NULL,
1450 0x0, NULL, HFILL}},
1451 {&hf_pdr_data_format,
1452 {"PDR Repository change data format", "pldm.platform.event.pdr.data_format", FT_UINT8, BASE_DEC, VALS(pldm_pdr_repository_chg_event_data_format),
1453 0x0, NULL, HFILL}},
1454 {&hf_pdr_num_change_recs,
1455 {"Number of PDR Records Changed", "pldm.platform.event.pdr_rec_change_num", FT_UINT8, BASE_DEC, NULL,
1456 0x0, NULL, HFILL}},
1457 {&hf_pdr_repo_change_event_data_op,
1458 {"PDR Repository change event record - data operation", "pldm.platform.event.pdr.record.data_op", FT_UINT8, BASE_DEC, VALS(pdr_repo_chg_event_data_operation),
1459 0x0, NULL, HFILL}},
1460 {&hf_pdr_repo_change_rec_num_change_entries,
1461 {"PDR Repository change event record - number of change entries", "pldm.platform.event.pdr.record.num_of_changes", FT_UINT8, BASE_DEC, NULL,
1462 0x0, NULL, HFILL}},
1463 {&hf_pdr_repo_change_event_record_pdr_type,
1464 {"PDR Repository change event record-PDR Type", "pldm.platform.event.pdr.record.pdr_type", FT_UINT32, BASE_DEC, VALS(platform_pdr_type),
1465 0x0, NULL, HFILL}},
1466 {&hf_pdr_repo_change_event_record_pdr_record_handle,
1467 {"PDR Repository change event record-PDR Record Handle", "pldm.platform.event.pdr.record.pdr_rec_handle", FT_UINT32, BASE_DEC, NULL,
1468 0x0, NULL, HFILL}},
1469 {&hf_heartbeat_format_ver,
1470 {"Heartbeat Format Version", "pldm.platform.event.heartbeat.format_version", FT_UINT8, BASE_DEC, NULL,
1471 0x0, NULL, HFILL}},
1472 {&hf_heartbeat_sequence_num,
1473 {"Heartbeat sequence number", "pldm.platform.event.heartbeat.seq", FT_UINT8, BASE_DEC, NULL,
1474 0x0, NULL, HFILL}},
1475 {&hf_sensor_rearm,
1476 {"Sensor re-armed", "pldm.platform.sensor_rearm", FT_UINT8, BASE_DEC, NULL,
1477 0x0, NULL, HFILL}},
1478 {&hf_sensor_rearm_none,
1479 {"No Sensor Re-armed", "pldm.platform.sensor_rearm_none", FT_UINT8, BASE_HEX, NULL,
1480 0x0, NULL, HFILL}},
1481 {&hf_pldm_sensor_reserved,
1482 {"PLDM Sensor Reserved Byte", "pldm.platform.sensor.reserved_byte", FT_UINT8, BASE_DEC, NULL,
1483 0x0, NULL, HFILL}},
1484 {&hf_sensor_prev_event_state,
1485 {"Sensor Previous Event State", "pldm.platform.prev_event", FT_UINT8, BASE_DEC, VALS(pldm_sensor_event_states),
1486 0x0, NULL, HFILL}},
1487 {&hf_sensor_present_event_state,
1488 {"Sensor Present Event State", "pldm.platform.present_event", FT_UINT8, BASE_DEC, VALS(pldm_sensor_event_states),
1489 0x0, NULL, HFILL}},
1490 {&hf_sensor_event_state,
1491 {"Sensor Event State", "pldm.platform.event_state", FT_UINT8, BASE_DEC, VALS(pldm_sensor_event_states),
1492 0x0, NULL, HFILL}},
1493 {&hf_sensor_composite_count,
1494 {"Sensor Composite Count", "pldm.platform.sensor_comp_count", FT_UINT8, BASE_DEC, NULL,
1495 0x0, NULL, HFILL}},
1496 {&hf_event_rearm,
1497 {"Rearm Event State", "pldm.platform.rearm_event_state", FT_UINT8, BASE_DEC, VALS(sensor_bool8),
1498 0x0, NULL, HFILL}},
1499 {&hf_sensor_event_msg_enable,
1500 {"Sensor Event Message Enable", "pldm.platform.sensor_event_enable", FT_UINT8, BASE_DEC, VALS(pldm_sensor_event_message_enable),
1501 0x0, NULL, HFILL}},
1502 {&hf_effecter_id,
1503 {"Effecter ID", "pldm.platform.effecter.id", FT_UINT16, BASE_DEC, NULL,
1504 0x0, NULL, HFILL}},
1505 {&hf_effecter_count,
1506 {"Effecter count", "pldm.platform.effecter.count", FT_UINT8, BASE_DEC, NULL,
1507 0x0, NULL, HFILL}},
1508 {&hf_effecter_datasize,
1509 {"Effecter Data Size", "pldm.platform.effecter.datasize", FT_UINT8, BASE_DEC, NULL,
1510 0x0, NULL, HFILL}},
1511 {&hf_effecter_value_u8,
1512 {"Effecter Value", "pldm.platform.effecter.value_u8", FT_UINT8, BASE_DEC, NULL,
1513 0x0, NULL, HFILL}},
1514 {&hf_effecter_value_s8,
1515 {"Effecter Value", "pldm.platform.effecter.value_s8", FT_INT8, BASE_DEC, NULL,
1516 0x0, NULL, HFILL}},
1517 {&hf_effecter_value_u16,
1518 {"Effecter Value", "pldm.platform.effecter.value_u16", FT_UINT16, BASE_DEC, NULL,
1519 0x0, NULL, HFILL}},
1520 {&hf_effecter_value_s16,
1521 {"Effecter Value", "pldm.platform.effecter.value_s16", FT_INT16, BASE_DEC, NULL,
1522 0x0, NULL, HFILL}},
1523 {&hf_effecter_value_u32,
1524 {"Effecter Value", "pldm.platform.effecter.value_u32", FT_UINT32, BASE_DEC, NULL,
1525 0x0, NULL, HFILL}},
1526 {&hf_effecter_value_s32,
1527 {"Effecter Value", "pldm.platform.effecter.value_s32", FT_INT32, BASE_DEC, NULL,
1528 0x0, NULL, HFILL}},
1529 {&hf_effecter_op_state,
1530 {"Effecter Operational State", "pldm.platform.effecter_op_state", FT_UINT8, BASE_DEC, VALS(pldm_effecter_oper_state),
1531 0x0, NULL, HFILL}},
1532 {&hf_effecter_set_request,
1533 {"Effecter Set Request", "pldm.platform.effecter_set_req", FT_UINT8, BASE_DEC, VALS(pldm_effecter_state_set_request),
1534 0x0, NULL, HFILL}},
1535 {&hf_effecter_state,
1536 {"Effecter State", "pldm.platform.effecter_state", FT_UINT8, BASE_DEC, NULL,
1537 0x0, NULL, HFILL}},
1539 /* PDR */
1540 {&hf_pdr_record_handle,
1541 {"PDR record handle", "pldm.platform.pdr.record_handle", FT_UINT32, BASE_DEC, NULL,
1542 0x0, NULL, HFILL}},
1543 {&hf_pdr_data_handle,
1544 {"PDR data transfer handle", "pldm.platform.pdr.data_handle", FT_UINT32, BASE_DEC, NULL,
1545 0x0, NULL, HFILL}},
1546 {&hf_pdr_transfer_op_flag,
1547 {"PDR transfer operation flag", "pldm.platform.pdr.transfer_op_flag", FT_UINT8, BASE_DEC, VALS(transfer_op_flags),
1548 0x0, NULL, HFILL}},
1549 {&hf_pdr_req_count,
1550 {"PDR request count", "pldm.platform.pdr.request.count", FT_UINT16, BASE_DEC, NULL,
1551 0x0, NULL, HFILL}},
1552 {&hf_pdr_record_change_num,
1553 {"PDR record change number", "pldm.platform.pdr.record_change_number", FT_UINT16, BASE_DEC, NULL,
1554 0x0, NULL, HFILL}},
1555 {&hf_pdr_next_record_handle,
1556 {"PDR next record handle", "pldm.platform.pdr.next_record_handle", FT_UINT32, BASE_DEC, NULL,
1557 0x0, NULL, HFILL}},
1558 {&hf_pdr_next_data_handle,
1559 {"PDR next data transfer handle", "pldm.platform.pdr.next_data_handle", FT_UINT32, BASE_DEC, NULL,
1560 0x0, NULL, HFILL}},
1561 {&hf_pdr_transfer_flag,
1562 {"PDR transfer flag", "pldm.platform.pdr.transfer_flag", FT_UINT8, BASE_DEC, VALS(pdr_transfer_flags),
1563 0x0, NULL, HFILL}},
1564 {&hf_pdr_response_count,
1565 {"PDR response count", "pldm.platform.pdr.response.count", FT_UINT16, BASE_DEC, NULL,
1566 0x0, NULL, HFILL}},
1567 {&hf_pdr_record_data,
1568 {"PDR Record Data Byte", "pldm.platform.pdr.record_data", FT_UINT8, BASE_HEX, NULL,
1569 0x0, NULL, HFILL}},
1570 {&hf_transfer_crc,
1571 {"PDR transfer CRC", "pldm.platform.pdr.crc", FT_UINT8, BASE_DEC, NULL,
1572 0x0, NULL, HFILL}},
1573 /*FRU*/
1574 {&hf_fru_completion_code,
1575 {"FRU completion code", "pldm.fru.completion_code", FT_UINT8, BASE_HEX, VALS(FRU_completion_code),
1576 0x0, NULL, HFILL}},
1577 {&hf_fru_major_ver,
1578 {"FRU Major version", "pldm.fru.ver.major", FT_UINT8, BASE_DEC, NULL,
1579 0x0, NULL, HFILL}},
1580 {&hf_fru_minor_ver,
1581 {"FRU Minor version", "pldm.fru.ver.minor", FT_UINT8, BASE_DEC, NULL,
1582 0x0, NULL, HFILL}},
1583 {&hf_fru_table_max_size,
1584 {"FRU Maximum table size", "pldm.fru.table.max", FT_UINT32, BASE_DEC, NULL,
1585 0x0, NULL, HFILL}},
1586 {&hf_fru_table_length,
1587 {"FRU Table length", "pldm.fru.table.len", FT_UINT32, BASE_DEC, NULL,
1588 0x0, NULL, HFILL}},
1589 {&hf_fru_num_record_identifiers,
1590 {"Total number of record set identifiers", "pldm.fru.num_identifiers", FT_UINT16, BASE_DEC, NULL,
1591 0x0, NULL, HFILL}},
1592 {&hf_fru_num_records,
1593 {"Total number of records in table", "pldm.fru.table.num_records", FT_UINT16, BASE_DEC, NULL,
1594 0x0, NULL, HFILL}},
1595 {&hf_fru_table_crc,
1596 {"FRU Table CRC", "pldm.fru.table.crc", FT_UINT32, BASE_DEC, NULL,
1597 0x0, NULL, HFILL}},
1598 {&hf_fru_data_handle,
1599 {"FRU Data transfer handle", "pldm.fru.table.handle", FT_UINT32, BASE_DEC, NULL,
1600 0x0, NULL, HFILL}},
1601 {&hf_fru_transfer_op_flag,
1602 {"FRU Data transfer operation flag", "pldm.fru.table.opflag", FT_UINT8, BASE_DEC, VALS(transfer_op_flags),
1603 0x0, NULL, HFILL}},
1604 {&hf_fru_next_data_handle,
1605 {"FRU Next data transfer handle", "pldm.fru.table.nexthandle", FT_UINT32, BASE_DEC, NULL,
1606 0x0, NULL, HFILL}},
1607 {&hf_fru_transfer_flag,
1608 {"FRU Data transfer flag", "pldm.fru.table.flag", FT_UINT8, BASE_DEC, VALS(transferFlags),
1609 0x0, NULL, HFILL}},
1610 {&hf_fru_table_handle,
1611 {"FRU Record Data Handle", "pldm.fru.table_handle", FT_UINT16, BASE_DEC, NULL,
1612 0x0, NULL, HFILL}},
1613 // FRU Record fields
1614 {&hf_fru_record_id,
1615 {"FRU Record Set Identifier", "pldm.fru.record.id", FT_UINT16, BASE_DEC, NULL,
1616 0x0, NULL, HFILL}},
1617 {&hf_fru_record_type,
1618 {"FRU Record Type", "pldm.fru.record.type", FT_UINT8, BASE_DEC, VALS(record_types),
1619 0x0, NULL, HFILL}},
1620 {&hf_fru_record_num_fields,
1621 {"Number of FRU fields", "pldm.fru.record.num_fields", FT_UINT8, BASE_DEC, NULL,
1622 0x0, NULL, HFILL}},
1623 {&hf_fru_record_encoding,
1624 {"FRU Record Encoding", "pldm.fru.record.encoding", FT_UINT8, BASE_DEC, VALS(record_encoding),
1625 0x0, NULL, HFILL}},
1626 {&hf_fru_record_field_type,
1627 {"FRU Record Field Type", "pldm.fru.record.field_type", FT_UINT8, BASE_DEC, VALS(field_types_general),
1628 0x0, NULL, HFILL}},
1629 {&hf_fru_record_field_len,
1630 {"FRU Record Field Length", "pldm.fru.record.field_length", FT_UINT8, BASE_DEC, NULL,
1631 0x0, NULL, HFILL}},
1632 {&hf_fru_record_field_value,
1633 {"FRU Record Field Value", "pldm.fru.record.field_value", FT_UINT8, BASE_HEX, NULL,
1634 0x0, NULL, HFILL}},
1635 {&hf_fru_record_field_value_uint16,
1636 {"FRU Record Field Value", "pldm.fru.record.field_value_u16", FT_UINT16, BASE_HEX, NULL,
1637 0x0, NULL, HFILL}},
1638 {&hf_fru_record_field_value_string,
1639 {"FRU Record Field Value", "pldm.fru.record.field_value", FT_STRING, BASE_NONE, NULL,
1640 0x0, NULL, HFILL}},
1641 {&hf_fru_record_crc,
1642 {"FRU Record CRC32 (Unchecked)", "pldm.fru.record.crc", FT_UINT32, BASE_HEX, NULL,
1643 0x0, NULL, HFILL}},
1646 static int *ett[] = {&ett_pldm};
1647 proto_pldm = proto_register_protocol("PLDM Protocol", "PLDM", "pldm");
1648 proto_register_field_array(proto_pldm, hf, array_length(hf));
1649 proto_register_subtree_array(ett, array_length(ett));
1650 register_dissector("pldm", dissect_pldm, proto_pldm);
1653 void proto_reg_handoff_pldm(void)
1655 static dissector_handle_t pldm_handle;
1656 pldm_handle = create_dissector_handle(dissect_pldm, proto_pldm);
1657 dissector_add_uint("mctp.type", 1, pldm_handle);