@@ -201,6 +201,12 @@ struct peer {
201
201
uint8_t pool_start ;
202
202
};
203
203
204
+ struct msg_type_support {
205
+ uint8_t msg_type ;
206
+ uint32_t * versions ;
207
+ size_t num_versions ;
208
+ };
209
+
204
210
struct ctx {
205
211
sd_event * event ;
206
212
sd_bus * bus ;
@@ -232,6 +238,10 @@ struct ctx {
232
238
233
239
uint8_t uuid [16 ];
234
240
241
+ // Supported message types and their versions
242
+ struct msg_type_support * supported_msg_types ;
243
+ size_t num_supported_msg_types ;
244
+
235
245
// Verbose logging
236
246
bool verbose ;
237
247
@@ -838,39 +848,62 @@ handle_control_get_version_support(struct ctx *ctx, int sd,
838
848
struct mctp_ctrl_cmd_get_mctp_ver_support * req = NULL ;
839
849
struct mctp_ctrl_resp_get_mctp_ver_support * resp = NULL ;
840
850
uint32_t * versions = NULL ;
841
- // space for 4 versions
842
- uint8_t respbuf [sizeof (* resp ) + 4 * sizeof (* versions )] = { 0 };
851
+ uint8_t * respbuf = NULL ;
843
852
size_t resp_len ;
853
+ ssize_t i , ver_idx = -1 , ver_count = 0 ;
854
+ int status ;
844
855
845
856
if (buf_size < sizeof (struct mctp_ctrl_cmd_get_mctp_ver_support )) {
846
857
warnx ("short Get Version Support message" );
847
858
return - ENOMSG ;
848
859
}
849
860
850
861
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
868
882
resp -> completion_code =
869
883
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 );
871
900
}
872
901
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 ;
874
907
}
875
908
876
909
static int handle_control_get_endpoint_id (struct ctx * ctx , int sd ,
@@ -927,24 +960,39 @@ static int handle_control_get_message_type_support(
927
960
{
928
961
struct mctp_ctrl_cmd_get_msg_type_support * req = NULL ;
929
962
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 ;
932
966
933
967
if (buf_size < sizeof (* req )) {
934
968
warnx ("short Get Message Type Support message" );
935
969
return - ENOMSG ;
936
970
}
937
971
938
972
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
+
939
982
resp = (void * )resp_buf ;
940
983
mctp_ctrl_msg_hdr_init_resp (& resp -> ctrl_hdr , req -> ctrl_hdr );
984
+ resp -> completion_code = MCTP_CTRL_CC_SUCCESS ;
941
985
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
+ }
946
992
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 ;
948
996
}
949
997
950
998
static int
@@ -3319,6 +3367,71 @@ static int method_net_learn_endpoint(sd_bus_message *call, void *data,
3319
3367
return rc ;
3320
3368
}
3321
3369
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
+
3322
3435
// clang-format off
3323
3436
static const sd_bus_vtable bus_link_owner_vtable [] = {
3324
3437
SD_BUS_VTABLE_START (0 ),
@@ -3672,6 +3785,17 @@ static const sd_bus_vtable bus_network_vtable[] = {
3672
3785
SD_BUS_VTABLE_PROPERTY_CONST ),
3673
3786
SD_BUS_VTABLE_END
3674
3787
};
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
+ };
3675
3799
// clang-format on
3676
3800
3677
3801
static int emit_endpoint_added (const struct peer * peer )
@@ -3822,6 +3946,14 @@ static int setup_bus(struct ctx *ctx)
3822
3946
goto out ;
3823
3947
}
3824
3948
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
+
3825
3957
rc = 0 ;
3826
3958
out :
3827
3959
return rc ;
@@ -4613,6 +4745,34 @@ static int parse_config(struct ctx *ctx)
4613
4745
return rc ;
4614
4746
}
4615
4747
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
+
4616
4776
static void setup_config_defaults (struct ctx * ctx )
4617
4777
{
4618
4778
ctx -> mctp_timeout = 250000 ; // 250ms
@@ -4624,7 +4784,13 @@ static void setup_config_defaults(struct ctx *ctx)
4624
4784
4625
4785
static void free_config (struct ctx * ctx )
4626
4786
{
4787
+ int i ;
4788
+
4627
4789
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 );
4628
4794
}
4629
4795
4630
4796
static int endpoint_send_allocate_endpoint_ids (
@@ -4778,6 +4944,8 @@ int main(int argc, char **argv)
4778
4944
setlinebuf (stdout );
4779
4945
4780
4946
setup_config_defaults (ctx );
4947
+ setup_ctrl_cmd_defaults (ctx );
4948
+
4781
4949
mctp_ops_init ();
4782
4950
4783
4951
rc = parse_args (ctx , argc , argv );
0 commit comments