@@ -208,6 +208,16 @@ struct msg_type_support {
208208 sd_bus_track * source_peer ;
209209};
210210
211+ struct vdm_type_support {
212+ uint8_t vid_format ;
213+ union {
214+ uint16_t pcie ;
215+ uint32_t iana ;
216+ } vendor_id ;
217+ uint16_t cmd_set ;
218+ sd_bus_track * source_peer ;
219+ };
220+
211221struct ctx {
212222 sd_event * event ;
213223 sd_bus * bus ;
@@ -243,6 +253,9 @@ struct ctx {
243253 struct msg_type_support * supported_msg_types ;
244254 size_t num_supported_msg_types ;
245255
256+ struct vdm_type_support * supported_vdm_types ;
257+ size_t num_supported_vdm_types ;
258+
246259 // Verbose logging
247260 bool verbose ;
248261
@@ -999,6 +1012,83 @@ static int handle_control_get_message_type_support(
9991012 return rc ;
10001013}
10011014
1015+ static int
1016+ handle_control_get_vdm_type_support (struct ctx * ctx , int sd ,
1017+ const struct sockaddr_mctp_ext * addr ,
1018+ const uint8_t * buf , const size_t buf_size )
1019+ {
1020+ size_t resp_len , max_rsp_len , vdm_count , vid_size_left ;
1021+ struct mctp_ctrl_resp_get_vdm_support * resp = NULL ;
1022+ struct mctp_ctrl_cmd_get_vdm_support * req = NULL ;
1023+ struct vdm_type_support * cur_vdm ;
1024+ uint8_t * resp_buf ;
1025+ int rc ;
1026+
1027+ if (buf_size < sizeof (* req )) {
1028+ warnx ("short Get Message Type Support message" );
1029+ return - ENOMSG ;
1030+ }
1031+
1032+ req = (void * )buf ;
1033+ vdm_count = ctx -> num_supported_vdm_types ;
1034+ // Allocate space for 32 bit VID + 16 bit cmd set
1035+ max_rsp_len = sizeof (* resp ) + sizeof (uint16_t );
1036+ resp_buf = malloc (max_rsp_len );
1037+ if (!resp_buf ) {
1038+ warnx ("Failed to allocate response buffer" );
1039+ return - ENOMEM ;
1040+ }
1041+ resp = (void * )resp_buf ;
1042+ mctp_ctrl_msg_hdr_init_resp (& resp -> ctrl_hdr , req -> ctrl_hdr );
1043+
1044+ if (vdm_count == 0 ) {
1045+ if (ctx -> verbose ) {
1046+ warnx ("Get VDM Type Support but no VDMs registered" );
1047+ }
1048+ resp_len = sizeof (struct mctp_ctrl_resp );
1049+ resp -> completion_code = MCTP_CTRL_CC_ERROR ;
1050+ } else if (req -> vendor_id_set_selector >= vdm_count ) {
1051+ if (ctx -> verbose ) {
1052+ warnx ("Get VDM Type Support selector %u out of range (max %zu)" ,
1053+ req -> vendor_id_set_selector , vdm_count );
1054+ }
1055+ resp_len = sizeof (struct mctp_ctrl_resp );
1056+ resp -> completion_code = MCTP_CTRL_CC_ERROR_INVALID_DATA ;
1057+ } else {
1058+ cur_vdm =
1059+ & ctx -> supported_vdm_types [req -> vendor_id_set_selector ];
1060+ vid_size_left = (cur_vdm -> vid_format ==
1061+ MCTP_GET_VDM_SUPPORT_PCIE_FORMAT_ID ) ?
1062+ sizeof (uint16_t ) :
1063+ 0 ;
1064+ resp_len = max_rsp_len - vid_size_left ;
1065+
1066+ resp -> completion_code = MCTP_CTRL_CC_SUCCESS ;
1067+ resp -> vendor_id_set_selector =
1068+ req -> vendor_id_set_selector == (vdm_count - 1 ) ?
1069+ MCTP_GET_VDM_SUPPORT_NO_MORE_CAP_SET :
1070+ req -> vendor_id_set_selector + 1 ;
1071+ resp -> vendor_id_format = cur_vdm -> vid_format ;
1072+ uint8_t * out_ptr = (uint8_t * )(resp + 1 );
1073+ out_ptr -= vid_size_left ;
1074+
1075+ if (cur_vdm -> vid_format ==
1076+ MCTP_GET_VDM_SUPPORT_PCIE_FORMAT_ID ) {
1077+ resp -> vendor_id_data_pcie =
1078+ htobe16 (cur_vdm -> vendor_id .pcie );
1079+ } else {
1080+ resp -> vendor_id_data_iana =
1081+ htobe32 (cur_vdm -> vendor_id .iana );
1082+ }
1083+ uint16_t * cmd_type_ptr = (uint16_t * )out_ptr ;
1084+ * cmd_type_ptr = htobe16 (cur_vdm -> cmd_set );
1085+ }
1086+
1087+ rc = reply_message (ctx , sd , resp , resp_len , addr );
1088+ free (resp_buf );
1089+ return rc ;
1090+ }
1091+
10021092static int
10031093handle_control_resolve_endpoint_id (struct ctx * ctx , int sd ,
10041094 const struct sockaddr_mctp_ext * addr ,
@@ -1202,6 +1292,10 @@ static int cb_listen_control_msg(sd_event_source *s, int sd, uint32_t revents,
12021292 rc = handle_control_get_message_type_support (ctx , sd , & addr ,
12031293 buf , buf_size );
12041294 break ;
1295+ case MCTP_CTRL_CMD_GET_VENDOR_MESSAGE_SUPPORT :
1296+ rc = handle_control_get_vdm_type_support (ctx , sd , & addr , buf ,
1297+ buf_size );
1298+ break ;
12051299 case MCTP_CTRL_CMD_RESOLVE_ENDPOINT_ID :
12061300 rc = handle_control_resolve_endpoint_id (ctx , sd , & addr , buf ,
12071301 buf_size );
@@ -3420,6 +3514,33 @@ static int on_dbus_peer_removed(sd_bus_track *track, void *userdata)
34203514 return 0 ;
34213515}
34223516
3517+ static int on_dbus_peer_removed_vdm_type (sd_bus_track * track , void * userdata )
3518+ {
3519+ struct ctx * ctx = userdata ;
3520+ size_t i ;
3521+
3522+ for (i = 0 ; i < ctx -> num_supported_vdm_types ; i ++ ) {
3523+ struct vdm_type_support * vdm_type =
3524+ & ctx -> supported_vdm_types [i ];
3525+
3526+ if (vdm_type -> source_peer != track )
3527+ continue ;
3528+ if (ctx -> verbose ) {
3529+ warnx ("Removing VDM type support entry vid_format %d cmd_set 0x%04x" ,
3530+ vdm_type -> vid_format , vdm_type -> cmd_set );
3531+ }
3532+ if (i != ctx -> num_supported_vdm_types - 1 ) {
3533+ * vdm_type = ctx -> supported_vdm_types
3534+ [ctx -> num_supported_vdm_types - 1 ];
3535+ }
3536+ ctx -> num_supported_vdm_types -- ;
3537+ break ;
3538+ }
3539+
3540+ sd_bus_track_unref (track );
3541+ return 0 ;
3542+ }
3543+
34233544static int method_register_type_support (sd_bus_message * call , void * data ,
34243545 sd_bus_error * berr )
34253546{
@@ -3506,6 +3627,104 @@ static int method_register_type_support(sd_bus_message *call, void *data,
35063627 return rc ;
35073628}
35083629
3630+ static int method_register_vdm_type_support (sd_bus_message * call , void * data ,
3631+ sd_bus_error * berr )
3632+ {
3633+ struct vdm_type_support new_vdm , * cur_vdm_type , * new_vdm_types_arr ;
3634+ struct ctx * ctx = data ;
3635+ uint16_t vid_pcie ;
3636+ uint32_t vid_iana ;
3637+ int rc ;
3638+
3639+ rc = sd_bus_message_read (call , "y" , & new_vdm .vid_format );
3640+ if (rc < 0 )
3641+ goto err ;
3642+
3643+ if (new_vdm .vid_format != MCTP_GET_VDM_SUPPORT_PCIE_FORMAT_ID &&
3644+ new_vdm .vid_format != MCTP_GET_VDM_SUPPORT_IANA_FORMAT_ID ) {
3645+ return sd_bus_error_setf (berr , SD_BUS_ERROR_INVALID_ARGS ,
3646+ "Unsupported VID format: %d" ,
3647+ new_vdm .vid_format );
3648+ }
3649+
3650+ if (new_vdm .vid_format == MCTP_GET_VDM_SUPPORT_PCIE_FORMAT_ID ) {
3651+ rc = sd_bus_message_read (call , "v" , "q" , & vid_pcie );
3652+ if (rc < 0 )
3653+ goto err ;
3654+ new_vdm .vendor_id .pcie = vid_pcie ;
3655+ } else if (new_vdm .vid_format == MCTP_GET_VDM_SUPPORT_IANA_FORMAT_ID ) {
3656+ rc = sd_bus_message_read (call , "v" , "u" , & vid_iana );
3657+ if (rc < 0 )
3658+ goto err ;
3659+ new_vdm .vendor_id .iana = vid_iana ;
3660+ }
3661+
3662+ rc = sd_bus_message_read (call , "q" , & new_vdm .cmd_set );
3663+ if (rc < 0 )
3664+ goto err ;
3665+
3666+ // Check for duplicates
3667+ for (size_t i = 0 ; i < ctx -> num_supported_vdm_types ; i ++ ) {
3668+ if (ctx -> supported_vdm_types [i ].vid_format !=
3669+ new_vdm .vid_format )
3670+ continue ;
3671+
3672+ if (ctx -> supported_vdm_types [i ].cmd_set != new_vdm .cmd_set )
3673+ continue ;
3674+
3675+ bool vid_matches = false;
3676+ if (new_vdm .vid_format == MCTP_GET_VDM_SUPPORT_PCIE_FORMAT_ID ) {
3677+ vid_matches =
3678+ (ctx -> supported_vdm_types [i ].vendor_id .pcie ==
3679+ new_vdm .vendor_id .pcie );
3680+ } else {
3681+ vid_matches =
3682+ (ctx -> supported_vdm_types [i ].vendor_id .iana ==
3683+ new_vdm .vendor_id .iana );
3684+ }
3685+
3686+ if (vid_matches ) {
3687+ return sd_bus_error_setf (berr ,
3688+ SD_BUS_ERROR_INVALID_ARGS ,
3689+ "VDM type already registered" );
3690+ }
3691+ }
3692+
3693+ new_vdm_types_arr = realloc (ctx -> supported_vdm_types ,
3694+ (ctx -> num_supported_vdm_types + 1 ) *
3695+ sizeof (struct vdm_type_support ));
3696+ if (!new_vdm_types_arr )
3697+ return sd_bus_error_setf (
3698+ berr , SD_BUS_ERROR_NO_MEMORY ,
3699+ "Failed to allocate memory for VDM types" );
3700+ ctx -> supported_vdm_types = new_vdm_types_arr ;
3701+
3702+ cur_vdm_type = & ctx -> supported_vdm_types [ctx -> num_supported_vdm_types ];
3703+ memcpy (cur_vdm_type , & new_vdm , sizeof (struct vdm_type_support ));
3704+
3705+ // Track peer
3706+ rc = sd_bus_track_new (ctx -> bus , & cur_vdm_type -> source_peer ,
3707+ on_dbus_peer_removed_vdm_type , ctx );
3708+ if (rc < 0 )
3709+ goto track_err ;
3710+
3711+ rc = sd_bus_track_add_sender (cur_vdm_type -> source_peer , call );
3712+ if (rc < 0 )
3713+ goto track_err ;
3714+
3715+ ctx -> num_supported_vdm_types ++ ;
3716+ return sd_bus_reply_method_return (call , "" );
3717+
3718+ track_err :
3719+ sd_bus_track_unref (cur_vdm_type -> source_peer );
3720+ set_berr (ctx , rc , berr );
3721+ return rc ;
3722+
3723+ err :
3724+ set_berr (ctx , rc , berr );
3725+ return rc ;
3726+ }
3727+
35093728// clang-format off
35103729static const sd_bus_vtable bus_link_owner_vtable [] = {
35113730 SD_BUS_VTABLE_START (0 ),
@@ -3868,6 +4087,13 @@ static const sd_bus_vtable mctp_base_vtable[] = {
38684087 SD_BUS_NO_RESULT ,
38694088 method_register_type_support ,
38704089 0 ),
4090+ SD_BUS_METHOD_WITH_ARGS ("RegisterVDMTypeSupport" ,
4091+ SD_BUS_ARGS ("y" , format ,
4092+ "v" , format_data ,
4093+ "q" , vendor_subtype ),
4094+ SD_BUS_NO_RESULT ,
4095+ method_register_vdm_type_support ,
4096+ 0 ),
38714097 SD_BUS_VTABLE_END ,
38724098};
38734099// clang-format on
@@ -4823,6 +5049,9 @@ static void setup_ctrl_cmd_defaults(struct ctx *ctx)
48235049 ctx -> supported_msg_types = NULL ;
48245050 ctx -> num_supported_msg_types = 0 ;
48255051
5052+ ctx -> supported_vdm_types = NULL ;
5053+ ctx -> num_supported_vdm_types = 0 ;
5054+
48265055 // Default to supporting only control messages
48275056 ctx -> supported_msg_types = malloc (sizeof (struct msg_type_support ));
48285057 if (!ctx -> supported_msg_types ) {
@@ -4868,6 +5097,9 @@ static void free_ctrl_cmd_defaults(struct ctx *ctx)
48685097 free (ctx -> supported_msg_types [i ].versions );
48695098 }
48705099 free (ctx -> supported_msg_types );
5100+ free (ctx -> supported_vdm_types );
5101+ ctx -> supported_vdm_types = NULL ;
5102+ ctx -> num_supported_vdm_types = 0 ;
48715103}
48725104
48735105static int endpoint_send_allocate_endpoint_ids (
0 commit comments