summaryrefslogtreecommitdiffstats
path: root/src/usr/mvpd
diff options
context:
space:
mode:
Diffstat (limited to 'src/usr/mvpd')
-rw-r--r--src/usr/mvpd/makefile32
-rwxr-xr-xsrc/usr/mvpd/mvpd.C940
-rwxr-xr-xsrc/usr/mvpd/mvpd.H366
-rw-r--r--src/usr/mvpd/test/makefile28
-rwxr-xr-xsrc/usr/mvpd/test/mvpdtest.H727
5 files changed, 2093 insertions, 0 deletions
diff --git a/src/usr/mvpd/makefile b/src/usr/mvpd/makefile
new file mode 100644
index 000000000..06df7a80b
--- /dev/null
+++ b/src/usr/mvpd/makefile
@@ -0,0 +1,32 @@
+# IBM_PROLOG_BEGIN_TAG
+# This is an automatically generated prolog.
+#
+# $Source: src/usr/mvpd/makefile $
+#
+# 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
+ROOTPATH = ../../..
+MODULE = mvpd
+
+OBJS = mvpd.o
+
+SUBDIRS = test.d
+
+BINARY_FILES = $(IMGDIR)/procmvpd.dat:9db474cbbd661c54957cb3a6c83cfc768f457d0c
+
+include ${ROOTPATH}/config.mk
diff --git a/src/usr/mvpd/mvpd.C b/src/usr/mvpd/mvpd.C
new file mode 100755
index 000000000..9b83414e4
--- /dev/null
+++ b/src/usr/mvpd/mvpd.C
@@ -0,0 +1,940 @@
+// IBM_PROLOG_BEGIN_TAG
+// This is an automatically generated prolog.
+//
+// $Source: src/usr/mvpd/mvpd.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
+/**
+ * @file mvpd.C
+ *
+ * @brief Implementation of the MVPD device driver
+ *
+ */
+
+// ----------------------------------------------
+// Includes
+// ----------------------------------------------
+#include <string.h>
+#include <trace/interface.H>
+#include <errl/errlentry.H>
+#include <errl/errlmanager.H>
+#include <targeting/targetservice.H>
+#include <devicefw/driverif.H>
+#include <vfs/vfs.H>
+#include <mvpd/mvpdreasoncodes.H>
+#include <mvpd/mvpdenums.H>
+
+#include "mvpd.H"
+
+// ----------------------------------------------
+// Globals
+// ----------------------------------------------
+bool g_loadModule = true;
+mutex_t g_mvpdMutex = MUTEX_INITIALIZER;
+
+// ----------------------------------------------
+// Trace definitions
+// ----------------------------------------------
+trace_desc_t* g_trac_mvpd = NULL;
+TRAC_INIT( & g_trac_mvpd, "MVPD", 4096 );
+
+// ------------------------
+// Macros for unit testing
+//#define TRACUCOMP(args...) TRACFCOMP(args)
+#define TRACUCOMP(args...)
+//#define TRACSSCOMP(args...) TRACFCOMP(args)
+#define TRACSSCOMP(args...)
+
+
+// ----------------------------------------------
+// Defines
+// ----------------------------------------------
+
+
+namespace MVPD
+{
+
+/**
+* @brief This function compares 2 mvpd record values. Used for binary
+* search to find a match.
+*
+* @param[in] e1 - Entry 1 to be compared.
+*
+* @param[in] e2 - Entry 2 to be compared.
+*
+* @return bool - Whether or not the e2 value is larger than the e1 value.
+*/
+bool compareKeywords ( const mvpdKeywordInfo e1,
+ const mvpdKeywordInfo e2 );
+
+/**
+* @brief This function compares 2 mvpd keyword values. Used for binary
+* search to find a match.
+*
+* @param[in] e1 - Entry 1 to be compared.
+*
+* @param[in] e2 - Entry 2 to be compared.
+*
+* @return bool - Whether or not the e2 value is larger than the e1 value.
+ */
+bool compareRecords ( const mvpdRecordInfo e1,
+ const mvpdRecordInfo e2 );
+
+/**
+ * @brief Swap the 16 bit size read from MVPD since it is stored in the
+ * MVPD byte swapped.
+ *
+ * @param[in] i_size - The size value to be byte swapped.
+ *
+ * @return uint16_t - The byte swapped value.
+ */
+uint16_t swapByteSize ( uint16_t i_size );
+
+/**
+ * @brief This function compares sizes to be sure buffers are large enough
+ * to handle the data to be put in them. If it is not, it will return
+ * an error.
+ *
+ * @param[in] i_bufferSize - The size of the buffer to check.
+ *
+ * @param[in] i_expectedSize - The minimum size the buffer should be.
+ *
+ * @return errlHndl_t - An error log will be returned if the buffer is not
+ * large enough.
+ */
+errlHndl_t checkBufferSize( size_t i_bufferSize,
+ size_t i_expectedSize );
+
+
+// Register with the routing code
+DEVICE_REGISTER_ROUTE( DeviceFW::READ,
+ DeviceFW::MVPD,
+ TARGETING::TYPE_PROC,
+ mvpdRead );
+DEVICE_REGISTER_ROUTE( DeviceFW::WRITE,
+ DeviceFW::MVPD,
+ TARGETING::TYPE_PROC,
+ mvpdRead );
+
+
+// ------------------------------------------------------------------
+// mvpdRead
+// ------------------------------------------------------------------
+errlHndl_t mvpdRead ( DeviceFW::OperationType i_opType,
+ TARGETING::Target * i_target,
+ void * io_buffer,
+ size_t & io_buflen,
+ int64_t i_accessType,
+ 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 ));
+
+ TRACSSCOMP( g_trac_mvpd,
+ ENTER_MRK"mvpdRead()" );
+
+ do
+ {
+ // Get the Record/keyword names
+ err = mvpdTranslateRecord( args.record,
+ recordName );
+
+ if( err )
+ {
+ break;
+ }
+
+ err = mvpdTranslateKeyword( args.keyword,
+ keywordName );
+
+ if( err )
+ {
+ break;
+ }
+
+ TRACSCOMP( g_trac_mvpd,
+ INFO_MRK"Read record (%s) and Keyword (%s)",
+ recordName, keywordName );
+
+ // Get the offset of the record requested
+ err = mvpdFindRecordOffset( recordName,
+ recordOffset,
+ i_target,
+ args );
+
+ if( err )
+ {
+ break;
+ }
+
+ // use record offset to find/read the keyword
+ err = mvpdRetrieveKeyword( keywordName,
+ recordName,
+ recordOffset,
+ i_target,
+ io_buffer,
+ io_buflen,
+ args );
+
+ if( err )
+ {
+ break;
+ }
+ } while( 0 );
+
+ TRACSSCOMP( g_trac_mvpd,
+ EXIT_MRK"mvpdRead()" );
+
+ return err;
+}
+
+
+// ------------------------------------------------------------------
+// mvpdWrite
+// ------------------------------------------------------------------
+errlHndl_t mvpdWrite ( DeviceFW::OperationType i_opType,
+ TARGETING::Target * i_target,
+ void * io_buffer,
+ size_t & io_buflen,
+ int64_t i_accessType,
+ va_list i_args )
+{
+ errlHndl_t err = NULL;
+ input_args_t args;
+ args.record = ((mvpdRecord)va_arg( i_args, uint64_t ));
+ args.keyword = ((mvpdKeyword)va_arg( i_args, uint64_t ));
+
+ TRACSSCOMP( g_trac_mvpd,
+ ENTER_MRK"mvpdWrite()" );
+
+ do
+ {
+ TRACFCOMP( g_trac_mvpd,
+ ERR_MRK"MVPD Writes are not supported yet!" );
+
+ /*@
+ * @errortype
+ * @reasoncode MVPD_OPERATION_NOT_SUPPORTED
+ * @severity ERRORLOG::ERRL_SEV_UNRECOVERABLE
+ * @moduleid MVPD_WRITE
+ * @userdata1 Requested Record
+ * @userdata2 Requested Keyword
+ * @devdesc MVPD Writes are not supported currently.
+ */
+ err = new ERRORLOG::ErrlEntry( ERRORLOG::ERRL_SEV_UNRECOVERABLE,
+ MVPD_WRITE,
+ MVPD_OPERATION_NOT_SUPPORTED,
+ args.record,
+ args.keyword );
+
+ break;
+ } while( 0 );
+
+ TRACSSCOMP( g_trac_mvpd,
+ EXIT_MRK"mvpdWrite()" );
+
+ return err;
+}
+
+
+// ------------------------------------------------------------------
+// mvpdTranslateRecord
+// ------------------------------------------------------------------
+errlHndl_t mvpdTranslateRecord ( mvpdRecord i_record,
+ const char *& o_record )
+{
+ errlHndl_t err = NULL;
+ uint32_t arraySize = 0x0;
+
+ TRACSSCOMP( g_trac_mvpd,
+ ENTER_MRK"mvpdTranslateRecord()" );
+
+ do
+ {
+ arraySize = (sizeof(mvpdRecords)/sizeof(mvpdRecords[0]));
+ mvpdRecordInfo tmpRecord;
+ tmpRecord.record = i_record;
+ const mvpdRecordInfo * entry = std::lower_bound( mvpdRecords,
+ &mvpdRecords[arraySize],
+ tmpRecord,
+ compareRecords );
+
+ if( ( entry == &mvpdRecords[arraySize] )||
+ ( i_record != entry->record ) )
+ {
+ TRACFCOMP( g_trac_mvpd,
+ ERR_MRK"No matching Record (0x%04x) found!",
+ i_record );
+
+ /*@
+ * @errortype
+ * @reasoncode MVPD_RECORD_NOT_FOUND
+ * @severity ERRORLOG::ERRL_SEV_UNRECOVERABLE
+ * @moduleid MVPD_TRANSLATE_RECORD
+ * @userdata1 Record enumeration.
+ * @userdata2 <UNUSED>
+ * @devdesc The record enumeration did not have a
+ * corresponding string value.
+ */
+ err = new ERRORLOG::ErrlEntry( ERRORLOG::ERRL_SEV_UNRECOVERABLE,
+ MVPD_TRANSLATE_RECORD,
+ MVPD_RECORD_NOT_FOUND,
+ i_record,
+ 0x0 );
+
+ break;
+ }
+
+ o_record = entry->recordName;
+ TRACDCOMP( g_trac_mvpd,
+ "record name: %s",
+ entry->recordName );
+ } while( 0 );
+
+ TRACSSCOMP( g_trac_mvpd,
+ EXIT_MRK"mvpdTranslateRecord()" );
+
+ return err;
+}
+
+
+// ------------------------------------------------------------------
+// mvpdTranslateKeyword
+// ------------------------------------------------------------------
+errlHndl_t mvpdTranslateKeyword ( mvpdKeyword i_keyword,
+ const char *& o_keyword )
+{
+ errlHndl_t err = NULL;
+ uint32_t arraySize = 0x0;
+
+ TRACSSCOMP( g_trac_mvpd,
+ ENTER_MRK"mvpdTranslateKeyword()" );
+
+ do
+ {
+ arraySize = (sizeof(mvpdKeywords)/sizeof(mvpdKeywords[0]));
+ mvpdKeywordInfo tmpKeyword;
+ tmpKeyword.keyword = i_keyword;
+ const mvpdKeywordInfo * entry = std::lower_bound( mvpdKeywords,
+ &mvpdKeywords[arraySize],
+ tmpKeyword,
+ compareKeywords );
+
+ if( ( entry == &mvpdKeywords[arraySize] ) ||
+ ( i_keyword != entry->keyword ) )
+ {
+ TRACFCOMP( g_trac_mvpd,
+ ERR_MRK"No matching Keyword found!" );
+
+ /*@
+ * @errortype
+ * @reasoncode MVPD_KEYWORD_NOT_FOUND
+ * @severity ERRORLOG::ERRL_SEV_UNRECOVERABLE
+ * @moduleid MVPD_TRANSLATE_KEYWORD
+ * @userdata1 Keyword Enumeration
+ * @userdata2 <UNUSED>
+ * @devdesc The keyword enumeration did not have a
+ * corresponding string value.
+ */
+ err = new ERRORLOG::ErrlEntry( ERRORLOG::ERRL_SEV_UNRECOVERABLE,
+ MVPD_TRANSLATE_KEYWORD,
+ MVPD_KEYWORD_NOT_FOUND,
+ i_keyword,
+ 0x0 );
+
+ break;
+ }
+
+ o_keyword = entry->keywordName;
+ TRACDCOMP( g_trac_mvpd,
+ "keyword name: %s",
+ entry->keywordName );
+ } while( 0 );
+
+ TRACSSCOMP( g_trac_mvpd,
+ EXIT_MRK"mvpdTranslateKeyword()" );
+
+ return err;
+}
+
+
+// ------------------------------------------------------------------
+// mvpdFindRecordOffset
+// ------------------------------------------------------------------
+errlHndl_t mvpdFindRecordOffset ( const char * i_record,
+ uint16_t & o_offset,
+ TARGETING::Target * i_target,
+ input_args_t i_args )
+{
+ errlHndl_t err = NULL;
+ uint64_t tmpOffset = 0x0;
+// uint8_t * record = NULL;
+ char record[RECORD_BYTE_SIZE] = { '\0' };
+ uint16_t offset = 0x0;
+ bool matchFound = false;
+
+ TRACSSCOMP( g_trac_mvpd,
+ ENTER_MRK"mvpdFindRecordOffset()" );
+
+ do
+ {
+ // --------------------------------------
+ // Start reading at beginning of file
+ // First 256 bytes are the TOC
+ // --------------------------------------
+ // TOC Format is as follows:
+ // 8 bytes per entry - 32 entries possible
+ // Entry:
+ // byte 0 - 3: ASCII Record Name
+ // byte 4 - 5: Size (byte swapped)
+ // byte 6 - 7: UNUSED
+ // --------------------------------------
+ while( ( tmpOffset < 0x100 ) &&
+ !matchFound )
+ {
+ TRACDCOMP( g_trac_mvpd,
+ INFO_MRK"read offset: 0x%08x",
+ tmpOffset );
+
+ // Read Record Name
+ err = mvpdFetchData( tmpOffset,
+ RECORD_BYTE_SIZE,
+ record,
+ i_target );
+ tmpOffset += RECORD_BYTE_SIZE;
+
+ if( err )
+ {
+ break;
+ }
+
+ if( !(memcmp( record, i_record, RECORD_BYTE_SIZE )) )
+ {
+ matchFound = true;
+
+ // Read the matching records offset
+ err = mvpdFetchData( tmpOffset,
+ RECORD_ADDR_BYTE_SIZE,
+ &offset,
+ i_target );
+
+ if( err )
+ {
+ break;
+ }
+ }
+ tmpOffset += (RECORD_ADDR_BYTE_SIZE + RECORD_TOC_UNUSED);
+ }
+
+ if( err )
+ {
+ break;
+ }
+ } while( 0 );
+
+ if( !matchFound )
+ {
+ TRACFCOMP( g_trac_mvpd,
+ ERR_MRK"No matching Record (%s) found in TOC!",
+ i_record );
+
+ /*@
+ * @errortype
+ * @reasoncode MVPD_RECORD_NOT_FOUND
+ * @severity ERRORLOG::ERRL_SEV_UNRECOVERABLE
+ * @moduleid MVPD_FIND_RECORD_OFFSET
+ * @userdata1 Requested Record
+ * @userdata2 Requested Keyword
+ * @devdesc The requested record was not found in the MVPD TOC.
+ */
+ err = new ERRORLOG::ErrlEntry( ERRORLOG::ERRL_SEV_UNRECOVERABLE,
+ MVPD_FIND_RECORD_OFFSET,
+ MVPD_RECORD_NOT_FOUND,
+ i_args.record,
+ i_args.keyword );
+ // Add trace to the log so we know what record was being requested.
+ err->collectTrace( "MVPD" );
+ }
+
+ // Return the offset found, after byte swapping it.
+ o_offset = swapByteSize( offset );
+
+ TRACSSCOMP( g_trac_mvpd,
+ EXIT_MRK"mvpdFindRecordOffset()" );
+
+ return err;
+}
+
+
+// ------------------------------------------------------------------
+// mvpdRetrieveKeyword
+// ------------------------------------------------------------------
+errlHndl_t mvpdRetrieveKeyword ( const char * i_keywordName,
+ const char * i_recordName,
+ uint16_t i_offset,
+ TARGETING::Target * i_target,
+ void * io_buffer,
+ size_t & io_buflen,
+ input_args_t i_args )
+{
+ errlHndl_t err = NULL;
+ uint16_t offset = i_offset;
+ uint16_t recordSize = 0x0;
+ uint16_t keywordSize = 0x0;
+// uint8_t * record = NULL;
+// uint8_t * keyword = NULL;
+ 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;
+
+ if( err )
+ {
+ break;
+ }
+
+ // Byte Swap
+ recordSize = swapByteSize( 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 MVPD_RECORD_MISMATCH
+ * @severity ERRORLOG::ERRL_SEV_UNRECOVERABLE
+ * @moduleid 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,
+ MVPD_RETRIEVE_KEYWORD,
+ MVPD_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 = swapByteSize( 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;
+ // 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 )
+ {
+ 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 MVPD_KEYWORD_NOT_FOUND
+ * @severity ERRORLOG::ERRL_SEV_UNRECOVERABLE
+ * @moduleid 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,
+ MVPD_RETRIEVE_KEYWORD,
+ MVPD_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"mvpdRetrieveKeyword()" );
+
+ return err;
+}
+
+
+// ------------------------------------------------------------------
+// mvpdFetchData
+// ------------------------------------------------------------------
+errlHndl_t mvpdFetchData ( uint64_t i_byteAddr,
+ size_t i_numBytes,
+ void * o_data,
+ TARGETING::Target * i_target )
+{
+ errlHndl_t err = NULL;
+
+ TRACSSCOMP( g_trac_mvpd,
+ ENTER_MRK"mvpdFetchData()" );
+
+ do
+ {
+ // --------------------------------------------------------------------
+ // TODO - For now this code will call to read a specific binary file
+ // for every request. Eventually that will be replaced with a function
+ // that will read from the actual PNOR section that contains MVPD for
+ // each of the processors in the system.
+ // This will be done with Story 35835.
+ // --------------------------------------------------------------------
+ err = mvpdReadBinaryFile( i_byteAddr,
+ i_numBytes,
+ o_data );
+
+ if( err )
+ {
+ break;
+ }
+ } while( 0 );
+
+ TRACSSCOMP( g_trac_mvpd,
+ EXIT_MRK"mvpdFetchData()" );
+
+ return err;
+}
+
+
+// ------------------------------------------------------------------
+// mvpdReadBinaryFile
+// ------------------------------------------------------------------
+errlHndl_t mvpdReadBinaryFile ( uint64_t i_offset,
+ size_t i_numBytes,
+ void * o_data )
+{
+ errlHndl_t err = NULL;
+ const char * fileName = "procmvpd.dat";
+ const char * startAddr = NULL;
+ size_t fileSize;
+
+ TRACSSCOMP( g_trac_mvpd,
+ ENTER_MRK"mvpdReadBinaryFile()" );
+
+ do
+ {
+ if( g_loadModule )
+ {
+ mutex_lock( &g_mvpdMutex );
+
+ if( g_loadModule )
+ {
+ // Load the file
+ TRACUCOMP( g_trac_mvpd,
+ "Load file" );
+ err = VFS::module_load( fileName );
+
+ if( err )
+ {
+ TRACFCOMP( g_trac_mvpd,
+ ERR_MRK"Error opening binary MVPD file: %s",
+ fileName );
+ mutex_unlock( &g_mvpdMutex );
+
+ break;
+ }
+
+ g_loadModule = false;
+ }
+ mutex_unlock( &g_mvpdMutex );
+ }
+
+ // Get the starting address of the file/module
+ TRACUCOMP( g_trac_mvpd,
+ "Get starting address/size" );
+ err = VFS::module_address( fileName,
+ startAddr,
+ fileSize );
+
+ if( err )
+ {
+ TRACFCOMP( g_trac_mvpd,
+ ERR_MRK"Error getting starting address of binary MVPD "
+ "file: %s",
+ fileName );
+
+ break;
+ }
+
+ // Check that we can read the amount of data we need to from the
+ // file we just loaded
+ TRACUCOMP( g_trac_mvpd,
+ "Check Size vs file size" );
+ if( (i_offset + i_numBytes) > fileSize )
+ {
+ TRACFCOMP( g_trac_mvpd,
+ ERR_MRK"Unable to read %d bytes from %s at offset 0x%08x "
+ "because file size is only %d bytes!",
+ i_numBytes,
+ fileName,
+ i_offset,
+ fileSize );
+
+ /*@
+ * @errortype
+ * @reasoncode MVPD_INSUFFICIENT_FILE_SIZE
+ * @severity ERRORLOG::ERRL_SEV_UNRECOVERABLE
+ * @moduleid MVPD_READ_BINARY_FILE
+ * @userdata1 File Size
+ * @userdata2[0:31] Starting offset into file
+ * @userdata2[32:63] Number of bytes to read
+ * @devdesc File is not sufficiently large to read number of
+ * bytes at offset given without overrunning file.
+ */
+ err = new ERRORLOG::ErrlEntry( ERRORLOG::ERRL_SEV_UNRECOVERABLE,
+ MVPD_READ_BINARY_FILE,
+ MVPD_INSUFFICIENT_FILE_SIZE,
+ fileSize,
+ TWO_UINT32_TO_UINT64( i_offset,
+ fileSize ) );
+
+ break;
+ }
+
+ // Retrieve the data requested
+ TRACUCOMP( g_trac_mvpd,
+ "Copy data out of file" );
+ memcpy( o_data, (startAddr + i_offset), i_numBytes );
+ } while( 0 );
+
+ TRACSSCOMP( g_trac_mvpd,
+ EXIT_MRK"mvpdReadBinaryFile()" );
+
+ return err;
+}
+
+
+// ------------------------------------------------------------------
+// checkBufferSize
+// ------------------------------------------------------------------
+errlHndl_t checkBufferSize( size_t i_bufferSize,
+ size_t i_expectedSize )
+{
+ errlHndl_t err = NULL;
+
+ if( !(i_bufferSize >= i_expectedSize) )
+ {
+ TRACFCOMP( g_trac_mvpd,
+ ERR_MRK"Buffer size (%d) is not larger than expected size "
+ "(%d)",
+ i_bufferSize,
+ i_expectedSize );
+
+ /*@
+ * @errortype
+ * @reasoncode MVPD_INSUFFICIENT_BUFFER_SIZE
+ * @severity ERRORLOG::ERRL_SEV_UNRECOVERABLE
+ * @moduleid MVPD_CHECK_BUFFER_SIZE
+ * @userdata1 Buffer Size
+ * @userdata2 Expected Buffer Size
+ * @devdesc Buffer size was not greater than or equal to
+ * expected buffer size.
+ */
+ err = new ERRORLOG::ErrlEntry( ERRORLOG::ERRL_SEV_UNRECOVERABLE,
+ MVPD_CHECK_BUFFER_SIZE,
+ MVPD_INSUFFICIENT_BUFFER_SIZE,
+ i_bufferSize,
+ i_expectedSize );
+ }
+
+ return err;
+}
+
+
+// ------------------------------------------------------------------
+// compareRecords
+// ------------------------------------------------------------------
+bool compareRecords ( const mvpdRecordInfo e1,
+ const mvpdRecordInfo e2 )
+{
+ if( e2.record > e1.record )
+ return true;
+ else
+ return false;
+}
+
+
+// ------------------------------------------------------------------
+// compareKeywords
+// ------------------------------------------------------------------
+bool compareKeywords ( const mvpdKeywordInfo e1,
+ const mvpdKeywordInfo e2 )
+{
+ if( e2.keyword > e1.keyword )
+ return true;
+ else
+ return false;
+}
+
+
+// ------------------------------------------------------------------
+// swapByteSize
+// ------------------------------------------------------------------
+uint16_t swapByteSize ( uint16_t i_size )
+{
+ uint16_t swappedSize = i_size & 0x00FF;
+ uint16_t tmp = i_size & 0xFF00;
+ tmp = tmp >> 8;
+ swappedSize = swappedSize << 8;
+ swappedSize = swappedSize | tmp;
+ return swappedSize;
+}
+
+} // end namespace MVPD
diff --git a/src/usr/mvpd/mvpd.H b/src/usr/mvpd/mvpd.H
new file mode 100755
index 000000000..195016c1c
--- /dev/null
+++ b/src/usr/mvpd/mvpd.H
@@ -0,0 +1,366 @@
+// IBM_PROLOG_BEGIN_TAG
+// This is an automatically generated prolog.
+//
+// $Source: src/usr/mvpd/mvpd.H $
+//
+// 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
+#ifndef __MVPD_H
+#define __MVPD_H
+
+/**
+ * @file mvpd.H
+ *
+ * @brief Provides the interfaces for the MVPD device driver
+ *
+ */
+
+// ----------------------------------------------
+// Includes
+// ----------------------------------------------
+#include <errl/errlentry.H>
+
+namespace MVPD
+{
+
+/**
+* @brief Miscelaneous MVPD definitions
+*/
+enum
+{
+ RECORD_BYTE_SIZE = 4,
+ RECORD_ADDR_BYTE_SIZE = 2,
+ KEYWORD_BYTE_SIZE = 2,
+ KEYWORD_SIZE_BYTE_SIZE = 1,
+ RECORD_TOC_UNUSED = 2,
+ RT_SKIP_BYTES = 3,
+
+};
+
+/**
+* @brief Structure for all MVPD dd input parameter arguments
+*/
+typedef struct
+{
+ mvpdRecord record;
+ mvpdKeyword keyword;
+} input_args_t;
+
+/**
+ * @brief Structure of information needed to access requested
+ * record/keyword combinations.
+ */
+typedef struct
+{
+ mvpdRecord record;
+ char recordName[MVPD_LAST_RECORD];
+} mvpdRecordInfo;
+
+/**
+ */
+typedef struct
+{
+ mvpdKeyword keyword;
+ char keywordName[MVPD_LAST_KEYWORD];
+} mvpdKeywordInfo;
+
+
+/**
+ * @brief Conversion of MVPD Records to corresponding character representation.
+ */
+const mvpdRecordInfo mvpdRecords[] =
+{
+ // -------------------------------------------------------------------
+ // NOTE: This list must remain an ordered list! There will be a
+ // testcase that checks this. When adding new entries to the
+ // list, be sure that the keyword in each entry (value 0)
+ // are in ascending order.
+ // -------------------------------------------------------------------
+ { CRP0, "CRP0" },
+ { CP00, "CP00" },
+ { VINI, "VINI" },
+ { LRP0, "LRP0" },
+ { LRP1, "LRP1" },
+ { LRP2, "LRP2" },
+ { LRP3, "LRP3" },
+ { LRP4, "LRP4" },
+ { LRP5, "LRP5" },
+ { LRP6, "LRP6" },
+ { LRP7, "LRP7" },
+ { LRP8, "LRP8" },
+ { LRP9, "LRP9" },
+ { LRPA, "LRPA" },
+ { LRPB, "LRPB" },
+ { LWP0, "LWP0" },
+ { LWP1, "LWP1" },
+ { LWP2, "LWP2" },
+ { LWP3, "LWP3" },
+ { LWP4, "LWP4" },
+ { LWP5, "LWP5" },
+ { LWP6, "LWP6" },
+ { LWP7, "LWP7" },
+ { LWP8, "LWP8" },
+ { LWP9, "LWP9" },
+ { LWPA, "LWPA" },
+ { LWPB, "LWPB" },
+ { VWML, "VWML" },
+ // -------------------------------------------------------------------
+ // DO NOT USE!! This is for test purposes ONLY!
+ { MVPD_TEST_RECORD, "TEST" },
+ // -------------------------------------------------------------------
+};
+
+/**
+ * @brief Conversion of MVPD Keywords to corresponding character representation.
+ */
+const mvpdKeywordInfo mvpdKeywords[] =
+{
+ // -------------------------------------------------------------------
+ // NOTE: This list must remain an ordered list! There will be a
+ // testcase that checks this. When adding new entries to
+ // the list, be sure that the keyword in each entry (value 0)
+ // are in ascending order.
+ // -------------------------------------------------------------------
+ { VD, "VD" },
+ { ED, "ED" },
+ { TE, "TE" },
+ { DD, "DD" },
+ { pdP, "#P" },
+ { ST, "ST" },
+ { DN, "DN" },
+ { PG, "PG" },
+ { PK, "PK" },
+ { pdR, "#R" },
+ { pdV, "#V" },
+ { pdH, "#H" },
+ { SB, "SB" },
+ { DR, "DR" },
+ { VZ, "VZ" },
+ { CC, "CC" },
+ { CE, "CE" },
+ { FN, "FN" },
+ { PN, "PN" },
+ { SN, "SN" },
+ { PR, "PR" },
+ { HE, "HE" },
+ { CT, "CT" },
+ { HW, "HW" },
+ { pdM, "#M" },
+ { IN, "IN" },
+ { pd2, "#2" },
+ { pd3, "#3" },
+ { OC, "OC" },
+ { FO, "FO" },
+ { pdI, "#I" },
+ // -------------------------------------------------------------------
+ // DO NOT USE!! This is for test purposes ONLY!
+ { MVPD_TEST_KEYWORD, "TEST" },
+ // -------------------------------------------------------------------
+};
+
+
+/**
+ * @brief This function will perform the steps required to do a read from
+ * the Hostboot MVPD data.
+ *
+ * @param[in] i_opType - Operation Type - See DeviceFW::OperationType in
+ * driververif.H
+ *
+ * @param[in] i_target - Processor Target device
+ *
+ * @param [in/out] io_buffer - Pointer to the data that was read from
+ * the target device. It will also be used to contain data to
+ * be written to the device.
+ *
+ * @param [in/out] io_buflen - Length of the buffer to be read or written
+ * to/from the target. This value should indicate the size of the
+ * io_buffer parameter that has been allocated. Being returned it will
+ * indicate the number of valid bytes in the buffer being returned.
+ *
+ * @param [in] i_accessType - Access Type - See DeviceFW::AccessType in
+ * usrif.H
+ *
+ * @param [in] i_args - This is an argument list for the device driver
+ * framework.
+ *
+ * @return errlHndl_t - NULL if successful, otherwise a pointer to the
+ * error log.
+*/
+errlHndl_t mvpdRead ( DeviceFW::OperationType i_opType,
+ TARGETING::Target * i_target,
+ void * io_buffer,
+ size_t & io_buflen,
+ int64_t i_accessType,
+ va_list i_args );
+
+/**
+ * @brief This function will perform the steps required to do a write to
+ * the Hostboot MVPD data.
+ *
+ * @param[in] i_opType - Operation Type - See DeviceFW::OperationType in
+ * driververif.H
+ *
+ * @param[in] i_target - Processor Target device
+ *
+ * @param [in/out] io_buffer - Pointer to the data that was read from
+ * the target device. It will also be used to contain data to
+ * be written to the device.
+ *
+ * @param [in/out] io_buflen - Length of the buffer to be read or written
+ * to/from the target. This value should indicate the size of the
+ * io_buffer parameter that has been allocated. Being returned it will
+ * indicate the number of valid bytes in the buffer being returned.
+ *
+ * @param [in] i_accessType - Access Type - See DeviceFW::AccessType in
+ * usrif.H
+ *
+ * @param [in] i_args - This is an argument list for the device driver
+ * framework.
+ *
+ * @return errlHndl_t - NULL if successful, otherwise a pointer to the
+ * error log.
+*/
+errlHndl_t mvpdWrite ( DeviceFW::OperationType i_opType,
+ TARGETING::Target * i_target,
+ void * io_buffer,
+ size_t & io_buflen,
+ int64_t i_accessType,
+ va_list i_args );
+
+/**
+ * @brief This function actually reads the data from the source of the MVPD
+ * data.
+ *
+ * @param[in] i_byteAddr - The offset to be read.
+ *
+ * @param[in] i_numBytes - The number of bytes to read.
+ *
+ * @param[out] o_data - The data buffer where the data will be placed.
+ *
+ * @param[in] i_target - Processor Target device.
+ *
+ * @return errHndl_t - NULL if successful, otherwise a pointer to the
+ * error log.
+*/
+errlHndl_t mvpdFetchData ( uint64_t i_byteAddr,
+ size_t i_numBytes,
+ void * o_data,
+ TARGETING::Target * i_target );
+
+/**
+ * @brief This function reads a binary file that contains the MVPD data for
+ * all targets.
+ *
+ * @param[in] i_offset - The offset to read.
+ *
+ * @param[in] i_numBytes - The number of bytes to read.
+ *
+ * @param[out] o_data - The Data buffer where the data will be placed.
+ *
+ * @return errHndl_t - NULL if successful, otherwise a pointer to the
+ * error log.
+*/
+errlHndl_t mvpdReadBinaryFile ( uint64_t i_offset,
+ size_t i_numBytes,
+ void * o_data );
+
+/**
+ * @brief This function will translate the enumeration for the MVPD record
+ * into a char * variable to be used for comparing what was read from
+ * the MVPD data.
+ *
+ * @param[in] i_record - The record enumeration.
+ *
+ * @param[out] o_record - The char representation of the record.
+ *
+ * @return errHndl_t - NULL if successful, otherwise a pointer to the
+ * error log.
+ */
+errlHndl_t mvpdTranslateRecord ( mvpdRecord i_record,
+ const char *& o_record );
+
+/**
+ * @brief This function will translate the enumeration for the MVPD keyword
+ * into a char * variable to be used for comparing what was read from
+ * the MVPD data.
+ *
+ * @param[in] i_keyword - The keyword enumeration.
+ *
+ * @param[out] o_keyword - The char representation of the record.
+ *
+ * @return errHndl_t - NULL if successful, otherwise a pointer to the
+ * error log.
+ */
+errlHndl_t mvpdTranslateKeyword ( mvpdKeyword i_keyword,
+ const char *& o_keyword );
+
+/**
+ * @brief This function will read the MVPD TOC to find the offset where the
+ * given record is located within the chunk of data.
+ *
+ * @param[in] i_record - String value for the record to look for.
+ *
+ * @param[out] o_offset - The offset where the record is located.
+ *
+ * @param[in] i_target - The target to retrieve the data for.
+ *
+ * @param[in] i_args - The input arguments.
+ *
+ * @return errHndl_t - NULL if successful, otherwise a pointer to the
+ * error log.
+ */
+errlHndl_t mvpdFindRecordOffset ( const char * i_record,
+ uint16_t & o_offset,
+ TARGETING::Target * i_target,
+ input_args_t i_args );
+
+/**
+ * @brief This function will read the required keyword from 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 reading.
+ *
+ * @param[in] i_target - The target to retrieve data for.
+ *
+ * @param[out] io_buffer - The buffer to place the data in.
+ *
+ * @param[in/out] io_buflen - Length of the buffer to be read or written
+ * to/from the target. This value should indicate the size of the
+ * io_buffer parameter that has been allocated. Being returned it will
+ * indicate the number of valid bytes in the buffer being returned.
+ *
+ * @param[in] i_args - The input arguments.
+ *
+ * @return errHndl_t - NULL if successful, otherwise a pointer to the
+ * error log.
+ */
+errlHndl_t mvpdRetrieveKeyword ( const char * i_keywordName,
+ const char * i_recordName,
+ uint16_t i_offset,
+ TARGETING::Target * i_target,
+ void * io_buffer,
+ size_t & io_buflen,
+ input_args_t i_args );
+
+
+}; // end MVPD namespace
+
+#endif // __MVPD_H
diff --git a/src/usr/mvpd/test/makefile b/src/usr/mvpd/test/makefile
new file mode 100644
index 000000000..8c7f74570
--- /dev/null
+++ b/src/usr/mvpd/test/makefile
@@ -0,0 +1,28 @@
+# IBM_PROLOG_BEGIN_TAG
+# This is an automatically generated prolog.
+#
+# $Source: src/usr/mvpd/test/makefile $
+#
+# 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
+ROOTPATH = ../../../..
+
+MODULE = testmvpd
+TESTS = *.H
+
+include ${ROOTPATH}/config.mk
diff --git a/src/usr/mvpd/test/mvpdtest.H b/src/usr/mvpd/test/mvpdtest.H
new file mode 100755
index 000000000..6386dabff
--- /dev/null
+++ b/src/usr/mvpd/test/mvpdtest.H
@@ -0,0 +1,727 @@
+// IBM_PROLOG_BEGIN_TAG
+// This is an automatically generated prolog.
+//
+// $Source: src/usr/mvpd/test/mvpdtest.H $
+//
+// 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
+#ifndef __MVPDTEST_H
+#define __MVPDTEST_H
+
+/**
+ * @file mvpdtest.H
+ *
+ * @brief Test cases for MVPD code
+ */
+#include <sys/time.h>
+
+#include <cxxtest/TestSuite.H>
+#include <errl/errlmanager.H>
+#include <errl/errlentry.H>
+#include <devicefw/driverif.H>
+#include <targeting/predicates/predicatectm.H>
+
+#include <mvpd/mvpdenums.H>
+#include <mvpd/mvpdreasoncodes.H>
+#include "../mvpd.H"
+
+
+extern trace_desc_t* g_trac_mvpd;
+
+using namespace TARGETING;
+using namespace MVPD;
+
+/**
+ * @brief Structure to define record/keyword pairs for MVPD tests.
+ */
+struct mvpdTestData
+{
+ mvpdRecord record;
+ mvpdKeyword keyword;
+
+ // NOTE: current sizes will be based off of dummy data that we have
+ // now plus approximately 10% as a buffer for future growth. These
+ // may need to be tweaked later.
+ size_t size;
+};
+
+/**
+ * @brief Data sample to be used for MVPD testing.
+ * NOTE: By reading this entire list, it also validates that the records
+ * and keywords that we expect to be there are actually there...
+ */
+mvpdTestData mvpdData[] =
+{
+ { CRP0, VD, 0x04 },
+ { CRP0, ED, 0x23 },
+ { CRP0, TE, 0x13 },
+ { CRP0, DD, 0x07 },
+ { CRP0, pdP, 0x150 },
+ { CRP0, ST, 0x05 },
+// { CRP0, DN, 0x03 }, // TODO - This doesn't match documentation,
+// pulling out for now
+ { CP00, VD, 0x04 },
+ { CP00, PG, 0x44 },
+ { CP00, PK, 0x45 },
+ { CP00, pdR, 0x5f90 },
+ { CP00, pdV, 0x130 },
+ { CP00, pdH, 0x190 },
+ { CP00, pdP, 0x1c0 },
+ { CP00, SB, 0x15 },
+ { LRP0, VD, 0x04 },
+ { LRP0, pdV, 0x150 },
+ { LRP0, pdP, 0x380 },
+ { LRP0, pdM, 0x220},
+ { LRP1, VD, 0x04 },
+ { LRP1, pdV, 0x150 },
+ { LRP1, pdP, 0x380 },
+ { LRP1, pdM, 0x220},
+ { LRP2, VD, 0x04 },
+ { LRP2, pdV, 0x150 },
+ { LRP2, pdP, 0x380 },
+ { LRP2, pdM, 0x220},
+ { LRP3, VD, 0x04 },
+ { LRP3, pdV, 0x150 },
+ { LRP3, pdP, 0x380 },
+ { LRP3, pdM, 0x220},
+ { LRP4, VD, 0x04 },
+ { LRP4, pdV, 0x150 },
+ { LRP4, pdP, 0x380 },
+ { LRP4, pdM, 0x220},
+ { LRP5, VD, 0x04 },
+ { LRP5, pdV, 0x150 },
+ { LRP5, pdP, 0x380 },
+ { LRP5, pdM, 0x220},
+ { LRP6, VD, 0x04 },
+ { LRP6, pdV, 0x150 },
+ { LRP6, pdP, 0x380 },
+ { LRP6, pdM, 0x220},
+ { LRP7, VD, 0x04 },
+ { LRP7, pdV, 0x150 },
+ { LRP7, pdP, 0x380 },
+ { LRP7, pdM, 0x220},
+ { LRP8, VD, 0x04 },
+ { LRP8, pdV, 0x150 },
+ { LRP8, pdP, 0x380 },
+ { LRP8, pdM, 0x220},
+ { LRP9, VD, 0x04 },
+ { LRP9, pdV, 0x150 },
+ { LRP9, pdP, 0x380 },
+ { LRP9, pdM, 0x220},
+ { LRPA, VD, 0x04 },
+ { LRPA, pdV, 0x150 },
+ { LRPA, pdP, 0x380 },
+ { LRPA, pdM, 0x220},
+ { LRPB, VD, 0x04 },
+ { LRPB, pdV, 0x150 },
+ { LRPB, pdP, 0x380 },
+ { LRPB, pdM, 0x220},
+ { LWP0, VD, 0x04 },
+ { LWP0, pd2, 0x60 },
+ { LWP0, pd3, 0x60 },
+ { LWP0, IN, 0x19 },
+ { LWP1, VD, 0x04 },
+ { LWP1, pd2, 0x60 },
+ { LWP1, pd3, 0x60 },
+ { LWP1, IN, 0x19 },
+ { LWP2, VD, 0x04 },
+ { LWP2, pd2, 0x60 },
+ { LWP2, pd3, 0x60 },
+ { LWP2, IN, 0x19 },
+ { LWP3, VD, 0x04 },
+ { LWP3, pd2, 0x60 },
+ { LWP3, pd3, 0x60 },
+ { LWP3, IN, 0x19 },
+ { LWP4, VD, 0x04 },
+ { LWP4, pd2, 0x60 },
+ { LWP4, pd3, 0x60 },
+ { LWP4, IN, 0x19 },
+ { LWP5, VD, 0x04 },
+ { LWP5, pd2, 0x60 },
+ { LWP5, pd3, 0x60 },
+ { LWP5, IN, 0x19 },
+ { LWP6, VD, 0x04 },
+ { LWP6, pd2, 0x60 },
+ { LWP6, pd3, 0x60 },
+ { LWP6, IN, 0x19 },
+ { LWP7, VD, 0x04 },
+ { LWP7, pd2, 0x60 },
+ { LWP7, pd3, 0x60 },
+ { LWP7, IN, 0x19 },
+ { LWP8, VD, 0x04 },
+ { LWP8, pd2, 0x60 },
+ { LWP8, pd3, 0x60 },
+ { LWP8, IN, 0x19 },
+ { LWP9, VD, 0x04 },
+ { LWP9, pd2, 0x60 },
+ { LWP9, pd3, 0x60 },
+ { LWP9, IN, 0x19 },
+ { LWPA, VD, 0x04 },
+ { LWPA, pd2, 0x60 },
+ { LWPA, pd3, 0x60 },
+ { LWPA, IN, 0x19 },
+ { LWPB, VD, 0x04 },
+ { LWPB, pd2, 0x60 },
+ { LWPB, pd3, 0x60 },
+ { LWPB, IN, 0x19 },
+ { VINI, DR, 0x12 },
+ { VINI, VZ, 0x04 },
+ { VINI, CC, 0x06 },
+ { VINI, CE, 0x03 },
+ { VINI, FN, 0x09 },
+ { VINI, PN, 0x09 },
+ { VINI, SN, 0x0f },
+ { VINI, PR, 0x0a },
+ { VINI, HE, 0x06 },
+ { VINI, CT, 0x06 },
+ { VINI, HW, 0x04 },
+ // TODO - Add VWML when available.
+};
+
+void getProcTargets( TargetHandleList & o_procList )
+{
+ // Get top level system target
+ TARGETING::TargetService & tS = TARGETING::targetService();
+ TARGETING::Target * sysTarget = NULL;
+ tS.getTopLevelTarget( sysTarget );
+ assert( sysTarget != NULL );
+
+ // Get a Proc Target
+ TARGETING::PredicateCTM predProc( TARGETING::CLASS_CHIP,
+ TARGETING::TYPE_PROC );
+ tS.getAssociated( o_procList,
+ sysTarget,
+ TARGETING::TargetService::CHILD,
+ TARGETING::TargetService::ALL,
+ &predProc );
+
+ TRACDCOMP( g_trac_mvpd,
+ "getProcTargets() - found %d Processors",
+ o_procList.size() );
+
+ return;
+}
+
+class MVPDTest: public CxxTest::TestSuite
+{
+ public:
+
+ /**
+ * @brief This function will test MVPD reads.
+ */
+ void testMvpdRead ( void )
+ {
+ errlHndl_t err = NULL;
+ uint64_t cmds = 0x0;
+ uint64_t fails = 0x0;
+ uint64_t theRecord = 0x0;
+ uint64_t theKeyword = 0x0;
+
+ TRACFCOMP( g_trac_mvpd,
+ ENTER_MRK"testMvpdRead()" );
+
+ do
+ {
+ TARGETING::Target * theTarget = NULL;
+
+ // Get the processor targets
+ TargetHandleList procList;
+ getProcTargets( procList );
+
+ if( ( 0 == procList.size() ) ||
+ ( NULL == procList[0] ) )
+ {
+ TRACFCOMP( g_trac_mvpd,
+ "testMvpdRead() - No Proc Targets found!" );
+ }
+
+ // Use the first Proc in the list
+ theTarget = procList[0];
+
+ uint8_t * theData = NULL;
+ size_t theSize = 0;
+ const uint32_t numCmds = sizeof(mvpdData)/sizeof(mvpdData[0]);
+ for( uint32_t curCmd = 0; curCmd < numCmds; curCmd++ )
+ {
+ theSize = mvpdData[curCmd].size;
+ theData = static_cast<uint8_t*>(malloc( theSize ));
+
+ // Read record/keyword pair
+ cmds++;
+ theRecord = (uint64_t)mvpdData[curCmd].record;
+ theKeyword = (uint64_t)mvpdData[curCmd].keyword;
+ err = deviceRead( theTarget,
+ theData,
+ theSize,
+ DEVICE_MVPD_ADDRESS( theRecord,
+ theKeyword ) );
+
+ if( err )
+ {
+ fails++;
+ TRACFCOMP( g_trac_mvpd,
+ ERR_MRK"testMvpdRead() - Failure on Record: "
+ "0x%04x, keyword: 0x%04x, of size: 0x%04x "
+ "- test %d",
+ mvpdData[curCmd].record,
+ mvpdData[curCmd].keyword,
+ theSize, curCmd );
+ TS_FAIL( "testMvpdRead() - Failure during MVPD read!" );
+ errlCommit( err,
+ MVPD_COMP_ID );
+
+ // Free the data
+ if( NULL != theData )
+ {
+ free( theData );
+ theData = NULL;
+ }
+ continue;
+ }
+
+ TRACDCOMP( g_trac_mvpd,
+ INFO_MRK"testMvpdRead Results:" );
+ for( uint32_t i = 0; i < theSize; i++ )
+ {
+ TRACDCOMP( g_trac_mvpd,
+ INFO_MRK" Byte[%d]: 0x%02x",
+ i, theData[i] );
+ }
+
+ // Free the data
+ if( NULL != theData )
+ {
+ free( theData );
+ theData = NULL;
+ }
+ }
+ } while( 0 );
+
+ TRACFCOMP( g_trac_mvpd,
+ "testMvpdRead - %d/%d fails",
+ fails, cmds );
+ }
+
+ /**
+ * @brief This function will test MVPD writes.
+ */
+ void testMvpdWrite ( void )
+ {
+ errlHndl_t err = NULL;
+ uint64_t cmds = 0x0;
+ uint64_t fails = 0x0;
+
+ TRACFCOMP( g_trac_mvpd,
+ ENTER_MRK"testMvpdWrite()" );
+
+ do
+ {
+ TARGETING::Target * theTarget = NULL;
+
+ // Get the processor targets
+ TargetHandleList procList;
+ getProcTargets( procList );
+
+ if( ( 0 == procList.size() ) ||
+ ( NULL == procList[0] ) )
+ {
+ TRACFCOMP( g_trac_mvpd,
+ "testMvpdWrite() - No Proc Targets found!" );
+ }
+
+ // Use the first Proc in the list
+ theTarget = procList[0];
+ uint8_t * theData = NULL;
+ size_t theSize = 0;
+
+ cmds++;
+ err = deviceWrite( theTarget,
+ theData,
+ theSize,
+ DEVICE_MVPD_ADDRESS( CRP0,
+ pdP ) );
+
+ if( NULL == err )
+ {
+ fails++;
+ TS_FAIL( "testMvpdWrite - Expected error from write "
+ "attempt since its not supported!" );
+ }
+ else
+ {
+ delete err;
+ err = NULL;
+ }
+ } while( 0 );
+
+ TRACFCOMP( g_trac_mvpd,
+ "testMvpdWrite - %d/%d fails",
+ fails, cmds );
+ }
+
+ /**
+ * @brief This function will test that an error is generated when a record
+ * is passed in that cannot be found in the structure that defines the
+ * Records string representation.
+ */
+ void testMvpdInvalidRecord ( void )
+ {
+ errlHndl_t err = NULL;
+ uint64_t cmds = 0x0;
+ uint64_t fails = 0x0;
+
+ TRACFCOMP( g_trac_mvpd,
+ ENTER_MRK"testMvpdInvalidRecord()" );
+
+ do
+ {
+ TARGETING::Target * theTarget = NULL;
+
+ // Get the processor targets
+ TargetHandleList procList;
+ getProcTargets( procList );
+
+ if( ( 0 == procList.size() ) ||
+ ( NULL == procList[0] ) )
+ {
+ TRACFCOMP( g_trac_mvpd,
+ "testMvpdInvalidRecord() - No Proc Targets "
+ "found!" );
+ }
+
+ // Use the first Proc in the list
+ theTarget = procList[0];
+ uint8_t * theData = NULL;
+ size_t theSize = 0;
+
+ cmds++;
+ err = deviceRead( theTarget,
+ theData,
+ theSize,
+ DEVICE_MVPD_ADDRESS( MVPD_LAST_RECORD,
+ pdP ) );
+
+ if( NULL == err )
+ {
+ fails++;
+ TS_FAIL( "testMvpdInvalidRecord() - Error expected with "
+ "record of type MVPD_LAST_RECORD (0x%04x), but "
+ "no error returned!",
+ MVPD_LAST_RECORD );
+ }
+ else
+ {
+ delete err;
+ err = NULL;
+ }
+ } while( 0 );
+
+ TRACFCOMP( g_trac_mvpd,
+ "testMvpdInvalidRecord - %d/%d fails",
+ fails, cmds );
+ }
+
+ /**
+ * @brief This function will test for a record which is not in the TOC of
+ * the MVPD area.
+ */
+ void testMvpdMissingRecord ( void )
+ {
+ errlHndl_t err = NULL;
+ uint64_t cmds = 0x0;
+ uint64_t fails = 0x0;
+
+ TRACFCOMP( g_trac_mvpd,
+ ENTER_MRK"testMvpdMissingRecord()" );
+
+ do
+ {
+ TARGETING::Target * theTarget = NULL;
+
+ // Get the processor targets
+ TargetHandleList procList;
+ getProcTargets( procList );
+
+ if( ( 0 == procList.size() ) ||
+ ( NULL == procList[0] ) )
+ {
+ TRACFCOMP( g_trac_mvpd,
+ "testMvpdMissingRecord() - No Proc Targets found!" );
+ }
+
+ // Use the first Proc in the list
+ theTarget = procList[0];
+ uint8_t * theData = NULL;
+ size_t theSize = 0;
+
+ cmds++;
+ err = deviceRead( theTarget,
+ theData,
+ theSize,
+ DEVICE_MVPD_ADDRESS( MVPD_TEST_RECORD,
+ pdP ) );
+
+ if( NULL == err )
+ {
+ fails++;
+ TS_FAIL( "testMvpdMissingRecord() - ");
+ }
+ else
+ {
+ delete err;
+ err = NULL;
+ }
+ } while( 0 );
+
+ TRACFCOMP( g_trac_mvpd,
+ "testMvpdMissingRecord - %d/%d fails",
+ fails, cmds );
+ }
+
+ /**
+ * @brief This function will test for a keyword that cannot be found
+ * in the expected record
+ */
+ void testMvpdMissingKeyword ( void )
+ {
+ errlHndl_t err = NULL;
+ uint64_t cmds = 0x0;
+ uint64_t fails = 0x0;
+
+ TRACFCOMP( g_trac_mvpd,
+ ENTER_MRK"testMvpdMissingKeyword()" );
+
+ do
+ {
+ TARGETING::Target * theTarget = NULL;
+
+ // Get the processor targets
+ TargetHandleList procList;
+ getProcTargets( procList );
+
+ if( ( 0 == procList.size() ) ||
+ ( NULL == procList[0] ) )
+ {
+ TRACFCOMP( g_trac_mvpd,
+ "testMvpdMissingKeyword() - No Proc Targets found!" );
+ }
+
+ // Use the first Proc in the list
+ theTarget = procList[0];
+ uint8_t * theData = NULL;
+ size_t theSize = 0;
+
+ cmds++;
+ err = deviceRead( theTarget,
+ theData,
+ theSize,
+ DEVICE_MVPD_ADDRESS( MVPD_FIRST_RECORD,
+ MVPD_TEST_KEYWORD ) );
+
+ if( NULL == err )
+ {
+ fails++;
+ TS_FAIL( "testMvpdMissingKeyword() - Expected error from "
+ "invalid Keyword missing from associated record!" );
+ }
+ else
+ {
+ delete err;
+ err = NULL;
+ }
+ } while( 0 );
+
+ TRACFCOMP( g_trac_mvpd,
+ "testMvpdMissingKeyword - %d/%d fails",
+ fails, cmds );
+ }
+
+ /**
+ * @brief This function will test that an error is generated when a keyword
+ * is passed in that cannot be found in the structure that defines the
+ * Keywords string representation.
+ */
+ void testMvpdInvalidKeyword ( void )
+ {
+ errlHndl_t err = NULL;
+ uint64_t cmds = 0x0;
+ uint64_t fails = 0x0;
+
+ TRACFCOMP( g_trac_mvpd,
+ ENTER_MRK"testMvpdInvalidKeyword()" );
+
+ do
+ {
+ TARGETING::Target * theTarget = NULL;
+
+ // Get the processor targets
+ TargetHandleList procList;
+ getProcTargets( procList );
+
+ if( ( 0 == procList.size() ) ||
+ ( NULL == procList[0] ) )
+ {
+ TRACFCOMP( g_trac_mvpd,
+ "testMvpdInvalidKeyword() - No Proc Targets found!" );
+ }
+
+ // Use the first Proc in the list
+ theTarget = procList[0];
+ uint8_t * theData = NULL;
+ size_t theSize = 0;
+
+ cmds++;
+ err = deviceRead( theTarget,
+ theData,
+ theSize,
+ DEVICE_MVPD_ADDRESS( CRP0,
+ MVPD_LAST_KEYWORD ) );
+
+ if( NULL == err )
+ {
+ fails++;
+ TS_FAIL( "testMvpdInvalidKeyword() - Error expected with "
+ "keyword of type MVPD_LAST_KEYWORD (0x%04x), but "
+ "no error returned!",
+ MVPD_LAST_KEYWORD );
+ }
+ else
+ {
+ delete err;
+ err = NULL;
+ }
+ } while( 0 );
+
+ TRACFCOMP( g_trac_mvpd,
+ "testMvpdInvalidKeyword - %d/%d fails",
+ fails, cmds );
+ }
+
+ /**
+ * @brief This function will test that an error is generated when a buffer
+ * that has an insufficient size is passed in to read a record/keyword.
+ */
+ void testMvpdInvalidBufferSize ( void )
+ {
+ errlHndl_t err = NULL;
+ uint64_t cmds = 0x0;
+ uint64_t fails = 0x0;
+
+ TRACFCOMP( g_trac_mvpd,
+ ENTER_MRK"testMvpdInvalidBufferSize()" );
+
+ do
+ {
+ TARGETING::Target * theTarget = NULL;
+
+ // Get the processor targets
+ TargetHandleList procList;
+ getProcTargets( procList );
+
+ if( ( 0 == procList.size() ) ||
+ ( NULL == procList[0] ) )
+ {
+ TRACFCOMP( g_trac_mvpd,
+ "testMvpdInvalidBufferSize() - No Proc Targets "
+ "found!" );
+ }
+
+ // Use the first Proc in the list
+ theTarget = procList[0];
+ uint8_t * theData = NULL;
+ size_t theSize = 0;
+
+ cmds++;
+ err = deviceRead( theTarget,
+ theData,
+ theSize,
+ DEVICE_MVPD_ADDRESS( CRP0,
+ DD ) );
+
+ if( NULL == err )
+ {
+ fails++;
+ TS_FAIL( "testMvpdInvalidBufferSize() - Error was expected "
+ "for an invalid size of 0x0 for a MVPD read!" );
+ }
+ else
+ {
+ delete err;
+ err = NULL;
+ }
+ } while( 0 );
+
+ TRACFCOMP( g_trac_mvpd,
+ "testMvpdInvalidBufferSize - %d/%d fails",
+ fails, cmds );
+ }
+
+ /**
+ * @brief This function will test the numerical order of the mvpdRecords
+ * and mvpdKeywords structures.
+ */
+ void testMvpdCheckStructOrder ( void )
+ {
+ uint64_t fails = 0x0;
+ mvpdRecord prevRecord = MVPD_FIRST_RECORD;
+ mvpdKeyword prevKeyword = MVPD_FIRST_KEYWORD;
+
+ TRACFCOMP( g_trac_mvpd,
+ ENTER_MRK"testMvpdCheckStructOrder()" );
+
+ // Check the mvpdRecords structure for proper order
+ uint32_t entry = 0x0;
+ for( entry = 0;
+ entry < (sizeof(mvpdRecords)/sizeof(mvpdRecords[0]));
+ entry++ )
+ {
+ if( !(mvpdRecords[entry].record >= prevRecord) )
+ {
+ fails++;
+ TS_FAIL( "testMvpdCheckStructOrder() - Record table out of "
+ "order! Cur Record: 0x%04x, Prev Record: 0x%04x",
+ mvpdRecords[entry].record,
+ prevRecord );
+ }
+ prevRecord = mvpdRecords[entry].record;
+ }
+
+ // Check the mvpdKeywords structure for proper order
+ for( entry = 0;
+ entry < (sizeof(mvpdKeywords)/sizeof(mvpdKeywords[0]));
+ entry++ )
+ {
+ if( !(mvpdKeywords[entry].keyword >= prevKeyword) )
+ {
+ fails++;
+ TS_FAIL( "testMvpdCheckStructOrder() - Keyword table out of "
+ "order! Cur Keyword: 0x%04x, Prev Keyword: 0x%04x",
+ mvpdKeywords[entry].keyword,
+ prevKeyword );
+ }
+ prevKeyword = mvpdKeywords[entry].keyword;
+ }
+
+ TRACFCOMP( g_trac_mvpd,
+ "testMvpdCheckStructOrder - %d fails",
+ fails );
+ }
+
+};
+
+#endif
OpenPOWER on IntegriCloud