From 56ecb493705fef5b2275b94329836f8690ef0865 Mon Sep 17 00:00:00 2001 From: Bill Hoffa Date: Wed, 19 Jul 2017 14:53:01 -0500 Subject: PNOR Write Fixes for FIRDATA collection path - Updated write_pnor_8B() to add ECC - Removed memcpy calls as they cause unaligned accesses - LPC accesses modified to only be 4 bytes at a time Change-Id: I2bc2fddce3e652f97890962754f8dfa2e2e8d9aa Reviewed-on: http://ralgit01.raleigh.ibm.com/gerrit1/43458 Tested-by: FSP CI Jenkins Reviewed-by: Prachi Gupta Reviewed-by: ILYA SMIRNOV Reviewed-by: William A. Bryan --- src/occ_gpe0/firdata/ast_mboxdd.c | 4 ++- src/occ_gpe0/firdata/ecc.c | 4 +-- src/occ_gpe0/firdata/firData.c | 2 +- src/occ_gpe0/firdata/lpc.c | 4 +-- src/occ_gpe0/firdata/pnor_mboxdd.c | 55 ++++++++++++++++++++++------ src/occ_gpe0/firdata/pnor_util.c | 74 +++++++++++++++++++++----------------- src/occ_gpe0/firdata/pnor_util.h | 4 +-- 7 files changed, 95 insertions(+), 52 deletions(-) (limited to 'src/occ_gpe0/firdata') diff --git a/src/occ_gpe0/firdata/ast_mboxdd.c b/src/occ_gpe0/firdata/ast_mboxdd.c index 2e98af8..397a01d 100644 --- a/src/occ_gpe0/firdata/ast_mboxdd.c +++ b/src/occ_gpe0/firdata/ast_mboxdd.c @@ -35,6 +35,7 @@ #include #include #include +#include errorHndl_t writeRegSIO(uint8_t i_regAddr, uint8_t i_data) { @@ -159,7 +160,8 @@ errorHndl_t doMessage( astMbox_t *io_mbox, mboxMessage_t *io_msg ) { break; } - sleep(1000); + + busy_wait(1000); } if ( l_err ) diff --git a/src/occ_gpe0/firdata/ecc.c b/src/occ_gpe0/firdata/ecc.c index 8e54af4..56c8169 100644 --- a/src/occ_gpe0/firdata/ecc.c +++ b/src/occ_gpe0/firdata/ecc.c @@ -1,11 +1,11 @@ /* IBM_PROLOG_BEGIN_TAG */ /* This is an automatically generated prolog. */ /* */ -/* $Source: src/occ/firdata/ecc.C $ */ +/* $Source: src/occ_gpe0/firdata/ecc.c $ */ /* */ /* OpenPOWER OnChipController Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2015 */ +/* Contributors Listed Below - COPYRIGHT 2015,2017 */ /* [+] International Business Machines Corp. */ /* */ /* */ diff --git a/src/occ_gpe0/firdata/firData.c b/src/occ_gpe0/firdata/firData.c index 85f3d85..f87f9d5 100644 --- a/src/occ_gpe0/firdata/firData.c +++ b/src/occ_gpe0/firdata/firData.c @@ -1410,7 +1410,7 @@ int32_t FirData_captureCsFirData( uint8_t * i_hBuf, uint32_t i_hBufSize, FirData_addTrgtsToPnor( &fd ); /* Write Buffer to PNOR */ - //rc = PNOR_writeFirData( fd.hData->pnorInfo, fd.pBuf, fd.pBufSize ); + rc = PNOR_writeFirData( fd.hData->pnorInfo, fd.pBuf, fd.pBufSize ); if ( SUCCESS != rc ) { TRAC_ERR( FUNC"Failed to process FIR data" ); diff --git a/src/occ_gpe0/firdata/lpc.c b/src/occ_gpe0/firdata/lpc.c index 6544c44..7b9ffca 100644 --- a/src/occ_gpe0/firdata/lpc.c +++ b/src/occ_gpe0/firdata/lpc.c @@ -208,12 +208,11 @@ errorHndl_t lpc_read( LpcTransType i_type, do { if( o_data == NULL ) { - TRACFCOMP( "o_data is NULL!" ); + TRAC_ERR("o_data is NULL!" ); l_err = -2; break; } - /* Generate the full absolute LPC address */ l_addr = checkAddr( i_type, i_addr ); @@ -366,6 +365,7 @@ errorHndl_t lpc_write( LpcTransType i_type, //is expected to be left aligned //adding (size - 1) <-- to incorporate reading more than one byte //multiply by 8 to convert from byte to bits + l_shift_amount = (7 - ((l_addr & 0x7) + (i_size-1))) * 8; l_data = (l_write_data << l_shift_amount); diff --git a/src/occ_gpe0/firdata/pnor_mboxdd.c b/src/occ_gpe0/firdata/pnor_mboxdd.c index 19aaf5d..9c5a4e6 100644 --- a/src/occ_gpe0/firdata/pnor_mboxdd.c +++ b/src/occ_gpe0/firdata/pnor_mboxdd.c @@ -186,7 +186,6 @@ errorHndl_t writeFlash(pnorMbox_t* i_pnorMbox, return FAIL; } - errorHndl_t l_flushErr = NO_ERROR; while (i_size) @@ -194,24 +193,60 @@ errorHndl_t writeFlash(pnorMbox_t* i_pnorMbox, uint32_t l_lpcAddr; uint32_t l_chunkLen; - l_err = adjustMboxWindow(i_pnorMbox, + + if (PAGE_PROGRAM_BYTES > i_size) + { + l_err = adjustMboxWindow(i_pnorMbox, + true, + i_addr, + PAGE_PROGRAM_BYTES, + &l_lpcAddr, + &l_chunkLen); + } + else + { + l_err = adjustMboxWindow(i_pnorMbox, true, i_addr, i_size, &l_lpcAddr, &l_chunkLen); + } if (l_err) { + PK_TRACE("Error adjusting MBOX Window for addr: " + "0x%x size: 0x%x", l_lpcAddr, i_size); break; } - //Directly do LPC access to space pointed to by BMC - l_err = lpc_write(LPC_TRANS_FW, l_lpcAddr, i_data, l_chunkLen); + //For whatever reason LPC writes can only handle 4 bytes at a time + //We write 256 bytes from the previous functions, so break up the + //large write into 4 byte writes + uint32_t l_size_written = 0; + uint32_t l_lpc_write_size = 4; //in bytes + uint8_t *l_lpc_write_data = i_data; - if (l_err) + while ( (i_size) && (l_size_written < i_size) && + (l_size_written < l_chunkLen)) { - break; + if (i_size - l_size_written < l_lpc_write_size) + { + l_lpc_write_size = i_size - l_size_written; + } + + //Directly do LPC access to space pointed to by BMC + l_err = lpc_write(LPC_TRANS_FW, l_lpcAddr, + l_lpc_write_data, l_lpc_write_size); + + if (l_err) + { + break; + } + + l_lpc_write_data += l_lpc_write_size; + l_size_written += l_lpc_write_size; + l_lpcAddr += l_lpc_write_size; } //Tell BMC to push data from LPC space into PNOR @@ -242,13 +277,8 @@ errorHndl_t writeFlash(pnorMbox_t* i_pnorMbox, if( l_err ) { i_size = 0; - } - - if(l_err) - { break; } - } while(0); @@ -301,6 +331,8 @@ errorHndl_t adjustMboxWindow(pnorMbox_t* i_pnorMbox, * Then open the new one at the right position. The required * alignment differs between protocol versions */ + PK_TRACE("astMboxDD::adjustMboxWindow using protocol version: %d", + i_pnorMbox->iv_protocolVersion); if (i_pnorMbox->iv_protocolVersion == 1) { l_wSize = i_isWrite ? i_pnorMbox->iv_writeWindowSize @@ -333,6 +365,7 @@ errorHndl_t adjustMboxWindow(pnorMbox_t* i_pnorMbox, if (l_err) { + PK_TRACE("Error creating Window"); break; } diff --git a/src/occ_gpe0/firdata/pnor_util.c b/src/occ_gpe0/firdata/pnor_util.c index 45c650a..fb579e2 100644 --- a/src/occ_gpe0/firdata/pnor_util.c +++ b/src/occ_gpe0/firdata/pnor_util.c @@ -29,6 +29,7 @@ #include #include #include +#include /*================================================================= */ /* The offset of the next byte to write */ @@ -36,7 +37,7 @@ uint32_t g_next_byte = 0xFFFFFFFF; /* Size of the FIRDATA section of PNOR */ uint32_t g_pnor_size = 0; /* Global PNOR Mbox object */ -pnorMbox_t* g_pnorMbox; +pnorMbox_t g_pnorMbox; /* Cache to queue up PNOR writes */ uint8_t g_write_cache[PAGE_PROGRAM_BYTES]; @@ -53,38 +54,39 @@ int32_t pnor_write_8B( uint64_t i_data ) if ( (g_next_byte == 0xFFFFFFFF) || /* initialized data */ ((g_next_byte + g_pnor_size) < (g_next_byte + 9)) ) /* make sure there is room */ { - TRACFCOMP("pnor_write_8B> g_next_byte=%.8X, g_pnor_size=%.8X",g_next_byte,g_pnor_size); + PK_TRACE("FAILURE: pnor_write_8B> g_next_byte=%.8X, g_pnor_size=%.8X", + g_next_byte,g_pnor_size); /* must have been some error in the prep */ return FAIL; } -//@TODO: Do we need ECC, or does the BMC handle that for us now? /* Create 9-byte ECC-ified version */ -// uint8_t data9[9]; -// injectECC( (uint8_t*)(&i_data), 8, data9 ); + uint8_t data9[9]; + injectECC( (uint8_t*)(&i_data), 8, data9 ); /* Copy data into the write cache until we queue up a big chunk of data to write. This is more efficient and avoids handling the write boundary of the PP command internally. */ -// uint32_t cpsz = 9; - - uint8_t data8[8]; - uint32_t cpsz = 8; + uint32_t cpsz = 9; if( (g_write_cache_index + cpsz) > PAGE_PROGRAM_BYTES ) { cpsz = PAGE_PROGRAM_BYTES - g_write_cache_index; } - memcpy( &(g_write_cache[g_write_cache_index]), data8, cpsz ); -// memcpy( &(g_write_cache[g_write_cache_index]), data9, cpsz ); + + int i; + for (i=0; i < cpsz; i++) + { + g_write_cache[g_write_cache_index+i] = data9[i]; + } g_write_cache_index += cpsz; /* Write a complete chunk into the flash */ if( g_write_cache_index == PAGE_PROGRAM_BYTES ) { - errorHndl_t tmp = writeFlash( g_pnorMbox, + errorHndl_t tmp = writeFlash( &g_pnorMbox, g_next_byte, PAGE_PROGRAM_BYTES, g_write_cache ); @@ -97,21 +99,22 @@ int32_t pnor_write_8B( uint64_t i_data ) return FAIL; } g_next_byte += PAGE_PROGRAM_BYTES; - memset( g_write_cache, 0xFF, PAGE_PROGRAM_BYTES ); - g_write_cache_index = 0; - - if( (8 - cpsz) > 0 ) + for (i=0; i < PAGE_PROGRAM_BYTES; i++) { - memcpy( &(g_write_cache[0]), &(data8[cpsz]), 8 - cpsz ); - g_write_cache_index = 8 - cpsz; + g_write_cache[i] = 0xFF; } + g_write_cache_index = 0; /* Handle the overflow */ -// if( (9 - cpsz) > 0 ) -// { -// memcpy( &(g_write_cache[0]), &(data9[cpsz]), 9 - cpsz ); -// g_write_cache_index = 9 - cpsz; -// } + if( (9 - cpsz) > 0 ) + { + for (i=0; i < 9-cpsz; i++) + { + g_write_cache[i] = data9[cpsz+i]; + } + + g_write_cache_index = 9 - cpsz; + } } return rc; @@ -127,16 +130,17 @@ errorHndl_t pnor_prep( HOMER_PnorInfo_t* i_pnorInfo ) errorHndl_t l_err = NO_ERROR; /* Figure out where to start */ - TRACFCOMP("FIRDATA is at %.8X..%.8X", i_pnorInfo->pnorOffset, i_pnorInfo->pnorOffset+i_pnorInfo->pnorSize ); - g_next_byte = i_pnorInfo->pnorOffset; g_pnor_size = i_pnorInfo->pnorSize; + g_next_byte = i_pnorInfo->pnorOffset; + + TRAC_IMP("pnor_prep: pnorOffset:0x%08X pnorSize:0x%08X", + g_next_byte, g_pnor_size); memset( g_write_cache, 0xFF, PAGE_PROGRAM_BYTES ); /* Can we rely on skiboot leaving things in a good state? */ - l_err = hwInit(g_pnorMbox); + l_err = hwInit(&g_pnorMbox); if( l_err ) { - TRACFCOMP("hwInit failed"); /* hit an error, stop any writes from happening */ g_next_byte = 0xFFFFFFFF; g_pnor_size = 0; @@ -151,7 +155,6 @@ int32_t PNOR_writeFirData( HOMER_PnorInfo_t i_pnorInfo, uint8_t * i_buf, uint32_t i_bufSize ) { int32_t rc = SUCCESS; - TRACFCOMP(">>PNOR_writeFirData"); do { @@ -159,7 +162,7 @@ int32_t PNOR_writeFirData( HOMER_PnorInfo_t i_pnorInfo, errorHndl_t l_err = pnor_prep( &i_pnorInfo ); if( l_err ) { - TRACFCOMP("pnor_prep failed"); + TRAC_ERR("PNOR_writeFirData: pnor_prepreturned failure"); rc = FAIL; break; /*nothing more to do here*/ } @@ -171,7 +174,8 @@ int32_t PNOR_writeFirData( HOMER_PnorInfo_t i_pnorInfo, /* Add PNOR data 8 bytes at a time. */ for ( idx = 0; idx < i_bufSize; idx += sz_dataChunk ) { - memcpy( &dataChunk, &i_buf[idx], sz_dataChunk ); + uint64_t* l_data_ptr = (uint64_t*)(&i_buf[idx]); + dataChunk = *l_data_ptr; rc = pnor_write_8B( dataChunk ); if ( SUCCESS != rc ) @@ -185,10 +189,14 @@ int32_t PNOR_writeFirData( HOMER_PnorInfo_t i_pnorInfo, /* Add any extra bytes if they exist at the end of the buffer. */ if ( idx != i_bufSize ) { + int i; uint32_t extraBytes = idx - i_bufSize; - - dataChunk = 0; - memcpy( &dataChunk, &i_buf[idx], extraBytes ); + uint8_t* l_src_ptr = (uint8_t*)(&i_buf[idx]); + uint8_t* l_dest_ptr = (uint8_t*)(&dataChunk); + for (i = 0; i < extraBytes; i++) + { + l_dest_ptr[i] = l_src_ptr[i]; + } rc = pnor_write_8B( dataChunk ); if ( SUCCESS != rc ) diff --git a/src/occ_gpe0/firdata/pnor_util.h b/src/occ_gpe0/firdata/pnor_util.h index d8b5518..d7af814 100644 --- a/src/occ_gpe0/firdata/pnor_util.h +++ b/src/occ_gpe0/firdata/pnor_util.h @@ -1,11 +1,11 @@ /* IBM_PROLOG_BEGIN_TAG */ /* This is an automatically generated prolog. */ /* */ -/* $Source: src/occ/firdata/pnor_util.H $ */ +/* $Source: src/occ_gpe0/firdata/pnor_util.h $ */ /* */ /* OpenPOWER OnChipController Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2015 */ +/* Contributors Listed Below - COPYRIGHT 2015,2017 */ /* [+] International Business Machines Corp. */ /* */ /* */ -- cgit v1.2.1