33
44#include " fru_utils.hpp"
55
6+ #include " gzip_utils.hpp"
7+
68#include < phosphor-logging/lg2.hpp>
79
810#include < array>
@@ -717,27 +719,66 @@ bool validateHeader(const std::array<uint8_t, I2C_SMBUS_BLOCK_MAX>& blockData)
717719 return true ;
718720}
719721
720- bool findFRUHeader (FRUReader& reader, const std::string& errorHelp,
721- std::array<uint8_t , I2C_SMBUS_BLOCK_MAX>& blockData,
722- off_t & baseOffset)
722+ std::string parseMacFromGzipXmlHeader (FRUReader& reader, off_t offset)
723+ {
724+ // gzip starts at offset 512. Read that from the FRU
725+ // in this case, 32k bytes is enough to hold the whole manifest
726+ constexpr size_t totalReadSize = 32UL * 1024UL ;
727+
728+ std::vector<uint8_t > headerData (totalReadSize, 0U );
729+
730+ int rc = reader.read (offset, totalReadSize, headerData.data ());
731+ if (rc <= 0 )
732+ {
733+ return {};
734+ }
735+
736+ std::optional<std::string> xml = gzipInflate (headerData);
737+ if (!xml)
738+ {
739+ return {};
740+ }
741+ std::vector<std::string> node = getNodeFromXml (
742+ *xml, " /GSSKU/BoardInfo/Main/NIC/*[Mode = 'Dedicated']/MacAddr0" );
743+ if (node.empty ())
744+ {
745+ lg2::debug (" No mac address found in gzip xml header" );
746+ return {};
747+ }
748+ if (node.size () > 1 )
749+ {
750+ lg2::warning (" Multiple mac addresses found in gzip xml header" );
751+ }
752+ return node[0 ];
753+ }
754+
755+ std::optional<FruSections> findFRUHeader (
756+ FRUReader& reader, const std::string& errorHelp, off_t startingOffset)
723757{
724- if (reader.read (baseOffset, 0x8 , blockData.data ()) < 0 )
758+ std::array<uint8_t , I2C_SMBUS_BLOCK_MAX> blockData = {};
759+ if (reader.read (startingOffset, 0x8 , blockData.data ()) < 0 )
725760 {
726761 lg2::error (" failed to read {ERR} base offset {OFFSET}" , " ERR" ,
727- errorHelp, " OFFSET" , baseOffset );
728- return false ;
762+ errorHelp, " OFFSET" , startingOffset );
763+ return std:: nullopt ;
729764 }
730765
731766 // check the header checksum
732767 if (validateHeader (blockData))
733768 {
734- return true ;
769+ FruSections fru = {};
770+ static_assert (fru.ipmiFruBlock .size () == blockData.size (),
771+ " size mismatch in block data" );
772+ std::memcpy (fru.ipmiFruBlock .data (), blockData.data (),
773+ I2C_SMBUS_BLOCK_MAX);
774+ fru.IpmiFruOffset = startingOffset;
775+ return fru;
735776 }
736777
737778 // only continue the search if we just looked at 0x0.
738- if (baseOffset != 0 )
779+ if (startingOffset != 0 )
739780 {
740- return false ;
781+ return std:: nullopt ;
741782 }
742783
743784 // now check for special cases where the IPMI data is at an offset
@@ -748,8 +789,8 @@ bool findFRUHeader(FRUReader& reader, const std::string& errorHelp,
748789 std::equal (tyanHeader.begin (), tyanHeader.end (), blockData.begin ()))
749790 {
750791 // look for the FRU header at offset 0x6000
751- baseOffset = 0x6000 ;
752- return findFRUHeader (reader, errorHelp, blockData, baseOffset );
792+ off_t tyanOffset = 0x6000 ;
793+ return findFRUHeader (reader, errorHelp, tyanOffset );
753794 }
754795
755796 // check if blockData starts with gigabyteHeader
@@ -760,27 +801,39 @@ bool findFRUHeader(FRUReader& reader, const std::string& errorHelp,
760801 blockData.begin ()))
761802 {
762803 // look for the FRU header at offset 0x4000
763- baseOffset = 0x4000 ;
764- return findFRUHeader (reader, errorHelp, blockData, baseOffset);
804+ off_t gbOffset = 0x4000 ;
805+ auto sections = findFRUHeader (reader, errorHelp, gbOffset);
806+ if (sections)
807+ {
808+ lg2::debug (" succeeded on GB parse" );
809+ // GB xml header is at 512 bytes
810+ sections->GigabyteXmlOffset = 512 ;
811+ }
812+ else
813+ {
814+ lg2::error (" Failed on GB parse" );
815+ }
816+ return sections;
765817 }
766818
767819 lg2::debug (" Illegal header {HEADER} base offset {OFFSET}" , " HEADER" ,
768- errorHelp, " OFFSET" , baseOffset );
820+ errorHelp, " OFFSET" , startingOffset );
769821
770- return false ;
822+ return std:: nullopt ;
771823}
772824
773825std::pair<std::vector<uint8_t >, bool > readFRUContents (
774826 FRUReader& reader, const std::string& errorHelp)
775827{
776828 std::array<uint8_t , I2C_SMBUS_BLOCK_MAX> blockData{};
777- off_t baseOffset = 0x0 ;
778-
779- if (!findFRUHeader (reader, errorHelp, blockData, baseOffset))
829+ std::optional<FruSections> sections = findFRUHeader (reader, errorHelp, 0 );
830+ if (!sections)
780831 {
781832 return {{}, false };
782833 }
783-
834+ const off_t baseOffset = sections->IpmiFruOffset ;
835+ std::memcpy (blockData.data (), sections->ipmiFruBlock .data (),
836+ blockData.size ());
784837 std::vector<uint8_t > device;
785838 device.insert (device.end (), blockData.begin (),
786839 std::next (blockData.begin (), 8 ));
@@ -897,6 +950,20 @@ std::pair<std::vector<uint8_t>, bool> readFRUContents(
897950 fruLength -= std::min (requestLength, fruLength);
898951 }
899952
953+ if (sections->GigabyteXmlOffset != 0 )
954+ {
955+ std::string macAddress =
956+ parseMacFromGzipXmlHeader (reader, sections->GigabyteXmlOffset );
957+ if (!macAddress.empty ())
958+ {
959+ // launder the mac address as we expect into
960+ // BOARD_INFO_AM2 to allow the rest of the
961+ // system to use it
962+ std::string mac = std::format (" MAC: {}" , macAddress);
963+ updateAddProperty (mac, " BOARD_INFO_AM2" , device);
964+ }
965+ }
966+
900967 return {device, true };
901968}
902969
0 commit comments