From ea01d258c6f7493c3c33f8404ce4af3eaf61ef22 Mon Sep 17 00:00:00 2001 From: Christian Geddes Date: Wed, 17 Jul 2019 16:13:08 -0500 Subject: Introduce eecache_editor.pl tool This commit introduces the eecache_editor tool which can be used to take an ecc-less EECACHE section from pnor and provide human readable information about its contents, read specific cache entries out, and to clear/overwite exists entries in a given cache. Change-Id: I4c74f5172e7a681d34b3b654158dc8d76332107a Reviewed-on: http://rchgit01.rchland.ibm.com/gerrit1/80622 Tested-by: Jenkins Server Tested-by: Jenkins OP Build CI Tested-by: Jenkins OP HW Tested-by: FSP CI Jenkins Reviewed-by: Matt Derksen Reviewed-by: Chen Du Reviewed-by: Daniel M Crowell --- src/build/tools/eecache_editor.pl | 795 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 795 insertions(+) create mode 100755 src/build/tools/eecache_editor.pl (limited to 'src') diff --git a/src/build/tools/eecache_editor.pl b/src/build/tools/eecache_editor.pl new file mode 100755 index 000000000..c5e3e66ad --- /dev/null +++ b/src/build/tools/eecache_editor.pl @@ -0,0 +1,795 @@ +#!/usr/local/bin/perl +# IBM_PROLOG_BEGIN_TAG +# This is an automatically generated prolog. +# +# $Source: src/build/tools/eecache_editor.pl $ +# +# OpenPOWER HostBoot Project +# +# Contributors Listed Below - COPYRIGHT 2019 +# [+] International Business Machines Corp. +# +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +# implied. See the License for the specific language governing +# permissions and limitations under the License. +# +# IBM_PROLOG_END_TAG + +use strict; +use Getopt::Long; +use File::Copy; + + +binmode STDOUT, ':bytes'; + +my $pnorBinaryPath = ""; +my $eecacheBinaryPath = ""; +my $newImagePath = ""; +my $outFilePath = "./eecache_editor_output.dat"; +my $masterHuid = 0; +my $port = 0; +my $engine = 0; +my $devAddr = 0; +my $muxHuid = 0; +my $muxSelect = 0xFF; +my $eepromSize = 0; +my $usage = 0; +my $uniqueId = ""; +my $verbose = 0; +my $onlyValid = 0; +my $clearEepromData = 0; +my $overwrite = 0; +my $summary = 0; +my $devOffset = 0xFFFF; # initialized to invalid offset + +# Goals of this tool: +# +# ** Handle both entire PNOR image as well as single EECACHE section as input ** +# +# 1) Given masterHuid, port, engine, devAddr, muxSelect lookup cached EEPROM value and replace +# it with a given binary file. (File size must be <= allocated space) +# +# 2) Given a binary pnor/eecache. Print summary of cached eeproms +# +# 3) Zero out a given cached eeprom +# +# 4) Extract the contents for a given masterHuid, port, engine, devAddr, muxSelect + +use constant VERSION_1_TOC_ENTRY_SIZE_BYTES => 17; +use constant VERSION_1_TOC_ENTRY_SIZE_BITS => (VERSION_1_TOC_ENTRY_SIZE_BYTES * 8) ; +use constant VERSION_1_NUM_ENTRIES => 50; +use constant VERSION_1_TOC_SIZE => (VERSION_1_TOC_ENTRY_SIZE_BYTES * VERSION_1_NUM_ENTRIES) + 5; + +use constant VERSION_2_TOC_ENTRY_SIZE_BYTES => 18; +use constant VERSION_2_TOC_ENTRY_SIZE_BITS => (VERSION_2_TOC_ENTRY_SIZE_BYTES * 8) ; +use constant VERSION_2_NUM_ENTRIES => 50; +use constant VERSION_2_TOC_SIZE => (VERSION_2_TOC_ENTRY_SIZE_BYTES * VERSION_2_NUM_ENTRIES) + 5; + +use constant VERSION_LATEST => 2; + +use constant EEPROM_ACCESS_I2C => 1; +use constant EEPROM_ACCESS_SPI => 2; + + + +my $eecacheVersion = VERSION_LATEST; + +GetOptions("pnor:s" => \$pnorBinaryPath, + "eecache:s" => \$eecacheBinaryPath, + "newImage:s" => \$newImagePath, + "newFile:s" => \$newImagePath, + "out:s" => \$outFilePath, + "of:s" => \$outFilePath, + "masterHuid:o" => \$masterHuid, + "port:o" => \$port, + "engine:o" => \$engine, + "devAddr:o" => \$devAddr, + "muxSelect:o" => \$muxSelect, + "eepromSize:o" => \$eepromSize, + "uniqueId:s" => \$uniqueId, + "devOffset:o" => \$devOffset, + "version:o" => \$eecacheVersion, + "onlyValid" => \$onlyValid, + "overwrite" => \$overwrite, + "clear" => \$clearEepromData, + "verbose" => \$verbose, + "usage" => \$usage, + "help" => \$usage, + "h" => \$usage); + +sub print_help() +{ + print "--------- EECACHE Editor Tool V 2.0 ---------\n"; + print "\n"; + print "Mandatory:\n\n"; + + print " --eecache Path to ECC-less eeprom cache section of PNOR (IE : EECACHE.bin )\n\n"; + + print "Optional:\n\n"; + + print " --clear If a matching eeprom is found, clear out its contents\n"; + print " --devAddr Device address of desired EEPROM\n"; + print " --devOffset Offset (KB) of where record begins in eeprom for SPI access\n"; + print " --engine Engine of I2C/SPI Master desired EEPROM exists on\n"; + print " --masterHuid HUID of the I2C/SPI Master Target\n"; + print " --muxSelect Mux Select (if needed) defaults to 0xFF \n"; + print " --onlyValid If printing summary, only print valid eeprom caches\n"; + print " --out Full path to desired out file, if not provided defaults to ./eecache_editor_output.dat\n"; + print " --port Port of I2C Master desired EEPROM exists on\n"; + print " --uniqueId Combination of unique I2C Slave information, alternative to passing\n"; + print " information in 1 thing at a time\n"; + print " --version Version of eecache (default to latest if this isn't provided)\n"; + print " --verbose Print extra information \n"; + print " --help Print this information \n"; + print "\n "; + print "Examples: \n\n"; + print " # prints out info about all eeproms in EECACHE.bin\n"; + print " eecache_editor.pl --eecache EECACHE.bin\n"; + print "\n"; + print " # (I2C) lookup eeprom matching input params and write contents of that EEPROM's cached data to outfile \n"; + print " eecache_editor.pl --eecache EECACHE.bin --version 1 --port 0 --engine 3 --muxSelect 8 --devAddr 0xa0 --masterHuid 0x50000\n"; + print "\n"; + print " # (I2C) lookup eeprom matching input params and clear the contents ( manipulate input binary )\n"; + print " eecache_editor.pl --eecache EECACHE.bin --port 0 --engine 3 --muxSelect 8 --devAddr 0xa0 --masterHuid 0x50000 --clear\n"; + print "\n"; + print " # (I2C) lookup eeprom matching input params and write new image's contents to offset in EECACHE where matching eeprom data exists ( manipulate input binary )\n"; + print " eecache_editor.pl --eecache EECACHE.bin --port 0 --engine 3 --muxSelect 8 --devAddr 0xa0 --masterHuid 0x50000 --newImage newSPD.dat\n"; + print "\n"; + print " # (SPI) lookup eeprom matching input params and write contents of that EEPROM's cached data to outfile \n"; + print " eecache_editor.pl --eecache EECACHE.bin --engine 3 --devOffset 0xc0 --masterHuid 0x50000\n"; + print "\n"; + print " # (SPI) lookup eeprom matching input params and clear the contents ( manipulate input binary )\n"; + print " eecache_editor.pl --eecache EECACHE.bin --engine 3 --devOffset 0xc0 --masterHuid 0x50000 --clear\n"; + print "\n"; + print " # (SPI) lookup eeprom matching input params and write new image's contents to offset in EECACHE where matching eeprom data exists ( manipulate input binary )\n"; + print " eecache_editor.pl --eecache EECACHE.bin --engine 3 --devOffset 0xc0 --masterHuid 0x50000 --newImage newSPD.dat\n"; + print "---------------------------------------------\n"; +} + +if( $usage ) +{ + print_help(); + exit 0; +} + +if( ($pnorBinaryPath eq "") && + ($eecacheBinaryPath eq "")) +{ + # Print error saying we need one of these filled in + print "ERROR Neither PNOR binary nor EECACHE section binary passed in. Cannot continue.\n\n"; + print_help(); + exit 0; +} + +# if PNOR is not empty, ignore eecacheBinary , we will +# output a full updated pnor since we were provided a pnor. +# but if no pnor is provided , we will just return and EECACHE sections +my $inputIsEntirePnor = 0; +if( $pnorBinaryPath ne "") +{ + $inputIsEntirePnor = 1; +} + +if($newImagePath ne "") +{ + $overwrite = 1; +} + +if ($eecacheVersion > VERSION_LATEST) +{ + print "ERROR: --version $eecacheVersion is greater than max ".VERSION_LATEST."\n\n"; + print_help(); + exit 0; +} + +if ($uniqueId eq "") +{ + if ($eecacheVersion == VERSION_LATEST) + { + # devOffset is specific to SPI access so check to see if it is valid + if ($devOffset != 0xFFFF) + { + $uniqueId = sprintf ("%.02X", EEPROM_ACCESS_SPI); + $uniqueId .= sprintf ("%.08X", $masterHuid); + $uniqueId .= sprintf ("%.02X", $engine); + $uniqueId .= sprintf ("%.04X", $devOffset); + $uniqueId .= "00"; # blank byte + } + else + { + $uniqueId = sprintf ("%.02X", EEPROM_ACCESS_I2C); + $uniqueId .= sprintf ("%.08X", $masterHuid); + $uniqueId .= sprintf ("%.02X", $port); + $uniqueId .= sprintf ("%.02X", $engine); + $uniqueId .= sprintf ("%.02X", $devAddr); + $uniqueId .= sprintf ("%.02X", $muxSelect); + } + } + elsif ($eecacheVersion == 1) + { + $uniqueId .= sprintf ("%.08X", $masterHuid); + $uniqueId .= sprintf ("%.02X", $port); + $uniqueId .= sprintf ("%.02X", $engine); + $uniqueId .= sprintf ("%.02X", $devAddr); + $uniqueId .= sprintf ("%.02X", $muxSelect); + } +} + +my $displayOnly = 0; + +unless (isUniqueIdValid($uniqueId)) +{ + if( $clearEepromData ) + { + print_help(); + print "\n ERROR: Detecting that user is trying to --clear data without providing what info on what eeprom to clear. Exiting. \n\n"; + exit 0; + } + $displayOnly = 1; + $verbose = 1; +} +else +{ + print "\nUnique ID we are looking up: 0x$uniqueId \n\n" ; +} + +# setup input and output files +my $input_fh; +my $output_fh; + +my $new_fh; + +if($inputIsEntirePnor) +{ + open $input_fh, '<', $pnorBinaryPath or die "failed to open $pnorBinaryPath: $!\n"; + if($overwrite) + { + open $output_fh, '>', $pnorBinaryPath or die "failed to open $pnorBinaryPath: $!\n"; + } + else + { + open $output_fh, '>', $outFilePath or die "failed to open $outFilePath: $!\n"; + } +} +else +{ + open $input_fh, '+<:raw', $eecacheBinaryPath or die "failed to open $eecacheBinaryPath: $!\n"; + if($overwrite) + { + $output_fh = $input_fh; + } + else + { + open $output_fh, '+>:raw', $outFilePath or die "failed to open $outFilePath: $!\n"; + copy($eecacheBinaryPath, $outFilePath) ; + } +} + +if($newImagePath ne "") +{ + open $new_fh, '<', $newImagePath or die "failed to open $newImagePath: $!\n"; +} + + + +# at this point we should know what we are trying to accomplish : +# +# IF ($displayOnly != 0) THEN we will only print a summary +# +# ELSE IF ($newImagePath != "") THEN we will write new contents if matching section found +# +# ELSE IF ($clear != 0) THEN clear the contents if matching section found +# +# ELSE if matching section found, then write contents to outfile + + + +# TODO handle entire PNOR +if($inputIsEntirePnor) +{ + #find EECACHE offset , seek to there +} +else +{ + # Parse the larger binary blob to get just the Table of Contents + my $eecacheTOC = readEecacheToc($input_fh); + + # The hashRef you key back has members: offset and size + # This represents offset and size of eeprom data in given + # binary. + my $hashRef = parseEecacheToc($eecacheTOC, $uniqueId); + + # if we are doing displayOnly then we are done, we can skip the following logic + if(!$displayOnly) + { + # If the offset is 0, then no match was found + if($hashRef->{'entry_offset'} != 0) + { + if($newImagePath ne "") # if a new image is available try to load it in + { + my $new_file_size = -s $newImagePath ; + my $new_file_data; + read($new_fh, $new_file_data, $new_file_size ); + + # Verify the new image is the correct size + if( $new_file_size != $hashRef->{'entry_size'}) + { + print "ERROR incorrect size, EECACHE is reporting size to be".$hashRef->{'entry_size'}."bytes but file proved is only".$new_file_size." bytes\n"; + exit 0; + } + + # seek to the offset inside EEACHE where this eeprom's cache lives + # and write the new file contents + seek($output_fh, $hashRef->{'entry_offset'} , 0); + print $output_fh $new_file_data; + } + elsif($clearEepromData) # if we are told to clear the data do that + { + print "Attempting Clearing starting at $hashRef->{'entry_offset'} $hashRef->{'header_offset'}!!!!!!!!\n"; + my $byteOfOnes = pack("H2", "FF") ; + my $byteOfZeroes = pack("H2", "00") ; + seek($output_fh, $hashRef->{'entry_offset'} , 0); + for(my $i = 0; $i < $hashRef->{'entry_size'}; $i++) + { + print $output_fh $byteOfOnes; + } + + # seek($output_fh, $hashRef->{'header_offset'} + 16, 0); + # print $output_fh $byteOfZeroes; + } + else + { + seek($input_fh, $hashRef->{'entry_offset'} , 0); + my $cur_pos = tell $input_fh; + print "reading $hashRef->{'entry_size'} from $cur_pos\n "; + my $cachedData; + read($input_fh, $cachedData, $hashRef->{'entry_size'}); + print $output_fh $cachedData; + } + } + } +} + +close $input_fh; +close $output_fh; + +# End of Main +exit 0; + + +# Start Subroutines + +sub readEecacheToc { + my $eecache_fh = shift; + + my $start_location = tell $eecache_fh; + + my $eecache_toc_version = 0; + + read($eecache_fh, $eecache_toc_version, 1) == 1 or die "failed to read single byte from eecache file handle"; + $eecache_toc_version = unpack 'C', $eecache_toc_version; + + my $eecache_toc; + + if( $eecache_toc_version == 1 ) + { + seek($eecache_fh, $start_location, 0); + read($eecache_fh, $eecache_toc, VERSION_1_TOC_SIZE) or die "failed to read ".VERSION_1_TOC_SIZE." bytes from eecache file handle"; ; + } + elsif ( $eecache_toc_version == 2) + { + seek($eecache_fh, $start_location, 0); + read($eecache_fh, $eecache_toc, VERSION_2_TOC_SIZE) or die "failed to read ".VERSION_2_TOC_SIZE." bytes from eecache file handle"; ; + } + else + { + die "Failed to find valid TOC, version found = $eecache_toc_version. Latest version this tool supports is ".VERSION_LATEST; + } + + return $eecache_toc; +} + +# Brief : Takes in binary blob representing EECACHE table of contents, as well as +# a uniqueID to match against, returns hash that contains size and offset of +# cached eeprom data inside EEACHE section +# +# If verbose is set, + +sub parseEecacheToc { + my $eecacheTOC = shift; + my $idToMatch = shift; + + # figure out what version of EECACHE header exists + my $headerVersion = 0; + my $tocEntrySizeBytes = 0; + my $tocEntries = 0; + + my ($version) = unpack('H2', "$eecacheTOC"); + if ($version == 0x01) + { + $headerVersion = 1; + $tocEntrySizeBytes = VERSION_1_TOC_ENTRY_SIZE_BYTES; + $tocEntries = VERSION_1_NUM_ENTRIES; + } + elsif ($version == 0x02) + { + $headerVersion = 2; + $tocEntrySizeBytes = VERSION_2_TOC_ENTRY_SIZE_BYTES; + $tocEntries = VERSION_2_NUM_ENTRIES; + } + else + { + die "Unsupported PNOR EECACHE level $version"; + } + + # verify uniqueId was built against same version as PNOR's EECACHE + unless (isUniqueIdValid($uniqueId) && ($headerVersion == $eecacheVersion)) + { + die "PNOR EECACHE version $headerVersion is not same as expected EECACHE version $eecacheVersion!" . + "Maybe changed expected with --version option"; + } + + # header entries start after on 6th byte + my $headerEntryOffset = 5; + + # this will end up being the return value + my %entryInfo; + $entryInfo{entry_offset} = 0; + $entryInfo{entry_size} = 0; + $entryInfo{header_offset} = 0; + + my $totalEntryCount = 0; + my $validEntryCount = 0; + + my $matchSummaryString = ""; + + # Some common variables between header versions + my $internal_offset = 0xFFFF; + my $cached_copy_valid = 0; + my $cached_copy_size = 0; + my $entry_size = 0; + my $entry_offset = 0; + my $bitFieldByte = 0; # last byte of header + my $entryUniqueID = "FFFFFFFFFFFFFFFF"; + + use Class::Struct; + + struct I2C_Entry_t => { + i2c_master_huid => '$', + port => '$', + engine => '$', + devAddr => '$', + mux_select => '$', + }; + + struct SPI_Entry_t => { + spi_master_huid => '$', + engine => '$', + offset_KB => '$', + }; + + for(my $i = 0; $i < $tocEntries; $i++) + { + my $eepromAccess = EEPROM_ACCESS_I2C; + my $master_eeprom = 0xFF; # default to invalid master eeprom + + my $entry = substr $eecacheTOC, $headerEntryOffset, $tocEntrySizeBytes; + + # update offset right away so we dont forget + $headerEntryOffset += $tocEntrySizeBytes; + my $entry_data; + + if ($headerVersion == 1) + { + ###### VERSION 1 ######## + # struct completeRecord + # { + # uint32_t i2c_master_huid; // HUID of i2c Master + # uint8_t port; // I2C Port + # uint8_t engine; // I2C Engine + # uint8_t devAddr; // I2C Device Address + # uint8_t mux_select; // Some I2C devices are behind a mux, this says + # // what setting on the mux is required + # uint32_t cache_copy_size; // Size of data saved in cache (in KB) + # uint32_t internal_offset; // offset from start of EECACHE section where cached + # // data exists + # uint8_t cached_copy_valid : 1, // This bit is set when we think the contents of the + # // cache is valid. + # unused : 7; + # + # } PACKED completeRecord; + # + # struct uniqueRecord + # { + # uint8_t uniqueID [NUM_BYTE_UNIQUE_ID]; + # uint8_t metaData [sizeof(completeRecord) - NUM_BYTE_UNIQUE_ID]; + # } PACKED uniqueRecord; + + # unpack according to src/include/usr/i2c/eeprom_const.H ( pasted above) + my @entryFields = unpack('H8 H2 H2 H2 H2 H8 H8 H2', "$entry"); + + $entryUniqueID = "@entryFields[0]@entryFields[1]@entryFields[2]@entryFields[3]@entryFields[4]"; + $eepromAccess = EEPROM_ACCESS_I2C; + $entry_data = I2C_Entry_t->new(); + $entry_data->i2c_master_huid( @entryFields[0] ); + $entry_data->port ( @entryFields[1] ); + $entry_data->engine ( @entryFields[2] ); + $entry_data->devAddr ( @entryFields[3] ); + $entry_data->mux_select ( @entryFields[4] ); + $bitFieldByte = @entryFields[7]; + $cached_copy_valid = (hex( "0x".@entryFields[7]) & 0x80) >> 7; + + + # if the entry ID is FFFFFFFFFFFFFFFF this indicates + # that the entry is not filled out + if($entryUniqueID == "FFFFFFFFFFFFFFFF") + { + next; + } + $cached_copy_size = @entryFields[5]; + $internal_offset = @entryFields[6]; + } + elsif ($headerVersion == 2) + { + ###### VERSION 2 ######## + # struct completeRecord + # { + # EepromAccessMethodType accessType; // how to access record + # union eepromAccess_t + # { + # struct i2cAccess_t + # { + # uint32_t i2c_master_huid; // HUID of i2c Master + # uint8_t port; // I2C Port + # uint8_t engine; // I2C Engine + # uint8_t devAddr; // I2C Device Address + # uint8_t mux_select; // Some I2C devices are behind a mux, this says + # // what setting on the mux is required + # } PACKED i2cAccess; + # struct spiAccess_t + # { + # uint32_t spi_master_huid; // HUID of SPI master + # uint8_t engine; // engine specific to eeprom + # uint16_t offset_KB; // offset in KB of where record begins in eeprom + # } PACKED spiAccess; + # } PACKED eepromAccess; + # uint32_t cache_copy_size; // Size of data saved in cache (in KB) + # uint32_t internal_offset; // offset from start of EECACHE section where cached + # // data exists + # uint8_t cached_copy_valid : 1, // This bit is set when we think the contents of the + # // cache is valid. + # master_eeprom : 1, // This bit marks this record as the master one (i.e. look at this one for change) + # unused : 6; + # + # } PACKED completeRecord; + # + # struct uniqueRecord + # { + # uint8_t uniqueID [NUM_BYTE_UNIQUE_ID]; + # uint8_t metaData [sizeof(completeRecord) - NUM_BYTE_UNIQUE_ID]; + # } PACKED uniqueRecord; + + ($eepromAccess) = unpack('H2', "$entry"); + if ($eepromAccess == EEPROM_ACCESS_I2C) + { + # unpack according to src/include/usr/i2c/eeprom_const.H ( pasted above) + my @entryFields = unpack('H2 H8 H2 H2 H2 H2 H8 H8 H2', "$entry"); + + $entryUniqueID = "@entryFields[0]@entryFields[1]@entryFields[2]@entryFields[3]@entryFields[4]@entryFields[5]"; + + $entry_data = I2C_Entry_t->new(); + $entry_data->i2c_master_huid( @entryFields[1] ); + $entry_data->port( @entryFields[2] ); + $entry_data->engine( @entryFields[3] ); + $entry_data->devAddr( @entryFields[4] ); + $entry_data->mux_select( @entryFields[5] ); + + $cached_copy_size = @entryFields[6]; + $internal_offset = @entryFields[7]; + + $bitFieldByte = @entryFields[8]; + $cached_copy_valid = (hex("0x".@entryFields[8]) & 0x80) >> 7; + $master_eeprom = (hex("0x".@entryFields[8]) & 0x40) >> 6; + } + elsif ($eepromAccess == EEPROM_ACCESS_SPI) + { + # unpack according to src/include/usr/i2c/eeprom_const.H ( pasted above) + my @entryFields = unpack('H2 H8 H2 H4 H2 H8 H8 H2', "$entry"); + + $entryUniqueID = "@entryFields[0]@entryFields[1]@entryFields[2]@entryFields[3]00"; + + $entry_data = SPI_Entry_t->new(); + $entry_data->spi_master_huid( @entryFields[1] ); + $entry_data->engine( @entryFields[2] ); + $entry_data->offset_KB( @entryFields[3] ); + + # @entryField[4] is just filler + + $cached_copy_size = @entryFields[5]; + $internal_offset = @entryFields[6]; + + $bitFieldByte = @entryFields[7]; + $cached_copy_valid = (hex("0x".@entryFields[7]) & 0x80) >> 7; + $master_eeprom = (hex("0x".@entryFields[7]) & 0x40) >> 6; + } + else + { + # entry is not filled out if eepromAccess is not I2C or SPI + next; + } + } + + $totalEntryCount++; + + if(uc $entryUniqueID eq uc $idToMatch) + { + $entryInfo{entry_offset} = $internal_offset; + $entryInfo{entry_size} = $cached_copy_size * 1024; # KB to Bytes + $entryInfo{header_offset} = $headerEntryOffset - $tocEntrySizeBytes; + + $matchSummaryString = "ENTRY FOUND ...\n"; + if ($eepromAccess == EEPROM_ACCESS_I2C) + { + if ($headerVersion >= 2) + { + $matchSummaryString .= + "accessType = 0x".$eepromAccess." I2C ACCESS\n"; + } + $matchSummaryString .= + "Master I2C Huid = 0x". $entry_data->i2c_master_huid ."\n". + "Port = 0x". $entry_data->port ."\n". + "Engine = 0x". $entry_data->engine ."\n". + "Device Address = 0x". $entry_data->devAddr ."\n". + "Mux Select = 0x". $entry_data->mux_select ."\n". + "Size of Cached Copy (KB) = 0x$cached_copy_size\n". + "Offset within EECACHE = 0x$internal_offset\n". + "Cached copy valid ? = 0x$cached_copy_valid (1st bit of 0x$bitFieldByte)\n"; + } + else # EEPROM_ACCESS_SPI + { + if ($headerVersion >= 2) + { + $matchSummaryString .= + "accessType = 0x".$eepromAccess." SPI ACCESS\n"; + } + $matchSummaryString .= + "Master SPI Huid = 0x". $entry_data->spi_master_huid ."\n". + "Engine = 0x". $entry_data->engine ."\n". + "Offset in EEPROM = 0x". $entry_data->offset_KB ."\n". + "Size of Cached Copy (KB) = 0x$cached_copy_size\n". + "Offset within EECACHE = 0x$internal_offset\n". + "Cached copy valid ? = $cached_copy_valid (1st bit of 0x$bitFieldByte)\n"; + } + if ($master_eeprom != 0xFF) + { + $matchSummaryString .= + "EEPROM master ? = $master_eeprom (2nd bit of 0x$bitFieldByte)\n"; + } + $matchSummaryString .= + "unique ID = 0x$entryUniqueID \n\n"; + + if(!$verbose) + { + last; + } + } + + if( !$cached_copy_valid ) + { + # skip if this entry is not valid and told to just + # print valid only entries + if($onlyValid) + { + next; + } + } + else + { + $validEntryCount++; + } + + my $entryString = ""; + if ($eepromAccess == EEPROM_ACCESS_I2C) + { + if ($headerVersion >= 2) + { + $entryString .= + "accessType = 0x".$eepromAccess." I2C ACCESS\n"; + } + $entryString .= + "Master I2C Huid = 0x". $entry_data->i2c_master_huid ."\n". + "Port = 0x". $entry_data->port ."\n". + "Engine = 0x". $entry_data->engine ."\n". + "Device Address = 0x". $entry_data->devAddr ."\n". + "Mux Select = 0x". $entry_data->mux_select ."\n". + "Size of Cached Copy (KB) = 0x$cached_copy_size\n". + "Offset within EECACHE = 0x$internal_offset\n". + "Cached copy valid ? = $cached_copy_valid (1st bit of 0x$bitFieldByte)\n"; + } + else + { + if ($headerVersion >= 2) + { + $entryString .= + "accessType = 0x".$eepromAccess." SPI ACCESS\n"; + } + $entryString .= + "Master SPI Huid = 0x". $entry_data->spi_master_huid ."\n". + "Engine = 0x". $entry_data->engine ."\n". + "Offset in EEPROM = 0x". $entry_data->offset_KB ."\n". + "Size of Cached Copy (KB) = 0x$cached_copy_size\n". + "Offset within EECACHE = 0x$internal_offset\n". + "Cached copy valid ? = $cached_copy_valid (1st bit of 0x$bitFieldByte)\n"; + } + + if ($master_eeprom != 0xFF) + { + $entryString .= + "EEPROM master ? = $master_eeprom (2nd bit of 0x$bitFieldByte)\n"; + } + $entryString .= + "unique ID = 0x$entryUniqueID \n\n"; + + printVerbose($entryString); + } + + printVerbose( + "Summary :\n". + " Total Entry Count : $totalEntryCount \n". + " Valid Entry Count : $validEntryCount \n". + " Max Possible Entries : $tocEntries\n\n"); + + if($matchSummaryString ne "") + { + print $matchSummaryString; + } + else + { + print "No Match Found! \n\n"; + } + + return \%entryInfo; +} + + +sub findEepromRecordOffset { + + + +} + +sub printVerbose { + + my $string = shift; + + if($verbose) + { + print $string; + } +} + +sub isUniqueIdValid +{ + my ($uniqueId) = @_; + + if( (($eecacheVersion == 1) && ($uniqueId == "00000000000000FF")) || + (($eecacheVersion == 2) && ($uniqueId == "0100000000000000FF")) || + (($eecacheVersion == 2) && ($uniqueId == "020000000000000000")) ) + { + return 0; + } + else + { + return 1; + } +} + -- cgit v1.2.1