Branch data Line data Source code
1 : : /**
2 : : * Copyright Notice:
3 : : * Copyright 2021-2026 DMTF. All rights reserved.
4 : : * License: BSD 3-Clause License. For full text see link: https://github.com/DMTF/libspdm/blob/main/LICENSE.md
5 : : **/
6 : :
7 : : #include "internal/libspdm_responder_lib.h"
8 : :
9 : 60 : libspdm_return_t libspdm_responder_handle_response_state(libspdm_context_t *spdm_context,
10 : : uint8_t request_code,
11 : : size_t *response_size,
12 : : void *response)
13 : : {
14 : : libspdm_return_t status;
15 : :
16 [ + + + + ]: 60 : switch (spdm_context->response_state) {
17 : 25 : case LIBSPDM_RESPONSE_STATE_BUSY:
18 : 25 : return libspdm_generate_error_response(spdm_context, SPDM_ERROR_CODE_BUSY,
19 : : 0, response_size, response);
20 : : /* NOTE: Need to reset status to Normal in the upper layer*/
21 : 19 : case LIBSPDM_RESPONSE_STATE_NEED_RESYNC:
22 : 19 : status = libspdm_generate_error_response(spdm_context,
23 : : SPDM_ERROR_CODE_REQUEST_RESYNCH, 0,
24 : : response_size, response);
25 [ - + ]: 19 : if (LIBSPDM_STATUS_IS_ERROR(status)) {
26 : 0 : return status;
27 : : }
28 : : /* NOTE: Need to let GET_VERSION reset the State*/
29 : 19 : libspdm_set_connection_state(spdm_context,
30 : : LIBSPDM_CONNECTION_STATE_NOT_STARTED);
31 : 19 : return LIBSPDM_STATUS_SUCCESS;
32 : : #if LIBSPDM_RESPOND_IF_READY_SUPPORT
33 : 15 : case LIBSPDM_RESPONSE_STATE_NOT_READY:
34 : : /* Do not update ErrorData if a previous request has not been completed.
35 : : *
36 : : * Only one deferred (ResponseNotReady) request is tracked per connection. A Requester shall
37 : : * not have multiple outstanding requests to the same Responder within a connection (the only
38 : : * exceptions are GET_VERSION and the large-message / CHUNK_SEND pair). A request awaiting its
39 : : * RESPOND_IF_READY completion is still outstanding, so a conformant Requester will not issue
40 : : * another request - in another session or otherwise - until this one completes. A Responder
41 : : * is not required to process more than one request message at a time, even across
42 : : * connections, so a single context-wide cache is sufficient and conformant. */
43 [ + + ]: 15 : if (request_code != SPDM_RESPOND_IF_READY) {
44 : 13 : spdm_context->cache_spdm_request_size = spdm_context->last_spdm_request_size;
45 : 13 : libspdm_copy_mem(spdm_context->cache_spdm_request,
46 : 13 : libspdm_get_scratch_buffer_cache_spdm_request_capacity(spdm_context),
47 : 13 : spdm_context->last_spdm_request,
48 : : spdm_context->last_spdm_request_size);
49 : : /* Record the session context of the original request. The validity of the
50 : : * RESPOND_IF_READY request is defined by the original request that caused the
51 : : * RESPOND_IF_READY flow, so the matching RESPOND_IF_READY must arrive in the same
52 : : * session context. */
53 : 13 : spdm_context->cache_spdm_request_session_id_valid =
54 : 13 : spdm_context->last_spdm_request_session_id_valid;
55 : 13 : spdm_context->cache_spdm_request_session_id =
56 : 13 : spdm_context->last_spdm_request_session_id;
57 : 13 : spdm_context->error_data.rd_exponent = 1;
58 : 13 : spdm_context->error_data.rd_tm = 1;
59 : 13 : spdm_context->error_data.request_code = request_code;
60 : 13 : spdm_context->error_data.token = spdm_context->current_token++;
61 : : }
62 : 15 : return libspdm_generate_extended_error_response(
63 : : spdm_context, SPDM_ERROR_CODE_RESPONSE_NOT_READY, 0,
64 : : sizeof(spdm_error_data_response_not_ready_t),
65 : 15 : (uint8_t *)(void *)&spdm_context->error_data,
66 : : response_size, response);
67 : : #endif /* LIBSPDM_RESPOND_IF_READY_SUPPORT */
68 : 1 : default:
69 : 1 : return LIBSPDM_STATUS_SUCCESS;
70 : : }
71 : : }
|