@@ -192,6 +192,16 @@ struct peer {
192
192
} recovery ;
193
193
};
194
194
195
+ struct msg_type_support {
196
+ size_t count ;
197
+
198
+ // Assume array index follows same order. Msg type at msg_types[0]
199
+ // will have version_counts[0] versions stored at versions[0]
200
+ uint8_t * msg_types ;
201
+ size_t * version_counts ;
202
+ uint32_t * * versions ;
203
+ };
204
+
195
205
struct ctx {
196
206
sd_event * event ;
197
207
sd_bus * bus ;
@@ -219,6 +229,9 @@ struct ctx {
219
229
220
230
uint8_t uuid [16 ];
221
231
232
+ // Supported message types and their versions
233
+ struct msg_type_support supported_msg_types ;
234
+
222
235
// Verbose logging
223
236
bool verbose ;
224
237
};
@@ -670,6 +683,7 @@ handle_control_get_version_support(struct ctx *ctx, int sd,
670
683
// space for 4 versions
671
684
uint8_t respbuf [sizeof (* resp ) + 4 * sizeof (* versions )];
672
685
size_t resp_len ;
686
+ ssize_t i , ver_idx = -1 , ver_count = 0 ;
673
687
674
688
if (buf_size < sizeof (struct mctp_ctrl_cmd_get_mctp_ver_support )) {
675
689
warnx ("short Get Version Support message" );
@@ -679,24 +693,32 @@ handle_control_get_version_support(struct ctx *ctx, int sd,
679
693
req = (void * )buf ;
680
694
resp = (void * )respbuf ;
681
695
memset (resp , 0x0 , sizeof (* resp ));
682
- versions = (void * )(resp + 1 );
683
- switch (req -> msg_type_number ) {
684
- case 0xff : // Base Protocol
685
- case 0x00 : // Control protocol
686
- // from DSP0236 1.3.1 section 12.6.2. Big endian.
687
- versions [0 ] = htonl (0xF1F0FF00 );
688
- versions [1 ] = htonl (0xF1F1FF00 );
689
- versions [2 ] = htonl (0xF1F2FF00 );
690
- versions [3 ] = htonl (0xF1F3F100 );
691
- resp -> number_of_entries = 4 ;
692
- resp -> completion_code = MCTP_CTRL_CC_SUCCESS ;
693
- resp_len = sizeof (* resp ) + 4 * sizeof (* versions );
694
- break ;
695
- default :
696
+ if (req -> msg_type_number == 0xFF ) {
697
+ // use same version for base spec and control protocol
698
+ req -> msg_type_number = 0 ;
699
+ }
700
+ for (i = 0 ; i < ctx -> supported_msg_types .count ; i ++ ) {
701
+ if (ctx -> supported_msg_types .msg_types [i ] ==
702
+ req -> msg_type_number ) {
703
+ ver_idx = i ;
704
+ break ;
705
+ }
706
+ }
707
+ if (ver_idx < 0 ) {
696
708
// Unsupported message type
697
709
resp -> completion_code =
698
710
MCTP_CTRL_CC_GET_MCTP_VER_SUPPORT_UNSUPPORTED_TYPE ;
699
- resp_len = sizeof (* resp );
711
+ // Number of enrties not needed in unsupprted cmd
712
+ resp_len = sizeof (* resp ) - sizeof (uint8_t );
713
+ } else {
714
+ versions = (void * )(resp + 1 );
715
+ ver_count = ctx -> supported_msg_types .version_counts [ver_idx ];
716
+ memcpy (versions , ctx -> supported_msg_types .versions [ver_idx ],
717
+ ver_count * sizeof (uint32_t ));
718
+ resp -> number_of_entries = ver_count ;
719
+
720
+ resp -> completion_code = MCTP_CTRL_CC_SUCCESS ;
721
+ resp_len = sizeof (* resp ) + ver_count * sizeof (uint32_t );
700
722
}
701
723
702
724
resp -> ctrl_hdr .command_code = req -> ctrl_hdr .command_code ;
@@ -761,28 +783,39 @@ static int handle_control_get_message_type_support(
761
783
const uint8_t * buf , const size_t buf_size )
762
784
{
763
785
struct mctp_ctrl_cmd_get_msg_type_support * req = NULL ;
764
- ;
765
786
struct mctp_ctrl_resp_get_msg_type_support * resp = NULL ;
766
- uint8_t resp_buf [ sizeof ( * resp ) + 1 ] ;
767
- size_t resp_len ;
787
+ uint8_t * resp_buf ;
788
+ size_t resp_len , type_count ;
768
789
769
790
if (buf_size < sizeof (* req )) {
770
791
warnx ("short Get Message Type Support message" );
771
792
return - ENOMSG ;
772
793
}
773
794
774
795
req = (void * )buf ;
796
+ type_count = ctx -> supported_msg_types .count ;
797
+ // Allocate extra space for the message types
798
+ resp_len = sizeof (* resp ) + type_count ;
799
+ resp_buf = malloc (resp_len );
800
+ if (!resp_buf ) {
801
+ warnx ("Failed to allocate response buffer" );
802
+ return - ENOMEM ;
803
+ }
804
+
775
805
resp = (void * )resp_buf ;
776
- resp -> ctrl_hdr .command_code = req -> ctrl_hdr .command_code ;
777
806
resp -> ctrl_hdr .rq_dgram_inst =
778
807
(req -> ctrl_hdr .rq_dgram_inst & IID_MASK ) | RQDI_RESP ;
808
+ resp -> ctrl_hdr .command_code = req -> ctrl_hdr .command_code ;
809
+ resp -> completion_code = MCTP_CTRL_CC_SUCCESS ;
779
810
780
- // Only control messages supported
781
- resp -> msg_type_count = 1 ;
782
- * ((uint8_t * )(resp + 1 )) = MCTP_CTRL_HDR_MSG_TYPE ;
783
- resp_len = sizeof ( * resp ) + resp -> msg_type_count ;
811
+ resp -> msg_type_count = type_count ;
812
+ // Append message types after msg_type_count
813
+ memcpy ((uint8_t * )(resp + 1 ), ctx -> supported_msg_types . msg_types ,
814
+ type_count ) ;
784
815
785
- return reply_message (ctx , sd , resp , resp_len , addr );
816
+ int result = reply_message (ctx , sd , resp , resp_len , addr );
817
+ free (resp_buf );
818
+ return result ;
786
819
}
787
820
788
821
static int
@@ -2829,6 +2862,91 @@ static int method_net_learn_endpoint(sd_bus_message *call, void *data,
2829
2862
return rc ;
2830
2863
}
2831
2864
2865
+ static int method_register_responder (sd_bus_message * call , void * data ,
2866
+ sd_bus_error * berr )
2867
+ {
2868
+ struct ctx * ctx = data ;
2869
+ uint8_t msg_type ;
2870
+ const uint32_t * versions = NULL ;
2871
+ size_t versions_len ;
2872
+ int rc ;
2873
+ int i ;
2874
+
2875
+ rc = sd_bus_message_read (call , "y" , & msg_type );
2876
+ if (rc < 0 )
2877
+ goto err ;
2878
+ rc = sd_bus_message_read_array (call , 'u' , (const void * * )& versions ,
2879
+ & versions_len );
2880
+ if (rc < 0 )
2881
+ goto err ;
2882
+
2883
+ if (versions_len == 0 ) {
2884
+ warnx ("No versions provided for message type %d" , msg_type );
2885
+ return sd_bus_error_setf (
2886
+ berr , SD_BUS_ERROR_INVALID_ARGS ,
2887
+ "No versions provided for message type %d" , msg_type );
2888
+ }
2889
+
2890
+ for (i = 0 ; i < ctx -> supported_msg_types .count ; i ++ ) {
2891
+ if (ctx -> supported_msg_types .msg_types [i ] == msg_type ) {
2892
+ warnx ("Message type %d already registered" , msg_type );
2893
+ return sd_bus_error_setf (
2894
+ berr , SD_BUS_ERROR_INVALID_ARGS ,
2895
+ "Message type %d already registered" , msg_type );
2896
+ }
2897
+ }
2898
+
2899
+ uint8_t * msg_types =
2900
+ realloc (ctx -> supported_msg_types .msg_types ,
2901
+ (ctx -> supported_msg_types .count + 1 ) * sizeof (uint8_t ));
2902
+ if (!msg_types ) {
2903
+ goto oom_err ;
2904
+ }
2905
+ ctx -> supported_msg_types .msg_types = msg_types ;
2906
+
2907
+ uint32_t * * versions_ptr = realloc (ctx -> supported_msg_types .versions ,
2908
+ (ctx -> supported_msg_types .count + 1 ) *
2909
+ sizeof (uint32_t * ));
2910
+ if (!versions_ptr ) {
2911
+ // realloc ptrs are not cleared. msg_types will have one byte extra capacity.
2912
+ // same for next alloc also.
2913
+ goto oom_err ;
2914
+ }
2915
+ ctx -> supported_msg_types .versions = versions_ptr ;
2916
+
2917
+ size_t * version_counts =
2918
+ realloc (ctx -> supported_msg_types .version_counts ,
2919
+ (ctx -> supported_msg_types .count + 1 ) * sizeof (size_t ));
2920
+ if (!version_counts ) {
2921
+ goto oom_err ;
2922
+ }
2923
+ ctx -> supported_msg_types .version_counts = version_counts ;
2924
+
2925
+ uint32_t * msg_versions = malloc (versions_len );
2926
+ if (!msg_versions ) {
2927
+ goto oom_err ;
2928
+ }
2929
+ // Assume callers's responsibility to provide version in uint32 format from spec
2930
+ memcpy (msg_versions , versions , versions_len );
2931
+
2932
+ ctx -> supported_msg_types .msg_types [ctx -> supported_msg_types .count ] =
2933
+ msg_type ;
2934
+ ctx -> supported_msg_types .versions [ctx -> supported_msg_types .count ] =
2935
+ msg_versions ;
2936
+ ctx -> supported_msg_types .version_counts [ctx -> supported_msg_types .count ] =
2937
+ versions_len / sizeof (uint32_t );
2938
+ ctx -> supported_msg_types .count ++ ;
2939
+
2940
+ return sd_bus_reply_method_return (call , "" );
2941
+
2942
+ oom_err :
2943
+ return sd_bus_error_setf (berr , SD_BUS_ERROR_NO_MEMORY ,
2944
+ "Failed to allocate memory" );
2945
+ err :
2946
+ set_berr (ctx , rc , berr );
2947
+ return rc ;
2948
+ }
2949
+
2832
2950
// clang-format off
2833
2951
static const sd_bus_vtable bus_link_owner_vtable [] = {
2834
2952
SD_BUS_VTABLE_START (0 ),
@@ -3145,6 +3263,17 @@ static const sd_bus_vtable bus_network_vtable[] = {
3145
3263
SD_BUS_VTABLE_PROPERTY_CONST ),
3146
3264
SD_BUS_VTABLE_END
3147
3265
};
3266
+
3267
+ static const sd_bus_vtable mctp_base_vtable [] = {
3268
+ SD_BUS_VTABLE_START (0 ),
3269
+ SD_BUS_METHOD_WITH_ARGS ("RegisterResponder" ,
3270
+ SD_BUS_ARGS ("y" , msg_type ,
3271
+ "au" , versions ),
3272
+ SD_BUS_NO_RESULT ,
3273
+ method_register_responder ,
3274
+ 0 ),
3275
+ SD_BUS_VTABLE_END ,
3276
+ };
3148
3277
// clang-format on
3149
3278
3150
3279
static int emit_endpoint_added (const struct peer * peer )
@@ -3295,6 +3424,14 @@ static int setup_bus(struct ctx *ctx)
3295
3424
goto out ;
3296
3425
}
3297
3426
3427
+ rc = sd_bus_add_object_vtable (ctx -> bus , NULL , MCTP_DBUS_PATH ,
3428
+ MCTP_DBUS_NAME ,
3429
+ mctp_base_vtable , ctx );
3430
+ if (rc < 0 ) {
3431
+ warnx ("Adding MCTP base vtable failed: %s" , strerror (- rc ));
3432
+ goto out ;
3433
+ }
3434
+
3298
3435
rc = 0 ;
3299
3436
out :
3300
3437
return rc ;
@@ -3996,13 +4133,68 @@ static int parse_config(struct ctx *ctx)
3996
4133
3997
4134
static void setup_config_defaults (struct ctx * ctx )
3998
4135
{
4136
+ uint32_t * ctrl_cmd_versions = NULL ;
4137
+ ctx -> supported_msg_types .msg_types = NULL ;
4138
+ ctx -> supported_msg_types .versions = NULL ;
4139
+ ctx -> supported_msg_types .version_counts = NULL ;
4140
+
3999
4141
ctx -> mctp_timeout = 250000 ; // 250ms
4000
4142
ctx -> default_role = ENDPOINT_ROLE_BUS_OWNER ;
4143
+ ctx -> supported_msg_types .count = 0 ;
4144
+
4145
+ // Default to supporting only control messages
4146
+ ctx -> supported_msg_types .msg_types = malloc (1 );
4147
+ if (!ctx -> supported_msg_types .msg_types ) {
4148
+ warnx ("Out of memory for supported message types" );
4149
+ goto oom_err ;
4150
+ }
4151
+ ctrl_cmd_versions = malloc (sizeof (uint32_t ) * 4 );
4152
+ if (!ctrl_cmd_versions ) {
4153
+ warnx ("Out of memory for versions" );
4154
+ goto oom_err ;
4155
+ }
4156
+ ctx -> supported_msg_types .versions = malloc (sizeof (uint32_t * ));
4157
+ if (!ctx -> supported_msg_types .versions ) {
4158
+ warnx ("Out of memory for versions" );
4159
+ goto oom_err ;
4160
+ }
4161
+ ctx -> supported_msg_types .version_counts = malloc (sizeof (size_t ));
4162
+ if (!ctx -> supported_msg_types .version_counts ) {
4163
+ warnx ("Out of memory for version counts" );
4164
+ goto oom_err ;
4165
+ }
4166
+
4167
+ ctx -> supported_msg_types .count = 1 ;
4168
+ ctx -> supported_msg_types .msg_types [0 ] = MCTP_CTRL_HDR_MSG_TYPE ;
4169
+ ctrl_cmd_versions [0 ] = htonl (0xF1F0FF00 );
4170
+ ctrl_cmd_versions [1 ] = htonl (0xF1F1FF00 );
4171
+ ctrl_cmd_versions [2 ] = htonl (0xF1F2FF00 );
4172
+ ctrl_cmd_versions [3 ] = htonl (0xF1F3F100 );
4173
+ ctx -> supported_msg_types .versions [0 ] = ctrl_cmd_versions ;
4174
+ ctx -> supported_msg_types .version_counts [0 ] = 4 ;
4175
+
4176
+ return ;
4177
+ oom_err :
4178
+ free (ctrl_cmd_versions );
4179
+ free (ctx -> supported_msg_types .msg_types );
4180
+ free (ctx -> supported_msg_types .versions );
4181
+ free (ctx -> supported_msg_types .version_counts );
4182
+ ctx -> supported_msg_types .msg_types = NULL ;
4183
+ ctx -> supported_msg_types .versions = NULL ;
4184
+ ctx -> supported_msg_types .version_counts = NULL ;
4001
4185
}
4002
4186
4003
4187
static void free_config (struct ctx * ctx )
4004
4188
{
4189
+ int i ;
4190
+
4005
4191
free (ctx -> config_filename );
4192
+ for (i = 0 ; i < ctx -> supported_msg_types .count ; i ++ ) {
4193
+ free (ctx -> supported_msg_types .versions [i ]);
4194
+ }
4195
+ free (ctx -> supported_msg_types .versions );
4196
+ free (ctx -> supported_msg_types .version_counts );
4197
+ free (ctx -> supported_msg_types .msg_types );
4006
4198
}
4007
4199
4008
4200
int main (int argc , char * * argv )
0 commit comments