/* IBM_PROLOG_BEGIN_TAG */ /* This is an automatically generated prolog. */ /* */ /* $Source: src/usr/hwpf/hwp/start_payload/start_payload.C $ */ /* */ /* IBM CONFIDENTIAL */ /* */ /* COPYRIGHT International Business Machines Corp. 2012,2013 */ /* */ /* p1 */ /* */ /* Object Code Only (OCO) source materials */ /* Licensed Internal Code Source Materials */ /* IBM HostBoot Licensed Internal Code */ /* */ /* The source code for this program is not published or otherwise */ /* divested of its trade secrets, irrespective of what has been */ /* deposited with the U.S. Copyright Office. */ /* */ /* Origin: 30 */ /* */ /* IBM_PROLOG_END_TAG */ /** * @file start_payload.C * * Support file for IStep: start_payload * Start Payload * * HWP_IGNORE_VERSION_CHECK * */ /******************************************************************************/ // Includes /******************************************************************************/ #include #include // printk status #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include // targeting support #include // fapi support #include #include #include "p8_set_pore_bar.H" #include "start_payload.H" #include #include // Uncomment these files as they become available: // #include "host_start_payload/host_start_payload.H" namespace START_PAYLOAD { using namespace TARGETING; using namespace fapi; using namespace ISTEP; using namespace ISTEP_ERROR; /** * @brief This function will call the Initservice interface to shutdown * Hostboot. This function will call shutdown, passing in system * attribute variables for the Payload base and Payload offset. * * @return errlHndl_t - NULL if succesful, otherwise a pointer to the error * log. */ errlHndl_t callShutdown ( void ); /** * @brief This function will check the Istep mode and send the appropriate * mailbox message to the Fsp to indicate what we're doing. * * @param[in] i_istepModeFlag - Whether or not Isteps is enabled. * * @param[in] i_spFuncs - The SpFuncs system attribute. * * @return errlHndl_t - NULL if successful, otherwise a pointer to the error * log. */ errlHndl_t notifyFsp ( bool i_istepModeFlag, TARGETING::SpFunctions i_spFuncs ); /** * @brief This function will clear the PORE BARs. Needs to be done * depending on payload type * * @return errlHndl_t - NULL if successful, otherwise a pointer to the error * log. */ errlHndl_t clearPoreBars ( void ) { errlHndl_t l_errl = NULL; TRACFCOMP( ISTEPS_TRACE::g_trac_isteps_trace, "set PORE bars back to 0" ); TARGETING::TargetHandleList l_procTargetList; getAllChips(l_procTargetList, TYPE_PROC); // loop thru all the cpus and reset the pore bars. for (TargetHandleList::const_iterator l_proc_iter = l_procTargetList.begin(); l_proc_iter != l_procTargetList.end(); ++l_proc_iter) { // make a local copy of the CPU target const TARGETING::Target* l_proc_target = *l_proc_iter; // trace HUID TRACFCOMP(ISTEPS_TRACE::g_trac_isteps_trace, "target HUID %.8X", TARGETING::get_huid(l_proc_target)); // cast OUR type of target to a FAPI type of target. fapi::Target l_fapi_proc_target( TARGET_TYPE_PROC_CHIP, (const_cast( l_proc_target)) ); // reset pore bar notes: // A mem_size of 0 means to ignore the image address // This image should have been moved to memory after winkle // call the HWP with each fapi::Target FAPI_INVOKE_HWP( l_errl, p8_set_pore_bar, l_fapi_proc_target, 0, 0, 0, SLW_MEMORY ); if ( l_errl ) { // capture the target data in the elog ERRORLOG::ErrlUserDetailsTarget(l_proc_target).addToLog( l_errl ); TRACFCOMP(ISTEPS_TRACE::g_trac_isteps_trace, "ERROR : p8_set_pore_bar, PLID=0x%x", l_errl->plid() ); break; } else { TRACFCOMP( ISTEPS_TRACE::g_trac_isteps_trace, "SUCCESS : p8_set_pore_bar" ); } } // end for return l_errl; } // // Wrapper function to call host_runtime_setup // void* call_host_runtime_setup( void *io_pArgs ) { TRACFCOMP( ISTEPS_TRACE::g_trac_isteps_trace, "call_host_runtime_setup entry" ); errlHndl_t l_err = NULL; IStepError l_StepError; // Need to wait here until Fsp tells us go INITSERVICE::waitForSyncPoint(); do { // Need to load up the runtime module if it isn't already loaded if ( !VFS::module_is_loaded( "libruntime.so" ) ) { l_err = VFS::module_load( "libruntime.so" ); if ( l_err ) { // load module returned with errl set TRACFCOMP( ISTEPS_TRACE::g_trac_isteps_trace, "Could not load runtime module" ); // break from do loop if error occured break; } } // Map the Host Data into the VMM if applicable l_err = RUNTIME::load_host_data(); if( l_err ) { break; } // Get the Payload kind -- various tasks rely on payload TARGETING::Target * sys = NULL; TARGETING::targetService().getTopLevelTarget( sys ); assert(sys != NULL); TARGETING::ATTR_PAYLOAD_KIND_type payload_kind = sys->getAttr(); //Start OCC in AVP (or Sapphire mode for now) if( is_avp_load() || is_sapphire_load() ) { TRACFCOMP( ISTEPS_TRACE::g_trac_isteps_trace, "Starting OCC" ); //Load modules needed by OCC bool occ_loaded = false; if ( !VFS::module_is_loaded( "libocc.so" ) ) { l_err = VFS::module_load( "libocc.so" ); if ( l_err ) { // load module returned with errl set TRACFCOMP( ISTEPS_TRACE::g_trac_isteps_trace, "Could not load occ module" ); // break from do loop if error occured break; } occ_loaded = true; } l_err = HBOCC::loadnStartAllOccs(); if(l_err) { TRACFCOMP( ISTEPS_TRACE::g_trac_isteps_trace, ERR_MRK"loadnStartAllOccs failed" ); } //make sure we always unload the module if (occ_loaded) { errlHndl_t l_tmpErrl = NULL; l_tmpErrl = VFS::module_unload( "libocc.so" ); if ( l_tmpErrl ) { TRACFCOMP( ISTEPS_TRACE::g_trac_isteps_trace, ERR_MRK"Error unloading libocc module" ); if(l_err) { errlCommit( l_tmpErrl, HWPF_COMP_ID ); } else { l_err = l_tmpErrl; } } } break; } if( is_sapphire_load() && (!INITSERVICE::spBaseServicesEnabled()) ) { // Write the devtree out in Sapphire mode when SP Base Services not // enabled l_err = DEVTREE::build_flatdevtree(); if ( l_err ) { TRACFCOMP( ISTEPS_TRACE::g_trac_isteps_trace, "Could not build dev tree" ); // break from do loop if error occured break; } } else if( TARGETING::PAYLOAD_KIND_PHYP == payload_kind ) { //If PHYP then clear out the PORE BARs l_err = clearPoreBars(); if( l_err ) { break; } //Update the MDRT value (for MS Dump) l_err = RUNTIME::write_MDRT_Count(); if(l_err != NULL) { TRACFCOMP( ISTEPS_TRACE::g_trac_isteps_trace, "write_MDRT_Count failed" ); break; } // Write the HostServices attributes into mainstore l_err = RUNTIME::populate_attributes(); if ( l_err ) { TRACFCOMP( ISTEPS_TRACE::g_trac_isteps_trace, "Could not populate attributes" ); // break from do loop if error occured break; } } else if( TARGETING::PAYLOAD_KIND_NONE == payload_kind ) { // Write the HostServices attributes into mainstore // for our testcases l_err = RUNTIME::populate_attributes(); if ( l_err ) { TRACFCOMP( ISTEPS_TRACE::g_trac_isteps_trace, "Could not populate attributes" ); // break from do loop if error occured break; } } // - Update HDAT/DEVTREE with tpmd logs } while(0); if( l_err ) { TRACFCOMP( ISTEPS_TRACE::g_trac_isteps_trace, "istep start_payload_failed see plid 0x%x", l_err->plid()); // Create IStep error log and cross reference error that occurred l_StepError.addErrorDetails( l_err ); // Commit Error errlCommit(l_err, ISTEP_COMP_ID); } TRACDCOMP( ISTEPS_TRACE::g_trac_isteps_trace, "call_host_runtime_setup exit" ); return l_StepError.getErrorHandle(); } // // Wrapper function to call host_start_payload // void* call_host_verify_hdat( void *io_pArgs ) { TRACDCOMP( ISTEPS_TRACE::g_trac_isteps_trace, "call_host_verify_hdat entry" ); errlHndl_t l_err = NULL; // Host Start Payload procedure, per documentation from Patrick. // - Verify target image // - TODO - Done via call to Secure Boot ROM. // - Will be done in future sprints // stub for now.. TRACDCOMP( ISTEPS_TRACE::g_trac_isteps_trace, "call_host_verify_hdat exit" ); return l_err; } // // Wrapper function to call host_start_payload // void* call_host_start_payload( void *io_pArgs ) { errlHndl_t l_errl = NULL; IStepError l_StepError; TRACDCOMP( ISTEPS_TRACE::g_trac_isteps_trace, "call_host_start_payload entry" ); // - Run CXX testcases l_errl = INITSERVICE::executeUnitTests(); if( l_errl == NULL ) { // - Call shutdown using payload base, and payload entry. // - base/entry will be from system attributes // - this will start the payload (Phyp) // NOTE: this call will not return if successful. l_errl = callShutdown(); }; if( l_errl ) { TRACFCOMP( ISTEPS_TRACE::g_trac_isteps_trace, "istep start_payload_failed see plid 0x%x", l_errl->plid()); // Create IStep error log and cross reference error that occurred l_StepError.addErrorDetails( l_errl ); // Commit Error errlCommit(l_errl, ISTEP_COMP_ID); } TRACDCOMP( ISTEPS_TRACE::g_trac_isteps_trace, "call_host_start_payload exit" ); // end task, returning any errorlogs to IStepDisp return l_StepError.getErrorHandle(); } // // Call shutdown // errlHndl_t callShutdown ( void ) { errlHndl_t err = NULL; uint64_t payloadBase = 0x0; uint64_t payloadEntry = 0x0; uint64_t payloadData = 0x0; bool istepModeFlag = false; uint64_t status = SHUTDOWN_STATUS_GOOD; TRACDCOMP( ISTEPS_TRACE::g_trac_isteps_trace, ENTER_MRK"callShutdown()" ); do { // Phyp needs us to program all of the I2C masters with the bus // divisor TRACFCOMP( ISTEPS_TRACE::g_trac_isteps_trace, "Setup I2C Masters" ); err = I2C::i2cSetupMasters(); if( err ) { TRACFCOMP( ISTEPS_TRACE::g_trac_isteps_trace, "Error setting up I2C Bus Divisors" ); break; } // Set scratch register to indicate Hostboot is [still] active. const char * hostboot_string = "hostboot"; mmio_scratch_write(MMIO_SCRATCH_HOSTBOOT_ACTIVE, *reinterpret_cast(hostboot_string)); // Get Target Service, and the system target. TargetService& tS = targetService(); TARGETING::Target* sys = NULL; (void) tS.getTopLevelTarget( sys ); if( NULL == sys ) { // Error getting system target to get payload related values. We // will create an error to be passed back. This will cause the // istep to fail. TRACFCOMP( ISTEPS_TRACE::g_trac_isteps_trace, ERR_MRK"System Target was NULL!" ); /*@ * @errortype * @reasoncode ISTEP_TARGET_NULL * @severity ERRORLOG::ERRL_SEV_CRITICAL_SYS_TERM * @moduleid ISTEP_START_PAYLOAD_CALL_SHUTDOWN * @userdata1 * @userdata2 * @devdesc System target was NULL! */ err = new ERRORLOG::ErrlEntry( ERRORLOG::ERRL_SEV_CRITICAL_SYS_TERM, ISTEP_START_PAYLOAD_CALL_SHUTDOWN, ISTEP_TARGET_NULL, 0x0, 0x0 ); break; } // Get Payload base/entry from attributes payloadBase = sys->getAttr(); payloadEntry = sys->getAttr(); TRACDCOMP( ISTEPS_TRACE::g_trac_isteps_trace, INFO_MRK"Payload Base: 0x%08x, Entry: 0x%08x", payloadBase, payloadEntry ); payloadBase = (payloadBase * MEGABYTE); TRACDCOMP( ISTEPS_TRACE::g_trac_isteps_trace, INFO_MRK" base: 0x%08x", payloadBase ); // Get Istep Mode flag istepModeFlag = sys->getAttr(); TRACDCOMP( ISTEPS_TRACE::g_trac_isteps_trace, INFO_MRK"Istep mode flag: %s", ((istepModeFlag) ? "Enabled" : "Disabled") ); // Get the Service Processor Functions TARGETING::SpFunctions spFuncs = sys->getAttr(); // Notify Fsp with appropriate mailbox message. err = notifyFsp( istepModeFlag, spFuncs ); if( err ) { break; } // Load payload data in Sapphire mode when SP Base Services not enabled if( is_sapphire_load() && (!INITSERVICE::spBaseServicesEnabled()) ) { payloadData = DEVTREE::get_flatdevtree_phys_addr(); } // do the shutdown. TRACFCOMP( ISTEPS_TRACE::g_trac_isteps_trace, "callShutdown finished, shutdown = 0x%x.", status ); INITSERVICE::doShutdown( status, false, payloadBase, payloadEntry, payloadData); } while( 0 ); TRACDCOMP( ISTEPS_TRACE::g_trac_isteps_trace, EXIT_MRK"callShutdown()" ); return err; } // // Notify the Fsp via Mailbox Message // errlHndl_t notifyFsp ( bool i_istepModeFlag, TARGETING::SpFunctions i_spFuncs ) { errlHndl_t err = NULL; TRACDCOMP( ISTEPS_TRACE::g_trac_isteps_trace, ENTER_MRK"notifyFsp()" ); do { if( i_istepModeFlag ) { // Istep Mode send istep complete TRACFCOMP( ISTEPS_TRACE::g_trac_isteps_trace, INFO_MRK"Isteps enabled, send istep complete msg" ); err = INITSERVICE::sendIstepCompleteMsg(); if( err ) { break; } } else { // Non-Istep mode send SYNC_POINT_REACHED TRACFCOMP( ISTEPS_TRACE::g_trac_isteps_trace, INFO_MRK"Isteps disabled, send SYNC_POINT_REACHED msg" ); err = INITSERVICE::sendSyncPoint(); if( err ) { break; } } } while( 0 ); TRACDCOMP( ISTEPS_TRACE::g_trac_isteps_trace, EXIT_MRK"notifyFsp()" ); return err; } }; // end namespace