2 * Routines for Platform Level Data Model(PLDM) packet
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
17 #include <epan/packet.h>
19 #define PLDM_MIN_LENGTH 4
20 #define PLDM_MAX_TYPES 8
23 static int proto_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
;
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
;
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
;
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
;
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
[] = {
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"},
189 static const value_string pldmBaseCmd
[] = {
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"},
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"},
214 static const value_string pldmFruCmds
[] = {
215 {1, "GetFRURecordTableMetadata"},
216 {2, "GetFRURecordTable"},
217 {3, "SetFRURecordTable"},
218 {4, "GetFRURecordByOption"},
222 static const value_string pldmBIOScmd
[] = {
225 {7, "SetBIOSAttributeCurrentValue"},
226 {8, "GetBIOSAttributeCurrentValueByHandle"},
232 static const value_string transferOperationFlags
[] = {
238 static const value_string transferFlags
[] = {
246 static const value_string completion_codes
[] = {
249 {0x2, "Invalid Data"},
250 {0x3, "Invalid Length"},
252 {0x5, "Unsupported PLDM command"},
253 {0x20, "Invalid PLDM type"},
257 static const value_string platform_completion_codes
[] = {
260 {0x2, "Invalid Data"},
261 {0x3, "Invalid Length"},
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"},
277 static const value_string event_message_global_enable
[] = {
280 {2, "Enable Polling"},
281 {3, "Enable Async Keep Alive"},
285 static const value_string transport_protocols
[] = {
288 {2, "Vendor Specific"},
292 static const value_string platform_event_message_classes
[] = {
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"},
303 static const value_string sensor_data_size
[] = {
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"},
320 static const value_string sensor_platform_event_message_classes
[] = {
321 {0, "Sensor Operational"},
322 {1, "State Sensor State"},
323 {2, "Numeric Sensor State"},
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"},
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"},
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"},
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"},
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"},
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"},
411 static const value_string transfer_op_flags
[] = {
412 {0, "Get Next Part"},
413 {1, "Get First Part"},
417 static const value_string pldm_effecter_state_set_request
[] = {
423 static const value_string pdr_transfer_flags
[] = {
427 {5, "Start and End"},
431 static const value_string sensor_bool8
[] = {
437 static const value_string result_status
[] = {
439 {1, "Logging Disabled"},
441 {3, "Accepted for Logging"},
443 {5, "Logging Rejected"},
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"},
458 static const value_string record_encoding
[] = {
467 static const value_string record_types
[] = {
468 {1, "General FRU Record"},
469 {254, "OEM FRU Record"},
473 static const value_string field_types_general
[] = {
475 {0x1, "Chassis Type"},
477 {0x3, "Part Number"},
478 {0x4, "Serial Number"},
479 {0x5, "Manufacturer"},
480 {0x6, "Manufacture Date"},
486 {0xc, "Description"},
487 {0xd, "Engineering Change Level"},
488 {0xe, "Other Information"},
489 {0xf, "Vendor IANA"},
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
{
501 /* Return number of characters written */
502 static int print_version_field(uint8_t bcd
, char *buffer
, size_t buffer_size
)
508 if (((bcd
) & 0xf0) == 0xf0) {
509 // First nibble all set, so get value from 2nd nibble - show as bcd
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;
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
, ".");
537 c_offset
+= snprintf(buf_ptr
+c_offset
, VER_BUF_LEN
-c_offset
, "-");
541 c_offset
+= print_version_field(minor
, buf_ptr
+c_offset
, VER_BUF_LEN
-c_offset
);
543 c_offset
+= snprintf(buf_ptr
+c_offset
, VER_BUF_LEN
-c_offset
, "-");
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
);
550 c_offset
+= snprintf(buf_ptr
+c_offset
, VER_BUF_LEN
-c_offset
, "-");
554 /*c_offset += */snprintf(buf_ptr
+c_offset
, VER_BUF_LEN
-c_offset
, "%c", alpha
);
556 c_offset
+= snprintf(buf_ptr
+c_offset
, VER_BUF_LEN
-c_offset
, ".");
557 snprintf(buf_ptr
+c_offset
, VER_BUF_LEN
-c_offset
, "-");
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
;
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
);
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
);
577 return tvb_captured_length(tvb
);
583 proto_tree_add_item(p_tree
, hf_pldm_base_TID
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
588 proto_tree_add_item(p_tree
, hf_pldm_base_TID
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
591 case 03: // GetPLDMVersion
593 proto_tree_add_item(p_tree
, hf_pldm_base_dataTransferHandle
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
595 proto_tree_add_item(p_tree
, hf_pldm_base_transferOperationFlag
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
597 proto_tree_add_item(p_tree
, hf_pldm_base_PLDMtype
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
599 proto_tree_add_item(p_tree
, hf_pldm_base_nextDataTransferHandle
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
601 proto_tree_add_item(p_tree
, hf_pldm_base_transferFlag
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
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
609 case 04: // GetPLDMTypes
611 uint8_t flag_bit
, curr_byte
;
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
);
625 case 05: // GetPLDMCommand
627 pldmT
= tvb_get_uint8(tvb
, offset
); // response depends on this
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");
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
);
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
) {
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
);
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) {
669 if (i
> 7 && i
% 8 == 0)
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
);
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)
685 if (byte
& flag_bit
) {
686 proto_tree_add_uint(p_tree
, hf_pldm_BIOS_commands
, tvb
, offset
, 1, i
);
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)
698 if (byte
& flag_bit
) {
699 proto_tree_add_uint(p_tree
, hf_pldm_FRU_commands
, tvb
, offset
, 1, i
);
705 col_append_str(pinfo
->cinfo
, COL_INFO
, "Invalid PLDM Command Request");
710 col_append_str(pinfo
->cinfo
, COL_INFO
, "Invalid PLDM command");
713 return tvb_captured_length(tvb
);
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
;
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
);
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
);
728 return tvb_captured_length(tvb
);
732 case 0x04: // Set Event Receiver command
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
);
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
);
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) {
746 proto_tree_add_item(p_tree
, hf_heartbeat_timer
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
750 case 0x0a: // Platform Event Message command
752 proto_tree_add_item(p_tree
, hf_pldm_platform_format_version
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
754 proto_tree_add_item(p_tree
, hf_pldm_base_TID
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
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
);
759 uint32_t sensor_event_class
;
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
);
765 proto_tree_add_item_ret_uint(p_tree
, hf_sensor_event_class
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
, &sensor_event_class
);
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
);
772 proto_tree_add_item(p_tree
, hf_sensor_prev_op_state
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
774 case 0x1: // State Sensor State
775 proto_tree_add_item(p_tree
, hf_sensor_offset
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
777 proto_tree_add_item(p_tree
, hf_event_state
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
779 proto_tree_add_item(p_tree
, hf_event_prev_state
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
781 case 0x2: // Numeric Sensor State
782 proto_tree_add_item(p_tree
, hf_event_state
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
784 proto_tree_add_item(p_tree
, hf_event_prev_state
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
787 proto_tree_add_item_ret_uint(p_tree
, hf_sensor_data_size
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
, &size
);
791 proto_tree_add_item(p_tree
, hf_sensor_value_u8
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
794 proto_tree_add_item(p_tree
, hf_sensor_value_s8
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
797 proto_tree_add_item(p_tree
, hf_sensor_value_u16
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
800 proto_tree_add_item(p_tree
, hf_sensor_value_s16
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
803 proto_tree_add_item(p_tree
, hf_sensor_value_u32
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
806 proto_tree_add_item(p_tree
, hf_sensor_value_s32
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
809 col_append_str(pinfo
->cinfo
, COL_INFO
, "Invalid byte");
813 col_append_str(pinfo
->cinfo
, COL_INFO
, "Invalid sensor event class");
817 case 0x4: // PLDM PDR Repository Change Event
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
);
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
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
);
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
);
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
);
844 case 0x6: // Heartbeat elapsed
846 proto_tree_add_item(p_tree
, hf_heartbeat_format_ver
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
848 proto_tree_add_item(p_tree
, hf_heartbeat_sequence_num
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
852 col_append_str(pinfo
->cinfo
, COL_INFO
, "Invalid platform message type");
856 proto_tree_add_item(p_tree
, hf_result_status
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
859 case 0x21: // GetStateSensorReadings(33)
861 proto_tree_add_item(p_tree
, hf_sensor_id
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
863 uint8_t sensor_rearm
= tvb_get_uint8(tvb
, offset
);
864 uint8_t flag_bit
= 1;
866 for (int i
= 0; i
< 8; i
++, flag_bit
<<= 1) {
867 if (sensor_rearm
& flag_bit
) {
869 proto_tree_add_uint(p_tree
, hf_sensor_rearm
, tvb
, offset
, 1, i
);
873 proto_tree_add_item(p_tree
, hf_sensor_rearm_none
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
876 proto_tree_add_item(p_tree
, hf_pldm_sensor_reserved
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
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
882 proto_tree_add_item(p_tree
, hf_sensor_present_op_state
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
884 proto_tree_add_item(p_tree
, hf_sensor_present_event_state
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
886 proto_tree_add_item(p_tree
, hf_sensor_prev_event_state
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
888 proto_tree_add_item(p_tree
, hf_sensor_event_state
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
892 case 0x11: // GetSensorReading(17)
894 proto_tree_add_item(p_tree
, hf_sensor_id
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
896 proto_tree_add_item(p_tree
, hf_event_rearm
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
900 proto_tree_add_item_ret_uint(p_tree
, hf_sensor_data_size
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
, &size
);
902 proto_tree_add_item(p_tree
, hf_sensor_present_op_state
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
904 proto_tree_add_item(p_tree
, hf_sensor_event_msg_enable
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
906 proto_tree_add_item(p_tree
, hf_sensor_present_event_state
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
908 proto_tree_add_item(p_tree
, hf_sensor_prev_event_state
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
910 proto_tree_add_item(p_tree
, hf_sensor_event_state
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
914 proto_tree_add_item(p_tree
, hf_sensor_value_u8
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
917 proto_tree_add_item(p_tree
, hf_sensor_value_s8
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
920 proto_tree_add_item(p_tree
, hf_sensor_value_u16
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
923 proto_tree_add_item(p_tree
, hf_sensor_value_s16
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
926 proto_tree_add_item(p_tree
, hf_sensor_value_u32
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
929 proto_tree_add_item(p_tree
, hf_sensor_value_s32
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
932 col_append_str(pinfo
->cinfo
, COL_INFO
, "Invalid byte");
936 case 0x31: // SetNumericEffecterValue(49)
938 proto_tree_add_item(p_tree
, hf_effecter_id
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
941 proto_tree_add_item_ret_uint(p_tree
, hf_effecter_datasize
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
, &size
);
945 proto_tree_add_item(p_tree
, hf_effecter_value_u8
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
948 proto_tree_add_item(p_tree
, hf_effecter_value_s8
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
951 proto_tree_add_item(p_tree
, hf_effecter_value_u16
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
954 proto_tree_add_item(p_tree
, hf_effecter_value_s16
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
957 proto_tree_add_item(p_tree
, hf_effecter_value_u32
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
960 proto_tree_add_item(p_tree
, hf_effecter_value_s32
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
963 col_append_str(pinfo
->cinfo
, COL_INFO
, "Invalid byte");
967 case 0x32: // GetNumericEffecterValue(50)
969 proto_tree_add_item(p_tree
, hf_effecter_id
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
972 proto_tree_add_item_ret_uint(p_tree
, hf_effecter_datasize
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
, &size
);
974 proto_tree_add_item(p_tree
, hf_effecter_op_state
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
978 proto_tree_add_item(p_tree
, hf_effecter_value_pnd_u8
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
980 proto_tree_add_item(p_tree
, hf_effecter_value_pres_u8
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
983 proto_tree_add_item(p_tree
, hf_effecter_value_pnd_s8
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
985 proto_tree_add_item(p_tree
, hf_effecter_value_pres_s8
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
988 proto_tree_add_item(p_tree
, hf_effecter_value_pnd_u16
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
990 proto_tree_add_item(p_tree
, hf_effecter_value_pres_u16
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
993 proto_tree_add_item(p_tree
, hf_effecter_value_pnd_s16
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
995 proto_tree_add_item(p_tree
, hf_effecter_value_pres_s16
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
998 proto_tree_add_item(p_tree
, hf_effecter_value_pnd_u32
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
1000 proto_tree_add_item(p_tree
, hf_effecter_value_pres_u32
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
1003 proto_tree_add_item(p_tree
, hf_effecter_value_pnd_s32
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
1005 proto_tree_add_item(p_tree
, hf_effecter_value_pres_s32
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
1008 col_append_str(pinfo
->cinfo
, COL_INFO
, "Invalid byte");
1013 case 0x39: // SetStateEffecterStates(57)
1015 proto_tree_add_item(p_tree
, hf_effecter_id
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
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
1021 proto_tree_add_item(p_tree
, hf_effecter_set_request
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
1023 proto_tree_add_item(p_tree
, hf_effecter_state
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
1027 case 0x51: // GetPDR
1029 proto_tree_add_item(p_tree
, hf_pdr_record_handle
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
1031 proto_tree_add_item(p_tree
, hf_pdr_data_handle
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
1033 proto_tree_add_item(p_tree
, hf_pdr_transfer_op_flag
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
1035 proto_tree_add_item(p_tree
, hf_pdr_req_count
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
1037 proto_tree_add_item(p_tree
, hf_pdr_record_change_num
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
1040 proto_tree_add_item(p_tree
, hf_pdr_next_record_handle
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
1042 proto_tree_add_item(p_tree
, hf_pdr_next_data_handle
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
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
);
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
);
1050 uint16_t pdr_length
= tvb_reported_length_remaining(tvb
, offset
);
1052 if (pdr_length
!= response_cnt
) {
1053 col_append_str(pinfo
->cinfo
, COL_INFO
, "Corrupt PDR Record data");
1056 while (response_cnt
> 0) {
1057 proto_tree_add_item(p_tree
, hf_pdr_record_data
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
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
);
1069 col_append_fstr(pinfo
->cinfo
, COL_INFO
, "Unsupported or Invalid PLDM command %x ", pldm_cmd
);
1072 return tvb_captured_length(tvb
);
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
);
1085 proto_tree_add_item_ret_uint(p_tree
, hf_fru_record_type
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
, &record_type
);
1087 proto_tree_add_item_ret_uint(p_tree
, hf_fru_record_num_fields
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
, &num_fields
);
1089 proto_tree_add_item_ret_uint(p_tree
, hf_fru_record_encoding
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
, &encoding
);
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
);
1096 proto_tree_add_item_ret_uint(p_tree
, hf_fru_record_field_len
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
, &field_len
);
1100 proto_tree_add_item(p_tree
, hf_fru_record_field_value_string
, tvb
, offset
, field_len
, ENC_ASCII
);
1103 proto_tree_add_item(p_tree
, hf_fru_record_field_value
, tvb
, offset
, field_len
, ENC_UTF_8
);
1106 proto_tree_add_item(p_tree
, hf_fru_record_field_value_uint16
, tvb
, offset
, field_len
, ENC_UTF_16
);
1109 proto_tree_add_item(p_tree
, hf_fru_record_field_value_uint16
, tvb
,
1110 offset
, field_len
, ENC_UTF_16
| ENC_LITTLE_ENDIAN
);
1113 proto_tree_add_item(p_tree
, hf_fru_record_field_value_uint16
, tvb
,
1114 offset
, field_len
, ENC_UTF_16
| ENC_BIG_ENDIAN
);
1117 col_append_str(pinfo
->cinfo
, COL_INFO
, "Unsupported or invalid FRU record encoding");
1120 offset
+= field_len
;
1122 col_append_str(pinfo
->cinfo
, COL_INFO
, "Unsupported or OEM FRU record type");
1125 bytes_left
= tvb_reported_length(tvb
) - offset
;
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;
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
);
1140 uint8_t completion_code
= tvb_get_uint8(tvb
, offset
);
1141 switch (completion_code
) {
1148 proto_tree_add_item(p_tree
, hf_fru_completion_code
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
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
);
1159 case 0x01: // Get Fru record table metadata
1161 proto_tree_add_item(p_tree
, hf_fru_major_ver
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
1163 proto_tree_add_item(p_tree
, hf_fru_minor_ver
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
1165 proto_tree_add_item(p_tree
, hf_fru_table_max_size
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
1167 proto_tree_add_item(p_tree
, hf_fru_table_length
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
1169 proto_tree_add_item(p_tree
, hf_fru_num_record_identifiers
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
1171 proto_tree_add_item(p_tree
, hf_fru_num_records
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
1173 proto_tree_add_item(p_tree
, hf_fru_table_crc
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
1176 case 0x02: // Get Fru record table
1178 proto_tree_add_item(p_tree
, hf_fru_data_handle
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
1180 proto_tree_add_item(p_tree
, hf_fru_transfer_op_flag
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
1182 proto_tree_add_item(p_tree
, hf_fru_next_data_handle
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
1184 proto_tree_add_item(p_tree
, hf_fru_transfer_flag
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
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");
1191 case 0x03: // Set Fru record table
1193 proto_tree_add_item(p_tree
, hf_fru_data_handle
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
1195 proto_tree_add_item(p_tree
, hf_pldm_base_transferFlag
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
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;
1201 proto_tree_add_item(p_tree
, hf_fru_record_crc
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
1204 proto_tree_add_item(p_tree
, hf_fru_next_data_handle
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
1207 case 0x04: // GetFruRecordByOption
1209 proto_tree_add_item(p_tree
, hf_fru_data_handle
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
1211 proto_tree_add_item(p_tree
, hf_fru_table_handle
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
1213 proto_tree_add_item(p_tree
, hf_fru_record_id
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
1215 proto_tree_add_item(p_tree
, hf_fru_record_type
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
1217 proto_tree_add_item(p_tree
, hf_fru_record_field_type
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
1219 proto_tree_add_item(p_tree
, hf_fru_transfer_op_flag
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
1221 proto_tree_add_item(p_tree
, hf_fru_next_data_handle
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
1223 proto_tree_add_item(p_tree
, hf_pldm_base_transferFlag
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
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;
1229 proto_tree_add_item(p_tree
, hf_fru_record_crc
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
1234 col_append_str(pinfo
->cinfo
, COL_INFO
, "Unsupported or Invalid PLDM command");
1238 return tvb_captured_length(tvb
);
1241 static int dissect_pldm(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
,
1244 col_set_str(pinfo
->cinfo
, COL_PROTOCOL
, "PLDM");
1245 col_clear(pinfo
->cinfo
, COL_INFO
);
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
);
1258 /* First byte is the MCTP msg type, it is 01 for PLDM over MCTP */
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
);
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
);
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
) {
1278 dissect_base(next_tvb
, pinfo
, pldm_tree
, &d
);
1281 dissect_platform(next_tvb
, pinfo
, pldm_tree
, &d
);
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
}},
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
}},
1307 {"PLDM Type", "pldm.type", FT_UINT8
, BASE_HEX
, VALS(pldm_types
),
1308 0x3f, "PLDM Specification Type", HFILL
}},
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
,
1315 {&hf_pldm_base_transferOperationFlag
,
1316 {"Transfer Operation Flag", "pldm.base.transferOperationFlag", FT_UINT8
, BASE_HEX
, VALS(transferOperationFlags
),
1318 {&hf_pldm_base_nextDataTransferHandle
,
1319 {"Next Data Transfer Handle", "pldm.base.nextDataTransferHandle", FT_UINT32
, BASE_DEC
, NULL
,
1321 {&hf_pldm_base_transferFlag
,
1322 {"Transfer Flag", "pldm.base.transferFlag", FT_UINT8
, BASE_HEX
, VALS(transferFlags
),
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
,
1330 {&hf_pldm_base_typesSupported
,
1331 {"PLDM Type Supported", "pldm.base.typeSupported", FT_UINT8
, BASE_HEX
, VALS(pldm_types
),
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
),
1349 {&hf_pldm_platform_completion_code
,
1350 {"Completion Code", "pldm.completionCode", FT_UINT8
, BASE_DEC
, VALS(platform_completion_codes
),
1352 {&hf_event_message_global
,
1353 {"Event message global enable", "pldm.platform.receiver.enable", FT_UINT8
, BASE_DEC
, VALS(event_message_global_enable
),
1356 {"Completion Code", "pldm.status", FT_UINT8
, BASE_DEC
, VALS(result_status
),
1358 {&hf_transport_protocol_type
,
1359 {"Transport protocol", "pldm.platform.receiver.transport", FT_UINT8
, BASE_DEC
, VALS(transport_protocols
),
1361 {&hf_event_receiver_addr_info
,
1362 {"Event receiver address info", "pldm.platform.receiver.addr_info", FT_UINT8
, BASE_DEC
, NULL
,
1364 {&hf_heartbeat_timer
,
1365 {"Heartbeat timer", "pldm.platform.receiver.timer", FT_UINT16
, BASE_DEC
, NULL
,
1368 {"Event Class", "pldm.platform.event.class", FT_UINT8
, BASE_DEC
, VALS(platform_event_message_classes
),
1371 {"Sensor ID", "pldm.platform.event.sensor_id", FT_UINT16
, BASE_DEC
, NULL
,
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
),
1376 {&hf_pldm_platform_format_version
,
1377 {"Format Version", "pldm.platform.event_format_version", FT_UINT8
, BASE_DEC
, NULL
,
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
),
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
),
1386 {"Sensor offset", "pldm.platform.event.sensor_offset", FT_UINT8
, BASE_DEC
, NULL
,
1389 {"Event state", "pldm.platform.event.state", FT_UINT8
, BASE_DEC
, VALS(pldm_sensor_event_states
),
1391 {&hf_event_prev_state
,
1392 {"Event previous state", "pldm.platform.event.prev_state", FT_UINT8
, BASE_DEC
, VALS(pldm_sensor_event_states
),
1394 {&hf_sensor_data_size
,
1395 {"Sensor data size", "pldm.platform.sensor.data_size", FT_UINT8
, BASE_DEC
, VALS(sensor_data_size
),
1397 {&hf_sensor_value_u8
,
1398 {"Sensor reading", "pldm.platform.event.sensor.data_u8", FT_UINT8
, BASE_DEC
, NULL
,
1400 {&hf_sensor_value_s8
,
1401 {"Sensor reading", "pldm.platform.event.sensor.data_s8", FT_INT8
, BASE_DEC
, NULL
,
1403 {&hf_sensor_value_u16
,
1404 {"Sensor reading", "pldm.platform.event.sensor.data_u16", FT_UINT16
, BASE_DEC
, NULL
,
1406 {&hf_sensor_value_s16
,
1407 {"Sensor reading", "pldm.platform.event.sensor.data_s16", FT_INT16
, BASE_DEC
, NULL
,
1409 {&hf_sensor_value_u32
,
1410 {"Sensor reading", "pldm.platform.event.sensor.data_u32", FT_UINT32
, BASE_DEC
, NULL
,
1412 {&hf_sensor_value_s32
,
1413 {"Sensor reading", "pldm.platform.event.sensor.data_s32", FT_INT32
, BASE_DEC
, NULL
,
1415 {&hf_effecter_value_pnd_u8
,
1416 {"Pending Effecter Value in uint8", "pldm.platform.effecter.pnd_val_u8", FT_UINT8
, BASE_DEC
, NULL
,
1418 {&hf_effecter_value_pnd_s8
,
1419 {"Pending Effecter Value in sint8", "pldm.platform.effecter.pnd_val_s8", FT_INT8
, BASE_DEC
, NULL
,
1421 {&hf_effecter_value_pnd_u16
,
1422 {"Pending Effecter Value in uint16", "pldm.platform.effecter.pnd_val_u16", FT_UINT16
, BASE_DEC
, NULL
,
1424 {&hf_effecter_value_pnd_s16
,
1425 {"Pending Effecter Value in sint16", "pldm.platform.effecter.pnd_val_s16", FT_INT16
, BASE_DEC
, NULL
,
1427 {&hf_effecter_value_pnd_u32
,
1428 {"Pending Effecter Value in uint32", "pldm.platform.effecter.pnd_val_u32", FT_UINT32
, BASE_DEC
, NULL
,
1430 {&hf_effecter_value_pnd_s32
,
1431 {"Pending Effecter Value in sint32", "pldm.platform.effecter.pnd_val_s32", FT_INT32
, BASE_DEC
, NULL
,
1433 {&hf_effecter_value_pres_u8
,
1434 {"Present Effecter Value in uint8", "pldm.platform.effecter.pres_val_u8", FT_UINT8
, BASE_DEC
, NULL
,
1436 {&hf_effecter_value_pres_s8
,
1437 {"Present Effecter Value in sint8", "pldm.platform.effecter.pres_val_s8", FT_INT8
, BASE_DEC
, NULL
,
1439 {&hf_effecter_value_pres_u16
,
1440 {"Present Effecter Value in uint16", "pldm.platform.effecter.pres_val_u16", FT_UINT16
, BASE_DEC
, NULL
,
1442 {&hf_effecter_value_pres_s16
,
1443 {"Present Effecter Value in sint16", "pldm.platform.effecter.pres_val_s16", FT_INT16
, BASE_DEC
, NULL
,
1445 {&hf_effecter_value_pres_u32
,
1446 {"Present Effecter Value in uint32", "pldm.platform.effecter.pres_val_u32", FT_UINT32
, BASE_DEC
, NULL
,
1448 {&hf_effecter_value_pres_s32
,
1449 {"Present Effecter Value in sint32", "pldm.platform.effecter.pres_val_s32", FT_INT32
, BASE_DEC
, NULL
,
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
),
1454 {&hf_pdr_num_change_recs
,
1455 {"Number of PDR Records Changed", "pldm.platform.event.pdr_rec_change_num", FT_UINT8
, BASE_DEC
, NULL
,
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
),
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
,
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
),
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
,
1469 {&hf_heartbeat_format_ver
,
1470 {"Heartbeat Format Version", "pldm.platform.event.heartbeat.format_version", FT_UINT8
, BASE_DEC
, NULL
,
1472 {&hf_heartbeat_sequence_num
,
1473 {"Heartbeat sequence number", "pldm.platform.event.heartbeat.seq", FT_UINT8
, BASE_DEC
, NULL
,
1476 {"Sensor re-armed", "pldm.platform.sensor_rearm", FT_UINT8
, BASE_DEC
, NULL
,
1478 {&hf_sensor_rearm_none
,
1479 {"No Sensor Re-armed", "pldm.platform.sensor_rearm_none", FT_UINT8
, BASE_HEX
, NULL
,
1481 {&hf_pldm_sensor_reserved
,
1482 {"PLDM Sensor Reserved Byte", "pldm.platform.sensor.reserved_byte", FT_UINT8
, BASE_DEC
, NULL
,
1484 {&hf_sensor_prev_event_state
,
1485 {"Sensor Previous Event State", "pldm.platform.prev_event", FT_UINT8
, BASE_DEC
, VALS(pldm_sensor_event_states
),
1487 {&hf_sensor_present_event_state
,
1488 {"Sensor Present Event State", "pldm.platform.present_event", FT_UINT8
, BASE_DEC
, VALS(pldm_sensor_event_states
),
1490 {&hf_sensor_event_state
,
1491 {"Sensor Event State", "pldm.platform.event_state", FT_UINT8
, BASE_DEC
, VALS(pldm_sensor_event_states
),
1493 {&hf_sensor_composite_count
,
1494 {"Sensor Composite Count", "pldm.platform.sensor_comp_count", FT_UINT8
, BASE_DEC
, NULL
,
1497 {"Rearm Event State", "pldm.platform.rearm_event_state", FT_UINT8
, BASE_DEC
, VALS(sensor_bool8
),
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
),
1503 {"Effecter ID", "pldm.platform.effecter.id", FT_UINT16
, BASE_DEC
, NULL
,
1505 {&hf_effecter_count
,
1506 {"Effecter count", "pldm.platform.effecter.count", FT_UINT8
, BASE_DEC
, NULL
,
1508 {&hf_effecter_datasize
,
1509 {"Effecter Data Size", "pldm.platform.effecter.datasize", FT_UINT8
, BASE_DEC
, NULL
,
1511 {&hf_effecter_value_u8
,
1512 {"Effecter Value", "pldm.platform.effecter.value_u8", FT_UINT8
, BASE_DEC
, NULL
,
1514 {&hf_effecter_value_s8
,
1515 {"Effecter Value", "pldm.platform.effecter.value_s8", FT_INT8
, BASE_DEC
, NULL
,
1517 {&hf_effecter_value_u16
,
1518 {"Effecter Value", "pldm.platform.effecter.value_u16", FT_UINT16
, BASE_DEC
, NULL
,
1520 {&hf_effecter_value_s16
,
1521 {"Effecter Value", "pldm.platform.effecter.value_s16", FT_INT16
, BASE_DEC
, NULL
,
1523 {&hf_effecter_value_u32
,
1524 {"Effecter Value", "pldm.platform.effecter.value_u32", FT_UINT32
, BASE_DEC
, NULL
,
1526 {&hf_effecter_value_s32
,
1527 {"Effecter Value", "pldm.platform.effecter.value_s32", FT_INT32
, BASE_DEC
, NULL
,
1529 {&hf_effecter_op_state
,
1530 {"Effecter Operational State", "pldm.platform.effecter_op_state", FT_UINT8
, BASE_DEC
, VALS(pldm_effecter_oper_state
),
1532 {&hf_effecter_set_request
,
1533 {"Effecter Set Request", "pldm.platform.effecter_set_req", FT_UINT8
, BASE_DEC
, VALS(pldm_effecter_state_set_request
),
1535 {&hf_effecter_state
,
1536 {"Effecter State", "pldm.platform.effecter_state", FT_UINT8
, BASE_DEC
, NULL
,
1540 {&hf_pdr_record_handle
,
1541 {"PDR record handle", "pldm.platform.pdr.record_handle", FT_UINT32
, BASE_DEC
, NULL
,
1543 {&hf_pdr_data_handle
,
1544 {"PDR data transfer handle", "pldm.platform.pdr.data_handle", FT_UINT32
, BASE_DEC
, NULL
,
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
),
1550 {"PDR request count", "pldm.platform.pdr.request.count", FT_UINT16
, BASE_DEC
, NULL
,
1552 {&hf_pdr_record_change_num
,
1553 {"PDR record change number", "pldm.platform.pdr.record_change_number", FT_UINT16
, BASE_DEC
, NULL
,
1555 {&hf_pdr_next_record_handle
,
1556 {"PDR next record handle", "pldm.platform.pdr.next_record_handle", FT_UINT32
, BASE_DEC
, NULL
,
1558 {&hf_pdr_next_data_handle
,
1559 {"PDR next data transfer handle", "pldm.platform.pdr.next_data_handle", FT_UINT32
, BASE_DEC
, NULL
,
1561 {&hf_pdr_transfer_flag
,
1562 {"PDR transfer flag", "pldm.platform.pdr.transfer_flag", FT_UINT8
, BASE_DEC
, VALS(pdr_transfer_flags
),
1564 {&hf_pdr_response_count
,
1565 {"PDR response count", "pldm.platform.pdr.response.count", FT_UINT16
, BASE_DEC
, NULL
,
1567 {&hf_pdr_record_data
,
1568 {"PDR Record Data Byte", "pldm.platform.pdr.record_data", FT_UINT8
, BASE_HEX
, NULL
,
1571 {"PDR transfer CRC", "pldm.platform.pdr.crc", FT_UINT8
, BASE_DEC
, NULL
,
1574 {&hf_fru_completion_code
,
1575 {"FRU completion code", "pldm.fru.completion_code", FT_UINT8
, BASE_HEX
, VALS(FRU_completion_code
),
1578 {"FRU Major version", "pldm.fru.ver.major", FT_UINT8
, BASE_DEC
, NULL
,
1581 {"FRU Minor version", "pldm.fru.ver.minor", FT_UINT8
, BASE_DEC
, NULL
,
1583 {&hf_fru_table_max_size
,
1584 {"FRU Maximum table size", "pldm.fru.table.max", FT_UINT32
, BASE_DEC
, NULL
,
1586 {&hf_fru_table_length
,
1587 {"FRU Table length", "pldm.fru.table.len", FT_UINT32
, BASE_DEC
, NULL
,
1589 {&hf_fru_num_record_identifiers
,
1590 {"Total number of record set identifiers", "pldm.fru.num_identifiers", FT_UINT16
, BASE_DEC
, NULL
,
1592 {&hf_fru_num_records
,
1593 {"Total number of records in table", "pldm.fru.table.num_records", FT_UINT16
, BASE_DEC
, NULL
,
1596 {"FRU Table CRC", "pldm.fru.table.crc", FT_UINT32
, BASE_DEC
, NULL
,
1598 {&hf_fru_data_handle
,
1599 {"FRU Data transfer handle", "pldm.fru.table.handle", FT_UINT32
, BASE_DEC
, NULL
,
1601 {&hf_fru_transfer_op_flag
,
1602 {"FRU Data transfer operation flag", "pldm.fru.table.opflag", FT_UINT8
, BASE_DEC
, VALS(transfer_op_flags
),
1604 {&hf_fru_next_data_handle
,
1605 {"FRU Next data transfer handle", "pldm.fru.table.nexthandle", FT_UINT32
, BASE_DEC
, NULL
,
1607 {&hf_fru_transfer_flag
,
1608 {"FRU Data transfer flag", "pldm.fru.table.flag", FT_UINT8
, BASE_DEC
, VALS(transferFlags
),
1610 {&hf_fru_table_handle
,
1611 {"FRU Record Data Handle", "pldm.fru.table_handle", FT_UINT16
, BASE_DEC
, NULL
,
1613 // FRU Record fields
1615 {"FRU Record Set Identifier", "pldm.fru.record.id", FT_UINT16
, BASE_DEC
, NULL
,
1617 {&hf_fru_record_type
,
1618 {"FRU Record Type", "pldm.fru.record.type", FT_UINT8
, BASE_DEC
, VALS(record_types
),
1620 {&hf_fru_record_num_fields
,
1621 {"Number of FRU fields", "pldm.fru.record.num_fields", FT_UINT8
, BASE_DEC
, NULL
,
1623 {&hf_fru_record_encoding
,
1624 {"FRU Record Encoding", "pldm.fru.record.encoding", FT_UINT8
, BASE_DEC
, VALS(record_encoding
),
1626 {&hf_fru_record_field_type
,
1627 {"FRU Record Field Type", "pldm.fru.record.field_type", FT_UINT8
, BASE_DEC
, VALS(field_types_general
),
1629 {&hf_fru_record_field_len
,
1630 {"FRU Record Field Length", "pldm.fru.record.field_length", FT_UINT8
, BASE_DEC
, NULL
,
1632 {&hf_fru_record_field_value
,
1633 {"FRU Record Field Value", "pldm.fru.record.field_value", FT_UINT8
, BASE_HEX
, NULL
,
1635 {&hf_fru_record_field_value_uint16
,
1636 {"FRU Record Field Value", "pldm.fru.record.field_value_u16", FT_UINT16
, BASE_HEX
, NULL
,
1638 {&hf_fru_record_field_value_string
,
1639 {"FRU Record Field Value", "pldm.fru.record.field_value", FT_STRING
, BASE_NONE
, NULL
,
1641 {&hf_fru_record_crc
,
1642 {"FRU Record CRC32 (Unchecked)", "pldm.fru.record.crc", FT_UINT32
, BASE_HEX
, NULL
,
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
);