bool Service::intrTaskWait(msg_t * & o_msg) { // wait for a shutdown message // or an interrupt bool shutdown = false; msg_q_t q = iv_intrTaskQ; o_msg = msg_wait(q); ATTN_FAST("...intr task woke up"); shutdown = o_msg->type == SHUTDOWN; if(shutdown) { // this was a shutdown message. // ack the message and tell the // task loop to exit iv_intrTaskQ = 0; iv_shutdownPrdTask = true; msg_respond(q, o_msg); ATTN_FAST("interrupt task shutting down"); } return shutdown; }
void SyncMessage::response(msg_q_t i_msgQ) { errlHndl_t err = NULL; // Send the response to the original caller of sendrecv() int rc = msg_respond(i_msgQ, iv_msg); if (rc) { TRACFCOMP( g_trac_trustedboot, ERR_MRK "SyncMessage::response msg_respond failure %d", rc); /*@ * @errortype ERRL_SEV_UNRECOVERABLE * @moduleid MOD_TPM_SYNCRESPONSE * @reasoncode RC_MSGRESPOND_FAIL * @userdata1 rc from msq_respond() * @devdesc msg_respond() failed * @custdesc Firmware error during system boot */ err = new ERRORLOG::ErrlEntry(ERRORLOG::ERRL_SEV_UNRECOVERABLE, MOD_TPM_SYNCRESPONSE, RC_MSGRESPOND_FAIL, rc, 0, true); err->collectTrace(SECURE_COMP_NAME); err->collectTrace(TRBOOT_COMP_NAME); // Log this failure here since we can't reply to caller errlCommit(err, TRBOOT_COMP_ID); } }
/// /// @brief sync handle response /// void BTSyncMessage::response(msg_q_t i_msgQ) { // Send the response to the original caller of sendrecv() int rc = msg_respond(i_msgQ, iv_msg); if (rc) { // Not much we're going to do here, so lets commit an error and // the original request will timeout. IPMI_TRAC(ERR_MRK "msg_respond() i/o error (response) %d", rc); /*@ * @errortype ERRL_SEV_UNRECOVERABLE * @moduleid IPMI::MOD_IPMISRV_REPLY * @reasoncode IPMI::RC_INVALID_QRESPONSE * @userdata1 rc from msg_respond() * @devdesc msg_respond() failed * @custdesc Firmware error during system boot */ errlHndl_t err = new ERRORLOG::ErrlEntry( ERRORLOG::ERRL_SEV_UNRECOVERABLE, IPMI::MOD_IPMISRV_REPLY, IPMI::RC_INVALID_QRESPONSE, rc, 0, true); err->collectTrace(IPMI_COMP_NAME); errlCommit(err, IPMI_COMP_ID); // Frotz the response data delete[] iv_data; iv_data = NULL; } }
/// /// @brief sync msg transmit /// bool BTSyncMessage::xmit(void) { errlHndl_t err = BTMessage::phy_xmit(); if (err) { // Something went wrong, so we need to respond back with the error iv_errl = err; msg_q_t mq = Singleton<IpmiRP>::instance().msgQueue(); int rc = msg_respond(mq, iv_msg); if (rc) { // Yuk. We can't respond back to our caller with that error. So, // we'll commit it. I don't see much sense in creating another // error log, so we'll just trace the msg_respond() failure. IPMI_TRAC(ERR_MRK "msg_respond() i/o error (transmit) %d", rc); err->collectTrace(IPMI_COMP_NAME); errlCommit(err, IPMI_COMP_ID); iv_errl = NULL; } } // If we had an i/o error we want the idle loop to stop // If we got EAGAIN we want the idle loop to stop as we just // put a message on the queue which couldn't be sent. return (iv_state != 0); }
void* consoleDaemon(void* unused) { // Detach and register daemon with shutdown path. task_detach(); INITSERVICE::registerShutdownEvent(g_msgq, SYNC, INITSERVICE::CONSOLE_PRIORITY); // Create a default output UART device if there isn't already one. // - Some devices are registered via the CONSOLE_UART_DEFINE_DEVICE // macro and therefore don't need this. if (NULL == Uart::g_device) { Uart::g_device = new Uart(); Uart::g_device->initialize(); } while(1) { msg_t* msg = msg_wait(g_msgq); switch (msg->type) { case DISPLAY: { if (NULL != msg->extra_data) { char timestamp[11]; sprintf(timestamp, "%3d.%05d|", msg->data[0], // 5 Digits worth of ns. (msg->data[1]*100000)/NS_PER_SEC); _display(timestamp); _display( static_cast<const char*>(msg->extra_data)); free(msg->extra_data); } msg_free(msg); break; } case SYNC: { msg_respond(g_msgq, msg); break; } } } return NULL; }
//@todo: RTC 119832 void IpmiSEL::execute(void) { //Mark as an independent daemon so if it crashes we terminate. task_detach(); // Register shutdown events with init service. // Done at the "end" of shutdown processesing. // This will flush out any IPMI messages which were sent as // part of the shutdown processing. We chose MBOX priority // as we don't want to accidentally get this message after // interrupt processing has stopped in case we need intr to // finish flushing the pipe. INITSERVICE::registerShutdownEvent(iv_msgQ, IPMISEL::MSG_STATE_SHUTDOWN, INITSERVICE::MBOX_PRIORITY); barrier_wait(&iv_sync_start); while(true) { msg_t* msg = msg_wait(iv_msgQ); const IPMISEL::msg_type msg_type = static_cast<IPMISEL::msg_type>(msg->type); // Invert the "default" by checking here. This allows the compiler // to warn us if the enum has an unhadled case but still catch // runtime errors where msg_type is set out of bounds. assert(msg_type <= IPMISEL::MSG_LAST_TYPE, "msg_type %d not handled", msg_type); switch(msg_type) { case IPMISEL::MSG_SEND_ESEL: IPMISEL::process_esel(msg); //done with msg msg_free(msg); break; case IPMISEL::MSG_STATE_SHUTDOWN: IPMI_TRAC(INFO_MRK "ipmisel shutdown event"); //Respond that we are done shutting down. msg_respond(iv_msgQ, msg); break; } } // while(1) IPMI_TRAC(EXIT_MRK "message loop"); return; } // execute
/////////////////////////////////////////////////////////////////////////////// // ErrlManager::errlogMsgHndlr() /////////////////////////////////////////////////////////////////////////////// void ErrlManager::errlogMsgHndlr () { TRACFCOMP( g_trac_errl, ENTER_MRK "Enter ErrlManager::errlogMsgHndlr" ); while( 1 ) { msg_t * theMsg = msg_wait( iv_msgQ ); TRACFCOMP( g_trac_errl, INFO_MRK"Got an error log Msg - Type: 0x%08x", theMsg->type ); //Process message just received switch( theMsg->type ) { case ERRLOG_ACCESS_PNOR_TYPE: { // PNOR is up and running now. setupPnorInfo(); //We are done with the msg msg_free(theMsg); // go back and wait for a next msg break; } case ERRLOG_ACCESS_TARG_TYPE: { // TARGETING is up and running now. // do we NOT need to send the error? TARGETING::Target * sys = NULL; TARGETING::targetService().getTopLevelTarget( sys ); TARGETING::SpFunctions spfn; if (!(sys && sys->tryGetAttr<TARGETING::ATTR_SP_FUNCTIONS>(spfn) && spfn.baseServices)) { iv_isSpBaseServices = false; // if there are queued errors, clear the Mbox flag // since they will never be sent, which will delete // the errors that have been fully processed ErrlListItr_t it = iv_errlList.begin(); while(it != iv_errlList.end()) { // Mark MBOX processing complete _clearFlag(*it, MBOX_FLAG); _updateErrlListIter(it); } } //We are done with the msg msg_free(theMsg); // go back and wait for a next msg break; } case ERRLOG_ACCESS_MBOX_TYPE: { // MBOX is up and running now. // do we need to send the errorlog TARGETING::Target * sys = NULL; TARGETING::targetService().getTopLevelTarget( sys ); TARGETING::SpFunctions spfn; if (sys && sys->tryGetAttr<TARGETING::ATTR_SP_FUNCTIONS>(spfn) && spfn.mailboxEnabled) { iv_isMboxEnabled = true; } // if we're supposed to and can now send msgs, do it. if (iv_isSpBaseServices && iv_isMboxEnabled) { // Register messageQ with Mailbox to receive message. errlHndl_t l_err = MBOX::msgq_register( MBOX::HB_ERROR_MSGQ, iv_msgQ ); if( l_err ) { TRACFCOMP(g_trac_errl, ERR_MRK "Msg queue already registered"); delete( l_err ); l_err = NULL; //If we got an error then it means the message queue //is registered with mailbox. //This should not happen. So assert here. assert(0); } // if errors came in before MBOX was ready, // the errors would be on this list. send them now. ErrlListItr_t it = iv_errlList.begin(); while(it != iv_errlList.end()) { // Check if MBOX processing is needed if (_isFlagSet(*it, MBOX_FLAG)) { // send errlog sendErrLogToFSP(it->first); // Mark MBOX processing complete _clearFlag(*it, MBOX_FLAG); } _updateErrlListIter(it); } } else { // Delete errors that have been completely processed ErrlListItr_t it = iv_errlList.begin(); while(it != iv_errlList.end()) { // Mark MBOX processing complete _clearFlag(*it, MBOX_FLAG); _updateErrlListIter(it); } } //We are done with the msg msg_free(theMsg); // go back and wait for a next msg break; } case ERRLOG_ACCESS_IPMI_TYPE: { #ifdef CONFIG_BMC_IPMI // IPMI is up and running now. iv_isIpmiEnabled = true; // if we can now send msgs, do it. // if errors came in before IPMI was ready, // the errors would be on this list. send them now. ErrlListItr_t it = iv_errlList.begin(); while(it != iv_errlList.end()) { // Check if IPMI processing is needed if (_isFlagSet(*it, IPMI_FLAG)) { // send errorlog sendErrLogToBmc(it->first); // Mark IPMI processing complete _clearFlag(*it, IPMI_FLAG); } _updateErrlListIter(it); } #endif //We are done with the msg msg_free(theMsg); // go back and wait for a next msg break; } case ERRLOG_ACCESS_ERRLDISP_TYPE: { #ifdef CONFIG_CONSOLE_OUTPUT_ERRORDISPLAY // Errldisplay now ready iv_isErrlDisplayEnabled = true; CONSOLE::displayf("ERRL", "Dumping errors reported prior to registration"); // Display errlogs to errldisplay ErrlListItr_t it = iv_errlList.begin(); while(it != iv_errlList.end()) { // Check if ERRLDISP processing is needed if (_isFlagSet(*it, ERRLDISP_FLAG)) { ERRORLOGDISPLAY::errLogDisplay().msgDisplay (it->first, ((it->first->reasonCode()) & 0xFF00)); // Mark ERRLDISP processing complete _clearFlag(*it, ERRLDISP_FLAG); } _updateErrlListIter(it); } #endif //We are done with the msg msg_free(theMsg); break; } case ERRLOG_NEEDS_TO_BE_COMMITTED_TYPE: { // Extract error log handle from the message. We need the // error log handle to pass along errlHndl_t l_err = (errlHndl_t) theMsg->extra_data; // Ask the ErrlEntry to assign commit component, commit time l_err->commit( (compId_t) theMsg->data[0] ); // Pair with all flags set to add to the errlList ErrlFlagPair_t l_pair(l_err, ALL_FLAGS); #ifdef CONFIG_CONSOLE_OUTPUT_ERRORDISPLAY // Display errl to errldisplay if (iv_isErrlDisplayEnabled) { ERRORLOGDISPLAY::errLogDisplay().msgDisplay (l_err, ( (l_err->reasonCode()) & 0xFF00)); // Mark ERRLDISP processing complete on this error _clearFlag(l_pair, ERRLDISP_FLAG); } #endif //Save the error log to PNOR bool l_savedToPnor = saveErrLogToPnor(l_err); // Check if we actually saved the msg to PNOR if (l_savedToPnor) { // Mark PNOR processing complete on this error _clearFlag(l_pair, PNOR_FLAG); } #ifdef STORE_ERRL_IN_L3 //Write the error log to L3 memory //useful ONLY for the hb-errl tool saveErrLogEntry ( l_err ); #endif //Try to send the error log if someone is there to receive if (!iv_isSpBaseServices) { // Mark MBOX processing complete on this error _clearFlag(l_pair, MBOX_FLAG); } else if (iv_isSpBaseServices && iv_isMboxEnabled) { sendErrLogToFSP(l_err); // Mark MBOX processing complete on this error _clearFlag(l_pair, MBOX_FLAG); } #ifdef CONFIG_BMC_IPMI if (iv_isIpmiEnabled) { // convert to SEL/eSEL and send to BMC over IPMI sendErrLogToBmc(l_err); // Mark IPMI processing complete on this error _clearFlag(l_pair, IPMI_FLAG); } #endif //Ask the ErrlEntry to process any callouts l_err->processCallout(); //Ask if it is a terminating log if( l_err->isTerminateLog() ) { TRACFCOMP( g_trac_errl, INFO_MRK "Terminating error was committed" " errlmanager is reqesting a shutdown."); INITSERVICE::doShutdown(l_err->plid(), true); TRACDCOMP( g_trac_errl, INFO_MRK"shutdown in progress" ); } // If l_errl has not been fully proccessed delete it // otherwise add to list if (l_pair.second == 0) { delete l_err; l_err = NULL; } else { iv_errlList.push_back(l_pair); } //We are done with the msg msg_free(theMsg); // else go back and wait for a next msg break; } case ERRLOG_COMMITTED_ACK_RESPONSE_TYPE: { //Hostboot must keep track and clean up hostboot error //logs in PNOR after it is committed by FSP. uint32_t l_tmpPlid = theMsg->data[0]>>32; TRACFCOMP( g_trac_errl, INFO_MRK"ack: %.8x", l_tmpPlid); bool didAck = ackErrLogInPnor(l_tmpPlid); if (!didAck) { // couldn't find that errlog in PNOR, look in our // errlMsgList - maybe it's there waiting ErrlListItr_t it = std::find_if(iv_errlList.begin(), iv_errlList.end(), std::bind1st(ptr_fun(&compareEidToPlid) ,l_tmpPlid)); // Check if such errl was found if (it != iv_errlList.end()) { // We found the errlog // Mark PNOR processing complete _clearFlag(*it, PNOR_FLAG); _updateErrlListIter(it); } } msg_free(theMsg); // We didn't have room before in PNOR to save an // error log, so try now since we just ACKed one. ErrlListItr_t it = std::find_if(iv_errlList.begin(), iv_errlList.end(), bind2nd(ptr_fun(_isFlagSet), PNOR_FLAG)); // Check if such errl was found if (it != iv_errlList.end()) { bool l_savedToPnor = saveErrLogToPnor(it->first); // check if we actually saved the msg to PNOR if (l_savedToPnor) { // Mark PNOR processing complete _clearFlag(*it, PNOR_FLAG); _updateErrlListIter(it); } // else, still couldn't save it (for some reason) so // it's still on the list. } break; } case ERRLOG_SHUTDOWN_TYPE: TRACFCOMP( g_trac_errl, INFO_MRK "Shutdown event received" ); //Start shutdown process for error log errlogShutdown(); // Respond that we are done shutting down. msg_respond ( iv_msgQ, theMsg ); TRACFCOMP( g_trac_errl, INFO_MRK "Shutdown event processed" ); break; default: // Default Message TRACFCOMP( g_trac_errl, ERR_MRK "Unexpected message type 0x%08x", theMsg->type ); msg_free(theMsg); break; } // switch } //The errlogMsgHndlr should run all the time. It only //exits when error log message thread is killed. TRACFCOMP( g_trac_errl, EXIT_MRK "Exit ErrlManager::errlogMsgHndlr" ); return; }
errlHndl_t AttributeSync::syncSectionFromFsp( TARGETING::SECTION_TYPE i_section_to_sync, msg_q_t i_pMsgQ ) { TARG_INF( ENTER_MRK "AttributeSync::syncSectionFromFsp" ); errlHndl_t l_errl = NULL; bool l_sync_complete = false; ATTR_SYNC_RC l_rc = ATTR_SYNC_FAILURE; TARGETING::sectionRefData l_page; iv_section_to_sync = i_section_to_sync; memset( &l_page, 0, sizeof(TARGETING::sectionRefData) ); do{ if (!SECUREBOOT::allowAttrOverrides()) { TARG_INF("AttributeSync::syncSectionFromFsp(): skipping since " "attribute overrides are not allowed and we don't " "trust the FSP"); break; } // send a request to FSP to sync to Hostboot l_errl = sendSyncToHBRequestMessage(); if (l_errl) { break; } do{ // wait for FSP to send the section's attribute data TARG_DBG( "Wait for message from FSP"); msg_t * l_pMsg = msg_wait(i_pMsgQ); // process message just received if ( ATTR_SYNC_SECTION_TO_HB == l_pMsg->type ) { TARG_DBG( "HB Attribute Sync Section message type received " "from the FSP"); // get the section id l_page.sectionId = ATTR_SYNC_GET_SECTION_ID(l_pMsg->data[0]); // get the page number l_page.pageNumber = ATTR_SYNC_GET_PAGE_NUMBER(l_pMsg->data[0]); // save a pointer to the page l_page.dataPtr = reinterpret_cast<uint8_t *> (l_pMsg->extra_data); // Validate the data received. Ignore page if // section id or page size is incorrect or if // there are no page received since we cannot send // an error back to the FSP at this point. We will // check later whether the correct number of valid // pages for the section was received when FSP send // us the sync complete message. // if no page received if ( NULL == l_page.dataPtr) { TARG_ERR("WARNING: " "no attribute page received from FSP"); } // if it's not the requested section else if ( iv_section_to_sync != l_page.sectionId ) { TARG_ERR("WARNING: " "section type received from FSP = %u, expecting %u", l_page.sectionId, iv_section_to_sync); //Free the memory free(l_pMsg->extra_data); l_pMsg->extra_data = NULL; } // page size should always be 4K else if ( PAGESIZE != l_pMsg->data[1] ) { TARG_ERR("WARNING: " "page size received from FSP = %u, expecting 4K", l_pMsg->data[1]); free(l_pMsg->extra_data); l_pMsg->extra_data = NULL; } else { iv_pages.push_back(l_page); } // Free memory allocated for message msg_free( l_pMsg ); l_pMsg = NULL; } else if ( ATTR_SYNC_COMPLETE_TO_HB == l_pMsg->type ) { TARG_DBG( "HB Attribute Sync Complete message type " "received from the FSP"); l_sync_complete = true; iv_total_pages = ATTR_SYNC_GET_PAGE_COUNT( l_pMsg->data[0] ); // check that the total # of valid pages received is correct if ( iv_pages.size() == iv_total_pages ) { // write the section to the Attribute virtual address // space l_rc = updateSectionData(); if (l_rc) { TARG_ERR( "HB failed in writing the attribute section" ); } } else { TARG_ERR( "total # of valid pages received = %u, " "expecting %u", iv_pages.size(), iv_total_pages); l_rc = ATTR_SYNC_FAILURE; } if (l_rc) { /*@ * @errortype * @moduleid TARG_MOD_ATTR_SYNC * @reasoncode TARG_RC_ATTR_SYNC_TO_HB_FAIL * @userdata1 return code * @userdata2 section to sync * @devdesc The attribute synchronization from * the FSP failed. */ l_errl = new ErrlEntry(ERRL_SEV_UNRECOVERABLE, TARG_MOD_ATTR_SYNC, TARG_RC_ATTR_SYNC_TO_HB_FAIL, l_rc, iv_section_to_sync); } // send a msg back to FSP indicating success/failure l_pMsg->data[0] = 0; ATTR_SYNC_ADD_RC( l_rc, l_pMsg->data[0] ); int l_respond_rc = msg_respond(i_pMsgQ, l_pMsg); if (l_respond_rc) { // Just output a trace here since FSP should // handle error case where it doesn't receive // a response from HB. TARG_ERR( "WARNING: Bad rc from msg_respond: %d", l_respond_rc); msg_free( l_pMsg ); l_pMsg = NULL; } } else { TARG_ERR( "WARNING: Invalid message type [0x%x] received " "from the FSP, ignoring...", l_pMsg->type); msg_free( l_pMsg ); l_pMsg = NULL; } }while (false == l_sync_complete); // free memory if ( iv_pages.size() ) { for ( size_t i = 0; i < iv_pages.size(); i++ ) { free( iv_pages[i].dataPtr ); } iv_pages.clear(); } }while (0); TARG_INF( EXIT_MRK "AttributeSync::syncSectionFromFsp" ); return l_errl; }
/** * @brief Message receiver */ void PnorRP::waitForMessage() { TRACFCOMP(g_trac_pnor, "PnorRP::waitForMessage>" ); errlHndl_t l_errhdl = NULL; msg_t* message = NULL; uint8_t* user_addr = NULL; uint8_t* eff_addr = NULL; uint64_t dev_offset = 0; uint64_t chip_select = 0xF; bool needs_ecc = false; int rc = 0; uint64_t status_rc = 0; uint64_t fatal_error = 0; while(1) { status_rc = 0; TRACUCOMP(g_trac_pnor, "PnorRP::waitForMessage> waiting for message" ); message = msg_wait( iv_msgQ ); if( message ) { /* data[0] = virtual address requested * data[1] = address to place contents */ eff_addr = (uint8_t*)message->data[0]; user_addr = (uint8_t*)message->data[1]; //figure out the real pnor offset l_errhdl = computeDeviceAddr( eff_addr, dev_offset, chip_select, needs_ecc ); if( l_errhdl ) { status_rc = -EFAULT; /* Bad address */ } else { switch(message->type) { case( MSG_MM_RP_READ ): l_errhdl = readFromDevice( dev_offset, chip_select, needs_ecc, user_addr, fatal_error ); if( l_errhdl || ( 0 != fatal_error ) ) { status_rc = -EIO; /* I/O error */ } break; case( MSG_MM_RP_WRITE ): l_errhdl = writeToDevice( dev_offset, chip_select, needs_ecc, user_addr ); if( l_errhdl ) { status_rc = -EIO; /* I/O error */ } break; default: TRACFCOMP( g_trac_pnor, "PnorRP::waitForMessage> Unrecognized message type : user_addr=%p, eff_addr=%p, msgtype=%d", user_addr, eff_addr, message->type ); /*@ * @errortype * @moduleid PNOR::MOD_PNORRP_WAITFORMESSAGE * @reasoncode PNOR::RC_INVALID_MESSAGE_TYPE * @userdata1 Message type * @userdata2 Requested Virtual Address * @devdesc PnorRP::waitForMessage> Unrecognized * message type * @custdesc A problem occurred while accessing * the boot flash. */ l_errhdl = new ERRORLOG::ErrlEntry( ERRORLOG::ERRL_SEV_UNRECOVERABLE, PNOR::MOD_PNORRP_WAITFORMESSAGE, PNOR::RC_INVALID_MESSAGE_TYPE, TO_UINT64(message->type), (uint64_t)eff_addr, true /*Add HB SW Callout*/); l_errhdl->collectTrace(PNOR_COMP_NAME); status_rc = -EINVAL; /* Invalid argument */ } } if( !l_errhdl && msg_is_async(message) ) { TRACFCOMP( g_trac_pnor, "PnorRP::waitForMessage> Unsupported Asynchronous Message : user_addr=%p, eff_addr=%p, msgtype=%d", user_addr, eff_addr, message->type ); /*@ * @errortype * @moduleid PNOR::MOD_PNORRP_WAITFORMESSAGE * @reasoncode PNOR::RC_INVALID_ASYNC_MESSAGE * @userdata1 Message type * @userdata2 Requested Virtual Address * @devdesc PnorRP::waitForMessage> Unrecognized message * type * @custdesc A problem occurred while accessing the boot * flash. */ l_errhdl = new ERRORLOG::ErrlEntry( ERRORLOG::ERRL_SEV_UNRECOVERABLE, PNOR::MOD_PNORRP_WAITFORMESSAGE, PNOR::RC_INVALID_ASYNC_MESSAGE, TO_UINT64(message->type), (uint64_t)eff_addr, true /*Add HB SW Callout*/); l_errhdl->collectTrace(PNOR_COMP_NAME); status_rc = -EINVAL; /* Invalid argument */ } if( l_errhdl ) { errlCommit(l_errhdl,PNOR_COMP_ID); } /* Expected Response: * data[0] = virtual address requested * data[1] = rc (0 or negative errno value) * extra_data = Specific reason code. */ message->data[1] = status_rc; message->extra_data = reinterpret_cast<void*>(fatal_error); rc = msg_respond( iv_msgQ, message ); if( rc ) { TRACFCOMP(g_trac_pnor, "PnorRP::waitForMessage> Error from msg_respond, giving up : rc=%d", rc ); break; } } } TRACFCOMP(g_trac_pnor, "< PnorRP::waitForMessage" ); }