@@ -201,6 +201,12 @@ struct peer {
201201 uint8_t pool_start ;
202202};
203203
204+ struct msg_type_support {
205+ uint8_t msg_type ;
206+ uint32_t * versions ;
207+ size_t num_versions ;
208+ };
209+
204210struct ctx {
205211 sd_event * event ;
206212 sd_bus * bus ;
@@ -232,6 +238,10 @@ struct ctx {
232238
233239 uint8_t uuid [16 ];
234240
241+ // Supported message types and their versions
242+ struct msg_type_support * supported_msg_types ;
243+ size_t num_supported_msg_types ;
244+
235245 // Verbose logging
236246 bool verbose ;
237247
@@ -838,39 +848,62 @@ handle_control_get_version_support(struct ctx *ctx, int sd,
838848 struct mctp_ctrl_cmd_get_mctp_ver_support * req = NULL ;
839849 struct mctp_ctrl_resp_get_mctp_ver_support * resp = NULL ;
840850 uint32_t * versions = NULL ;
841- // space for 4 versions
842- uint8_t respbuf [sizeof (* resp ) + 4 * sizeof (* versions )] = { 0 };
851+ uint8_t * respbuf = NULL ;
843852 size_t resp_len ;
853+ ssize_t i , ver_idx = -1 , ver_count = 0 ;
854+ int status ;
844855
845856 if (buf_size < sizeof (struct mctp_ctrl_cmd_get_mctp_ver_support )) {
846857 warnx ("short Get Version Support message" );
847858 return - ENOMSG ;
848859 }
849860
850861 req = (void * )buf ;
851- resp = (void * )respbuf ;
852- mctp_ctrl_msg_hdr_init_resp (& resp -> ctrl_hdr , req -> ctrl_hdr );
853- versions = (void * )(resp + 1 );
854- switch (req -> msg_type_number ) {
855- case 0xff : // Base Protocol
856- case 0x00 : // Control protocol
857- // from DSP0236 1.3.1 section 12.6.2. Big endian.
858- versions [0 ] = htonl (0xF1F0FF00 );
859- versions [1 ] = htonl (0xF1F1FF00 );
860- versions [2 ] = htonl (0xF1F2FF00 );
861- versions [3 ] = htonl (0xF1F3F100 );
862- resp -> number_of_entries = 4 ;
863- resp -> completion_code = MCTP_CTRL_CC_SUCCESS ;
864- resp_len = sizeof (* resp ) + 4 * sizeof (* versions );
865- break ;
866- default :
867- // Unsupported message type
862+ if (req -> msg_type_number == 0xFF ) {
863+ // use same version for base spec and control protocol
864+ req -> msg_type_number = 0 ;
865+ }
866+ for (i = 0 ; i < ctx -> num_supported_msg_types ; i ++ ) {
867+ if (ctx -> supported_msg_types [i ].msg_type ==
868+ req -> msg_type_number ) {
869+ ver_idx = i ;
870+ break ;
871+ }
872+ }
873+
874+ if (ver_idx < 0 ) {
875+ respbuf = malloc (sizeof (struct mctp_ctrl_resp ));
876+ if (!respbuf ) {
877+ warnx ("Failed to allocate response buffer" );
878+ return - ENOMEM ;
879+ }
880+ resp = (void * )respbuf ;
881+ // Nobody registered yet as responder for this type
868882 resp -> completion_code =
869883 MCTP_CTRL_CC_GET_MCTP_VER_SUPPORT_UNSUPPORTED_TYPE ;
870- resp_len = sizeof (* resp );
884+ resp_len = sizeof (struct mctp_ctrl_resp );
885+ } else {
886+ ver_count = ctx -> supported_msg_types [ver_idx ].num_versions ;
887+ respbuf =
888+ malloc (sizeof (* resp ) + (ver_count * sizeof (uint32_t )));
889+ if (!respbuf ) {
890+ warnx ("Failed to allocate response buffer for versions" );
891+ return - ENOMEM ;
892+ }
893+ resp = (void * )respbuf ;
894+ resp -> number_of_entries = ver_count ;
895+ versions = (void * )(resp + 1 );
896+ memcpy (versions , ctx -> supported_msg_types [ver_idx ].versions ,
897+ ver_count * sizeof (uint32_t ));
898+ resp -> completion_code = MCTP_CTRL_CC_SUCCESS ;
899+ resp_len = sizeof (* resp ) + ver_count * sizeof (uint32_t );
871900 }
872901
873- return reply_message (ctx , sd , resp , resp_len , addr );
902+ mctp_ctrl_msg_hdr_init_resp (& resp -> ctrl_hdr , req -> ctrl_hdr );
903+
904+ status = reply_message (ctx , sd , resp , resp_len , addr );
905+ free (respbuf );
906+ return status ;
874907}
875908
876909static int handle_control_get_endpoint_id (struct ctx * ctx , int sd ,
@@ -927,24 +960,39 @@ static int handle_control_get_message_type_support(
927960{
928961 struct mctp_ctrl_cmd_get_msg_type_support * req = NULL ;
929962 struct mctp_ctrl_resp_get_msg_type_support * resp = NULL ;
930- uint8_t resp_buf [sizeof (* resp ) + 1 ] = { 0 };
931- size_t resp_len ;
963+ uint8_t * resp_buf , * msg_types ;
964+ size_t resp_len , type_count ;
965+ size_t i ;
932966
933967 if (buf_size < sizeof (* req )) {
934968 warnx ("short Get Message Type Support message" );
935969 return - ENOMSG ;
936970 }
937971
938972 req = (void * )buf ;
973+ type_count = ctx -> num_supported_msg_types ;
974+ // Allocate extra space for the message types
975+ resp_len = sizeof (* resp ) + type_count ;
976+ resp_buf = malloc (resp_len );
977+ if (!resp_buf ) {
978+ warnx ("Failed to allocate response buffer" );
979+ return - ENOMEM ;
980+ }
981+
939982 resp = (void * )resp_buf ;
940983 mctp_ctrl_msg_hdr_init_resp (& resp -> ctrl_hdr , req -> ctrl_hdr );
984+ resp -> completion_code = MCTP_CTRL_CC_SUCCESS ;
941985
942- // Only control messages supported
943- resp -> msg_type_count = 1 ;
944- * ((uint8_t * )(resp + 1 )) = MCTP_CTRL_HDR_MSG_TYPE ;
945- resp_len = sizeof (* resp ) + resp -> msg_type_count ;
986+ resp -> msg_type_count = type_count ;
987+ // Append message types after msg_type_count
988+ msg_types = (uint8_t * )(resp + 1 );
989+ for (i = 0 ; i < type_count ; i ++ ) {
990+ msg_types [i ] = ctx -> supported_msg_types [i ].msg_type ;
991+ }
946992
947- return reply_message (ctx , sd , resp , resp_len , addr );
993+ int result = reply_message (ctx , sd , resp , resp_len , addr );
994+ free (resp_buf );
995+ return result ;
948996}
949997
950998static int
@@ -3319,6 +3367,71 @@ static int method_net_learn_endpoint(sd_bus_message *call, void *data,
33193367 return rc ;
33203368}
33213369
3370+ static int method_register_responder (sd_bus_message * call , void * data ,
3371+ sd_bus_error * berr )
3372+ {
3373+ struct ctx * ctx = data ;
3374+ uint8_t msg_type ;
3375+ const uint32_t * versions = NULL ;
3376+ size_t versions_len ;
3377+ int rc , i ;
3378+
3379+ rc = sd_bus_message_read (call , "y" , & msg_type );
3380+ if (rc < 0 )
3381+ goto err ;
3382+ rc = sd_bus_message_read_array (call , 'u' , (const void * * )& versions ,
3383+ & versions_len );
3384+ if (rc < 0 )
3385+ goto err ;
3386+
3387+ if (versions_len == 0 ) {
3388+ warnx ("No versions provided for message type %d" , msg_type );
3389+ return sd_bus_error_setf (
3390+ berr , SD_BUS_ERROR_INVALID_ARGS ,
3391+ "No versions provided for message type %d" , msg_type );
3392+ }
3393+
3394+ for (i = 0 ; i < ctx -> num_supported_msg_types ; i ++ ) {
3395+ if (ctx -> supported_msg_types [i ].msg_type == msg_type ) {
3396+ warnx ("Message type %d already registered" , msg_type );
3397+ return sd_bus_error_setf (
3398+ berr , SD_BUS_ERROR_INVALID_ARGS ,
3399+ "Message type %d already registered" , msg_type );
3400+ }
3401+ }
3402+
3403+ struct msg_type_support * msg_types =
3404+ realloc (ctx -> supported_msg_types ,
3405+ (ctx -> num_supported_msg_types + 1 ) *
3406+ sizeof (struct msg_type_support ));
3407+ if (!msg_types ) {
3408+ goto oom_err ;
3409+ }
3410+ ctx -> supported_msg_types = msg_types ;
3411+ ctx -> supported_msg_types [ctx -> num_supported_msg_types ].msg_type =
3412+ msg_type ;
3413+ ctx -> supported_msg_types [ctx -> num_supported_msg_types ].num_versions =
3414+ versions_len / sizeof (uint32_t );
3415+ ctx -> supported_msg_types [ctx -> num_supported_msg_types ].versions =
3416+ malloc (versions_len );
3417+ if (!ctx -> supported_msg_types [ctx -> num_supported_msg_types ].versions ) {
3418+ goto oom_err ;
3419+ }
3420+ // Assume callers's responsibility to provide version in uint32 format from spec
3421+ memcpy (ctx -> supported_msg_types [ctx -> num_supported_msg_types ].versions ,
3422+ versions , versions_len );
3423+
3424+ ctx -> num_supported_msg_types ++ ;
3425+
3426+ return sd_bus_reply_method_return (call , "" );
3427+ oom_err :
3428+ return sd_bus_error_setf (berr , SD_BUS_ERROR_NO_MEMORY ,
3429+ "Failed to allocate memory" );
3430+ err :
3431+ set_berr (ctx , rc , berr );
3432+ return rc ;
3433+ }
3434+
33223435// clang-format off
33233436static const sd_bus_vtable bus_link_owner_vtable [] = {
33243437 SD_BUS_VTABLE_START (0 ),
@@ -3672,6 +3785,17 @@ static const sd_bus_vtable bus_network_vtable[] = {
36723785 SD_BUS_VTABLE_PROPERTY_CONST ),
36733786 SD_BUS_VTABLE_END
36743787};
3788+
3789+ static const sd_bus_vtable mctp_base_vtable [] = {
3790+ SD_BUS_VTABLE_START (0 ),
3791+ SD_BUS_METHOD_WITH_ARGS ("RegisterResponder" ,
3792+ SD_BUS_ARGS ("y" , msg_type ,
3793+ "au" , versions ),
3794+ SD_BUS_NO_RESULT ,
3795+ method_register_responder ,
3796+ 0 ),
3797+ SD_BUS_VTABLE_END ,
3798+ };
36753799// clang-format on
36763800
36773801static int emit_endpoint_added (const struct peer * peer )
@@ -3822,6 +3946,14 @@ static int setup_bus(struct ctx *ctx)
38223946 goto out ;
38233947 }
38243948
3949+ rc = sd_bus_add_object_vtable (ctx -> bus , NULL , MCTP_DBUS_PATH ,
3950+ MCTP_DBUS_NAME ,
3951+ mctp_base_vtable , ctx );
3952+ if (rc < 0 ) {
3953+ warnx ("Adding MCTP base vtable failed: %s" , strerror (- rc ));
3954+ goto out ;
3955+ }
3956+
38253957 rc = 0 ;
38263958out :
38273959 return rc ;
@@ -4613,6 +4745,34 @@ static int parse_config(struct ctx *ctx)
46134745 return rc ;
46144746}
46154747
4748+ static void setup_ctrl_cmd_defaults (struct ctx * ctx )
4749+ {
4750+ ctx -> supported_msg_types = NULL ;
4751+ ctx -> num_supported_msg_types = 0 ;
4752+
4753+ // Default to supporting only control messages
4754+ ctx -> supported_msg_types = malloc (sizeof (struct msg_type_support ));
4755+ if (!ctx -> supported_msg_types ) {
4756+ warnx ("Out of memory for supported message types" );
4757+ return ;
4758+ }
4759+ ctx -> num_supported_msg_types = 1 ;
4760+ ctx -> supported_msg_types [0 ].msg_type = MCTP_CTRL_HDR_MSG_TYPE ;
4761+
4762+ ctx -> supported_msg_types [0 ].versions = malloc (sizeof (uint32_t ) * 4 );
4763+ if (!ctx -> supported_msg_types [0 ].versions ) {
4764+ warnx ("Out of memory for versions" );
4765+ free (ctx -> supported_msg_types );
4766+ ctx -> num_supported_msg_types = 0 ;
4767+ return ;
4768+ }
4769+ ctx -> supported_msg_types [0 ].num_versions = 4 ;
4770+ ctx -> supported_msg_types [0 ].versions [0 ] = htonl (0xF1F0FF00 );
4771+ ctx -> supported_msg_types [0 ].versions [1 ] = htonl (0xF1F1FF00 );
4772+ ctx -> supported_msg_types [0 ].versions [2 ] = htonl (0xF1F2FF00 );
4773+ ctx -> supported_msg_types [0 ].versions [3 ] = htonl (0xF1F3F100 );
4774+ }
4775+
46164776static void setup_config_defaults (struct ctx * ctx )
46174777{
46184778 ctx -> mctp_timeout = 250000 ; // 250ms
@@ -4624,7 +4784,13 @@ static void setup_config_defaults(struct ctx *ctx)
46244784
46254785static void free_config (struct ctx * ctx )
46264786{
4787+ int i ;
4788+
46274789 free (ctx -> config_filename );
4790+ for (i = 0 ; i < ctx -> num_supported_msg_types ; i ++ ) {
4791+ free (ctx -> supported_msg_types [i ].versions );
4792+ }
4793+ free (ctx -> supported_msg_types );
46284794}
46294795
46304796static int endpoint_send_allocate_endpoint_ids (
@@ -4778,6 +4944,8 @@ int main(int argc, char **argv)
47784944 setlinebuf (stdout );
47794945
47804946 setup_config_defaults (ctx );
4947+ setup_ctrl_cmd_defaults (ctx );
4948+
47814949 mctp_ops_init ();
47824950
47834951 rc = parse_args (ctx , argc , argv );
0 commit comments