Get chip ID/EC from hardware if not synced in attributes

Signed-off-by: Zane Shelley <zshelle@us.ibm.com>
Change-Id: I988fd16c1514d9fe2058f8becdfcf3a39abf8b85
diff --git a/util/pdbg.cpp b/util/pdbg.cpp
index f0142b5..605df77 100644
--- a/util/pdbg.cpp
+++ b/util/pdbg.cpp
@@ -62,7 +62,7 @@
 pdbg_target* getPibTrgt(pdbg_target* i_procTrgt)
 {
     // The input target must be a processor.
-    assert(0x05 == getTrgtType(i_procTrgt));
+    assert(TYPE_PROC == getTrgtType(i_procTrgt));
 
     // Get the pib path.
     char path[16];
@@ -80,7 +80,7 @@
 pdbg_target* getFsiTrgt(pdbg_target* i_procTrgt)
 {
     // The input target must be a processor.
-    assert(0x05 == getTrgtType(i_procTrgt));
+    assert(TYPE_PROC == getTrgtType(i_procTrgt));
 
     // Get the fsi path.
     char path[16];
@@ -95,6 +95,30 @@
 
 //------------------------------------------------------------------------------
 
+int getCfam(pdbg_target* i_trgt, uint32_t i_addr, uint32_t& o_val)
+{
+    // Only processor targets are supported.
+    assert(TYPE_PROC == getTrgtType(i_trgt));
+
+    auto fsiTrgt = util::pdbg::getFsiTrgt(i_trgt);
+
+    int rc = fsi_read(fsiTrgt, i_addr, &o_val);
+
+    if (0 != rc)
+    {
+        trace::err("fsi_read failure: trgt=%s addr=0x%08x",
+                   util::pdbg::getPath(fsiTrgt), i_addr);
+    }
+
+    return rc;
+}
+
+//------------------------------------------------------------------------------
+
+// IMPORTANT:
+// The ATTR_CHIP_ID attribute will be synced from Hostboot to the BMC at some
+// point during the IPL. It is possible that this information is needed before
+// the sync occurs, in which case the value will return 0.
 uint32_t __getChipId(pdbg_target* i_trgt)
 {
     uint32_t attr = 0;
@@ -102,6 +126,10 @@
     return attr;
 }
 
+// IMPORTANT:
+// The ATTR_EC attribute will be synced from Hostboot to the BMC at some point
+// during the IPL. It is possible that this information is needed before the
+// sync occurs, in which case the value will return 0.
 uint8_t __getChipEc(pdbg_target* i_trgt)
 {
     uint8_t attr = 0;
@@ -111,7 +139,27 @@
 
 uint32_t __getChipIdEc(pdbg_target* i_trgt)
 {
-    return ((__getChipId(i_trgt) & 0xffff) << 16) | __getChipEc(i_trgt);
+    auto chipId = __getChipId(i_trgt);
+    auto chipEc = __getChipEc(i_trgt);
+
+    if (((0 == chipId) || (0 == chipEc)) && (TYPE_PROC == getTrgtType(i_trgt)))
+    {
+        // There is a special case where the model/level attributes have not
+        // been initialized in the devtree. This is possible on the epoch IPL
+        // where an attention occurs before Hostboot is able to update the
+        // devtree information on the BMC. It may is still possible to get this
+        // information from chips with CFAM access (i.e. a processor) via the
+        // CFAM chip ID register.
+
+        uint32_t val = 0;
+        if (0 == getCfam(i_trgt, 0x100a, val))
+        {
+            chipId = ((val & 0x0F0FF000) >> 12);
+            chipEc = ((val & 0xF0000000) >> 24) | ((val & 0x00F00000) >> 20);
+        }
+    }
+
+    return ((chipId & 0xffff) << 16) | (chipEc & 0xff);
 }
 
 void __addChip(std::vector<libhei::Chip>& o_chips, pdbg_target* i_trgt,
@@ -124,10 +172,9 @@
 
     if (0 == i_type)
     {
-        // There is a special case where the model/level attributes have not
-        // been initialized in the devtree. This is possible on the epoch IPL
-        // where an attention occurs before Hostboot is able to update the
-        // devtree information on the BMC. For now, just ignore the chip.
+        // This is a special case. See the details in __getChipIdEC(). There is
+        // nothing more we can do with this chip since we don't know what it is.
+        // So ignore the chip for now.
     }
     else
     {