diff options
author | Dan Crowell <dcrowell@us.ibm.com> | 2013-01-09 12:48:13 -0600 |
---|---|---|
committer | A. Patrick Williams III <iawillia@us.ibm.com> | 2013-02-06 14:18:33 -0600 |
commit | 7696bed6681d260f46d6878b5201560ed78715af (patch) | |
tree | 1731e489e444856d0644b17c0b39946988c3f512 | |
parent | 1ee9befb99004f26dcc81af879ce14907d405ad8 (diff) | |
download | talos-hostboot-7696bed6681d260f46d6878b5201560ed78715af.tar.gz talos-hostboot-7696bed6681d260f46d6878b5201560ed78715af.zip |
Enable MVPD Writes
Add support for writing MVPD keywords to both PNOR and out to
the EEPROM (via FSP mailbox). Also enabled a few more test
cases related to MVPD.
Added MER0 record to the standalone procmvpd.dat file and
enabled the support in the code.
Change-Id: If16c2863a11daaac3363fcf30bb2c92ad3e92b41
RTC: 39177
Reviewed-on: http://gfw160.austin.ibm.com:8080/gerrit/2962
Tested-by: Jenkins Server
Reviewed-by: ADAM R. MUHLE <armuhle@us.ibm.com>
Reviewed-by: A. Patrick Williams III <iawillia@us.ibm.com>
-rw-r--r-- | src/include/usr/vpd/mvpdenums.H | 1 | ||||
-rw-r--r-- | src/include/usr/vpd/vpdreasoncodes.H | 3 | ||||
-rw-r--r-- | src/usr/hwpf/hwp/mvpd_accessors/mvpdRingFuncs.C | 62 | ||||
-rw-r--r-- | src/usr/hwpf/test/fapiwinkletest.H | 445 | ||||
-rw-r--r-- | src/usr/vpd/makefile | 5 | ||||
-rwxr-xr-x | src/usr/vpd/mvpd.C | 614 | ||||
-rwxr-xr-x | src/usr/vpd/mvpd.H | 67 | ||||
-rwxr-xr-x | src/usr/vpd/spd.C | 117 | ||||
-rwxr-xr-x | src/usr/vpd/spd.H | 2 | ||||
-rwxr-xr-x | src/usr/vpd/test/mvpdtest.H | 186 | ||||
-rwxr-xr-x | src/usr/vpd/test/spdtest.H | 277 | ||||
-rw-r--r-- | src/usr/vpd/vpd.C | 6 |
12 files changed, 1307 insertions, 478 deletions
diff --git a/src/include/usr/vpd/mvpdenums.H b/src/include/usr/vpd/mvpdenums.H index ec512694f..43ce0acf9 100644 --- a/src/include/usr/vpd/mvpdenums.H +++ b/src/include/usr/vpd/mvpdenums.H @@ -73,6 +73,7 @@ enum mvpdRecord LWPD = 0x1f, LWPE = 0x20, VWML = 0x21, + MER0 = 0x22, // Last Record MVPD_LAST_RECORD, diff --git a/src/include/usr/vpd/vpdreasoncodes.H b/src/include/usr/vpd/vpdreasoncodes.H index 55de5f773..2ecbba770 100644 --- a/src/include/usr/vpd/vpdreasoncodes.H +++ b/src/include/usr/vpd/vpdreasoncodes.H @@ -55,6 +55,8 @@ enum vpdModuleId VPD_MVPD_RETRIEVE_KEYWORD = 0x37, VPD_MVPD_FETCH_DATA = 0x38, VPD_MVPD_CHECK_BUFFER_SIZE = 0x39, + VPD_MVPD_WRITE_KEYWORD = 0x3A, + VPD_MVPD_FIND_KEYWORD_ADDR = 0x3B, // DIMM SPD VPD_SPD_GET_KEYWORD_VALUE = 0x61, @@ -103,6 +105,7 @@ enum vpdReasonCode VPD_SIZE_MISMATCH = VPD_COMP_ID | 0x12, VPD_INVALID_WRITE_METHOD = VPD_COMP_ID | 0x13, VPD_NULL_ENTRY = VPD_COMP_ID | 0x14, + VPD_UNSUPPORTED_WRITE = VPD_COMP_ID | 0x15, }; }; // end MVPD diff --git a/src/usr/hwpf/hwp/mvpd_accessors/mvpdRingFuncs.C b/src/usr/hwpf/hwp/mvpd_accessors/mvpdRingFuncs.C index 47b1e4c65..7c94e1cd3 100644 --- a/src/usr/hwpf/hwp/mvpd_accessors/mvpdRingFuncs.C +++ b/src/usr/hwpf/hwp/mvpd_accessors/mvpdRingFuncs.C @@ -1,26 +1,25 @@ - /* IBM_PROLOG_BEGIN_TAG - * This is an automatically generated prolog. - * - * $Source: src/usr/hwpf/hwp/mvpdRingFuncs.C $ - * - * IBM CONFIDENTIAL - * - * COPYRIGHT International Business Machines Corp. 2012 - * - * 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 other- - * wise divested of its trade secrets, irrespective of what has - * been deposited with the U.S. Copyright Office. - * - * Origin: 30 - * - * IBM_PROLOG_END_TAG - */ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/usr/hwpf/hwp/mvpd_accessors/mvpdRingFuncs.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 mvpdRingFuncs.C * @@ -273,16 +272,6 @@ fapi::ReturnCode mvpdRingFunc( const mvpdRingFuncOp i_mvpdRingFuncOp, i_fapiTarget, l_recordBuf, l_recordLen ); -#if 0 // TODO remove once DD supports write RTC 39177,enable for unit test - if (l_fapirc == FAPI_RC_PLAT_ERR_SEE_DATA) - { - FAPI_DBG( "mvpdRingFunc: Fake that fapiSetMvpdField worked" ); - TRACDBIN( g_fapiImpTd, "mvpdRingFunc: Dump Ring Buffer:", - l_recordBuf, - 0x100 ); - l_fapirc=FAPI_RC_SUCCESS; - } -#endif // RTC 39177 if ( l_fapirc ) { FAPI_ERR("mvpdRingFunc: fapiSetMvpdField failed"); @@ -374,20 +363,21 @@ fapi::ReturnCode mvpdRingFuncFind( const uint8_t i_chipletId, break; } // dump record info for debug - FAPI_DBG("mvpdRingFuncFind:%d ringId=0x%x chipletId=0x%x size=0x%x", + FAPI_DBG("mvpdRingFuncFind:%d ringId=0x%x chipletId=0x%x ringlen=0x%x size=0x%x", l_offset, l_pScanData->iv_ringId, l_pScanData->iv_chipletId, + FAPI_BE32TOH(l_pScanData->iv_length), FAPI_BE32TOH(l_pScanData->iv_size) ); if ( (l_pScanData->iv_ringId == i_ringId) && (l_pScanData->iv_chipletId == i_chipletId) ) { - FAPI_DBG( "mvpdRingFuncFind: Found it: 0x%x.0x%x, 0x%x", + FAPI_DBG( "mvpdRingFuncFind: Found it: ring=0x%x, chiplet=0x%x, ringlen=0x%x", i_ringId, i_chipletId, - FAPI_BE32TOH(l_pScanData->iv_size) ); + FAPI_BE32TOH(l_pScanData->iv_length) ); if (l_offset+FAPI_BE32TOH(l_pScanData->iv_size)>i_recordBufLen) { diff --git a/src/usr/hwpf/test/fapiwinkletest.H b/src/usr/hwpf/test/fapiwinkletest.H index 5ab22fcca..6ada8741f 100644 --- a/src/usr/hwpf/test/fapiwinkletest.H +++ b/src/usr/hwpf/test/fapiwinkletest.H @@ -26,7 +26,6 @@ // set to 1 for doing unit tests, set to 0 for production #define RTC51716 0 -#define RTC39177 0 /** * @file fapiwinkletest.H * @@ -45,6 +44,11 @@ #include <getMvpdRing.H> #include <setMvpdRing.H> +#include <errl/errlmanager.H> +#include <errl/errlentry.H> +#include <devicefw/driverif.H> +#include <trace/interface.H> + // pull in CompressedScanData def from proc_slw_build HWP #include <p8_scan_compression.H> @@ -134,9 +138,14 @@ public: TS_TRACE( "testGetMvpdPdr exit" ); } - // @note: - // ring modifiers are from MVPD #R record, 2012-05-22. - // This will change and the unit test will need to be changed... + // Structure used to save/restore the VPD + typedef struct saveRestoreData_t { + TARGETING::Target* target; + uint8_t* CP00_pdG; + size_t CP00_pdG_size; + uint8_t* CP00_pdR; + size_t CP00_pdR_size; + } saveRestoreData_t; /** * @brief Fetch Repair Rings @@ -149,25 +158,36 @@ public: uint32_t l_ringId = 0; uint32_t l_chipletId = 0; uint32_t l_bufsize = 0x200; -#if RTC51716 // TODO comment out until mvpd test data is fixed. RTC 51716 + errlHndl_t l_errhdl = NULL; + // This data needs to be in sync with the procmvpd.dat file - // the setMvpdFunc tests use the last row, index = 3. The test + // the setMvpdFunc tests use the last row. The test // expects it to be a mid x20 byte ring in the #G keyword struct _testRRstr { - fapi::MvpdRecord record; fapi::MvpdKeyword keyword; uint32_t ringIdval; uint32_t chipletIdval; uint32_t size; + uint32_t rc; } l_ringModifiers[] = { - { MVPD_RECORD_CP00, MVPD_KEYWORD_PDG,0xa4, 0xFF , 0x20 }, //last #G - { MVPD_RECORD_CP00, MVPD_KEYWORD_PDR,0xe0, 0x8 , 0x20 },//first #R - { MVPD_RECORD_CP00, MVPD_KEYWORD_PDR,0xe2, 0x16 ,0x138 },//big #R - { MVPD_RECORD_CP00, MVPD_KEYWORD_PDG,0xa2, 0x8 , 0x20 }, //mid #G + { MVPD_KEYWORD_PDG, 0xa4, 0xFF, 0x20, //last #G + fapi::RC_REPAIR_RING_NOT_FOUND }, + { MVPD_KEYWORD_PDR, 0xe0, 0x08, 0x20, //first #R + FAPI_RC_SUCCESS }, + { MVPD_KEYWORD_PDR, 0xe2, 0x16, 0x20, //big #R + FAPI_RC_SUCCESS }, + { MVPD_KEYWORD_PDG, 0xa2, 0x08, 0x20, //mid #G + FAPI_RC_SUCCESS }, + { MVPD_KEYWORD_PDR, 0xe1, 0x16, 0x20,//big #R + FAPI_RC_SUCCESS }, }; -#endif // RTC 51716 + const size_t VALID_INDEX = 2; + const size_t TEST_INDEX = 4; + TS_TRACE( "testRepairRings entry" ); + std::list<saveRestoreData_t> l_srData; + TARGETING::TargetHandleList l_cpuTargetList; getAllChips(l_cpuTargetList, TYPE_PROC); @@ -183,6 +203,76 @@ public: "target HUID %.8X", TARGETING::get_huid(l_cpu_target)); + //-- Save the entire VPD record to restore later + saveRestoreData_t tmpsave; + tmpsave.target = l_cpu_target; + + // do a read with NULL buffer to get the record size + l_errhdl = deviceRead( l_cpu_target, + NULL, + tmpsave.CP00_pdG_size, + DEVICE_MVPD_ADDRESS( MVPD_RECORD_CP00, + MVPD_KEYWORD_PDG ) ); + if( l_errhdl ) + { + TS_FAIL("Error finding size of CP00/#G for %.8X", + TARGETING::get_huid(l_cpu_target)); + errlCommit( l_errhdl, VPD_COMP_ID ); + continue; + } + + // now go get the data + tmpsave.CP00_pdG = new uint8_t[tmpsave.CP00_pdG_size]; + l_errhdl = deviceRead( l_cpu_target, + tmpsave.CP00_pdG, + tmpsave.CP00_pdG_size, + DEVICE_MVPD_ADDRESS( MVPD_RECORD_CP00, + MVPD_KEYWORD_PDG ) ); + if( l_errhdl ) + { + TS_FAIL("Error reading CP00/#G from %.8X", + TARGETING::get_huid(l_cpu_target)); + errlCommit( l_errhdl, VPD_COMP_ID ); + delete[] tmpsave.CP00_pdG; + continue; + } + + // do a read with NULL buffer to get the record size + l_errhdl = deviceRead( l_cpu_target, + NULL, + tmpsave.CP00_pdR_size, + DEVICE_MVPD_ADDRESS( MVPD_RECORD_CP00, + MVPD_KEYWORD_PDR ) ); + if( l_errhdl ) + { + TS_FAIL("Error finding size of CP00/#R for %.8X", + TARGETING::get_huid(l_cpu_target)); + errlCommit( l_errhdl, VPD_COMP_ID ); + continue; + } + + // now go get the data + tmpsave.CP00_pdR = new uint8_t[tmpsave.CP00_pdR_size]; + l_errhdl = deviceRead( l_cpu_target, + tmpsave.CP00_pdR, + tmpsave.CP00_pdR_size, + DEVICE_MVPD_ADDRESS( MVPD_RECORD_CP00, + MVPD_KEYWORD_PDR ) ); + if( l_errhdl ) + { + TS_FAIL("Error reading CP00/#R from %.8X", + TARGETING::get_huid(l_cpu_target)); + errlCommit( l_errhdl, VPD_COMP_ID ); + delete[] tmpsave.CP00_pdR; + continue; + } + + // add to the master list + l_srData.push_back(tmpsave); + + //-- + + // cast OUR type of target to a FAPI type of target. fapi::Target l_fapi_cpu_target( TARGET_TYPE_PROC_CHIP, @@ -190,7 +280,11 @@ public: (const_cast<TARGETING::Target*>(l_cpu_target)) ); // allocate some space to put the record(s) - l_pRingBuf = new uint8_t[ l_bufsize]; + if( l_pRingBuf != NULL ) + { + delete[] l_pRingBuf; + } + l_pRingBuf = new uint8_t[l_bufsize]; // ---------------------------------------------------------------- // Pass in 0 for the ring modifier, should return with "not found" @@ -218,20 +312,17 @@ public: fapi::RC_REPAIR_RING_NOT_FOUND, static_cast<uint32_t>(l_fapirc) ); fapiLogError(l_fapirc); - return; } -#if RTC51716 // TODO comment out until mvpd test data is fixed. RTC 51716 - uint8_t i = 2; // ---------------------------------------------------------------- // Pass in a buffer size that is too small with a valid - // ringId/chipletId, should return with correct length - // and invalid size return code. + // ringId/chipletId, should return error with correct length + // and invalid size return code.. // ---------------------------------------------------------------- TS_TRACE( "testRepairRings: pass buffer too small %d ", i ); l_ringBufsize = 0x0; - l_ringId = l_ringModifiers[i].ringIdval; - l_chipletId = l_ringModifiers[i].chipletIdval; + l_ringId = l_ringModifiers[VALID_INDEX].ringIdval; + l_chipletId = l_ringModifiers[VALID_INDEX].chipletIdval; l_fapirc = getMvpdRing( MVPD_RECORD_CP00, MVPD_KEYWORD_PDR, l_fapi_cpu_target, @@ -246,28 +337,29 @@ public: if ( l_fapirc != fapi::RC_REPAIR_RING_INVALID_SIZE ) { // note: "uint32_t" below is an _operator_ of fapi::ReturnCode - TS_FAIL("testRepairRings: expect invalid size FAIL: 0x%x, 0x%x", + TS_FAIL("testRepairRings: expect invalid size FAIL: exp=0x%x, act=0x%x, ring=0x%X", fapi::RC_REPAIR_RING_INVALID_SIZE, - static_cast<uint32_t>(l_fapirc)); + static_cast<uint32_t>(l_fapirc), + l_ringId); fapiLogError(l_fapirc); - return; } - if ( l_ringBufsize != l_ringModifiers[i].size ) + else if ( l_ringBufsize != l_ringModifiers[VALID_INDEX].size ) { - TS_FAIL( "testRepairRings: size mismatch FAIL: 0x%x, 0x%x", - l_ringModifiers[i].size, + TS_FAIL( "testRepairRings: size mismatch FAIL1 on ring 0x%X: exp=0x%x, act=0x%x", + l_ringId, + l_ringModifiers[VALID_INDEX].size, l_ringBufsize ); - return; } + // ---------------------------------------------------------------- // Pass in a NULL pointer with a valid ringId/chipletId, should // return with correct length and successful return code. // ---------------------------------------------------------------- TS_TRACE( "testRepairRings: get size of ring %d ", i ); l_ringBufsize = 0x0; - l_ringId = l_ringModifiers[i].ringIdval; - l_chipletId = l_ringModifiers[i].chipletIdval; + l_ringId = l_ringModifiers[VALID_INDEX].ringIdval; + l_chipletId = l_ringModifiers[VALID_INDEX].chipletIdval; l_fapirc = getMvpdRing( MVPD_RECORD_CP00, MVPD_KEYWORD_PDR, l_fapi_cpu_target, @@ -287,14 +379,13 @@ public: static_cast<uint32_t>(l_fapirc)); fapiLogError(l_fapirc); - return; } - if ( l_ringBufsize != l_ringModifiers[i].size ) + else if ( l_ringBufsize != l_ringModifiers[VALID_INDEX].size ) { - TS_FAIL( "testRepairRings: size mismatch FAIL: 0x%x, 0x%x", - l_ringModifiers[i].size, + TS_FAIL( "testRepairRings: size mismatch FAIL2 on ring 0x%X: exp=0x%x, act=0x%x", + l_ringId, + l_ringModifiers[VALID_INDEX].size, l_ringBufsize ); - return; } // ---------------------------------------------------------------- @@ -302,12 +393,13 @@ public: // ---------------------------------------------------------------- const uint32_t numRings = sizeof(l_ringModifiers)/sizeof(l_ringModifiers[0]); - for (i=0;i<numRings;i++) { + for (size_t i=0;i<numRings;i++) + { TS_TRACE( "testRepairRings: get ring %d", i ); l_ringBufsize = l_bufsize; l_ringId = l_ringModifiers[i].ringIdval; l_chipletId = l_ringModifiers[i].chipletIdval; - l_fapirc = getMvpdRing( l_ringModifiers[i].record, + l_fapirc = getMvpdRing( MVPD_RECORD_CP00, l_ringModifiers[i].keyword, l_fapi_cpu_target, l_chipletId, @@ -317,21 +409,29 @@ public: TS_TRACE("testRepairRings ringId=0x%x chipletId=0x%x size=0x%x", l_ringId, l_chipletId, l_ringBufsize ); - if ( l_fapirc ) + if ( l_fapirc != l_ringModifiers[i].rc ) { // note: uint32_t below is an _operator_ of fapi::ReturnCode - TS_FAIL( "testRepairRings: getMvpdRing rc FAIL: 0x%x, 0x%x", - fapi::FAPI_RC_SUCCESS, - static_cast<uint32_t>(l_fapirc) ); + TS_FAIL( "testRepairRings: getMvpdRing rc FAIL 1: rc=0x%x, ring=0x%X, chiplet=0x%X, i=%d", + static_cast<uint32_t>(l_fapirc), + l_ringId, + l_chipletId, + i ); fapiLogError(l_fapirc); - return; + continue; } + else if( l_fapirc != fapi::FAPI_RC_SUCCESS ) + { + // not an error, but the next check isn't valid + continue; + } + if ( l_ringBufsize != l_ringModifiers[i].size ) { - TS_FAIL( "testRepairRings: size mismatch FAIL: 0x%x, 0x%x", - l_ringModifiers[i].size, - l_ringBufsize ); - return; + TS_FAIL( "testRepairRings: size mismatch FAIL3 on ring %X: exp=0x%x, act=0x%x", + l_ringId, + l_ringModifiers[i].size, + l_ringBufsize ); } // Dump ring buffer here. @@ -339,25 +439,20 @@ public: l_pRingBuf, l_ringBufsize ); } -#endif // RTC 51716 -#if RTC39177 // TODO comment out til mvpd dd supports write. RTC 39177 // ---------------------------------------------------------------- - // update the data. - // TODO write different data, once the DD is written(story 39177) - // read it back to verify, then put the original data back. - // for now, there is a debug byte dump in mvpdRingFunc to - // manually verify in unit test + // write different data, read it back to verify, then put the + // original data back. // ---------------------------------------------------------------- uint32_t l_offset =0; uint8_t l_data = 0; uint8_t *l_pData = NULL; - i = 3; // use data from last fetch test case. - TS_TRACE( "testRepairRings: update in place ring %d", i ); - l_ringId = l_ringModifiers[i].ringIdval; - l_chipletId = l_ringModifiers[i].chipletIdval; - l_ringBufsize = l_ringModifiers[i].size; + // use data from last fetch test case. + TS_TRACE( "testRepairRings: update in place ring %d", TEST_INDEX ); + l_ringId = l_ringModifiers[TEST_INDEX].ringIdval; + l_chipletId = l_ringModifiers[TEST_INDEX].chipletIdval; + l_ringBufsize = l_ringModifiers[TEST_INDEX].size; // put in recognizable data for the debug data dump l_pData = l_pRingBuf+sizeof(CompressedScanData); @@ -369,8 +464,8 @@ public: TRACDBIN( g_trac_test, "testRepairRings: updated ring data:", l_pRingBuf, l_ringBufsize ); - l_fapirc = setMvpdRing( l_ringModifiers[i].record, - l_ringModifiers[i].keyword, + l_fapirc = setMvpdRing( MVPD_RECORD_CP00, + l_ringModifiers[TEST_INDEX].keyword, l_fapi_cpu_target, l_chipletId, l_ringId, @@ -380,19 +475,17 @@ public: if ( l_fapirc != fapi::FAPI_RC_SUCCESS ) { // note: "uint32_t" below is an _operator_ of fapi::ReturnCode - TS_FAIL( "testRepairRings: setMvpdRing rc FAIL: 0x%x, 0x%x", + TS_FAIL( "testRepairRings: setMvpdRing rc FAIL 1: exp=0x%x, rc=0x%x", fapi::FAPI_RC_SUCCESS, - static_cast<uint32_t>(l_fapirc) ); - + static_cast<uint32_t>(l_fapirc) ); fapiLogError(l_fapirc); - return; } // ---------------------------------------------------------------- // write back a smaller ring to cause a shift left in the record // ---------------------------------------------------------------- - TS_TRACE( "testRepairRings: shrink a ring %d", i ); - l_ringBufsize = l_ringModifiers[i].size-4; + TS_TRACE( "testRepairRings: shrink a ring %d", TEST_INDEX ); + l_ringBufsize = l_ringModifiers[TEST_INDEX].size-4; reinterpret_cast<CompressedScanData *>(l_pRingBuf)-> iv_size = l_ringBufsize; @@ -406,8 +499,8 @@ public: TRACDBIN( g_trac_test, "testRepairRings: updated ring data:", l_pRingBuf, l_ringBufsize ); - l_fapirc = setMvpdRing( l_ringModifiers[i].record, - l_ringModifiers[i].keyword, + l_fapirc = setMvpdRing( MVPD_RECORD_CP00, + l_ringModifiers[TEST_INDEX].keyword, l_fapi_cpu_target, l_chipletId, l_ringId, @@ -417,19 +510,18 @@ public: if ( l_fapirc != fapi::FAPI_RC_SUCCESS ) { // note: "uint32_t" below is an _operator_ of fapi::ReturnCode - TS_FAIL( "testRepairRings: setMvpdRing rc FAIL: 0x%x, 0x%x", + TS_FAIL( "testRepairRings: setMvpdRing rc FAIL 2: exp=0x%x, rc=0x%x", fapi::FAPI_RC_SUCCESS, static_cast<uint32_t>(l_fapirc) ); fapiLogError(l_fapirc); - return; } // ---------------------------------------------------------------- // write back a larger ring to cause a shift right in the record // ---------------------------------------------------------------- - TS_TRACE( "testRepairRings: grow a ring %d", i ); - l_ringBufsize = l_ringModifiers[i].size+16; + TS_TRACE( "testRepairRings: grow a ring %d", TEST_INDEX ); + l_ringBufsize = l_ringModifiers[TEST_INDEX].size+16; reinterpret_cast<CompressedScanData *>(l_pRingBuf)-> iv_size = l_ringBufsize; @@ -443,8 +535,8 @@ public: TRACDBIN( g_trac_test, "testRepairRings: updated ring data:", l_pRingBuf, l_ringBufsize ); - l_fapirc = setMvpdRing( l_ringModifiers[i].record, - l_ringModifiers[i].keyword, + l_fapirc = setMvpdRing( MVPD_RECORD_CP00, + l_ringModifiers[TEST_INDEX].keyword, l_fapi_cpu_target, l_chipletId, l_ringId, @@ -454,12 +546,11 @@ public: if ( l_fapirc != fapi::FAPI_RC_SUCCESS ) { // note: "uint32_t" below is an _operator_ of fapi::ReturnCode - TS_FAIL( "testRepairRings: setMvpdRing rc FAIL: 0x%x, 0x%x", + TS_FAIL( "testRepairRings: setMvpdRing rc FAIL 3: exp=0x%x, rc=0x%x", fapi::FAPI_RC_SUCCESS, static_cast<uint32_t>(l_fapirc) ); fapiLogError(l_fapirc); - return; } // ---------------------------------------------------------------- @@ -468,7 +559,7 @@ public: TS_TRACE( "testRepairRings: append a ring" ); l_ringId = 0x77; l_chipletId = 0x88; - l_ringBufsize = l_ringModifiers[i].size; + l_ringBufsize = l_ringModifiers[TEST_INDEX].size; reinterpret_cast<CompressedScanData *>(l_pRingBuf)-> iv_size = l_ringBufsize; reinterpret_cast<CompressedScanData *>(l_pRingBuf)-> @@ -486,8 +577,8 @@ public: TRACDBIN( g_trac_test, "testRepairRings: updated ring data:", l_pRingBuf, l_ringBufsize ); - l_fapirc = setMvpdRing( l_ringModifiers[i].record, - l_ringModifiers[i].keyword, + l_fapirc = setMvpdRing( MVPD_RECORD_CP00, + l_ringModifiers[TEST_INDEX].keyword, l_fapi_cpu_target, l_chipletId, l_ringId, @@ -497,14 +588,88 @@ public: if ( l_fapirc != fapi::FAPI_RC_SUCCESS ) { // note: "uint32_t" below is an _operator_ of fapi::ReturnCode - TS_FAIL( "testRepairRings: setMvpdRing rc FAIL: 0x%x, 0x%x", + TS_FAIL( "testRepairRings: setMvpdRing rc FAIL 4: exp=0x%x, rc=0x%x", fapi::FAPI_RC_SUCCESS, static_cast<uint32_t>(l_fapirc) ); fapiLogError(l_fapirc); - return; } + // read back data to prove the writes worked + l_ringId = l_ringModifiers[TEST_INDEX].ringIdval; + l_chipletId = l_ringModifiers[TEST_INDEX].chipletIdval; + l_ringBufsize = l_ringModifiers[TEST_INDEX].size+16; + l_fapirc = getMvpdRing( MVPD_RECORD_CP00, + l_ringModifiers[TEST_INDEX].keyword, + l_fapi_cpu_target, + l_chipletId, + l_ringId, + l_pRingBuf, + l_ringBufsize ); + + if ( l_fapirc != fapi::FAPI_RC_SUCCESS ) + { + TS_FAIL( "testRepairRings: getMvpdRing rc FAIL 2: 0x%x, 0x%x", + fapi::FAPI_RC_SUCCESS, + static_cast<uint32_t>(l_fapirc) ); + fapiLogError(l_fapirc); + } + else + { + l_pData = l_pRingBuf+sizeof(CompressedScanData); + for( l_offset = 0,l_data=0x30; + l_offset < l_ringBufsize-sizeof(CompressedScanData); + l_offset++) + { + if( l_pData[l_offset] != l_data++ ) + { + TS_FAIL("Mismatch after write on ring %X", + l_ringId); + TRACFBIN(g_trac_test, + "ringdata=", + l_pRingBuf,l_ringBufsize); + } + } + } + + // read back data to prove the writes worked + l_ringId = 0x77; + l_chipletId = 0x88; + l_ringBufsize = l_ringModifiers[TEST_INDEX].size; + l_fapirc = getMvpdRing( MVPD_RECORD_CP00, + l_ringModifiers[TEST_INDEX].keyword, + l_fapi_cpu_target, + l_chipletId, + l_ringId, + l_pRingBuf, + l_ringBufsize ); + + if ( l_fapirc != fapi::FAPI_RC_SUCCESS ) + { + TS_FAIL( "testRepairRings: getMvpdRing rc FAIL 3: 0x%x, 0x%x", + fapi::FAPI_RC_SUCCESS, + static_cast<uint32_t>(l_fapirc) ); + fapiLogError(l_fapirc); + } + else + { + l_pData = l_pRingBuf+sizeof(CompressedScanData); + for (l_offset = 0,l_data=0x50; + l_offset < l_ringBufsize-sizeof(CompressedScanData); + l_offset++) + { + if( l_pData[l_offset] != l_data++ ) + { + TS_FAIL("Mismatch after write on ring %X", + l_ringId); + TRACFBIN(g_trac_test, + "ringdata=", + l_pRingBuf,l_ringBufsize); + } + } + } + + // ---------------------------------------------------------------- // Pass in a buffer size that does not match the exact size // of the ringId/chipletId, should return with correct length @@ -515,8 +680,8 @@ public: l_chipletId, l_ringBufsize ); l_ringBufsize = l_bufsize; - l_ringId = l_ringModifiers[i].ringIdval; - l_chipletId = l_ringModifiers[i].chipletIdval; + l_ringId = l_ringModifiers[TEST_INDEX].ringIdval; + l_chipletId = l_ringModifiers[TEST_INDEX].chipletIdval; l_fapirc = setMvpdRing( MVPD_RECORD_CP00, MVPD_KEYWORD_PDR, l_fapi_cpu_target, @@ -528,19 +693,19 @@ public: if ( l_fapirc != fapi::RC_MVPD_RING_FUNC_INVALID_PARAMETER ) { // note: "uint32_t" below is an _operator_ of fapi::ReturnCode - TS_FAIL("testRepairRings:invalid ring size rc FAIL: 0x%x, 0x%x", + TS_FAIL("testRepairRings:invalid ring size rc FAIL: exp=0x%x, act=0x%x", fapi::RC_REPAIR_RING_INVALID_SIZE, static_cast<uint32_t>(l_fapirc)); fapiLogError(l_fapirc); - return; } + // ---------------------------------------------------------------- // Pass in 0 for the ring modifier, should return with "not found" // error // ---------------------------------------------------------------- TS_TRACE( "testRepairRings: pass in invalid ringId" ); - l_ringBufsize = l_ringModifiers[i].size; + l_ringBufsize = l_ringModifiers[TEST_INDEX].size; l_ringId = 0; // ringId l_chipletId = 0; // chipletId l_fapirc = setMvpdRing( MVPD_RECORD_CP00, @@ -558,20 +723,19 @@ public: if ( l_fapirc != fapi::RC_MVPD_RING_FUNC_INVALID_PARAMETER ) { // note: "uint32_t" below is an _operator_ of fapi::ReturnCode - TS_FAIL( "testRepairRings: rc FAIL: 0x%x, 0x%x", + TS_FAIL( "testRepairRings: rc FAIL: exp=0x%x, act=0x%x", fapi::RC_REPAIR_RING_NOT_FOUND, static_cast<uint32_t>(l_fapirc) ); fapiLogError(l_fapirc); - return; } // ---------------------------------------------------------------- // Pass in a NULL pointer with a valid ringId/chipletId, should // return with correct length and successful return code. // ---------------------------------------------------------------- - TS_TRACE( "testRepairRings: get size of ring(from set) %d ", i ); + TS_TRACE( "testRepairRings: get size of ring(from set) %d ", TEST_INDEX ); l_ringBufsize = 0x0; - l_ringId = l_ringModifiers[i].ringIdval; - l_chipletId = l_ringModifiers[i].chipletIdval; + l_ringId = l_ringModifiers[TEST_INDEX].ringIdval; + l_chipletId = l_ringModifiers[TEST_INDEX].chipletIdval; l_fapirc = setMvpdRing( MVPD_RECORD_CP00, MVPD_KEYWORD_PDR, l_fapi_cpu_target, @@ -587,17 +751,110 @@ public: if ( l_fapirc != fapi::RC_MVPD_RING_FUNC_INVALID_PARAMETER ) { // note: "uint32_t" below is an _operator_ of fapi::ReturnCode - TS_FAIL( "testRepairRings: setMvpdRing rc FAIL: 0x%x, 0x%x", + TS_FAIL( "testRepairRings: setMvpdRing rc FAIL 5: exp=0x%x, act=0x%x", fapi::RC_MVPD_RING_FUNC_INVALID_PARAMETER, static_cast<uint32_t>(l_fapirc)); fapiLogError(l_fapirc); - return; } -#endif // RTC 39177 - // delete allocated space + + // ---------------------------------------------------------------- + // Pass in an invalid chiplet id with a valid ring, should fail + // ---------------------------------------------------------------- + l_ringBufsize = l_bufsize; + l_ringId = l_ringModifiers[TEST_INDEX].ringIdval; + l_chipletId = 0x22; + TS_TRACE("testRepairRing:invalid chiplet ring=0x%X chiplet=0x%X size=0x%x", + l_ringId, + l_chipletId, + l_ringBufsize ); + l_fapirc = getMvpdRing( MVPD_RECORD_CP00, + MVPD_KEYWORD_PDR, + l_fapi_cpu_target, + l_chipletId, + l_ringId, + l_pRingBuf, + l_ringBufsize ); + + if ( l_fapirc != fapi::RC_REPAIR_RING_NOT_FOUND ) + { + // note: "uint32_t" below is an _operator_ of fapi::ReturnCode + TS_FAIL("testRepairRings:invalid chipletid rc FAIL: exp=0x%x, act=0x%x", + fapi::RC_REPAIR_RING_NOT_FOUND, + static_cast<uint32_t>(l_fapirc)); + + fapiLogError(l_fapirc); + } + + } + + //-- Put the original data back into the vpd + for( std::list<saveRestoreData_t>::iterator sv = l_srData.begin(); + sv != l_srData.end(); + ++sv ) + { + if( sv->target == NULL ) + { + continue; + } + + if( sv->CP00_pdG != NULL ) + { + l_errhdl = deviceWrite( sv->target, + sv->CP00_pdG, + sv->CP00_pdG_size, + DEVICE_MVPD_ADDRESS( MVPD_RECORD_CP00, + MVPD_KEYWORD_PDG ) ); + if( l_errhdl ) + { + TS_FAIL("Error restoring CP00/#G to %.8X", + TARGETING::get_huid(sv->target)); + errlCommit( l_errhdl, VPD_COMP_ID ); + } + delete[] sv->CP00_pdG; + sv->CP00_pdG = NULL; + } + + if( sv->CP00_pdR != NULL ) + { + l_errhdl = deviceWrite( sv->target, + sv->CP00_pdR, + sv->CP00_pdR_size, + DEVICE_MVPD_ADDRESS( MVPD_RECORD_CP00, + MVPD_KEYWORD_PDR ) ); + if( l_errhdl ) + { + TS_FAIL("Error restoring CP00/#R to %.8X", + TARGETING::get_huid(sv->target)); + errlCommit( l_errhdl, VPD_COMP_ID ); + } + delete[] sv->CP00_pdR; + sv->CP00_pdR = NULL; + } + } + //-- + + // delete allocated space + if( l_pRingBuf ) + { delete[] l_pRingBuf; } + for( std::list<saveRestoreData_t>::iterator sv = l_srData.begin(); + sv != l_srData.end(); + ++sv ) + { + if( sv->CP00_pdG != NULL ) + { + delete[] sv->CP00_pdG; + sv->CP00_pdG = NULL; + } + if( sv->CP00_pdR != NULL ) + { + delete[] sv->CP00_pdR; + sv->CP00_pdR = NULL; + } + } + TS_TRACE( "testRepairRings exit" ); } diff --git a/src/usr/vpd/makefile b/src/usr/vpd/makefile index 5834a325c..36d41d0db 100644 --- a/src/usr/vpd/makefile +++ b/src/usr/vpd/makefile @@ -27,7 +27,8 @@ OBJS = vpd.o spd.o mvpd.o dimmPres.o SUBDIRS = test.d -BINARY_FILES = $(IMGDIR)/procmvpd.dat:fd9fac85d9132c287f81468045c79f1c98409811 -BINARY_FILES += $(IMGDIR)/dimmspd.dat:9a6e6b6a7f6d3fc77a12d38537279d402124d699 +BINARY_FILES = $(IMGDIR)/dimmspd.dat:9a6e6b6a7f6d3fc77a12d38537279d402124d699 +#BINARY_FILES += $(IMGDIR)/procmvpd.dat:fb03d27717e1f0d36bb4582a07b5aaaf90de41d6 +BINARY_FILES += $(IMGDIR)/procmvpd.dat:dc85f0e2f7b26f3928c817be3f0c37a9cc0e0bed include ${ROOTPATH}/config.mk diff --git a/src/usr/vpd/mvpd.C b/src/usr/vpd/mvpd.C index cf935758e..30d1f3c62 100755 --- a/src/usr/vpd/mvpd.C +++ b/src/usr/vpd/mvpd.C @@ -75,7 +75,7 @@ uint64_t g_mvpdPnorAddr = 0x0; // By setting to false, allows debug at a later time by allowing to // substitute a binary file (procmvpd.dat) into PNOR. -const bool g_readPNOR = true; +const bool g_usePNOR = true; /** @@ -219,6 +219,9 @@ errlHndl_t mvpdWrite ( DeviceFW::OperationType i_opType, va_list i_args ) { errlHndl_t err = NULL; + const char * recordName = NULL; + const char * keywordName = NULL; + uint16_t recordOffset = 0x0; input_args_t args; args.record = ((mvpdRecord)va_arg( i_args, uint64_t )); args.keyword = ((mvpdKeyword)va_arg( i_args, uint64_t )); @@ -228,26 +231,51 @@ errlHndl_t mvpdWrite ( DeviceFW::OperationType i_opType, do { - // TODO - This will be implemented with story 39177 - TRACFCOMP( g_trac_mvpd, - ERR_MRK"MVPD Writes are not supported yet!" ); + // Get the Record/keyword names + err = mvpdTranslateRecord( args.record, + recordName ); - /*@ - * @errortype - * @reasoncode VPD::VPD_OPERATION_NOT_SUPPORTED - * @severity ERRORLOG::ERRL_SEV_UNRECOVERABLE - * @moduleid VPD::VPD_MVPD_WRITE - * @userdata1 Requested Record - * @userdata2 Requested Keyword - * @devdesc MVPD Writes are not supported currently. - */ - err = new ERRORLOG::ErrlEntry( ERRORLOG::ERRL_SEV_UNRECOVERABLE, - VPD::VPD_MVPD_WRITE, - VPD::VPD_OPERATION_NOT_SUPPORTED, - args.record, - args.keyword ); + if( err ) + { + break; + } + + err = mvpdTranslateKeyword( args.keyword, + keywordName ); + + if( err ) + { + break; + } + + TRACSCOMP( g_trac_mvpd, + INFO_MRK"Write record (%s) and Keyword (%s)", + recordName, keywordName ); + + // Get the offset of the record requested + err = mvpdFindRecordOffset( recordName, + recordOffset, + i_target, + args ); - break; + if( err ) + { + break; + } + + // use record offset to find/read the keyword + err = mvpdWriteKeyword( keywordName, + recordName, + recordOffset, + i_target, + io_buffer, + io_buflen, + args ); + + if( err ) + { + break; + } } while( 0 ); TRACSSCOMP( g_trac_mvpd, @@ -497,220 +525,56 @@ errlHndl_t mvpdRetrieveKeyword ( const char * i_keywordName, input_args_t i_args ) { errlHndl_t err = NULL; - uint16_t offset = i_offset; - uint16_t recordSize = 0x0; - uint16_t keywordSize = 0x0; - char record[RECORD_BYTE_SIZE] = { '\0' }; - char keyword[KEYWORD_BYTE_SIZE] = { '\0' }; - bool matchFound = false; TRACSSCOMP( g_trac_mvpd, ENTER_MRK"mvpdRetrieveKeyword()" ); do { - // Read size of Record - err = mvpdFetchData( offset, - RECORD_ADDR_BYTE_SIZE, - &recordSize, - i_target ); - offset += RECORD_ADDR_BYTE_SIZE; - + // First go find the keyword in memory + size_t keywordSize = 0x0; + uint64_t byteAddr = 0x0; + err = mvpdFindKeywordAddr( i_keywordName, + i_recordName, + i_offset, + i_target, + keywordSize, + byteAddr, + i_args ); if( err ) { break; } - // Byte Swap - recordSize = le16toh( recordSize ); - - // Skip 3 bytes - RT - // Read 4 bytes ( Record name ) - compare with expected - offset += RT_SKIP_BYTES; - err = mvpdFetchData( offset, - RECORD_BYTE_SIZE, - record, - i_target ); - offset += RECORD_BYTE_SIZE; - - if( err ) + // If the buffer is NULL, return the keyword size in io_buflen + if( NULL == io_buffer ) { + io_buflen = keywordSize; break; } - if( memcmp( record, i_recordName, RECORD_BYTE_SIZE ) ) + // check size of usr buffer with io_buflen + err = checkBufferSize( io_buflen, + (size_t)keywordSize ); + if( err ) { - TRACFCOMP( g_trac_mvpd, - ERR_MRK"Record(%s) for offset (0x%04x) did not match " - "expected record(%s)!", - record, - i_offset, - i_recordName ); - - /*@ - * @errortype - * @reasoncode VPD::VPD_RECORD_MISMATCH - * @severity ERRORLOG::ERRL_SEV_UNRECOVERABLE - * @moduleid VPD::VPD_MVPD_RETRIEVE_KEYWORD - * @userdata1 Current offset into MVPD - * @userdata2 Start of Record offset - * @devdesc Record name does not match value expected for - * offset read. - */ - err = new ERRORLOG::ErrlEntry( ERRORLOG::ERRL_SEV_UNRECOVERABLE, - VPD::VPD_MVPD_RETRIEVE_KEYWORD, - VPD::VPD_RECORD_MISMATCH, - offset, - i_offset ); - // Add trace so we see what record was being compared - err->collectTrace( "MVPD" ); - break; } - // While size < size of record - // Size of record is the input offset, plus the record size, plus - // 2 bytes for the size value. - while( ( offset < (recordSize + i_offset + RECORD_ADDR_BYTE_SIZE) ) ) - { - TRACDCOMP( g_trac_mvpd, - INFO_MRK"Looking for keyword, reading offset: 0x%04x", - offset ); - - // read keyword name (2 bytes) - err = mvpdFetchData( offset, - KEYWORD_BYTE_SIZE, - keyword, - i_target ); - offset += KEYWORD_BYTE_SIZE; - - if( err ) - { - break; - } - - TRACDCOMP( g_trac_mvpd, - INFO_MRK"Read keyword name: %s", - keyword ); - - // Check if we're reading a '#' keyword. They have a 2 byte size - uint32_t keywordLength = KEYWORD_SIZE_BYTE_SIZE; - bool isPoundKwd = false; - if( !(memcmp( keyword, "#", 1 )) ) - { - TRACDCOMP( g_trac_mvpd, - INFO_MRK"Reading # keyword, adding 1 byte to size " - "to read!" ); - isPoundKwd = true; - keywordLength++; - } - - // Read keyword size - err = mvpdFetchData( offset, - keywordLength, - &keywordSize, - i_target ); - offset += keywordLength; - - if( err ) - { - break; - } - - if( isPoundKwd ) - { - // Swap it since 2 byte sizes are byte swapped. - keywordSize = le16toh( keywordSize ); - } - else - { - keywordSize = keywordSize >> 8; - } - - TRACDCOMP( g_trac_mvpd, - INFO_MRK"Read keyword size: 0x%04x", - keywordSize ); - - // if keyword equal i_keywordName - if( !(memcmp( keyword, i_keywordName, KEYWORD_BYTE_SIZE ) ) ) - { - matchFound = true; - - // If the buffer is NULL, return the keyword size in io_buflen - if( NULL == io_buffer ) - { - io_buflen = keywordSize; - break; - } - - // check size of usr buffer with io_buflen - err = checkBufferSize( io_buflen, - (size_t)keywordSize ); - - if( err ) - { - break; - } - - // Read keyword data into io_buffer - err = mvpdFetchData( offset, - keywordSize, - io_buffer, - i_target ); - - if( err ) - { - break; - } - io_buflen = keywordSize; - - // found our match, break out - break; - } - else - { - // set offset to next keyword (based on current keyword size) - offset += keywordSize; - } - } - - if( err || - matchFound ) + // Read keyword data into io_buffer + err = mvpdFetchData( i_offset+byteAddr, + keywordSize, + io_buffer, + i_target ); + if( err ) { break; } - } while( 0 ); - // If keyword not found in expected Record, flag error. - if( !matchFound && - NULL == err ) - { - TRACFCOMP( g_trac_mvpd, - ERR_MRK"No matching %s keyword found within %s record!", - i_keywordName, - i_recordName ); - - /*@ - * @errortype - * @reasoncode VPD::VPD_KEYWORD_NOT_FOUND - * @severity ERRORLOG::ERRL_SEV_UNRECOVERABLE - * @moduleid VPD::VPD_MVPD_RETRIEVE_KEYWORD - * @userdata1 Start of Record Offset - * @userdata2[0:31] Requested Record - * @userdata2[32:63] Requested Keyword - * @devdesc Keyword was not found in Record starting at given - * offset. - */ - err = new ERRORLOG::ErrlEntry( ERRORLOG::ERRL_SEV_UNRECOVERABLE, - VPD::VPD_MVPD_RETRIEVE_KEYWORD, - VPD::VPD_KEYWORD_NOT_FOUND, - i_offset, - TWO_UINT32_TO_UINT64( i_args.record, - i_args.keyword ) ); + // Everything worked + io_buflen = keywordSize; - // Add trace so we know what Record/Keyword was missing - err->collectTrace( "MVPD" ); - } + } while(0); TRACSSCOMP( g_trac_mvpd, EXIT_MRK"mvpdRetrieveKeyword()" ); @@ -734,7 +598,7 @@ errlHndl_t mvpdFetchData ( uint64_t i_byteAddr, do { - if( g_readPNOR ) + if( likely( g_usePNOR ) ) { // Call a function in the common VPD code VPD::pnorInformation info; @@ -945,5 +809,335 @@ bool compareKeywords ( const mvpdKeywordInfo e1, return false; } +// ------------------------------------------------------------------ +// mvpdFindKeywordAddr +// ------------------------------------------------------------------ +errlHndl_t mvpdFindKeywordAddr ( const char * i_keywordName, + const char * i_recordName, + uint16_t i_offset, + TARGETING::Target * i_target, + size_t& o_keywordSize, + uint64_t& o_byteAddr, + input_args_t i_args ) +{ + errlHndl_t err = NULL; + uint16_t offset = i_offset; + uint16_t recordSize = 0x0; + uint16_t keywordSize = 0x0; + char record[RECORD_BYTE_SIZE] = { '\0' }; + char keyword[KEYWORD_BYTE_SIZE] = { '\0' }; + bool matchFound = false; + + TRACSSCOMP( g_trac_mvpd, + ENTER_MRK"mvpdFindKeywordAddr()" ); + + do + { + // Read size of Record + err = mvpdFetchData( offset, + RECORD_ADDR_BYTE_SIZE, + &recordSize, + i_target ); + offset += RECORD_ADDR_BYTE_SIZE; + + if( err ) + { + break; + } + + // Byte Swap + recordSize = le16toh( recordSize ); + + // Skip 3 bytes - RT + // Read 4 bytes ( Record name ) - compare with expected + offset += RT_SKIP_BYTES; + err = mvpdFetchData( offset, + RECORD_BYTE_SIZE, + record, + i_target ); + offset += RECORD_BYTE_SIZE; + + if( err ) + { + break; + } + + if( memcmp( record, i_recordName, RECORD_BYTE_SIZE ) ) + { + TRACFCOMP( g_trac_mvpd, + ERR_MRK"Record(%s) for offset (0x%04x) did not match " + "expected record(%s)!", + record, + i_offset, + i_recordName ); + + /*@ + * @errortype + * @reasoncode VPD::VPD_RECORD_MISMATCH + * @severity ERRORLOG::ERRL_SEV_UNRECOVERABLE + * @moduleid VPD::VPD_MVPD_FIND_KEYWORD_ADDR + * @userdata1 Current offset into MVPD + * @userdata2 Start of Record offset + * @devdesc Record name does not match value expected for + * offset read. + */ + err = new ERRORLOG::ErrlEntry( ERRORLOG::ERRL_SEV_UNRECOVERABLE, + VPD::VPD_MVPD_FIND_KEYWORD_ADDR, + VPD::VPD_RECORD_MISMATCH, + offset, + i_offset ); + // Add trace so we see what record was being compared + err->collectTrace( "MVPD" ); + + break; + } + + // While size < size of record + // Size of record is the input offset, plus the record size, plus + // 2 bytes for the size value. + while( ( offset < (recordSize + i_offset + RECORD_ADDR_BYTE_SIZE) ) ) + { + TRACDCOMP( g_trac_mvpd, + INFO_MRK"Looking for keyword, reading offset: 0x%04x", + offset ); + + // read keyword name (2 bytes) + err = mvpdFetchData( offset, + KEYWORD_BYTE_SIZE, + keyword, + i_target ); + offset += KEYWORD_BYTE_SIZE; + + if( err ) + { + break; + } + + TRACDCOMP( g_trac_mvpd, + INFO_MRK"Read keyword name: %s", + keyword ); + + // Check if we're reading a '#' keyword. They have a 2 byte size + uint32_t keywordLength = KEYWORD_SIZE_BYTE_SIZE; + bool isPoundKwd = false; + if( !(memcmp( keyword, "#", 1 )) ) + { + TRACDCOMP( g_trac_mvpd, + INFO_MRK"Reading # keyword, adding 1 byte to size " + "to read!" ); + isPoundKwd = true; + keywordLength++; + } + + // Read keyword size + err = mvpdFetchData( offset, + keywordLength, + &keywordSize, + i_target ); + offset += keywordLength; + + if( err ) + { + break; + } + + if( isPoundKwd ) + { + // Swap it since 2 byte sizes are byte swapped. + keywordSize = le16toh( keywordSize ); + } + else + { + keywordSize = keywordSize >> 8; + } + + TRACDCOMP( g_trac_mvpd, + INFO_MRK"Read keyword size: 0x%04x", + keywordSize ); + + // if keyword equal i_keywordName + if( !(memcmp( keyword, i_keywordName, KEYWORD_BYTE_SIZE ) ) ) + { + // send back the relevant data + o_keywordSize = keywordSize; + o_byteAddr = offset - i_offset; //make address relative + + // found our match, break out + matchFound = true; + break; + } + else + { + // set offset to next keyword (based on current keyword size) + offset += keywordSize; + } + } + + if( err || + matchFound ) + { + break; + } + } while( 0 ); + + // If keyword not found in expected Record, flag error. + if( !matchFound && + NULL == err ) + { + TRACFCOMP( g_trac_mvpd, + ERR_MRK"No matching %s keyword found within %s record!", + i_keywordName, + i_recordName ); + + /*@ + * @errortype + * @reasoncode VPD::VPD_KEYWORD_NOT_FOUND + * @severity ERRORLOG::ERRL_SEV_UNRECOVERABLE + * @moduleid VPD::VPD_MVPD_FIND_KEYWORD_ADDR + * @userdata1 Start of Record Offset + * @userdata2[0:31] Requested Record + * @userdata2[32:63] Requested Keyword + * @devdesc Keyword was not found in Record starting at given + * offset. + */ + err = new ERRORLOG::ErrlEntry( ERRORLOG::ERRL_SEV_UNRECOVERABLE, + VPD::VPD_MVPD_FIND_KEYWORD_ADDR, + VPD::VPD_KEYWORD_NOT_FOUND, + i_offset, + TWO_UINT32_TO_UINT64( i_args.record, + i_args.keyword ) ); + + // Add trace so we know what Record/Keyword was missing + err->collectTrace( "MVPD" ); + } + + TRACSSCOMP( g_trac_mvpd, + EXIT_MRK"mvpdFindKeywordAddr()" ); + + return err; +} + + +// ------------------------------------------------------------------ +// mvpdWriteKeyword +// ------------------------------------------------------------------ +errlHndl_t mvpdWriteKeyword ( const char * i_keywordName, + const char * i_recordName, + uint16_t i_offset, + TARGETING::Target * i_target, + void * i_buffer, + size_t & i_buflen, + input_args_t i_args ) +{ + errlHndl_t err = NULL; + + TRACSSCOMP( g_trac_mvpd, + ENTER_MRK"mvpdWriteKeyword()" ); + + do + { + // Note, there is no way to tell if a keyword is writable without + // hardcoding it so we will just assume that the callers know + // what they are doing + + // First go find the keyword in memory + size_t keywordSize = 0x0; + uint64_t byteAddr = 0x0; + err = mvpdFindKeywordAddr( i_keywordName, + i_recordName, + i_offset, + i_target, + keywordSize, + byteAddr, + i_args ); + if( err ) + { + break; + } + + // check size of usr buffer with io_buflen + err = checkBufferSize( i_buflen, + keywordSize ); + if( err ) + { + break; + } + + // Now write it out to PNOR + if( likely( g_usePNOR ) ) + { + // Setup info needed to write from PNOR + VPD::pnorInformation info; + info.segmentSize = MVPD_SECTION_SIZE; + info.maxSegments = MVPD_MAX_SECTIONS; + info.pnorSection = PNOR::MODULE_VPD; + info.pnorSide = PNOR::CURRENT_SIDE; + err = VPD::writePNOR( i_offset+byteAddr, + keywordSize, + i_buffer, + i_target, + info, + g_mvpdPnorAddr, + &g_mvpdMutex ); + + if( err ) + { + break; + } + } + else + { + TRACFCOMP( g_trac_mvpd, + ERR_MRK"There is no way to write mvpd when not using PNOR!" ); + + /*@ + * @errortype + * @reasoncode VPD::VPD_INVALID_WRITE_METHOD + * @severity ERRORLOG::ERRL_SEV_UNRECOVERABLE + * @moduleid VPD::VPD_MVPD_WRITE_KEYWORD + * @userdata1 Write Offset + * @userdata2 Number of Bytes to Write + * @devdesc g_usePNOR is false, but there isn't an + * alternate way to write PNOR. + */ + err = new ERRORLOG::ErrlEntry( ERRORLOG::ERRL_SEV_UNRECOVERABLE, + VPD::VPD_MVPD_WRITE_KEYWORD, + VPD::VPD_INVALID_WRITE_METHOD, + byteAddr, + keywordSize ); + + break; + } + + VPD::VpdWriteMsg_t msgdata; + + // Quick double-check that our constants agree with the values in the + // VPD message structure + assert( sizeof(msgdata.record) == RECORD_BYTE_SIZE ); + assert( sizeof(msgdata.keyword) == KEYWORD_BYTE_SIZE ); + + // Finally, send it down to the FSP + msgdata.rec_num = i_target->getAttr<TARGETING::ATTR_VPD_REC_NUM>(); + memcpy( msgdata.record, i_recordName, RECORD_BYTE_SIZE ); + memcpy( msgdata.keyword, i_keywordName, KEYWORD_BYTE_SIZE ); + err = VPD::sendMboxWriteMsg( keywordSize, + i_buffer, + i_target, + VPD::VPD_WRITE_PROC, + msgdata ); + + if( err ) + { + break; + } + + + } while(0); + + TRACSSCOMP( g_trac_mvpd, + EXIT_MRK"mvpdWriteKeyword()" ); + + return err; +} } // end namespace MVPD diff --git a/src/usr/vpd/mvpd.H b/src/usr/vpd/mvpd.H index 680119fcd..26aba4c49 100755 --- a/src/usr/vpd/mvpd.H +++ b/src/usr/vpd/mvpd.H @@ -70,7 +70,7 @@ typedef struct typedef struct { mvpdRecord record; - char recordName[MVPD_LAST_RECORD]; + char recordName[RECORD_BYTE_SIZE+1]; } mvpdRecordInfo; /** @@ -78,7 +78,7 @@ typedef struct typedef struct { mvpdKeyword keyword; - char keywordName[MVPD_LAST_KEYWORD]; + char keywordName[KEYWORD_BYTE_SIZE+1]; } mvpdKeywordInfo; @@ -127,6 +127,7 @@ const mvpdRecordInfo mvpdRecords[] = { LWPD, "LWPD" }, { LWPE, "LWPE" }, { VWML, "VWML" }, + { MER0, "MER0" }, // ------------------------------------------------------------------- // DO NOT USE!! This is for test purposes ONLY! { MVPD_TEST_RECORD, "TEST" }, @@ -181,7 +182,7 @@ const mvpdKeywordInfo mvpdKeywords[] = { CH, "CH" }, // ------------------------------------------------------------------- // DO NOT USE!! This is for test purposes ONLY! - { MVPD_TEST_KEYWORD, "TEST" }, + { MVPD_TEST_KEYWORD, "XX" }, // ------------------------------------------------------------------- }; @@ -374,6 +375,66 @@ errlHndl_t mvpdRetrieveKeyword ( const char * i_keywordName, size_t & io_buflen, input_args_t i_args ); +/** + * @brief This function will write the required keyword into the MVPD data. + * + * @param[in] i_keywordName - String representation of the keyword. + * + * @param[in] i_recordName - String representation of the record. + * + * @param[in] i_offset - The offset to start writing. + * + * @param[in] i_target - The target to write data for. + * + * @param[in] i_buffer - The buffer to pull the data from. + * + * @param[in] i_buflen - Length of the buffer to be written + * to the target's VPD area. This value should indicate the size of the + * io_buffer parameter that has been allocated. + * + * @param[in] i_args - The input arguments. + * + * @return errHndl_t - NULL if successful, otherwise a pointer to the + * error log. + */ +errlHndl_t mvpdWriteKeyword ( const char * i_keywordName, + const char * i_recordName, + uint16_t i_offset, + TARGETING::Target * i_target, + void * i_buffer, + size_t & i_buflen, + input_args_t i_args ); + +/** + * @brief This function will locate the byte address of a keyword + * within its VPD section. + * + * @param[in] i_keywordName - String representation of the keyword. + * + * @param[in] i_recordName - String representation of the record. + * + * @param[in] i_offset - The offset to start writing. + * + * @param[in] i_target - The target to write data for. + * + * @param[out] o_keywordSize - Size of keyword in bytes. + * + * @param[out] o_byteAddr - Address of keyword, relative to this target's + * section. + * + * @param[in] i_args - The original input arguments. + * + * @return errHndl_t - NULL if successful, otherwise a pointer to the + * error log. + */ +errlHndl_t mvpdFindKeywordAddr ( const char * i_keywordName, + const char * i_recordName, + uint16_t i_offset, + TARGETING::Target * i_target, + size_t& o_keywordSize, + uint64_t& o_byteAddr, + input_args_t i_args ); + }; // end MVPD namespace diff --git a/src/usr/vpd/spd.C b/src/usr/vpd/spd.C index 27df54b2a..c62bd91f4 100755 --- a/src/usr/vpd/spd.C +++ b/src/usr/vpd/spd.C @@ -603,51 +603,7 @@ errlHndl_t spdWriteValue ( uint64_t i_keyword, } // Check write flag - if( entry->writable ) - { - // Check the Size to be equal to entry written - err = spdCheckSize( io_buflen, - entry->length, - i_keyword ); - - if( err ) - { - break; - } - - //@todo: RTC:39177 - Need to handle writes that are not on a - // byte boundary by reading the rest of the byte first - assert( (entry->length)%8 == 0 ); - - // Write value - err = spdWriteData( entry->offset, - io_buflen, - io_buffer, - i_target ); - - if( err ) - { - break; - } - - // Send mbox message with new data to Fsp - VPD::VpdWriteMsg_t msgdata; - msgdata.rec_num = i_target->getAttr<TARGETING::ATTR_VPD_REC_NUM>(); - //XXXX=offset relative to whole section - memcpy( msgdata.record, "XXXX", 4 ); - msgdata.offset = entry->offset; - err = VPD::sendMboxWriteMsg( io_buflen, - io_buffer, - i_target, - VPD::VPD_WRITE_DIMM, - msgdata ); - - if( err ) - { - break; - } - } - else + if( !(entry->writable) ) { // Error if not writable TRACFCOMP( g_trac_spd, @@ -674,6 +630,77 @@ errlHndl_t spdWriteValue ( uint64_t i_keyword, break; } + + // Check the Size to be equal to entry written + err = spdCheckSize( io_buflen, + entry->length, + i_keyword ); + + if( err ) + { + break; + } + + // We are not handling writes that are not on a byte + // boundary until we absolutely need to. There are + // no writable keywords that are not on byte boundaries + if( entry->useBitMask ) + { + // Error if not writable + TRACFCOMP( g_trac_spd, + ERR_MRK"Trying to write keyword (0x%04x) that is not a full byte size", + i_keyword ); + + /*@ + * @errortype + * @reasoncode VPD::VPD_UNSUPPORTED_WRITE + * @severity ERRORLOG::ERRL_SEV_UNRECOVERABLE + * @moduleid VPD::VPD_SPD_WRITE_VALUE + * @userdata1 SPD Keyword + * @userdata2[0:15] Keyword Length (in bytes) + * @userdata2[16:31] Keyword Bitmask + * @userdata2[32:63] Memory Type + * @devdesc Writes to non-byte SPD keywords are unsupported. + */ + err = new ERRORLOG::ErrlEntry( ERRORLOG::ERRL_SEV_UNRECOVERABLE, + VPD::VPD_SPD_WRITE_VALUE, + VPD::VPD_UNSUPPORTED_WRITE, + i_keyword, + TWO_UINT16_ONE_UINT32_TO_UINT64( + entry->length, + entry->bitMask, + i_DDRRev ) ); + + break; + } + + // Write value + err = spdWriteData( entry->offset, + io_buflen, + io_buffer, + i_target ); + + if( err ) + { + break; + } + + // Send mbox message with new data to Fsp + VPD::VpdWriteMsg_t msgdata; + msgdata.rec_num = i_target->getAttr<TARGETING::ATTR_VPD_REC_NUM>(); + //XXXX=offset relative to whole section + memcpy( msgdata.record, "XXXX", sizeof(msgdata.record) ); + msgdata.offset = entry->offset; + err = VPD::sendMboxWriteMsg( io_buflen, + io_buffer, + i_target, + VPD::VPD_WRITE_DIMM, + msgdata ); + + if( err ) + { + break; + } } while( 0 ); TRACSSCOMP( g_trac_spd, diff --git a/src/usr/vpd/spd.H b/src/usr/vpd/spd.H index b21d34bf9..267c5aa48 100755 --- a/src/usr/vpd/spd.H +++ b/src/usr/vpd/spd.H @@ -52,7 +52,7 @@ enum // Basic Memory Type Enumerations SPD_DDR3 = 0xB, - SPD_DDR4 = 0xC, // TODO - Proposed value from draft Spec. + SPD_DDR4 = 0xC, // @todo - Proposed value from draft Spec. (RTC:61138) }; /** diff --git a/src/usr/vpd/test/mvpdtest.H b/src/usr/vpd/test/mvpdtest.H index 9480f2881..a7685550e 100755 --- a/src/usr/vpd/test/mvpdtest.H +++ b/src/usr/vpd/test/mvpdtest.H @@ -66,43 +66,19 @@ mvpdTestData mvpdData[] = { CRP0, ED }, { CRP0, TE }, { CRP0, DD }, -// { CRP0, pdP }, // TODO - no #P in test data, pull for now RTC 51716 +// { CRP0, pdP }, // TODO - no #P in test data { CRP0, ST }, -// { CRP0, DN, 0x03 }, // TODO - This doesn't match documentation, -// pulling out for now { CP00, VD }, { CP00, PG }, -// { CP00, PK }, // TODO - no PK in test data. pull for now RTC 51716 +// { CP00, PK }, // TODO - no PK in test data { CP00, pdR }, { CP00, pdG }, { CP00, pdV }, { CP00, pdH }, -// { CP00, pdP }, // TODO - no #P in test data, pull for now RTC 51716 +// { CP00, pdP }, // TODO - no #P in test data { CP00, SB }, { CP00, MK }, { CP00, PB }, -/* // TODO no LRP0,LRP1,LRP2,LRP3 in test data, pull for now RTC 51716 - { LRP0, VD }, - { LRP0, pdV }, - { LRP0, pdP }, - { LRP0, pdM }, - { LRP0, CH }, - { LRP1, VD }, - { LRP1, pdV }, - { LRP1, pdP }, - { LRP1, pdM }, - { LRP1, CH }, - { LRP2, VD }, - { LRP2, pdV }, - { LRP2, pdP }, - { LRP2, pdM }, - { LRP2, CH }, - { LRP3, VD }, - { LRP3, pdV }, - { LRP3, pdP }, - { LRP3, pdM }, - { LRP3, CH }, -*/ { LRP4, VD }, { LRP4, pdV }, { LRP4, pdP }, @@ -118,7 +94,7 @@ mvpdTestData mvpdData[] = { LRP6, pdP }, { LRP6, pdM }, { LRP6, CH }, -/* // TODO no LRP7,LRP8,LRP9,LRPA,LRPB,LWPO,LWP1,LWP2,LWP3 in test data, pull for now RTC 51716 +/* // TODO no LRP7,LRP8,LRP9,LRPA,LRPB,LWPO,LWP1,LWP2,LWP3 in test data { LRP7, VD }, { LRP7, pdV }, { LRP7, pdP }, @@ -188,7 +164,7 @@ mvpdTestData mvpdData[] = { LWP6, pd2 }, { LWP6, pd3 }, { LWP6, IN }, -/* // TODO no LWP7,LWP8,LWP9,LWPA,LWPB in test data, pull for now RTC 51716 +/* // TODO no LWP7,LWP8,LWP9,LWPA,LWPB in test data { LWP7, VD }, { LWP7, pd2 }, { LWP7, pd3 }, @@ -233,7 +209,10 @@ mvpdTestData mvpdData[] = { VINI, HE }, { VINI, CT }, { VINI, HW }, - // TODO - Add VWML when available. + + { VWML, pdI }, + + { MER0, pdI }, }; void getProcTargets( TargetHandleList & o_procList ) @@ -400,13 +379,16 @@ class MVPDTest: public CxxTest::TestSuite errlHndl_t err = NULL; uint64_t cmds = 0x0; uint64_t fails = 0x0; + uint8_t* testData = NULL; + uint8_t* origData = NULL; + uint8_t* verifyData = NULL; TRACFCOMP( g_trac_mvpd, ENTER_MRK"testMvpdWrite()" ); do { - TARGETING::Target * theTarget = NULL; + TARGETING::Target * theTgt = NULL; // Get the processor targets TargetHandleList procList; @@ -422,11 +404,10 @@ class MVPDTest: public CxxTest::TestSuite } // Use the first Proc in the list - theTarget = procList[0]; + theTgt = procList[0]; // check to see if the target is functional - if - (!theTarget->getAttr<TARGETING::ATTR_HWAS_STATE>().functional) + if(!theTgt->getAttr<TARGETING::ATTR_HWAS_STATE>().functional) { TRACFCOMP( g_trac_mvpd, @@ -435,35 +416,142 @@ class MVPDTest: public CxxTest::TestSuite continue; // add continue because target is non functional } - size_t theSize = 1; - uint8_t * theData = new uint8_t[theSize]; + // first figure out how big the keyword is + cmds++; + size_t theSize = 0; + err = deviceRead( theTgt, + testData, + theSize, + DEVICE_MVPD_ADDRESS(VWML,pdI) ); + if( err ) + { + fails++; + TRACFCOMP( g_trac_mvpd, + ERR_MRK"testMvpdWrite() - failure getting size of VWML/#I, RC=%.4X", + err->reasonCode() ); + TS_FAIL( "testMvpdWrite() - Failure calling deviceRead!" ); + errlCommit( err, + VPD_COMP_ID ); + continue; + } + // save off the original data + origData = new uint8_t[theSize]; cmds++; - err = deviceWrite( theTarget, - theData, + err = deviceRead( theTgt, + origData, + theSize, + DEVICE_MVPD_ADDRESS(VWML,pdI) ); + if( err ) + { + fails++; + TRACFCOMP( g_trac_mvpd, + ERR_MRK"testMvpdWrite() - failure reading VWML/#I, RC=%.4X", + err->reasonCode() ); + TS_FAIL( "testMvpdWrite() - Failure calling deviceRead!" ); + errlCommit( err, + VPD_COMP_ID ); + continue; + } + TRACFBIN( g_trac_mvpd, "orig=", origData, theSize ); + + // fill it up with some dummy data + testData = new uint8_t[theSize]; + for( size_t x=0; x<theSize; x++ ) + { + testData[x] = x; + } + + // write the new data in + cmds++; + err = deviceWrite( theTgt, + testData, theSize, - DEVICE_MVPD_ADDRESS( CRP0, - pdP ) ); + DEVICE_MVPD_ADDRESS(VWML,pdI) ); + if( err ) + { + fails++; + TRACFCOMP( g_trac_mvpd, + ERR_MRK"testMvpdWrite() - failure writing VWML/#I, RC=%.4X", + err->reasonCode() ); + TS_FAIL( "testMvpdWrite() - Failure calling deviceWrite!" ); + errlCommit( err, + VPD_COMP_ID ); + continue; + } - if( NULL == err ) + // verify the data got written + cmds++; + verifyData = new uint8_t[theSize]; + err = deviceRead( theTgt, + verifyData, + theSize, + DEVICE_MVPD_ADDRESS(VWML,pdI) ); + if( err ) { fails++; - TS_FAIL( "testMvpdWrite - Expected error from write " - "attempt since its not supported!" ); + TRACFCOMP( g_trac_mvpd, + ERR_MRK"testMvpdWrite() - failure reading VWML/#I to verify, RC=%.4X", + err->reasonCode() ); + TS_FAIL( "testMvpdWrite() - Failure calling deviceRead!" ); + errlCommit( err, + VPD_COMP_ID ); + continue; } - else + TRACFBIN( g_trac_mvpd, "verif=", verifyData, theSize ); + + // compare what we read to what we wrote + if( memcmp( testData, verifyData, theSize ) ) { - delete err; - err = NULL; + fails++; + TRACFBIN( g_trac_mvpd, "wrote=", testData, theSize ); + TRACFBIN( g_trac_mvpd, "read=", verifyData, theSize ); + TS_FAIL( "testMvpdWrite - Data mismatch!" ); } - if( NULL != theData ) + // put the original data back to be a good citizen + cmds++; + err = deviceWrite( theTgt, + origData, + theSize, + DEVICE_MVPD_ADDRESS(VWML,pdI) ); + if( err ) { - delete theData; - theData = NULL; + fails++; + TRACFCOMP( g_trac_mvpd, + ERR_MRK"testMvpdWrite() - failure writing original data back into VWML/#I, RC=%.4X", + err->reasonCode() ); + TS_FAIL( "testMvpdWrite() - Failure calling deviceRead!" ); + errlCommit( err, + VPD_COMP_ID ); + continue; } + } while( 0 ); + if( NULL != testData ) + { + delete[] testData; + testData = NULL; + } + + if( NULL != origData ) + { + delete[] origData; + origData = NULL; + } + + if( NULL != verifyData ) + { + delete[] verifyData; + verifyData = NULL; + } + + if( cmds == 0 ) + { + TS_FAIL( "testMvpdWrite - No tests ran, something is wrong..." ); + } + TRACFCOMP( g_trac_mvpd, "testMvpdWrite - %d/%d fails", fails, cmds ); diff --git a/src/usr/vpd/test/spdtest.H b/src/usr/vpd/test/spdtest.H index 38b53bf23..5ef8a6107 100755 --- a/src/usr/vpd/test/spdtest.H +++ b/src/usr/vpd/test/spdtest.H @@ -207,6 +207,11 @@ class SPDTest: public CxxTest::TestSuite theData = NULL; } + if( cmds == 0 ) + { + TS_FAIL( "testSpdRead - No tests ran, something is wrong..." ); + } + TRACFCOMP( g_trac_spd, "testSpdRead - %d/%d fails", fails, cmds ); @@ -215,16 +220,17 @@ class SPDTest: public CxxTest::TestSuite /** * @brief Test a SPD Write */ - void testSpdWrite ( void ) + void testSpdWriteDQ ( void ) { errlHndl_t err = NULL; uint64_t cmds = 0x0; uint64_t fails = 0x0; - uint8_t * theData = NULL; + uint8_t * testData = NULL; uint8_t * origData = NULL; + uint8_t * verifyData = NULL; TRACFCOMP( g_trac_spd, - ENTER_MRK"testSpdWrite()" ); + ENTER_MRK"testSpdWriteDQ()" ); do { @@ -238,7 +244,7 @@ class SPDTest: public CxxTest::TestSuite ( NULL == dimmList[0] ) ) { TRACFCOMP( g_trac_spd, - "testSpdWrite - No DIMMs found!" ); + "testSpdWriteDQ - No DIMMs found!" ); break; } @@ -255,7 +261,7 @@ class SPDTest: public CxxTest::TestSuite if( err ) { fails++; - TS_FAIL( "testSpdWrite - failed to read memtype!" ); + TS_FAIL( "testSpdWriteDQ - failed to read memtype!" ); errlCommit( err, VPD_COMP_ID ); break; @@ -279,98 +285,301 @@ class SPDTest: public CxxTest::TestSuite { fails++; TRACFCOMP( g_trac_spd, - "testSpdWrite - memory type: 0x%04x", + "testSpdWriteDQ - memory type: 0x%04x", memType ); - TS_FAIL( "testSpdWrite - Unsupported Memory Type!" ); + TS_FAIL( "testSpdWriteDQ - Unsupported Memory Type!" ); errlCommit( err, VPD_COMP_ID ); break; } // Allocate data buffer - theData = static_cast<uint8_t*>(malloc( theSize )); + origData = static_cast<uint8_t*>(malloc( theSize )); // Read the data out first err = deviceRead( theTarget, - theData, + origData, theSize, DEVICE_SPD_ADDRESS( DIMM_BAD_DQ_DATA ) ); if( err ) { fails++; - TS_FAIL( "testSpdWrite - failed to read DIMM Bad DQ data!" ); + TS_FAIL( "testSpdWriteDQ - failed to read DIMM Bad DQ data!" ); errlCommit( err, VPD_COMP_ID ); break; } - origData = static_cast<uint8_t*>(malloc( theSize )); - memcpy( origData, theData, theSize ); + // fill it up with some dummy data + testData = static_cast<uint8_t*>(malloc( theSize )); + for( size_t x=0; x<theSize; x++ ) + { + testData[x] = x; + } - // Write the data back + // Write the test data in err = deviceWrite( theTarget, - theData, + testData, theSize, DEVICE_SPD_ADDRESS( DIMM_BAD_DQ_DATA ) ); if( err ) { - // No error returned, failure fails++; - TS_FAIL( "testSpdWrite - Error writing data to DIMM Bad DQ " + TS_FAIL( "testSpdWriteDQ - Error writing data to DIMM Bad DQ " "data" ); break; } - else - { - delete err; - err = NULL; - } // Read the data out again to check it + verifyData = static_cast<uint8_t*>(malloc( theSize )); err = deviceRead( theTarget, - theData, + verifyData, theSize, DEVICE_SPD_ADDRESS( DIMM_BAD_DQ_DATA ) ); if( err ) { fails++; - TS_FAIL( "testSpdWrite - failed to read DIMM Bad DQ data! [2]" ); + TS_FAIL( "testSpdWriteDQ - failed to read DIMM Bad DQ data! [2]" ); errlCommit( err, VPD_COMP_ID ); break; } - if( memcmp( theData, origData, theSize ) ) + if( memcmp( testData, verifyData, theSize ) ) { fails++; - TS_FAIL( "testSpdWrite - DIMM Bad DQ data does not match what we wrote!" ); - TRACFBIN( g_trac_spd, "orig=", origData, theSize ); - TRACFBIN( g_trac_spd, "read=", theData, theSize ); + TS_FAIL( "testSpdWriteDQ - DIMM Bad DQ data does not match what we wrote!" ); + TRACFBIN( g_trac_spd, "wrote=", testData, theSize ); + TRACFBIN( g_trac_spd, "read=", verifyData, theSize ); } + // put the original data back to be a good citizen + err = deviceWrite( theTarget, + origData, + theSize, + DEVICE_SPD_ADDRESS( DIMM_BAD_DQ_DATA ) ); + + if( err ) + { + fails++; + TS_FAIL( "testSpdWriteDQ - Error writing original data back to DIMM Bad DQ " + "data" ); + break; + } + + } while( 0 ); - if( NULL != theData ) + if( NULL != testData ) { - free( theData ); - theData = NULL; + delete testData; + testData = NULL; } if( NULL != origData ) { - free( origData ); - theData = NULL; + delete origData; + origData = NULL; + } + + if( NULL != verifyData ) + { + delete verifyData; + verifyData = NULL; + } + + if( cmds == 0 ) + { + TS_FAIL( "testSpdWriteDQ - No tests ran, something is wrong..." ); } TRACFCOMP( g_trac_spd, - "testSpdWrite - %d/%d fails", + "testSpdWriteDQ - %d/%d fails", fails, cmds ); } /** + * @brief Test a SPD Write to a value that is less than 1 byte + * + * Note - There are no writable keywords that fit this criteria + * so this test is disabled by default. To enable, modify the + * table in spdDDR3.H to make something writable. + */ + void _testSpdWriteSmall ( void ) + { + errlHndl_t err = NULL; + uint64_t cmds = 0x0; + uint64_t fails = 0x0; + uint8_t* testData = NULL; + uint8_t* origData = NULL; + + TRACFCOMP( g_trac_spd, + ENTER_MRK"testSpdWriteSmall()" ); + + do + { + TARGETING::Target * theTarget = NULL; + + // Get DIMM Targets + TargetHandleList dimmList; + getDIMMTargets( dimmList ); + + if( ( 0 == dimmList.size() ) || + ( NULL == dimmList[0] ) ) + { + TRACFCOMP( g_trac_spd, + "testSpdWriteSmall - No DIMMs found!" ); + break; + } + + // Operate on first DIMM + cmds++; + theTarget = dimmList[0]; + + // Get Memory Type + uint8_t memType = 0x0; + err = getMemType( theTarget, + memType ); + if( err ) + { + fails++; + TS_FAIL( "testSpdWriteSmall - failed to read memtype!" ); + errlCommit( err, + VPD_COMP_ID ); + break; + } + + // Get the size + size_t theSize = 0; + uint16_t theKeyword = INVALID_SPD_KEYWORD; + if( SPD_DDR3 == memType ) + { + for( uint32_t entry = 0; + entry < (sizeof(ddr3Data)/sizeof(ddr3Data[0])); + entry++ ) + { + if( ddr3Data[entry].writable + && ddr3Data[entry].useBitMask ) + { + theSize = ddr3Data[entry].length; + theKeyword = ddr3Data[entry].keyword; + TRACFCOMP( g_trac_spd, + "testSpdWriteSmall - Using keyword 0x%04x", + theKeyword ); + break; + } + } + } + else + { + fails++; + TRACFCOMP( g_trac_spd, + "testSpdWriteSmall - memory type: 0x%04x", + memType ); + TS_FAIL( "testSpdWriteSmall - Unsupported Memory Type!" ); + errlCommit( err, + VPD_COMP_ID ); + break; + } + + cmds++; + if( theKeyword == INVALID_SPD_KEYWORD ) + { + fails++; + TS_FAIL( "testSpdWriteSmall - Could not find a keyword to work with!" ); + break; + } + + // Read the data out + cmds++; + origData = new uint8_t[theSize]; + err = deviceRead( theTarget, + origData, + theSize, + DEVICE_SPD_ADDRESS( theKeyword ) ); + if( err ) + { + fails++; + TS_FAIL( "testSpdWriteSmall - failed to read keyword!" ); + errlCommit( err, + VPD_COMP_ID ); + break; + } + + // fill test array up with some dummy data + testData = new uint8_t[theSize]; + for( size_t x=0; x<theSize; x++ ) + { + testData[x] = 0x55; + } + + // Write the test data + cmds++; + err = deviceWrite( theTarget, + testData, + theSize, + DEVICE_SPD_ADDRESS( theKeyword ) ); + if( !err ) + { + fails++; + TS_FAIL( "testSpdWriteSmall - Did not get expected error writing data" ); + + // Put the original data back to be a good citizen + cmds++; + err = deviceWrite( theTarget, + origData, + theSize, + DEVICE_SPD_ADDRESS( theKeyword ) ); + if( err ) + { + fails++; + TS_FAIL( "testSpdWriteSmall - Error writing original data back" ); + } + + break; + } + else + { + cmds++; + if( err->reasonCode() != VPD::VPD_UNSUPPORTED_WRITE ) + { + fails++; + TRACFCOMP( g_trac_spd, + "testSpdWriteSmall - RC from write = 0x%04x", + err->reasonCode() ); + TS_FAIL( "testSpdWriteSmall - Did not get VPD_UNSUPPORTED_WRITE error writing data" ); + } + + delete err; + } + + } while( 0 ); + + if( NULL != testData ) + { + delete[] testData; + testData = NULL; + } + + if( NULL != origData ) + { + delete[] origData; + origData = NULL; + } + + if( cmds == 0 ) + { + TS_FAIL( "testSpdWriteSmall - No tests ran, something is wrong..." ); + } + + TRACFCOMP( g_trac_spd, + "testSpdWriteSmall - %d/%d fails", + fails, cmds ); + } + /** * @brief Test an invalid Keyword to a DIMM target. */ void testSpdInvalidKeyword ( void ) @@ -542,7 +751,7 @@ class SPDTest: public CxxTest::TestSuite err = NULL; } } while( 0 ); - + TRACFCOMP( g_trac_spd, "testSpdInvalidWrite - %d/%d fails", fails, cmds ); diff --git a/src/usr/vpd/vpd.C b/src/usr/vpd/vpd.C index e23279309..54fefa8b9 100644 --- a/src/usr/vpd/vpd.C +++ b/src/usr/vpd/vpd.C @@ -24,6 +24,7 @@ #include <errl/errlentry.H> #include <errl/errlmanager.H> #include <errl/errludtarget.H> +#include <vpd/vpdreasoncodes.H> #include "vpd.H" // ---------------------------------------------- @@ -261,12 +262,9 @@ errlHndl_t sendMboxWriteMsg ( size_t i_numBytes, msg->data[0] = i_record.data0; msg->data[1] = i_numBytes; - //should never need more than 4KB @fixme - assert( i_numBytes < PAGESIZE); - + //Copy the data into the message msg->extra_data = malloc( i_numBytes ); memcpy( msg->extra_data, i_data, i_numBytes ); - TRACFCOMP( g_trac_vpd, "extra_data=%p", msg->extra_data ); TRACFCOMP( g_trac_vpd, INFO_MRK"Send msg to FSP to write VPD type %.8X, record %d, offset 0x%X", |