diff --git a/module/transport/src/mod_transport.c b/module/transport/src/mod_transport.c index 876130fc7a7abf94e2331f5177b728f23ebda032..30727ad301f92142cc6872f859eee4c86430a9c0 100644 --- a/module/transport/src/mod_transport.c +++ b/module/transport/src/mod_transport.c @@ -1,6 +1,6 @@ /* * Arm SCP/MCP Software - * Copyright (c) 2022-2024, Arm Limited and Contributors. All rights reserved. + * Copyright (c) 2022-2025, Arm Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause * @@ -240,12 +240,23 @@ static int transport_respond( fwk_assert(transport_type != MOD_TRANSPORT_CHANNEL_TRANSPORT_TYPE_NONE); + if (channel_ctx->max_payload_size < size) { + fwk_unexpected(); + return FWK_E_PARAM; + } + #if defined(BUILD_HAS_OUTBAND_MSG_SUPPORT) if (transport_type == MOD_TRANSPORT_CHANNEL_TRANSPORT_TYPE_OUT_BAND) { /* Use shared mailbox for out-band messages */ buffer = ((struct mod_transport_buffer *) channel_ctx->config->out_band_mailbox_address); + if (buffer == NULL) { + FWK_LOG_ERR( + "%s ERROR: NULL buffer in \"%s()\"", MOD_NAME, __func__); + return FWK_E_PANIC; + } + /* Copy the header and other fields from the write buffer */ fwk_str_memcpy( buffer, channel_ctx->out, sizeof(struct mod_transport_buffer)); @@ -259,22 +270,28 @@ static int transport_respond( (payload == NULL ? channel_ctx->out->payload : payload), size); } -#else -# if defined(BUILD_HAS_INBAND_MSG_SUPPORT) +#endif +#if defined(BUILD_HAS_INBAND_MSG_SUPPORT) if (transport_type == MOD_TRANSPORT_CHANNEL_TRANSPORT_TYPE_IN_BAND) { /* Use internal write buffer for in-band messages */ buffer = channel_ctx->out; + if (buffer == NULL) { + FWK_LOG_ERR( + "%s ERROR: NULL buffer in \"%s()\"", MOD_NAME, __func__); + return FWK_E_PANIC; + } + /* Copy the payload from the payload parameter */ if (payload != NULL) { fwk_str_memcpy(buffer->payload, payload, size); } } -# endif #endif if (buffer == NULL) { - FWK_LOG_ERR("%s ERROR: NULL buffer in \"%s()\"", MOD_NAME, __func__); + FWK_LOG_ERR( + "%s ERROR: Invalid transport_type in \"%s()\"", MOD_NAME, __func__); return FWK_E_PANIC; } @@ -310,7 +327,6 @@ static int transport_respond( status = channel_ctx->driver_api->trigger_event( channel_ctx->config->driver_id); } - return status; } @@ -335,11 +351,23 @@ static int transport_transmit( fwk_assert(transport_type != MOD_TRANSPORT_CHANNEL_TRANSPORT_TYPE_NONE); + if (channel_ctx->max_payload_size < size) { + fwk_unexpected(); + return FWK_E_PARAM; + } + #if defined(BUILD_HAS_OUTBAND_MSG_SUPPORT) if (transport_type == MOD_TRANSPORT_CHANNEL_TRANSPORT_TYPE_OUT_BAND) { /* Use shared mailbox for out-band messages */ buffer = ((struct mod_transport_buffer *) channel_ctx->config->out_band_mailbox_address); + if (buffer == NULL) { + FWK_LOG_ERR( + "%s ERROR: NULL buffer in \"%s()\"", MOD_NAME, __func__); + fwk_unexpected(); + return FWK_E_PANIC; + } + /* * If the agent/platform has not yet read the previous message we * abandon this transmission. We don't want to poll on the BUSY/FREE @@ -350,11 +378,6 @@ static int transport_transmit( (uint32_t)0) { return FWK_E_BUSY; } - } else { -# if !defined(BUILD_HAS_INBAND_MSG_SUPPORT) - FWK_LOG_ERR("%s ERROR. IN-BAND MESSAGES NOT SUPPORTED!", MOD_NAME); - return FWK_E_SUPPORT; -# endif } #endif @@ -362,19 +385,23 @@ static int transport_transmit( if (transport_type == MOD_TRANSPORT_CHANNEL_TRANSPORT_TYPE_IN_BAND) { /* Use internal write buffer for in-band messages */ buffer = channel_ctx->out; + if (buffer == NULL) { + FWK_LOG_ERR( + "%s ERROR: NULL buffer in \"%s()\"", MOD_NAME, __func__); + fwk_unexpected(); + return FWK_E_PANIC; + } + /* reserved fields must be set to zero */ buffer->reserved0 = 0; buffer->reserved1 = 0; - } else { -# if !defined(BUILD_HAS_OUTBAND_MSG_SUPPORT) - FWK_LOG_ERR("%s ERROR. OUT-BAND MESSAGES NOT SUPPORTED!", MOD_NAME); - return FWK_E_SUPPORT; -# endif } #endif if (buffer == NULL) { - FWK_LOG_ERR("%s ERROR: NULL buffer in \"%s()\"", MOD_NAME, __func__); + FWK_LOG_ERR( + "%s ERROR: Invalid transport_type in \"%s()\"", MOD_NAME, __func__); + fwk_unexpected(); return FWK_E_PANIC; } diff --git a/module/transport/test/mod_transport_unit_test.c b/module/transport/test/mod_transport_unit_test.c index 7c6a44ad7f38ee11f9dd2d69b867880b04b8204b..3cdb6298c407ac67f265a7d063165dc5dbe06e27 100644 --- a/module/transport/test/mod_transport_unit_test.c +++ b/module/transport/test/mod_transport_unit_test.c @@ -1,6 +1,6 @@ /* * Arm SCP/MCP Software - * Copyright (c) 2022-2024, Arm Limited and Contributors. All rights reserved. + * Copyright (c) 2022-2025, Arm Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -28,30 +28,81 @@ #define BUILD_HAS_BASE_PROTOCOL +#ifndef BUILD_HAS_INBAND_MSG_SUPPORT +# error Unit test requires BUILD_HAS_INBAND_MSG_SUPPORT +#endif +#ifndef BUILD_HAS_OUTBAND_MSG_SUPPORT +# error Unit test requires BUILD_HAS_OUTBAND_MSG_SUPPORT +#endif + #define FAKE_MODULE_ID 0x5 #define TEST_MAILBOX_SIZE 100 enum fake_services { - FAKE_SERVICE_IDX_PSCI, - FAKE_SERVICE_IDX_OSPM, + FAKE_SERVICE_IDX_OUT_BAND_TEST_CHANNEL, + FAKE_SERVICE_IDX_IN_BAND_TEST_CHANNEL, FAKE_SERVICE_IDX_COUNT, }; -void setUp(void) +int mock_send_message(struct mod_transport_buffer *message, fwk_id_t device_id) +{ + return FWK_SUCCESS; +} + +int mock_get_message(struct mod_transport_buffer *message, fwk_id_t device_id) +{ + return FWK_SUCCESS; +} + +int mock_trigger_event(fwk_id_t device_id) { - fwk_id_t service_id = - FWK_ID_ELEMENT_INIT(FAKE_MODULE_ID, FAKE_SERVICE_IDX_OSPM); + return FWK_SUCCESS; +} + +struct mod_transport_driver_api mock_mod_transport_driver_api = { + .send_message = mock_send_message, + .get_message = mock_get_message, + .trigger_event = mock_trigger_event, +}; - transport_init(service_id, FAKE_SERVICE_IDX_COUNT, NULL); +void setUp(void) +{ + fwk_id_t module_id = FWK_ID_MODULE_INIT(FAKE_MODULE_ID); + fwk_id_t ib_channel_id = FWK_ID_ELEMENT_INIT( + FAKE_MODULE_ID, FAKE_SERVICE_IDX_IN_BAND_TEST_CHANNEL); + fwk_id_t ob_channel_id = FWK_ID_ELEMENT_INIT( + FAKE_MODULE_ID, FAKE_SERVICE_IDX_OUT_BAND_TEST_CHANNEL); - fwk_id_get_element_idx_ExpectAndReturn(service_id, FAKE_SERVICE_IDX_OSPM); + transport_init(module_id, FAKE_SERVICE_IDX_COUNT, NULL); - static const struct mod_transport_channel_config config = { + fwk_id_get_element_idx_ExpectAndReturn( + ib_channel_id, FAKE_SERVICE_IDX_IN_BAND_TEST_CHANNEL); + static const struct mod_transport_channel_config ib_config = { .transport_type = MOD_TRANSPORT_CHANNEL_TRANSPORT_TYPE_IN_BAND, .channel_type = MOD_TRANSPORT_CHANNEL_TYPE_REQUESTER, .in_band_mailbox_size = TEST_MAILBOX_SIZE }; - transport_channel_init(service_id, 0, &config); + transport_channel_init(ib_channel_id, 0, &ib_config); + + uintptr_t out_band_mailbox = (uintptr_t)fwk_mm_alloc(1, TEST_MAILBOX_SIZE); + fwk_id_get_element_idx_ExpectAndReturn( + ob_channel_id, FAKE_SERVICE_IDX_OUT_BAND_TEST_CHANNEL); + static struct mod_transport_channel_config ob_config = { + .transport_type = MOD_TRANSPORT_CHANNEL_TRANSPORT_TYPE_OUT_BAND, + .channel_type = MOD_TRANSPORT_CHANNEL_TYPE_REQUESTER, + .out_band_mailbox_size = TEST_MAILBOX_SIZE, + }; + ob_config.out_band_mailbox_address = out_band_mailbox; + transport_channel_init(ob_channel_id, 0, &ob_config); + + struct transport_channel_ctx *channel_ctx; + channel_ctx = + &transport_ctx.channel_ctx_table[FAKE_SERVICE_IDX_IN_BAND_TEST_CHANNEL]; + channel_ctx->driver_api = &mock_mod_transport_driver_api; + channel_ctx = + &transport_ctx + .channel_ctx_table[FAKE_SERVICE_IDX_OUT_BAND_TEST_CHANNEL]; + channel_ctx->driver_api = &mock_mod_transport_driver_api; } void tearDown(void) @@ -61,27 +112,48 @@ void tearDown(void) void test_transport_payload_size(void) { struct transport_channel_ctx *channel_ctx = - &transport_ctx.channel_ctx_table[FAKE_SERVICE_IDX_OSPM]; + &transport_ctx.channel_ctx_table[FAKE_SERVICE_IDX_IN_BAND_TEST_CHANNEL]; TEST_ASSERT_EQUAL( TEST_MAILBOX_SIZE - sizeof(struct mod_transport_buffer), channel_ctx->max_payload_size); } +void test_transport_write_payload_invalid_state_unlocked(void) +{ + int status; + + fwk_id_t service_id = FWK_ID_ELEMENT_INIT( + FAKE_MODULE_ID, FAKE_SERVICE_IDX_IN_BAND_TEST_CHANNEL); + char string[] = "Test"; + + /* We are not going through a proper message cycle so let's set the lock */ + struct transport_channel_ctx *channel_ctx = + &transport_ctx.channel_ctx_table[FAKE_SERVICE_IDX_IN_BAND_TEST_CHANNEL]; + channel_ctx->locked = false; + + fwk_id_get_element_idx_ExpectAndReturn( + service_id, FAKE_SERVICE_IDX_IN_BAND_TEST_CHANNEL); + + status = transport_write_payload(service_id, 0, string, sizeof(string)); + TEST_ASSERT_EQUAL(FWK_E_ACCESS, status); +} + void test_transport_write_payload_invalid_param_null_payload(void) { int status; - fwk_id_t service_id = - FWK_ID_ELEMENT_INIT(FAKE_MODULE_ID, FAKE_SERVICE_IDX_OSPM); + fwk_id_t service_id = FWK_ID_ELEMENT_INIT( + FAKE_MODULE_ID, FAKE_SERVICE_IDX_IN_BAND_TEST_CHANNEL); char string[] = "Test"; /* We are not going through a proper message cycle so let's set the lock */ struct transport_channel_ctx *channel_ctx = - &transport_ctx.channel_ctx_table[FAKE_SERVICE_IDX_OSPM]; + &transport_ctx.channel_ctx_table[FAKE_SERVICE_IDX_IN_BAND_TEST_CHANNEL]; channel_ctx->locked = true; - fwk_id_get_element_idx_ExpectAndReturn(service_id, FAKE_SERVICE_IDX_OSPM); + fwk_id_get_element_idx_ExpectAndReturn( + service_id, FAKE_SERVICE_IDX_IN_BAND_TEST_CHANNEL); status = transport_write_payload(service_id, 0, NULL, sizeof(string)); TEST_ASSERT_EQUAL(FWK_E_PARAM, status); @@ -92,16 +164,17 @@ void test_transport_write_payload_invalid_param_large_size(void) int status; size_t offset = 50; - fwk_id_t service_id = - FWK_ID_ELEMENT_INIT(FAKE_MODULE_ID, FAKE_SERVICE_IDX_OSPM); + fwk_id_t service_id = FWK_ID_ELEMENT_INIT( + FAKE_MODULE_ID, FAKE_SERVICE_IDX_IN_BAND_TEST_CHANNEL); char payload[] = "Test"; /* We are not going through a proper message cycle so let's set the lock */ struct transport_channel_ctx *channel_ctx = - &transport_ctx.channel_ctx_table[FAKE_SERVICE_IDX_OSPM]; + &transport_ctx.channel_ctx_table[FAKE_SERVICE_IDX_IN_BAND_TEST_CHANNEL]; channel_ctx->locked = true; - fwk_id_get_element_idx_ExpectAndReturn(service_id, FAKE_SERVICE_IDX_OSPM); + fwk_id_get_element_idx_ExpectAndReturn( + service_id, FAKE_SERVICE_IDX_IN_BAND_TEST_CHANNEL); status = transport_write_payload( service_id, offset, payload, SIZE_MAX - (offset / 2)); @@ -112,16 +185,17 @@ void test_transport_write_payload_invalid_param_large_offset(void) { int status; - fwk_id_t service_id = - FWK_ID_ELEMENT_INIT(FAKE_MODULE_ID, FAKE_SERVICE_IDX_OSPM); + fwk_id_t service_id = FWK_ID_ELEMENT_INIT( + FAKE_MODULE_ID, FAKE_SERVICE_IDX_IN_BAND_TEST_CHANNEL); char payload[] = "Test"; /* We are not going through a proper message cycle so let's set the lock */ struct transport_channel_ctx *channel_ctx = - &transport_ctx.channel_ctx_table[FAKE_SERVICE_IDX_OSPM]; + &transport_ctx.channel_ctx_table[FAKE_SERVICE_IDX_IN_BAND_TEST_CHANNEL]; channel_ctx->locked = true; - fwk_id_get_element_idx_ExpectAndReturn(service_id, FAKE_SERVICE_IDX_OSPM); + fwk_id_get_element_idx_ExpectAndReturn( + service_id, FAKE_SERVICE_IDX_IN_BAND_TEST_CHANNEL); status = transport_write_payload( service_id, SIZE_MAX - 2, payload, sizeof(payload)); @@ -132,16 +206,17 @@ void test_transport_write_payload_invalid_param_offset_beyond_end(void) { int status; - fwk_id_t service_id = - FWK_ID_ELEMENT_INIT(FAKE_MODULE_ID, FAKE_SERVICE_IDX_OSPM); + fwk_id_t service_id = FWK_ID_ELEMENT_INIT( + FAKE_MODULE_ID, FAKE_SERVICE_IDX_IN_BAND_TEST_CHANNEL); char payload[] = "Test"; /* We are not going through a proper message cycle so let's set the lock */ struct transport_channel_ctx *channel_ctx = - &transport_ctx.channel_ctx_table[FAKE_SERVICE_IDX_OSPM]; + &transport_ctx.channel_ctx_table[FAKE_SERVICE_IDX_IN_BAND_TEST_CHANNEL]; channel_ctx->locked = true; - fwk_id_get_element_idx_ExpectAndReturn(service_id, FAKE_SERVICE_IDX_OSPM); + fwk_id_get_element_idx_ExpectAndReturn( + service_id, FAKE_SERVICE_IDX_IN_BAND_TEST_CHANNEL); status = transport_write_payload( service_id, channel_ctx->max_payload_size, payload, 1); @@ -152,16 +227,17 @@ void test_transport_write_payload_valid_param_start(void) { int status; - fwk_id_t service_id = - FWK_ID_ELEMENT_INIT(FAKE_MODULE_ID, FAKE_SERVICE_IDX_OSPM); + fwk_id_t service_id = FWK_ID_ELEMENT_INIT( + FAKE_MODULE_ID, FAKE_SERVICE_IDX_IN_BAND_TEST_CHANNEL); char payload[] = "Test"; /* We are not going through a proper message cycle so let's set the lock */ struct transport_channel_ctx *channel_ctx = - &transport_ctx.channel_ctx_table[FAKE_SERVICE_IDX_OSPM]; + &transport_ctx.channel_ctx_table[FAKE_SERVICE_IDX_IN_BAND_TEST_CHANNEL]; channel_ctx->locked = true; - fwk_id_get_element_idx_ExpectAndReturn(service_id, FAKE_SERVICE_IDX_OSPM); + fwk_id_get_element_idx_ExpectAndReturn( + service_id, FAKE_SERVICE_IDX_IN_BAND_TEST_CHANNEL); status = transport_write_payload(service_id, 0, payload, sizeof(payload)); TEST_ASSERT_EQUAL(FWK_SUCCESS, status); @@ -176,16 +252,17 @@ void test_transport_write_payload_valid_param_end(void) { int status; - fwk_id_t service_id = - FWK_ID_ELEMENT_INIT(FAKE_MODULE_ID, FAKE_SERVICE_IDX_OSPM); + fwk_id_t service_id = FWK_ID_ELEMENT_INIT( + FAKE_MODULE_ID, FAKE_SERVICE_IDX_IN_BAND_TEST_CHANNEL); char payload[] = "T"; /* We are not going through a proper message cycle so let's set the lock */ struct transport_channel_ctx *channel_ctx = - &transport_ctx.channel_ctx_table[FAKE_SERVICE_IDX_OSPM]; + &transport_ctx.channel_ctx_table[FAKE_SERVICE_IDX_IN_BAND_TEST_CHANNEL]; channel_ctx->locked = true; - fwk_id_get_element_idx_ExpectAndReturn(service_id, FAKE_SERVICE_IDX_OSPM); + fwk_id_get_element_idx_ExpectAndReturn( + service_id, FAKE_SERVICE_IDX_IN_BAND_TEST_CHANNEL); status = transport_write_payload( service_id, channel_ctx->max_payload_size - 1, payload, 1); @@ -196,11 +273,384 @@ void test_transport_write_payload_valid_param_end(void) payload[0], dst_payload[channel_ctx->max_payload_size - 1]); } +void test_transport_respond_invalid_state_null_buffer_ib(void) +{ + int status; + + fwk_id_t service_id = FWK_ID_ELEMENT_INIT( + FAKE_MODULE_ID, FAKE_SERVICE_IDX_IN_BAND_TEST_CHANNEL); + char payload[] = "Test"; + + struct transport_channel_ctx *channel_ctx = + &transport_ctx.channel_ctx_table[FAKE_SERVICE_IDX_IN_BAND_TEST_CHANNEL]; + channel_ctx->locked = true; + + channel_ctx->out = NULL; + + fwk_id_get_element_idx_ExpectAndReturn( + service_id, FAKE_SERVICE_IDX_IN_BAND_TEST_CHANNEL); + + status = transport_respond(service_id, payload, sizeof(payload)); + + TEST_ASSERT_EQUAL(FWK_E_PANIC, status); + TEST_ASSERT_EQUAL(true, channel_ctx->locked); +} + +void test_transport_respond_invalid_state_null_buffer_ob(void) +{ + int status; + + fwk_id_t service_id = FWK_ID_ELEMENT_INIT( + FAKE_MODULE_ID, FAKE_SERVICE_IDX_OUT_BAND_TEST_CHANNEL); + char payload[] = "Test"; + + struct transport_channel_ctx *channel_ctx = + &transport_ctx + .channel_ctx_table[FAKE_SERVICE_IDX_OUT_BAND_TEST_CHANNEL]; + channel_ctx->locked = true; + + channel_ctx->config->out_band_mailbox_address = (uintptr_t)NULL; + + fwk_id_get_element_idx_ExpectAndReturn( + service_id, FAKE_SERVICE_IDX_OUT_BAND_TEST_CHANNEL); + + status = transport_respond(service_id, payload, sizeof(payload)); + + TEST_ASSERT_EQUAL(FWK_E_PANIC, status); + TEST_ASSERT_EQUAL(true, channel_ctx->locked); +} + +void test_transport_respond_invalid_param_large_size(void) +{ + int status; + + fwk_id_t service_id = FWK_ID_ELEMENT_INIT( + FAKE_MODULE_ID, FAKE_SERVICE_IDX_IN_BAND_TEST_CHANNEL); + char payload[] = "Test"; + + struct transport_channel_ctx *channel_ctx = + &transport_ctx.channel_ctx_table[FAKE_SERVICE_IDX_IN_BAND_TEST_CHANNEL]; + channel_ctx->locked = true; + + fwk_id_get_element_idx_ExpectAndReturn( + service_id, FAKE_SERVICE_IDX_IN_BAND_TEST_CHANNEL); + + status = transport_respond( + service_id, payload, channel_ctx->max_payload_size + 1); + + TEST_ASSERT_EQUAL(FWK_E_PARAM, status); +} + +void test_transport_respond_invalid_param_null_payload_ib(void) +{ + int status; + + fwk_id_t service_id = FWK_ID_ELEMENT_INIT( + FAKE_MODULE_ID, FAKE_SERVICE_IDX_IN_BAND_TEST_CHANNEL); + + struct transport_channel_ctx *channel_ctx = + &transport_ctx.channel_ctx_table[FAKE_SERVICE_IDX_IN_BAND_TEST_CHANNEL]; + channel_ctx->locked = true; + + uint8_t *dst_payload = (uint8_t *)channel_ctx->out->payload; + char payload[] = "Test"; + memcpy(dst_payload, payload, sizeof(payload)); + + fwk_id_get_element_idx_ExpectAndReturn( + service_id, FAKE_SERVICE_IDX_IN_BAND_TEST_CHANNEL); + + status = transport_respond(service_id, NULL, sizeof(payload)); + + TEST_ASSERT_EQUAL(FWK_SUCCESS, status); + + /* Destination payload should be untouched. */ + for (size_t i = 0; i < sizeof(payload); i++) { + TEST_ASSERT_EQUAL(payload[i], dst_payload[i]); + } +} + +void test_transport_respond_invalid_param_null_payload_ob(void) +{ + int status; + + fwk_id_t service_id = FWK_ID_ELEMENT_INIT( + FAKE_MODULE_ID, FAKE_SERVICE_IDX_OUT_BAND_TEST_CHANNEL); + + struct transport_channel_ctx *channel_ctx = + &transport_ctx + .channel_ctx_table[FAKE_SERVICE_IDX_OUT_BAND_TEST_CHANNEL]; + channel_ctx->locked = true; + + struct mod_transport_buffer *buffer = NULL; + buffer = ((struct mod_transport_buffer *) + channel_ctx->config->out_band_mailbox_address); + + /* When in out-band mode and given a NULL buffer transport_respond copies + * from the out buffer */ + uint8_t *src_payload = (uint8_t *)channel_ctx->out->payload; + char payload[] = "Test"; + memcpy(src_payload, payload, sizeof(payload)); + + fwk_id_get_element_idx_ExpectAndReturn( + service_id, FAKE_SERVICE_IDX_OUT_BAND_TEST_CHANNEL); + + status = transport_respond(service_id, NULL, sizeof(payload)); + + TEST_ASSERT_EQUAL(FWK_SUCCESS, status); + + uint8_t *dst_payload = (uint8_t *)buffer->payload; + for (size_t i = 0; i < sizeof(payload); i++) { + TEST_ASSERT_EQUAL(payload[i], dst_payload[i]); + } +} + +void test_transport_respond_valid_param_ib(void) +{ + int status; + + fwk_id_t service_id = FWK_ID_ELEMENT_INIT( + FAKE_MODULE_ID, FAKE_SERVICE_IDX_IN_BAND_TEST_CHANNEL); + char payload[] = "Test"; + + struct transport_channel_ctx *channel_ctx = + &transport_ctx.channel_ctx_table[FAKE_SERVICE_IDX_IN_BAND_TEST_CHANNEL]; + channel_ctx->locked = true; + + fwk_id_get_element_idx_ExpectAndReturn( + service_id, FAKE_SERVICE_IDX_IN_BAND_TEST_CHANNEL); + + status = transport_respond(service_id, payload, sizeof(payload)); + + TEST_ASSERT_EQUAL(FWK_SUCCESS, status); + TEST_ASSERT_EQUAL(false, channel_ctx->locked); + + uint8_t *dst_payload = (uint8_t *)channel_ctx->out->payload; + for (size_t i = 0; i < sizeof(payload); i++) { + TEST_ASSERT_EQUAL(payload[i], dst_payload[i]); + } +} + +void test_transport_respond_valid_param_ob(void) +{ + int status; + + fwk_id_t service_id = FWK_ID_ELEMENT_INIT( + FAKE_MODULE_ID, FAKE_SERVICE_IDX_OUT_BAND_TEST_CHANNEL); + char payload[] = "Test"; + + struct transport_channel_ctx *channel_ctx = + &transport_ctx + .channel_ctx_table[FAKE_SERVICE_IDX_OUT_BAND_TEST_CHANNEL]; + channel_ctx->locked = true; + + struct mod_transport_buffer *buffer = NULL; + buffer = ((struct mod_transport_buffer *) + channel_ctx->config->out_band_mailbox_address); + buffer->status = MOD_TRANSPORT_MAILBOX_STATUS_FREE_MASK; + + fwk_id_get_element_idx_ExpectAndReturn( + service_id, FAKE_SERVICE_IDX_OUT_BAND_TEST_CHANNEL); + + status = transport_respond(service_id, payload, sizeof(payload)); + + TEST_ASSERT_EQUAL(FWK_SUCCESS, status); + TEST_ASSERT_EQUAL(false, channel_ctx->locked); + + uint8_t *dst_payload = (uint8_t *)buffer->payload; + for (size_t i = 0; i < sizeof(payload); i++) { + TEST_ASSERT_EQUAL(payload[i], dst_payload[i]); + } +} + +void test_transport_transmit_invalid_state_null_buffer_ib(void) +{ + int status; + + fwk_id_t service_id = FWK_ID_ELEMENT_INIT( + FAKE_MODULE_ID, FAKE_SERVICE_IDX_IN_BAND_TEST_CHANNEL); + char payload[] = "Test"; + + struct transport_channel_ctx *channel_ctx = + &transport_ctx.channel_ctx_table[FAKE_SERVICE_IDX_IN_BAND_TEST_CHANNEL]; + channel_ctx->locked = true; + + channel_ctx->out = NULL; + + fwk_id_get_element_idx_ExpectAndReturn( + service_id, FAKE_SERVICE_IDX_IN_BAND_TEST_CHANNEL); + + status = transport_transmit(service_id, 0, payload, sizeof(payload), false); + + TEST_ASSERT_EQUAL(FWK_E_PANIC, status); +} + +void test_transport_transmit_invalid_state_null_buffer_ob(void) +{ + int status; + + fwk_id_t service_id = FWK_ID_ELEMENT_INIT( + FAKE_MODULE_ID, FAKE_SERVICE_IDX_OUT_BAND_TEST_CHANNEL); + char payload[] = "Test"; + + struct transport_channel_ctx *channel_ctx = + &transport_ctx + .channel_ctx_table[FAKE_SERVICE_IDX_OUT_BAND_TEST_CHANNEL]; + channel_ctx->locked = true; + + channel_ctx->config->out_band_mailbox_address = (uintptr_t)NULL; + + fwk_id_get_element_idx_ExpectAndReturn( + service_id, FAKE_SERVICE_IDX_OUT_BAND_TEST_CHANNEL); + + status = transport_transmit(service_id, 0, payload, sizeof(payload), false); + + TEST_ASSERT_EQUAL(FWK_E_PANIC, status); +} + +void test_transport_transmit_invalid_param_large_size(void) +{ + int status; + + fwk_id_t service_id = FWK_ID_ELEMENT_INIT( + FAKE_MODULE_ID, FAKE_SERVICE_IDX_IN_BAND_TEST_CHANNEL); + char payload[] = "Test"; + + struct transport_channel_ctx *channel_ctx = + &transport_ctx.channel_ctx_table[FAKE_SERVICE_IDX_IN_BAND_TEST_CHANNEL]; + channel_ctx->locked = true; + + fwk_id_get_element_idx_ExpectAndReturn( + service_id, FAKE_SERVICE_IDX_IN_BAND_TEST_CHANNEL); + + status = transport_transmit( + service_id, 0, payload, channel_ctx->max_payload_size + 1, false); + + TEST_ASSERT_EQUAL(FWK_E_PARAM, status); +} + +void test_transport_transmit_invalid_param_null_payload_ib(void) +{ + int status; + + fwk_id_t service_id = FWK_ID_ELEMENT_INIT( + FAKE_MODULE_ID, FAKE_SERVICE_IDX_IN_BAND_TEST_CHANNEL); + + struct transport_channel_ctx *channel_ctx = + &transport_ctx.channel_ctx_table[FAKE_SERVICE_IDX_IN_BAND_TEST_CHANNEL]; + + uint8_t *dst_payload = (uint8_t *)channel_ctx->out->payload; + char payload[] = "Test"; + memcpy(dst_payload, payload, sizeof(payload)); + + fwk_id_get_element_idx_ExpectAndReturn( + service_id, FAKE_SERVICE_IDX_IN_BAND_TEST_CHANNEL); + + status = transport_transmit(service_id, 0, NULL, 5, false); + + TEST_ASSERT_EQUAL(FWK_SUCCESS, status); + + /* Destination payload should be untouched. */ + for (size_t i = 0; i < sizeof(payload); i++) { + TEST_ASSERT_EQUAL(payload[i], dst_payload[i]); + } +} + +void test_transport_transmit_invalid_param_null_payload_ob(void) +{ + int status; + + fwk_id_t service_id = FWK_ID_ELEMENT_INIT( + FAKE_MODULE_ID, FAKE_SERVICE_IDX_OUT_BAND_TEST_CHANNEL); + + struct transport_channel_ctx *channel_ctx = + &transport_ctx + .channel_ctx_table[FAKE_SERVICE_IDX_OUT_BAND_TEST_CHANNEL]; + + struct mod_transport_buffer *buffer = NULL; + buffer = ((struct mod_transport_buffer *) + channel_ctx->config->out_band_mailbox_address); + buffer->status = MOD_TRANSPORT_MAILBOX_STATUS_FREE_MASK; + + uint8_t *dst_payload = (uint8_t *)buffer->payload; + char payload[] = "Test"; + memcpy(dst_payload, payload, sizeof(payload)); + + fwk_id_get_element_idx_ExpectAndReturn( + service_id, FAKE_SERVICE_IDX_OUT_BAND_TEST_CHANNEL); + + status = transport_transmit(service_id, 0, NULL, 5, false); + + TEST_ASSERT_EQUAL(FWK_SUCCESS, status); + + /* Destination payload should be untouched. */ + for (size_t i = 0; i < sizeof(payload); i++) { + TEST_ASSERT_EQUAL(payload[i], dst_payload[i]); + } +} + +void test_transport_transmit_valid_param_ib(void) +{ + int status; + + fwk_id_t channel_id = FWK_ID_ELEMENT_INIT( + FAKE_MODULE_ID, FAKE_SERVICE_IDX_IN_BAND_TEST_CHANNEL); + char payload[] = "Test"; + + struct transport_channel_ctx *channel_ctx = + &transport_ctx.channel_ctx_table[FAKE_SERVICE_IDX_IN_BAND_TEST_CHANNEL]; + channel_ctx->locked = true; + + fwk_id_get_element_idx_ExpectAndReturn( + channel_id, FAKE_SERVICE_IDX_IN_BAND_TEST_CHANNEL); + + status = transport_transmit(channel_id, 0, payload, sizeof(payload), false); + + TEST_ASSERT_EQUAL(FWK_SUCCESS, status); + + uint8_t *dst_payload = (uint8_t *)channel_ctx->out->payload; + for (size_t i = 0; i < sizeof(payload); i++) { + TEST_ASSERT_EQUAL(payload[i], dst_payload[i]); + } +} + +void test_transport_transmit_valid_param_ob(void) +{ + int status; + + fwk_id_t channel_id = FWK_ID_ELEMENT_INIT( + FAKE_MODULE_ID, FAKE_SERVICE_IDX_OUT_BAND_TEST_CHANNEL); + char payload[] = "Test"; + + struct transport_channel_ctx *channel_ctx = + &transport_ctx + .channel_ctx_table[FAKE_SERVICE_IDX_OUT_BAND_TEST_CHANNEL]; + channel_ctx->locked = true; + + struct mod_transport_buffer *buffer = NULL; + buffer = ((struct mod_transport_buffer *) + channel_ctx->config->out_band_mailbox_address); + buffer->status = MOD_TRANSPORT_MAILBOX_STATUS_FREE_MASK; + + fwk_id_get_element_idx_ExpectAndReturn( + channel_id, FAKE_SERVICE_IDX_OUT_BAND_TEST_CHANNEL); + + status = transport_transmit(channel_id, 0, payload, sizeof(payload), false); + + TEST_ASSERT_EQUAL(FWK_SUCCESS, status); + + uint8_t *dst_payload = (uint8_t *)buffer->payload; + for (size_t i = 0; i < sizeof(payload); i++) { + TEST_ASSERT_EQUAL(payload[i], dst_payload[i]); + } +} + int scmi_test_main(void) { UNITY_BEGIN(); RUN_TEST(test_transport_payload_size); + + RUN_TEST(test_transport_write_payload_invalid_state_unlocked); RUN_TEST(test_transport_write_payload_invalid_param_null_payload); RUN_TEST(test_transport_write_payload_invalid_param_large_size); RUN_TEST(test_transport_write_payload_invalid_param_large_offset); @@ -208,6 +658,22 @@ int scmi_test_main(void) RUN_TEST(test_transport_write_payload_valid_param_start); RUN_TEST(test_transport_write_payload_valid_param_end); + RUN_TEST(test_transport_respond_invalid_state_null_buffer_ib); + RUN_TEST(test_transport_respond_invalid_state_null_buffer_ob); + RUN_TEST(test_transport_respond_invalid_param_large_size); + RUN_TEST(test_transport_respond_invalid_param_null_payload_ib); + RUN_TEST(test_transport_respond_invalid_param_null_payload_ob); + RUN_TEST(test_transport_respond_valid_param_ib); + RUN_TEST(test_transport_respond_valid_param_ob); + + RUN_TEST(test_transport_transmit_invalid_state_null_buffer_ib); + RUN_TEST(test_transport_transmit_invalid_state_null_buffer_ob); + RUN_TEST(test_transport_transmit_invalid_param_large_size); + RUN_TEST(test_transport_transmit_invalid_param_null_payload_ib); + RUN_TEST(test_transport_transmit_invalid_param_null_payload_ob); + RUN_TEST(test_transport_transmit_valid_param_ib); + RUN_TEST(test_transport_transmit_valid_param_ob); + return UNITY_END(); }