static void conn_autocommit_event(int fd, short event, void *_userdata) { struct maria_status *ms = (struct maria_status *)_userdata; MYSQL *conn = (MYSQL *)ms->data; lua_State *L = ms->L; int errorcode = mysql_errno(conn); if (errorcode) { FAN_RESUME(L, NULL, luamariadb_push_errno(L, ms->conn_data)); UNREF_CO(ms->conn_data); } else { my_bool ret = 0; int status = mysql_autocommit_cont(&ret, conn, ms->status); if (status) { wait_for_status(L, ms->conn_data, conn, status, conn_autocommit_event, ms->extra); } else if (ret == 0) { lua_pushboolean(L, true); FAN_RESUME(L, NULL, 1); UNREF_CO(ms->conn_data); } else { FAN_RESUME(L, NULL, luamariadb_push_errno(L, ms->conn_data)); UNREF_CO(ms->conn_data); } } event_free(ms->event); free(ms); }
static void stmt_send_long_data_event(int fd, short event, void *_userdata) { struct maria_status *ms = (struct maria_status *)_userdata; st_data *st = (st_data *)ms->data; lua_State *L = ms->L; int errorcode = mysql_stmt_errno(st->my_stmt); if (errorcode) { FAN_RESUME(L, NULL, luamariadb_push_stmt_error(L, st)); UNREF_CO(st); } else { my_bool ret = 0; int status = mysql_stmt_send_long_data_cont(&ret, st->my_stmt, ms->status); if (status) { wait_for_status(L, st->conn_data, st, status, stmt_send_long_data_event, ms->extra); } else if (ret == 0) { int count = stmt_send_long_data_result(L, st); FAN_RESUME(L, NULL, count); UNREF_CO(st); } else { FAN_RESUME(L, NULL, luamariadb_push_stmt_error(L, st)); UNREF_CO(st); } } event_free(ms->event); free(ms); }
/******************************************************************************* * Function Name: nack_detected * Description : Check if a '0' was not issued in ack bit time slot. This is * called a "NACK". * Arguments : channel - * Which RIIC channel to use * Return Value : RIIC_OK - * No NACK detected. * RIIC_BUSY_TMO - * Channel is busy. Timeout occurred. * RIIC_STOP_TMO - * Timeout waiting for detection of stop condition. * RIIC_NACK_ERR - * NACK detected. *******************************************************************************/ static riic_ret_t nack_detected(uint8_t channel) { volatile uint8_t tmp; /* If NACK error, request a stop. */ if (1 == (*g_riic_channels[channel]).ICSR2.BIT.NACKF) { /* NACK detected. */ (*g_riic_channels[channel]).ICSR2.BIT.NACKF = 0; (*g_riic_channels[channel]).ICSR2.BIT.STOP = 0; /* Issue stop. */ (*g_riic_channels[channel]).ICCR2.BIT.SP = 1; /* Do a dummy read. (See Master Reception flowchart.) */ tmp = (*g_riic_channels[channel]).ICDRR; /* Wait for a detected stop condition. */ if(RIIC_OK != wait_for_status(channel, RIIC_STOP_TMO)) { return RIIC_STOP_TMO; } if(RIIC_OK != wait_for_status(channel, RIIC_BUSY_TMO)) { return RIIC_BUSY_TMO; } (*g_riic_channels[channel]).ICSR2.BIT.STOP = 0; return RIIC_NACK_ERR; } else { /* No NACK detected. */ return RIIC_OK; } } /* End of function nack_detected() */
LUA_API int conn_autocommit_start(lua_State *L) { conn_data *conn = getconnection(L); my_bool auto_mode = lua_toboolean(L, 2); my_bool ret = 0; int status = mysql_autocommit_start(&ret, &conn->my_conn, auto_mode); if (status) { REF_CO(conn); wait_for_status(L, conn, &conn->my_conn, status, conn_autocommit_event, 0); return lua_yield(L, 0); } else if (ret == 0) { lua_pushboolean(L, true); return 1; } else { return luamariadb_push_errno(L, conn); } }
LUA_API int set_character_set_start(lua_State *L) { conn_data *conn = getconnection(L); const char *charset = luaL_checkstring(L, 2); int ret = 0; int status = mysql_set_character_set_start(&ret, &conn->my_conn, charset); if (status) { REF_CO(conn); wait_for_status(L, conn, &conn->my_conn, status, set_character_set_cont, 0); return lua_yield(L, 0); } else if (ret == 0) { lua_pushboolean(L, 1); return 1; } else { return luamariadb_push_errno(L, conn); } }
/******************************************************************************* * Function Name: riic_tx_byte * Description : Transmits one byte in master mode over RIIC channel * Arguments : channel - * Which RIIC channel to use * tx_data - * Byte to transmit * Return Value : RIIC_OK - * Byte transmitted successfully. * RIIC_TDRE_TMO - * Timeout occured waiting for last transfer to finish. * RIIC_NACK_ERR - * NACK detected. *******************************************************************************/ static riic_ret_t riic_master_tx_byte(uint8_t channel, uint8_t tx_data) { riic_ret_t result = RIIC_OK; /* Wait for TDRE status. */ result = wait_for_status(channel, RIIC_TDRE_TMO); /* Proceed with write. */ if (RIIC_OK == result) { /* Copying data to the TX register starts transmission. */ (*g_riic_channels[channel]).ICDRT = (uint8_t)(tx_data); /* Check for NACK. */ result = nack_detected(channel); } return result; } /* End of function riic_tx_byte() */
LUA_API int stmt_close_start(lua_State *L, st_data *st) { st->closed = 1; my_bool ret = 0; int status = mysql_stmt_close_start(&ret, st->my_stmt); if (status) { REF_CO(st); wait_for_status(L, st->conn_data, st, status, stmt_close_cont, 0); return lua_yield(L, 0); } else if (ret == 0) { luaL_unref(L, LUA_REGISTRYINDEX, st->table); lua_pushboolean(L, 1); return 1; } else { return luamariadb_push_errno(L, st->conn_data); } return 0; }
LUA_API int st_send_long_data(lua_State *L) { st_data *st = getstatement(L); size_t size = 0; int num = luaL_checkinteger(L, 2); const char *data = luaL_checklstring(L, 3, &size); my_bool ret = 0; int status = mysql_stmt_send_long_data_start(&ret, st->my_stmt, num, data, size); if (status) { REF_CO(st); wait_for_status(L, st->conn_data, st, status, stmt_send_long_data_event, 0); return lua_yield(L, 0); } else if (ret == 0) { return stmt_send_long_data_result(L, st); } else { return luamariadb_push_stmt_error(L, st); } }
static void stmt_close_cont(int fd, short event, void *_userdata) { struct maria_status *ms = (struct maria_status *)_userdata; lua_State *L = ms->L; st_data *st = (st_data *)ms->data; my_bool ret = 0; int status = mysql_stmt_close_cont(&ret, st->my_stmt, ms->status); if (status) { wait_for_status(L, st->conn_data, st, status, stmt_close_cont, ms->extra); } else if (ret == 0) { luaL_unref(L, LUA_REGISTRYINDEX, st->table); lua_pushboolean(L, 1); FAN_RESUME(L, NULL, 1); UNREF_CO(st); } else { luaL_unref(L, LUA_REGISTRYINDEX, st->table); FAN_RESUME(L, NULL, luamariadb_push_errno(L, ms->conn_data)); UNREF_CO(st); } }
static void set_character_set_cont(int fd, short event, void *_userdata) { struct maria_status *ms = (struct maria_status *)_userdata; MYSQL *conn = (MYSQL *)ms->data; lua_State *L = ms->L; int ret = 0; int status = mysql_set_character_set_cont(&ret, conn, ms->status); if (status) { wait_for_status(L, ms->conn_data, conn, status, set_character_set_cont, ms->extra); } else if (ret == 0) { lua_pushboolean(L, 1); FAN_RESUME(L, NULL, 1); UNREF_CO(ms->conn_data); } else { FAN_RESUME(L, NULL, luamariadb_push_errno(L, ms->conn_data)); UNREF_CO(ms->conn_data); } event_free(ms->event); free(ms); }
/******************************************************************************* * Function Name: R_RIIC_MasterReceive * Description : Receive data over RIIC. * : Supports entry on start or restart conditions. * : For entry on restart condition, R_RIIC_MasterTransmitHead() should * : already have been called before this. * Arguments : channel - * Which RIIC channel to use * slave_addr - * Slave address * p_data_buff - * Pointer to data buffer * num_bytes - * Number of bytes to read * Return Value : RIIC_OK - * Operation completed successfully. * RIIC_LOCKED - * This task has not locked this RIIC channel yet. * RIIC_BUSY_TMO - * Channel is busy. Timeout occurred. * RIIC_TDRE_TMO - * Timeout occured waiting for last transfer to finish. * RIIC_TEND_TMO - * Timeout occurred waiting for data to finish transmitting. * RIIC_STOP_TMO - * Timeout waiting for detection of stop condition. * RIIC_START_TMO - * Timeout waiting for detection of start condition * RIIC_RDRF_TMO - * Timeout waiting for receive data * RIIC_NACK_ERR - * NACK received. * RIIC_LOCKED - * RIIC channel was already locked for another operation. * RIIC_NO_CHANNEL - * Channel requested is not a valid RIIC channel. *******************************************************************************/ riic_ret_t R_RIIC_MasterReceive(uint8_t channel, uint8_t slave_addr, uint8_t * p_data_buff, const uint32_t num_bytes) { /* Return value */ riic_ret_t ret = RIIC_OK; /* Loop variable */ uint32_t count = 1; if(RIIC_IDLE_MODE == g_riic_mode[channel]) { if(RIIC_OK != wait_for_status(channel, RIIC_BUSY_TMO)) { return RIIC_BUSY_TMO; } (*g_riic_channels[channel]).ICSR2.BIT.START = 0; /* Issue start condition. */ (*g_riic_channels[channel]).ICCR2.BIT.ST = 1; } else if (MASTER_TRANSMIT_MODE == g_riic_mode[channel]) { /* Test to see if this channel is already locked. It should be since the mode is not IDLE. R_RIIC_MasterTransmitHead() must have been called before this function and it should already have locked the channel. If this returns that the lock was obtained then a function called this one out-of-turn. */ if ( RIIC_OK == riic_lock(channel)) { /* This function was called out-of-turn. */ /* Give up lock */ riic_unlock(channel); return RIIC_LOCKED; } /* Issue re-start condition. */ (*g_riic_channels[channel]).ICSR2.BIT.START = 0; (*g_riic_channels[channel]).ICCR2.BIT.RS = 1; } else { riic_unlock(channel); return RIIC_MODE_ERR; } if(RIIC_OK != wait_for_status(channel, RIIC_START_TMO)) { /* Give up lock */ riic_unlock(channel); return RIIC_START_TMO; } /* Wait for TDRE status. */ if(RIIC_OK != wait_for_status(channel, RIIC_TDRE_TMO)) { /* Give up lock */ riic_unlock(channel); return RIIC_TDRE_TMO; } /*** Send slave address + READ-bit (b7). ***/ (*g_riic_channels[channel]).ICDRT = slave_addr | 0x01; /* Wait for receive data ready status. */ if(RIIC_OK != wait_for_status(channel, RIIC_RDRF_TMO)) { /* Give up lock */ riic_unlock(channel); return RIIC_RDRF_TMO; } /* Check for NACK */ ret = nack_detected(channel); if (RIIC_OK != ret) { /* Give up lock */ riic_unlock(channel); return ret; } /* Dummy read ICDRR. Starts outputting clocks to perform real read. */ (*g_riic_channels[channel]).ICDRR; while (count < (num_bytes)) { /* Wait for receive data ready status. */ if(RIIC_OK != wait_for_status(channel, RIIC_RDRF_TMO)) { /* Give up lock */ riic_unlock(channel); return RIIC_RDRF_TMO; } /* Set the WAIT bit - (The period between ninth clock cycle and first clock cycle is held low.) Low-hold is released by reading ICDRR.*/ if(count == (num_bytes - 2)) { (*g_riic_channels[channel]).ICMR3.BIT.WAIT = 1; } /* Set bit to send NACK */ else if (count == (num_bytes - 1)) { (*g_riic_channels[channel]).ICMR3.BIT.ACKBT = 1; } else { /* Do nothing. */ } /* Copy data to application read buffer, and increment its pointer. */ *p_data_buff = (*g_riic_channels[channel]).ICDRR; p_data_buff++; count++; } /* If num_bytes is 1 then the while loop above will be skipped. The ACKBT bit still needs to be set. */ if (num_bytes <= 1) { /* Set bit to send NACK */ (*g_riic_channels[channel]).ICMR3.BIT.ACKBT = 1; } if(RIIC_OK != wait_for_status(channel, RIIC_RDRF_TMO)) { /* Give up lock */ riic_unlock(channel); return RIIC_RDRF_TMO; } /* Issue Stop. */ (*g_riic_channels[channel]).ICSR2.BIT.STOP = 0; (*g_riic_channels[channel]).ICCR2.BIT.SP = 1; /* Read final byte. */ *p_data_buff = (*g_riic_channels[channel]).ICDRR; (*g_riic_channels[channel]).ICMR3.BIT.WAIT = 0; /* Wait for a detected stop condition. */ if(RIIC_OK != wait_for_status(channel, RIIC_STOP_TMO)) { /* Give up lock */ riic_unlock(channel); ret = RIIC_STOP_TMO; } (*g_riic_channels[channel]).ICSR2.BIT.NACKF = 0; (*g_riic_channels[channel]).ICSR2.BIT.STOP = 0; /* Give up lock */ riic_unlock(channel); g_riic_mode[channel] = RIIC_IDLE_MODE; return ret; } /* End of function R_RIIC_MasterReceive() */
/******************************************************************************* * Function Name: R_RIIC_MasterTransmit * Description : Transmits data over RIIC. R_RIIC_MasterTransmitHead() should * already have been called before this * Arguments : channel - * Which RIIC channel to use * p_data_buff - * Pointer to data buffer * num_bytes - * Number of bytes to transmit * If num_bytes = 0, then only the stop is processed. * Return Value : RIIC_OK - * Operation completed successfully. * RIIC_BUSY_TMO - * Channel is busy. Timeout occurred. * RIIC_TDRE_TMO - * Timeout occured waiting for last transfer to finish. * RIIC_TEND_TMO - * Timeout occurred waiting for data to finish transmitting. * RIIC_STOP_TMO - * Timeout waiting for detection of stop condition. * RIIC_LOCKED - * RIIC channel was already locked for another operation. * RIIC_NO_CHANNEL - * Channel requested is not a valid RIIC channel. *******************************************************************************/ riic_ret_t R_RIIC_MasterTransmit(uint8_t channel, uint8_t * p_data_buff, const uint32_t num_bytes) { uint32_t count; /* Local loop counter variable. */ riic_ret_t ret = RIIC_OK;/* Return value */ /* Test to see if this channel is already locked. It should be since R_RIIC_MasterTransmitHead() must be called before this function and it should already have locked the channel. If this returns that the lock was obtained then a function called this one out-of-turn. */ if (RIIC_OK == riic_lock(channel)) { /* This function was called out-of-turn. */ /* Give up lock */ riic_unlock(channel); return RIIC_LOCKED; } if(num_bytes > 0) /* Skip ahead and just do the Stop otherwise */ { /* Transmit data. */ for (count = 0; count < num_bytes; count++) { /* Send 1 byte at a time */ ret = riic_master_tx_byte(channel, p_data_buff[count]); /* Check result. */ if (RIIC_OK != ret) { /* Give up lock */ riic_unlock(channel); return ret; } } /* Wait for transmission completed status. */ if(RIIC_OK != wait_for_status(channel, RIIC_TEND_TMO)) { /* Give up lock */ riic_unlock(channel); return RIIC_TEND_TMO; } /* Check for NACK */ ret = nack_detected(channel); if (RIIC_OK != ret) { /* Give up lock */ riic_unlock(channel); return ret; } } /* Request to issue a stop condition. */ (*g_riic_channels[channel]).ICSR2.BIT.STOP = 0; (*g_riic_channels[channel]).ICCR2.BIT.SP = 1; /* Wait for a detected stop condition. */ ret = wait_for_status(channel, RIIC_STOP_TMO); if (RIIC_OK != ret) { /* Give up lock */ riic_unlock(channel); return ret; } /* Clear status before exit. */ (*g_riic_channels[channel]).ICSR2.BIT.NACKF = 0; (*g_riic_channels[channel]).ICSR2.BIT.STOP = 0; /* Give up lock */ riic_unlock(channel); g_riic_mode[channel] = RIIC_IDLE_MODE; return RIIC_OK; } /* End of function R_RIIC_MasterTransmit() */
/******************************************************************************* * Function Name: R_RIIC_MasterTransmitHead * Description : Transmits header information on I2C bus to precede other write * or read operations. Starts out a transmission with a start * condition but does not end with a stop. Leaves bus state ready * for continuing operations. * Parameters : source_buf - * Pointer to the buffer holding the data to be transmitted. * nr_bytes - * The number of bytes to transmit. * Return Value : RIIC_OK - * Operation completed successfully. * RIIC_BUSY_TMO - * Channel is busy. Timeout occurred. * RIIC_TDRE_TMO - * Timeout occured waiting for last transfer to finish. * RIIC_TEND_TMO - * Timeout occurred waiting for data to finish transmitting. * RIIC_STOP_TMO - * Timeout waiting for detection of stop condition. * RIIC_LOCKED - * RIIC channel was already locked for another operation. * RIIC_NO_CHANNEL - * Channel requested is not a valid RIIC channel. * RIIC_NACK_ERR - * Got a NACK when an ACK was expected. *******************************************************************************/ riic_ret_t R_RIIC_MasterTransmitHead(uint8_t channel, uint8_t * p_data_buff, const uint32_t num_bytes) { uint32_t count; /* Local loop counter variable. */ /* Return value */ riic_ret_t ret = RIIC_OK; /* Try to lock this channel. */ ret = riic_lock(channel); /* Check result */ if ( RIIC_OK != ret ) { /* Either already locked or invalid channel. */ return ret; } /* Wait for RIIC bus free. */ if(RIIC_OK != wait_for_status(channel, RIIC_BUSY_TMO)) { /* Give up lock */ riic_unlock(channel); return RIIC_BUSY_TMO; } /* Generate start condition. */ (*g_riic_channels[channel]).ICCR2.BIT.ST = 1; /* Check for NACK */ ret = nack_detected(channel); if (RIIC_OK != ret) { /* Give up lock */ riic_unlock(channel); return ret; } /* Transmit header. */ for (count = 0; count < num_bytes; count++) { /* Aspetto il bus libero prima di trasmettere il dato successivo? */ //wait_for_status(channel, RIIC_BUSY_TMO); /* Aspetto lo stato alto della sola linea dati * Provare con e senza **/ wait_for_status(channel, RIIC_DATA_HIGH); /* Send 1 byte at a time */ ret = riic_master_tx_byte(channel, p_data_buff[count]); /* Check result. */ if (RIIC_OK != ret) { /* Give up lock */ riic_unlock(channel); return ret; } /* AAA Wait for complete end of transmission status. * intra bytes transmission * Provare con e senza... * */ if(num_bytes >= 2 && count < (num_bytes - 1)) wait_for_status(channel, RIIC_TEND_TMO); } /* Wait for complete end of transmission status. */ ret = wait_for_status(channel, RIIC_TEND_TMO); if(RIIC_OK != ret) { ret |= RIIC_TEND_TMO; /* If NACK detected, it issues stop to complete the transmission. */ ret |= nack_detected(channel); /* Give up lock */ riic_unlock(channel); return ret; } /* Check for NACK */ ret = nack_detected(channel); if (RIIC_OK != ret) { /* Give up lock */ riic_unlock(channel); } /* Since this is just sending the header, riic_unlock() will be called later from R_RIIC_MasterReceive() or R_RIIC_MasterTransmit(). */ g_riic_mode[channel] = MASTER_TRANSMIT_MODE; return ret; } /* End of function R_RIIC_MasterTransmitHead() */
int state_config( int fd, int itf, Msgs *msgs ){ Message *tmp; int newstate = S1; diag( COMPONENT, DIAG_INFO, "State S4: config" ); ilmi_state = down; if( config->atmfAtmLayerUniVersion == 0 ){ diag( COMPONENT, DIAG_ERROR, "remote IME did not negotiate " "a UNI version -- using configured uni version." ); } else if( config->atmfAtmLayerUniVersion < atmfAtmLayerUniVersionValue ){ diag( COMPONENT, DIAG_ERROR, "remote IME does not support" " the locally configured uni version" ); atmfAtmLayerUniVersionValue = config->atmfAtmLayerUniVersion; } if( config->atmfAtmLayerDeviceType == 2 /* NODE */ ){ action_A6( fd, msgs ); /* stop timer */ action_A10( fd, msgs ); /* Start signalling */ action_A14( fd, msgs ); /* request address status */ action_A7( fd, msgs ); /* retries = 0 */ action_A5( fd, msgs ); /* start timer */ newstate = S5; /* retrieve network prefixes */ } else if( config->atmfAtmLayerDeviceType == 1 /* USER */ ){ diag( COMPONENT, DIAG_ERROR, "Remote device is also a host" ); action_A10( fd, msgs ); /* start signalling */ action_A14( fd, msgs ); /* get next prefix */ action_A7( fd, msgs ); /* retries = 0 */ action_A5( fd, msgs ); /* start timer */ newstate = S6; } else if( config->atmfAtmLayerDeviceType == 0 /* ??? */ ){ diag( COMPONENT, DIAG_ERROR, "Remote IME does not know " "what type of device it is -- assume NODE" ); action_A6( fd, msgs ); /* stop timer */ action_A10( fd, msgs ); /* Start signalling */ action_A14( fd, msgs ); /* request address status */ action_A7( fd, msgs ); /* retries = 0 */ action_A5( fd, msgs ); /* start timer */ newstate = S5; /* retrieve network prefixes */ } while(( tmp = wait_for_status( fd, itf, msgs )) == NULL ){ if( ilmi_errno == ETIMEOUT ){ action_A14( fd, msgs ); /* request address status */ action_A8( fd, msgs ); /* retries++ */ action_A5( fd, msgs ); /* start timer */ } else if( ilmi_errno == ECOLDSTART ){ return S1; } } action_get_sysgroup( fd, msgs ); while(( tmp = wait_for_sysgroup( fd, itf, msgs )) == NULL ){ if( ilmi_errno == ETIMEOUT ){ action_get_sysgroup( fd, msgs ); action_A8( fd, msgs ); /* retries++ */ action_A5( fd, msgs ); /* start timer */ } else if( ilmi_errno == ECOLDSTART ){ return S1; } } return newstate; }
size_t tpm2_process_command(const void *tpm2_command, size_t command_size, void *tpm2_response, size_t max_response) { uint32_t status; uint32_t expected_status_bits; size_t payload_size; size_t bytes_to_go; const uint8_t *cmd_body = tpm2_command; uint8_t *rsp_body = tpm2_response; union fifo_transfer_buffer fifo_buffer; const int HEADER_SIZE = 6; struct tpm2_info *tpm_info = car_get_var_ptr(&g_tpm_info); /* Do not try using an uninitialized TPM. */ if (!tpm_info->vendor_id) return 0; /* Skip the two byte tag, read the size field. */ payload_size = read_be32(cmd_body + 2); /* Sanity check. */ if (payload_size != command_size) { printk(BIOS_ERR, "Command size mismatch: encoded %zd != requested %zd\n", payload_size, command_size); trace_dump("W", TPM_DATA_FIFO_REG, command_size, cmd_body, 1); printk(BIOS_DEBUG, "\n"); return 0; } /* Let the TPM know that the command is coming. */ write_tpm_sts(TPM_STS_COMMAND_READY); /* * TPM commands and responses written to and read from the FIFO * register (0x24) are datagrams of variable size, prepended by a 6 * byte header. * * The specification description of the state machine is a bit vague, * but from experience it looks like there is no need to wait for the * sts.expect bit to be set, at least with the 9670 and cr50 devices. * Just write the command into FIFO, making sure not to exceed the * burst count or the maximum PDU size, whatever is smaller. */ fifo_buffer.tx_buffer = cmd_body; fifo_transfer(command_size, fifo_buffer, fifo_transmit); /* Now tell the TPM it can start processing the command. */ write_tpm_sts(TPM_STS_GO); /* Now wait for it to report that the response is ready. */ expected_status_bits = TPM_STS_VALID | TPM_STS_DATA_AVAIL; if (!wait_for_status(expected_status_bits, expected_status_bits)) { /* * If timed out, which should never happen, let's at least * print out the offending command. */ trace_dump("W", TPM_DATA_FIFO_REG, command_size, cmd_body, 1); printk(BIOS_DEBUG, "\n"); return 0; } /* * The response is ready, let's read it. First we read the FIFO * payload header, to see how much data to expect. The response header * size is fixed to six bytes, the total payload size is stored in * network order in the last four bytes. */ tpm2_read_reg(TPM_DATA_FIFO_REG, rsp_body, HEADER_SIZE); /* Find out the total payload size, skipping the two byte tag. */ payload_size = read_be32(rsp_body + 2); if (payload_size > max_response) { /* * TODO(vbendeb): at least drain the FIFO here or somehow let * the TPM know that the response can be dropped. */ printk(BIOS_ERR, " TPM response too long (%zd bytes)", payload_size); return 0; } /* * Now let's read all but the last byte in the FIFO to make sure the * status register is showing correct flow control bits: 'more data' * until the last byte and then 'no more data' once the last byte is * read. */ bytes_to_go = payload_size - 1 - HEADER_SIZE; fifo_buffer.rx_buffer = rsp_body + HEADER_SIZE; fifo_transfer(bytes_to_go, fifo_buffer, fifo_receive); /* Verify that there is still data to read. */ read_tpm_sts(&status); if ((status & expected_status_bits) != expected_status_bits) { printk(BIOS_ERR, "unexpected intermediate status %#x\n", status); return 0; } /* Read the last byte of the PDU. */ tpm2_read_reg(TPM_DATA_FIFO_REG, rsp_body + payload_size - 1, 1); /* Terminate the dump, if enabled. */ if (debug_level_) printk(BIOS_DEBUG, "\n"); /* Verify that 'data available' is not asseretd any more. */ read_tpm_sts(&status); if ((status & expected_status_bits) != TPM_STS_VALID) { printk(BIOS_ERR, "unexpected final status %#x\n", status); return 0; } /* Move the TPM back to idle state. */ write_tpm_sts(TPM_STS_COMMAND_READY); return payload_size; }