@@ -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{
@@ -3439,15 +3560,13 @@ static int method_register_type_support(sd_bus_message *call, void *data,
34393560 goto err ;
34403561
34413562 if (versions_len == 0 ) {
3442- warnx ("No versions provided for message type %d" , msg_type );
34433563 return sd_bus_error_setf (
34443564 berr , SD_BUS_ERROR_INVALID_ARGS ,
34453565 "No versions provided for message type %d" , msg_type );
34463566 }
34473567
34483568 for (i = 0 ; i < ctx -> num_supported_msg_types ; i ++ ) {
34493569 if (ctx -> supported_msg_types [i ].msg_type == msg_type ) {
3450- warnx ("Message type %d already registered" , msg_type );
34513570 return sd_bus_error_setf (
34523571 berr , SD_BUS_ERROR_INVALID_ARGS ,
34533572 "Message type %d already registered" , msg_type );
@@ -3506,6 +3625,104 @@ static int method_register_type_support(sd_bus_message *call, void *data,
35063625 return rc ;
35073626}
35083627
3628+ static int method_register_vdm_type_support (sd_bus_message * call , void * data ,
3629+ sd_bus_error * berr )
3630+ {
3631+ struct vdm_type_support new_vdm , * cur_vdm_type , * new_vdm_types_arr ;
3632+ struct ctx * ctx = data ;
3633+ uint16_t vid_pcie ;
3634+ uint32_t vid_iana ;
3635+ int rc ;
3636+
3637+ rc = sd_bus_message_read (call , "y" , & new_vdm .vid_format );
3638+ if (rc < 0 )
3639+ goto err ;
3640+
3641+ if (new_vdm .vid_format != MCTP_GET_VDM_SUPPORT_PCIE_FORMAT_ID &&
3642+ new_vdm .vid_format != MCTP_GET_VDM_SUPPORT_IANA_FORMAT_ID ) {
3643+ return sd_bus_error_setf (berr , SD_BUS_ERROR_INVALID_ARGS ,
3644+ "Unsupported VID format: %d" ,
3645+ new_vdm .vid_format );
3646+ }
3647+
3648+ if (new_vdm .vid_format == MCTP_GET_VDM_SUPPORT_PCIE_FORMAT_ID ) {
3649+ rc = sd_bus_message_read (call , "v" , "q" , & vid_pcie );
3650+ if (rc < 0 )
3651+ goto err ;
3652+ new_vdm .vendor_id .pcie = vid_pcie ;
3653+ } else if (new_vdm .vid_format == MCTP_GET_VDM_SUPPORT_IANA_FORMAT_ID ) {
3654+ rc = sd_bus_message_read (call , "v" , "u" , & vid_iana );
3655+ if (rc < 0 )
3656+ goto err ;
3657+ new_vdm .vendor_id .iana = vid_iana ;
3658+ }
3659+
3660+ rc = sd_bus_message_read (call , "q" , & new_vdm .cmd_set );
3661+ if (rc < 0 )
3662+ goto err ;
3663+
3664+ // Check for duplicates
3665+ for (size_t i = 0 ; i < ctx -> num_supported_vdm_types ; i ++ ) {
3666+ if (ctx -> supported_vdm_types [i ].vid_format !=
3667+ new_vdm .vid_format )
3668+ continue ;
3669+
3670+ if (ctx -> supported_vdm_types [i ].cmd_set != new_vdm .cmd_set )
3671+ continue ;
3672+
3673+ bool vid_matches = false;
3674+ if (new_vdm .vid_format == MCTP_GET_VDM_SUPPORT_PCIE_FORMAT_ID ) {
3675+ vid_matches =
3676+ (ctx -> supported_vdm_types [i ].vendor_id .pcie ==
3677+ new_vdm .vendor_id .pcie );
3678+ } else {
3679+ vid_matches =
3680+ (ctx -> supported_vdm_types [i ].vendor_id .iana ==
3681+ new_vdm .vendor_id .iana );
3682+ }
3683+
3684+ if (vid_matches ) {
3685+ return sd_bus_error_setf (berr ,
3686+ SD_BUS_ERROR_INVALID_ARGS ,
3687+ "VDM type already registered" );
3688+ }
3689+ }
3690+
3691+ new_vdm_types_arr = realloc (ctx -> supported_vdm_types ,
3692+ (ctx -> num_supported_vdm_types + 1 ) *
3693+ sizeof (struct vdm_type_support ));
3694+ if (!new_vdm_types_arr )
3695+ return sd_bus_error_setf (
3696+ berr , SD_BUS_ERROR_NO_MEMORY ,
3697+ "Failed to allocate memory for VDM types" );
3698+ ctx -> supported_vdm_types = new_vdm_types_arr ;
3699+
3700+ cur_vdm_type = & ctx -> supported_vdm_types [ctx -> num_supported_vdm_types ];
3701+ memcpy (cur_vdm_type , & new_vdm , sizeof (struct vdm_type_support ));
3702+
3703+ // Track peer
3704+ rc = sd_bus_track_new (ctx -> bus , & cur_vdm_type -> source_peer ,
3705+ on_dbus_peer_removed_vdm_type , ctx );
3706+ if (rc < 0 )
3707+ goto track_err ;
3708+
3709+ rc = sd_bus_track_add_sender (cur_vdm_type -> source_peer , call );
3710+ if (rc < 0 )
3711+ goto track_err ;
3712+
3713+ ctx -> num_supported_vdm_types ++ ;
3714+ return sd_bus_reply_method_return (call , "" );
3715+
3716+ track_err :
3717+ sd_bus_track_unref (cur_vdm_type -> source_peer );
3718+ set_berr (ctx , rc , berr );
3719+ return rc ;
3720+
3721+ err :
3722+ set_berr (ctx , rc , berr );
3723+ return rc ;
3724+ }
3725+
35093726// clang-format off
35103727static const sd_bus_vtable bus_link_owner_vtable [] = {
35113728 SD_BUS_VTABLE_START (0 ),
@@ -3868,6 +4085,13 @@ static const sd_bus_vtable mctp_base_vtable[] = {
38684085 SD_BUS_NO_RESULT ,
38694086 method_register_type_support ,
38704087 0 ),
4088+ SD_BUS_METHOD_WITH_ARGS ("RegisterVDMTypeSupport" ,
4089+ SD_BUS_ARGS ("y" , format ,
4090+ "v" , format_data ,
4091+ "q" , vendor_subtype ),
4092+ SD_BUS_NO_RESULT ,
4093+ method_register_vdm_type_support ,
4094+ 0 ),
38714095 SD_BUS_VTABLE_END ,
38724096};
38734097// clang-format on
@@ -4823,6 +5047,9 @@ static void setup_ctrl_cmd_defaults(struct ctx *ctx)
48235047 ctx -> supported_msg_types = NULL ;
48245048 ctx -> num_supported_msg_types = 0 ;
48255049
5050+ ctx -> supported_vdm_types = NULL ;
5051+ ctx -> num_supported_vdm_types = 0 ;
5052+
48265053 // Default to supporting only control messages
48275054 ctx -> supported_msg_types = malloc (sizeof (struct msg_type_support ));
48285055 if (!ctx -> supported_msg_types ) {
@@ -4868,6 +5095,9 @@ static void free_ctrl_cmd_defaults(struct ctx *ctx)
48685095 free (ctx -> supported_msg_types [i ].versions );
48695096 }
48705097 free (ctx -> supported_msg_types );
5098+ free (ctx -> supported_vdm_types );
5099+ ctx -> supported_vdm_types = NULL ;
5100+ ctx -> num_supported_vdm_types = 0 ;
48715101}
48725102
48735103static int endpoint_send_allocate_endpoint_ids (
0 commit comments