diff options
author | Corey Swenson <cswenson@us.ibm.com> | 2015-01-16 15:56:31 -0600 |
---|---|---|
committer | A. Patrick Williams III <iawillia@us.ibm.com> | 2015-02-12 10:41:48 -0600 |
commit | 3eb0fabc51df77382919c3d24b0f38b8f4eb8051 (patch) | |
tree | 0ce444da4689c50a0f10b25bb56c95e047d781c2 /src/usr/vpd/ipvpd.C | |
parent | 2dbd115aa927b95af61f9d691d068e3ae3989bad (diff) | |
download | blackbird-hostboot-3eb0fabc51df77382919c3d24b0f38b8f4eb8051.tar.gz blackbird-hostboot-3eb0fabc51df77382919c3d24b0f38b8f4eb8051.zip |
Get list of records from EEPROM when loading PNOR cache
Change-Id: I01613b61816d7c5a98851b5769986e971e133c43
RTC: 115944
Reviewed-on: http://gfw160.aus.stglabs.ibm.com:8080/gerrit/15314
Tested-by: Jenkins Server
Reviewed-by: Daniel M. Crowell <dcrowell@us.ibm.com>
Reviewed-by: A. Patrick Williams III <iawillia@us.ibm.com>
Diffstat (limited to 'src/usr/vpd/ipvpd.C')
-rw-r--r-- | src/usr/vpd/ipvpd.C | 285 |
1 files changed, 200 insertions, 85 deletions
diff --git a/src/usr/vpd/ipvpd.C b/src/usr/vpd/ipvpd.C index 229a50d27..57d5a9ce8 100644 --- a/src/usr/vpd/ipvpd.C +++ b/src/usr/vpd/ipvpd.C @@ -459,94 +459,86 @@ errlHndl_t IpVpdFacade::loadPnor ( TARGETING::Target * i_target ) input_args_t sRecArgs; sRecArgs.location = VPD::SEEPROM; - // Loop through all possible record types - for( uint32_t rec = 0; rec < iv_recSize; rec++ ) + std::list<TocPtRecord> recList; + recList.clear(); + err = getRecordListSeeprom( recList, + i_target, + sRecArgs ); + if( err ) { - sRecArgs.record = iv_vpdRecords[rec].record; - // Read the record offset from SEEPROM - err = findRecordOffsetSeeprom ( iv_vpdRecords[rec].recordName, - sRecOffset, - sRecLength, - i_target, - sRecArgs ); - if( err ) + TRACFCOMP(g_trac_vpd,"IpVPdFacade::loadPnor() getRecordListSeeprom failed"); + return err; + } + + for ( std::list<TocPtRecord>::iterator it = recList.begin(); + it != recList.end(); it++ ) + { + // Copy the record name to the toc structure asciiRec + memcpy( pTocEntry.asciiRec, + (*it).record_name, + RECORD_BYTE_SIZE ); + + // Swap the bytes to match SEEPROM VPD format + pTocEntry.offset[0] = ((uint8_t*)(&pRecOffset))[1]; + pTocEntry.offset[1] = ((uint8_t*)(&pRecOffset))[0]; + + // Just a signature after every TOC entry + pTocEntry.unusedByte[0] = 0x5A; + pTocEntry.unusedByte[1] = 0x5A; + + // Write TOC to temp data + memcpy( (tmpVpdPtr + pTocOffset), + &pTocEntry, + IPVPD_TOC_ENTRY_SIZE ); + + // Byte swap fields, skip 'large resource' byte + sRecOffset = le16toh( (*it).record_offset ) + 1; + sRecLength = le16toh( (*it).record_length ); + + // Make sure we don't exceed our allocated space in PNOR + if( (pRecOffset + sRecLength) > iv_vpdSectionSize ) { - TRACDCOMP(g_trac_vpd,"IpVpdFacade::loadPnor() " - "Did not find SEEPROM record %d recordName %s", - iv_vpdRecords[rec].record, iv_vpdRecords[rec].recordName); - // Not all records will be found, don't log the error - // @todo RTC 115944 Need specific list of records to check here - delete err; - err = NULL; + TRACFCOMP(g_trac_vpd,"IpVpdFacade::loadPnor()> The amount of space required (0x%X) for the VPD cache exceeds the available space (0x%X)", pRecOffset + sRecLength, iv_vpdSectionSize ); + /*@ + * @errortype + * @reasoncode VPD::VPD_CACHE_SIZE_EXCEEDED + * @severity ERRORLOG::ERRL_SEV_UNRECOVERABLE + * @moduleid VPD::VPD_IPVPD_LOAD_PNOR + * @userdata1 HUID of target chip + * @userdata2[00:31] Available size + * @userdata2[32:63] Requested size + * @devdesc The amount of space required for the VPD + * cache exceeds the available space + * @custdesc Fatal firmware boot error + */ + err = new ERRORLOG::ErrlEntry( ERRORLOG::ERRL_SEV_UNRECOVERABLE, + VPD::VPD_IPVPD_LOAD_PNOR, + VPD::VPD_CACHE_SIZE_EXCEEDED, + TARGETING::get_huid(i_target), + TWO_UINT32_TO_UINT64( + iv_vpdSectionSize, + pRecOffset + sRecLength ), + true /*Add HB SW Callout*/ ); + err->collectTrace( "VPD", 256 ); + break; } - else - { - // Copy the record name to the toc structure asciiRec - memcpy( pTocEntry.asciiRec, - iv_vpdRecords[rec].recordName, - RECORD_BYTE_SIZE ); - - // Swap the bytes to match SEEPROM VPD format - pTocEntry.offset[0] = ((uint8_t*)(&pRecOffset))[1]; - pTocEntry.offset[1] = ((uint8_t*)(&pRecOffset))[0]; - - // Just a signature after every TOC entry - pTocEntry.unusedByte[0] = 0x5A; - pTocEntry.unusedByte[1] = 0x5A; - - // Write TOC to temp data - memcpy( (tmpVpdPtr + pTocOffset), - &pTocEntry, - IPVPD_TOC_ENTRY_SIZE ); - - // Make sure we don't exceed our allocated space in PNOR - if( (pRecOffset + sRecLength) > iv_vpdSectionSize ) - { - TRACFCOMP(g_trac_vpd,"IpVpdFacade::loadPnor()> The amount of space required (0x%X) for the VPD cache exceeds the available space (0x%X)", pRecOffset + sRecLength, iv_vpdSectionSize ); - /*@ - * @errortype - * @reasoncode VPD::VPD_CACHE_SIZE_EXCEEDED - * @severity ERRORLOG::ERRL_SEV_UNRECOVERABLE - * @moduleid VPD::VPD_IPVPD_LOAD_PNOR - * @userdata1 HUID of target chip - * @userdata2[00:31] Available size - * @userdata2[32:63] Requested size - * @devdesc The amount of space required for the VPD - * cache exceeds the available space - * @custdesc Fatal firmware boot error - */ - err = new ERRORLOG::ErrlEntry( ERRORLOG::ERRL_SEV_UNRECOVERABLE, - VPD::VPD_IPVPD_LOAD_PNOR, - VPD::VPD_CACHE_SIZE_EXCEEDED, - TARGETING::get_huid(i_target), - TWO_UINT32_TO_UINT64( - iv_vpdSectionSize, - pRecOffset + sRecLength ), - true /*Add HB SW Callout*/ ); - err->collectTrace( "VPD", 256 ); - break; - } - - // Read record data from SEEPROM, put it into temp data - uint8_t* pRecPtr = tmpVpdPtr + pRecOffset; - err = fetchData( sRecOffset, - sRecLength, - pRecPtr, - i_target, - sRecArgs.location ); - if( err ) - { - TRACFCOMP(g_trac_vpd,"IpVpdFacade::loadPnor() " - "Error reading record data, record %d recordName %s", - iv_vpdRecords[rec].record, - iv_vpdRecords[rec].recordName); - break; - } - // Increment the PNOR TOC and record offsets - pTocOffset += IPVPD_TOC_ENTRY_SIZE; - pRecOffset += sRecLength; + // Read record data from SEEPROM, put it into temp data + uint8_t* pRecPtr = tmpVpdPtr + pRecOffset; + err = fetchData( sRecOffset, + sRecLength, + pRecPtr, + i_target, + sRecArgs.location ); + if( err ) + { + TRACFCOMP(g_trac_vpd,"IpVpdFacade::loadPnor() Error reading record %s",(*it).record_name); + break; } + + // Increment the PNOR TOC and record offsets + pTocOffset += IPVPD_TOC_ENTRY_SIZE; + pRecOffset += sRecLength; } if( !err ) @@ -567,8 +559,7 @@ errlHndl_t IpVpdFacade::loadPnor ( TARGETING::Target * i_target ) &iv_mutex ); if( err ) { - TRACFCOMP(g_trac_vpd,"IpVpdFacade::loadPnor() " - "Error writing PNOR VPD data"); + TRACFCOMP(g_trac_vpd,"IpVpdFacade::loadPnor() Error writing PNOR VPD data"); } } else @@ -1193,6 +1184,130 @@ errlHndl_t IpVpdFacade::findRecordOffsetSeeprom ( const char * i_record, // ------------------------------------------------------------------ +// IpVpdFacade::getRecordListSeeprom +// ------------------------------------------------------------------ +errlHndl_t +IpVpdFacade::getRecordListSeeprom ( std::list<TocPtRecord> & o_recList, + TARGETING::Target * i_target, + input_args_t i_args ) +{ + errlHndl_t err = NULL; + char l_buffer[256] = { 0 }; + uint16_t offset = 0x0; + + TRACSSCOMP( g_trac_vpd, ENTER_MRK"IpVpdFacade::getRecordListSeeprom()" ); + + // Skip the ECC data + large resource ID in the VHDR + offset = VHDR_ECC_DATA_SIZE + VHDR_RESOURCE_ID_SIZE; + + // Read PT keyword from VHDR to find the VTOC. + size_t pt_len = sizeof(l_buffer); + err = retrieveKeyword( "PT", + "VHDR", + offset, + 0, + i_target, + l_buffer, + pt_len, + i_args ); + if (err) + { + return err; + } + + TocPtRecord *toc_rec = reinterpret_cast<TocPtRecord*>(l_buffer); + if (pt_len < sizeof(TocPtRecord) || + (memcmp(toc_rec->record_name, "VTOC", + sizeof(toc_rec->record_name)) != 0)) + { + TRACFCOMP( g_trac_vpd, ERR_MRK"IpVpdFacade::getRecordListSeeprom: VHDR is invalid!"); + + /*@ + * @errortype + * @reasoncode VPD::VPD_RECORD_INVALID_VHDR + * @severity ERRORLOG::ERRL_SEV_UNRECOVERABLE + * @moduleid VPD::VPD_IPVPD_GET_RECORD_LIST_SEEPROM + * @userdata1 VHDR length + * @userdata2 Target HUID + * @devdesc The VHDR was invalid + */ + err = new ERRORLOG::ErrlEntry( + ERRORLOG::ERRL_SEV_UNRECOVERABLE, + VPD::VPD_IPVPD_FIND_RECORD_OFFSET_SEEPROM, + VPD::VPD_RECORD_INVALID_VHDR, + pt_len, + TARGETING::get_huid(i_target) ); + + // Could be the VPD of the target wasn't set up properly + // -- DECONFIG so that we can possibly keep booting + err->addHwCallout( i_target, + HWAS::SRCI_PRIORITY_HIGH, + HWAS::DECONFIG, + HWAS::GARD_NULL ); + + // Or HB code didn't look for the record properly + err->addProcedureCallout(HWAS::EPUB_PRC_HB_CODE, + HWAS::SRCI_PRIORITY_LOW); + + err->collectTrace( "VPD" ); + return err; + } + + offset = le16toh( toc_rec->record_offset ) + 1; // skip 'large resource' + + // Read the PT keyword(s) from the VTOC + for (uint16_t index = 0; index < 2; ++index) + { + pt_len = sizeof(l_buffer); + err = retrieveKeyword( "PT", + "VTOC", + offset, + index, + i_target, + l_buffer, + pt_len, + i_args ); + if ( err ) + { + // There may be only one PT keyword + if ( index != 0 ) + { + delete err; + err = NULL; + } + break; + } + + // Scan through the VTOC PT keyword records + // Copy the records to the list + for ( size_t vtoc_pt_offset = 0; + vtoc_pt_offset < pt_len; + vtoc_pt_offset += sizeof(TocPtRecord) ) + { + toc_rec = + reinterpret_cast<TocPtRecord*>(l_buffer + vtoc_pt_offset); + + // Save record if on the list for this target + for ( uint32_t rec = 0; rec < iv_recSize; rec++ ) + { + if ( memcmp( toc_rec->record_name, + iv_vpdRecords[rec].recordName, + RECORD_BYTE_SIZE ) == 0 ) + { + o_recList.push_back(*toc_rec); + break; + } + } + } + } + + TRACSSCOMP( g_trac_vpd,EXIT_MRK"IpVpdFacade::getRecordListSeeprom()" ); + + return err; +} + + +// ------------------------------------------------------------------ // IpVpdFacade::retrieveKeyword // ------------------------------------------------------------------ errlHndl_t IpVpdFacade::retrieveKeyword ( const char * i_keywordName, |