changeset 10942:eaa343de0d06

PSARC/2009/490 x86 Generic FMA Topology Enumerator 6785310 Implement SMBIOS contained elements/handles 6841286 Need x86 generic FMA topo enumerator 6853537 x86gentopo needs OEM-Specific SMBIOS structures 6865771 Topology relationships should be derived from contained handles & elements of SMBIOS 6865814 Chip enumerator should derive serials & labels using libsmbios, if SMBIOS is FM aware 6865845 /dev/fm should export the Initial APICID, SMBIOS based ID/instance to the chip enumerator 6866456 Generic Topology FMRI ereport
author Tom Pothier <Tom.Pothier@Sun.COM>
date Tue, 03 Nov 2009 21:14:05 -0500
parents 005529612762
children b45d62b629cd
files usr/src/cmd/fm/eversholt/files/i386/i86pc/intel.esc usr/src/cmd/mdb/intel/modules/generic_cpu/gcpu.c usr/src/cmd/smbios/smbios.c usr/src/common/smbios/smb_info.c usr/src/common/smbios/smb_open.c usr/src/lib/fm/topo/libtopo/common/mapfile-vers usr/src/lib/fm/topo/libtopo/common/topo_mod.map usr/src/lib/fm/topo/maps/i86pc/Makefile usr/src/lib/fm/topo/maps/i86pc/i86pc-hc-topology.xml usr/src/lib/fm/topo/maps/i86pc/i86pc-legacy-hc-topology.xml usr/src/lib/fm/topo/modules/common/pcibus/did_props.c usr/src/lib/fm/topo/modules/i86pc/Makefile usr/src/lib/fm/topo/modules/i86pc/chip/Makefile usr/src/lib/fm/topo/modules/i86pc/chip/chip.c usr/src/lib/fm/topo/modules/i86pc/chip/chip.h usr/src/lib/fm/topo/modules/i86pc/chip/chip_amd.c usr/src/lib/fm/topo/modules/i86pc/chip/chip_intel.c usr/src/lib/fm/topo/modules/i86pc/chip/chip_smbios.c usr/src/lib/fm/topo/modules/i86pc/x86pi/Makefile usr/src/lib/fm/topo/modules/i86pc/x86pi/x86pi.c usr/src/lib/fm/topo/modules/i86pc/x86pi/x86pi_bboard.c usr/src/lib/fm/topo/modules/i86pc/x86pi/x86pi_chassis.c usr/src/lib/fm/topo/modules/i86pc/x86pi/x86pi_generic.c usr/src/lib/fm/topo/modules/i86pc/x86pi/x86pi_hostbridge.c usr/src/lib/fm/topo/modules/i86pc/x86pi/x86pi_impl.h usr/src/lib/fm/topo/modules/i86pc/x86pi/x86pi_subr.c usr/src/lib/libsmbios/common/mapfile-vers usr/src/pkgdefs/SUNWfmd/prototype_i386 usr/src/uts/common/io/devfm.c usr/src/uts/common/os/fm.c usr/src/uts/common/sys/devfm.h usr/src/uts/common/sys/fm/protocol.h usr/src/uts/common/sys/smbios.h usr/src/uts/common/sys/smbios_impl.h usr/src/uts/i86pc/cpu/amd_opteron/ao_mca.c usr/src/uts/i86pc/cpu/authenticamd/authamd_main.c usr/src/uts/i86pc/cpu/generic_cpu/gcpu_mca.c usr/src/uts/i86pc/cpu/genuineintel/gintel_main.c usr/src/uts/i86pc/os/cmi.c usr/src/uts/i86pc/os/cmi_hw.c usr/src/uts/i86pc/os/startup.c usr/src/uts/i86xpv/os/xen_machdep.c usr/src/uts/intel/Makefile.files usr/src/uts/intel/io/devfm_machdep.c usr/src/uts/intel/io/mc-amd/mcamd.h usr/src/uts/intel/io/mc-amd/mcamd_drv.c usr/src/uts/intel/io/mc-amd/mcamd_subr.c usr/src/uts/intel/os/fmsmb.c usr/src/uts/intel/sys/cpu_module.h usr/src/uts/intel/sys/fm/smb/fmsmb.h usr/src/uts/intel/sys/hypervisor.h
diffstat 51 files changed, 6213 insertions(+), 505 deletions(-) [+]
line wrap: on
line diff
--- a/usr/src/cmd/fm/eversholt/files/i386/i86pc/intel.esc	Tue Nov 03 17:06:24 2009 -0800
+++ b/usr/src/cmd/fm/eversholt/files/i386/i86pc/intel.esc	Tue Nov 03 21:14:05 2009 -0500
@@ -434,12 +434,12 @@
  */
 
 #define CONTAINS_RANK (payloadprop_contains("resource", \
-    asru(motherboard/chip/memory-controller/dram-channel/dimm/rank)) || \
+    asru(chip/memory-controller/dram-channel/dimm/rank)) || \
     payloadprop_contains("resource", \
-    asru(motherboard/chip/memory-controller/dram-channel/dimm)))
+    asru(chip/memory-controller/dram-channel/dimm)))
 
 #define	STAT_CPU_MEM_CE_PGFLTS \
-    stat.ce_pgflt@motherboard/chip/memory-controller/dram-channel/dimm
+    stat.ce_pgflt@chip/memory-controller/dram-channel/dimm
 
 #define SET_RES_OFFSET \
     (!payloadprop_defined("resource[0].hc-specific.offset") || \
@@ -448,21 +448,21 @@
 
 engine STAT_CPU_MEM_CE_PGFLTS;
 
-event ereport.cpu.intel.quickpath.mem_ue@motherboard/chip/memory-controller
+event ereport.cpu.intel.quickpath.mem_ue@chip/memory-controller
     {within(12s)};
 
 event fault.memory.intel.page_ue@
-    motherboard/chip/memory-controller/dram-channel/dimm/rank,
+    chip/memory-controller/dram-channel/dimm/rank,
     message=0, response=0;		/* do not message individual pageflts */
 
 prop fault.memory.intel.page_ue@
-    motherboard/chip/memory-controller/dram-channel/dimm/rank
+    chip/memory-controller/dram-channel/dimm/rank
     { CONTAINS_RANK && (payloadprop_defined("physaddr") ||
     payloadprop_defined("resource[0].hc-specific.offset")) &&
     SET_ADDR && SET_RES_OFFSET } (0)->
-    ereport.cpu.intel.quickpath.mem_ue@motherboard/chip/memory-controller;
+    ereport.cpu.intel.quickpath.mem_ue@chip/memory-controller;
 
-#define	CHIPDIMM motherboard/chip/memory-controller/dram-channel/dimm
+#define	CHIPDIMM chip/memory-controller/dram-channel/dimm
 
 event fault.memory.intel.dimm_ue@CHIPDIMM/rank;
 
@@ -475,12 +475,12 @@
 
 prop error.memory.intel.dimm_ue_ep@CHIPDIMM/rank
     { CONTAINS_RANK } (1)->
-    ereport.cpu.intel.quickpath.mem_ue@motherboard/chip/memory-controller;
+    ereport.cpu.intel.quickpath.mem_ue@chip/memory-controller;
 
 prop fault.memory.intel.dimm_ue@CHIPDIMM/rank (0)-> EREPORT_BUS_ERROR;
 
 event ereport.cpu.intel.quickpath.mem_ce@
-    motherboard/chip/memory-controller{within(12s)};
+    chip/memory-controller{within(12s)};
 
 engine serd.memory.intel.page_ce@CHIPDIMM/rank, N=PAGE_CE_COUNT, T=PAGE_CE_TIME;
 event fault.memory.intel.page_ce@CHIPDIMM/rank, message=0, response=0,
@@ -490,7 +490,7 @@
     { CONTAINS_RANK && (payloadprop_defined("physaddr") ||
     payloadprop_defined("resource[0].hc-specific.offset")) &&
     SET_ADDR && SET_RES_OFFSET } (0)->
-    ereport.cpu.intel.quickpath.mem_ce@motherboard/chip/memory-controller;
+    ereport.cpu.intel.quickpath.mem_ce@chip/memory-controller;
 
 engine serd.memory.intel.dimm_ce@CHIPDIMM, N=PAGE_CE_COUNT, T=PAGE_CE_TIME;
 event fault.memory.intel.dimm_ce@CHIPDIMM,
@@ -498,7 +498,7 @@
 prop fault.memory.intel.dimm_ce@CHIPDIMM
     { !confprop_defined(CHIPDIMM, "dimm-size") &&
     count(STAT_CPU_MEM_CE_PGFLTS) > 512 } (0)->
-    ereport.cpu.intel.quickpath.mem_ce@motherboard/chip/memory-controller;
+    ereport.cpu.intel.quickpath.mem_ce@chip/memory-controller;
 
 #define	CPU_MEM_DIMM_CE(dimm_size, n, t, fault_rate) \
 	prop fault.memory.intel.dimm_ce@CHIPDIMM { \
@@ -506,7 +506,7 @@
 	    count(STAT_CPU_MEM_CE_PGFLTS) > fault_rate && \
 	    setserdn(n) & setserdt(t) } (0)-> \
 	    ereport.cpu.intel.quickpath.mem_ce@ \
-	    motherboard/chip/memory-controller;
+	    chip/memory-controller;
 
 CPU_MEM_DIMM_CE("16G", 16, 1week, 2000)
 CPU_MEM_DIMM_CE("8G", 8, 1week, 2000)
@@ -515,69 +515,69 @@
 CPU_MEM_DIMM_CE("1G", 4, 4week, 500)
 CPU_MEM_DIMM_CE("512M", 4, 8week, 250)
 
-event ereport.cpu.intel.quickpath.mem_unknown@motherboard/chip/memory-controller {within(12s)};
-event ereport.cpu.intel.quickpath.mem_unknown@motherboard/chip/memory-controller/dram-channel
+event ereport.cpu.intel.quickpath.mem_unknown@chip/memory-controller {within(12s)};
+event ereport.cpu.intel.quickpath.mem_unknown@chip/memory-controller/dram-channel
     {within(12s)};
 event ereport.cpu.intel.quickpath.mem_unknown@
-    motherboard/chip/memory-controller/dram-channel/dimm/rank{within(12s)};
-event upset.discard@motherboard/chip/memory-controller;
-event upset.discard@motherboard/chip/memory-controller/dram-channel/dimm/rank;
+    chip/memory-controller/dram-channel/dimm/rank{within(12s)};
+event upset.discard@chip/memory-controller;
+event upset.discard@chip/memory-controller/dram-channel/dimm/rank;
 
-prop upset.discard@motherboard/chip/memory-controller (0)->
-    ereport.cpu.intel.quickpath.mem_unknown@motherboard/chip/memory-controller,
+prop upset.discard@chip/memory-controller (0)->
+    ereport.cpu.intel.quickpath.mem_unknown@chip/memory-controller,
     ereport.cpu.intel.quickpath.mem_unknown@
-    motherboard/chip/memory-controller/dram-channel;
+    chip/memory-controller/dram-channel;
 
 prop upset.discard@
-    motherboard/chip/memory-controller/dram-channel/dimm/rank (1)->
+    chip/memory-controller/dram-channel/dimm/rank (1)->
     ereport.cpu.intel.quickpath.mem_unknown@
-    motherboard/chip/memory-controller/dram-channel/dimm/rank;
+    chip/memory-controller/dram-channel/dimm/rank;
 
-event ereport.cpu.intel.quickpath.mem_parity@motherboard/chip/memory-controller {within(1s)};
-event fault.cpu.intel.quickpath.mem_parity@motherboard/chip/memory-controller;
+event ereport.cpu.intel.quickpath.mem_parity@chip/memory-controller {within(1s)};
+event fault.cpu.intel.quickpath.mem_parity@chip/memory-controller;
 
-prop fault.cpu.intel.quickpath.mem_parity@motherboard/chip/memory-controller (1)->
-    ereport.cpu.intel.quickpath.mem_parity@motherboard/chip/memory-controller;
+prop fault.cpu.intel.quickpath.mem_parity@chip/memory-controller (1)->
+    ereport.cpu.intel.quickpath.mem_parity@chip/memory-controller;
 
-event ereport.cpu.intel.quickpath.mem_addr_parity@motherboard/chip/memory-controller {within(1s)};
+event ereport.cpu.intel.quickpath.mem_addr_parity@chip/memory-controller {within(1s)};
 event fault.cpu.intel.quickpath.mem_addr_parity@
-    motherboard/chip/memory-controller;
+    chip/memory-controller;
 event fault.cpu.intel.quickpath.mem_addr_parity@CHIPDIMM;
 event fault.cpu.intel.quickpath.mem_addr_parity@CHIPDIMM/rank;
 
 prop fault.cpu.intel.quickpath.mem_addr_parity@
-    motherboard/chip/memory-controller (1)->
-    ereport.cpu.intel.quickpath.mem_addr_parity@motherboard/chip/memory-controller;
+    chip/memory-controller (1)->
+    ereport.cpu.intel.quickpath.mem_addr_parity@chip/memory-controller;
 
 prop fault.cpu.intel.quickpath.mem_addr_parity@CHIPDIMM
     { payloadprop_contains("resource", asru(CHIPDIMM)) } (1)->
-    ereport.cpu.intel.quickpath.mem_addr_parity@motherboard/chip/memory-controller;
+    ereport.cpu.intel.quickpath.mem_addr_parity@chip/memory-controller;
 
 prop fault.cpu.intel.quickpath.mem_addr_parity@CHIPDIMM/rank
     { payloadprop_contains("resource", asru(CHIPDIMM/rank)) } (1)->
-    ereport.cpu.intel.quickpath.mem_addr_parity@motherboard/chip/memory-controller;
+    ereport.cpu.intel.quickpath.mem_addr_parity@chip/memory-controller;
 
-event ereport.cpu.intel.quickpath.mem_bad_addr@motherboard/chip/memory-controller {within(1s)};
-event fault.cpu.intel.quickpath.mem_bad_addr@motherboard/chip/memory-controller;
+event ereport.cpu.intel.quickpath.mem_bad_addr@chip/memory-controller {within(1s)};
+event fault.cpu.intel.quickpath.mem_bad_addr@chip/memory-controller;
 
-prop fault.cpu.intel.quickpath.mem_bad_addr@motherboard/chip/memory-controller (1)->
-    ereport.cpu.intel.quickpath.mem_bad_addr@motherboard/chip/memory-controller;
+prop fault.cpu.intel.quickpath.mem_bad_addr@chip/memory-controller (1)->
+    ereport.cpu.intel.quickpath.mem_bad_addr@chip/memory-controller;
 
-event ereport.cpu.intel.quickpath.mem_spare@motherboard/chip/memory-controller {within(1s)};
+event ereport.cpu.intel.quickpath.mem_spare@chip/memory-controller {within(1s)};
 event fault.cpu.intel.quickpath.mem_spare@
-    motherboard/chip/memory-controller/dram-channel/dimm;
+    chip/memory-controller/dram-channel/dimm;
 
 prop fault.cpu.intel.quickpath.mem_spare@
-    motherboard/chip/memory-controller/dram-channel/dimm (1)->
-    ereport.cpu.intel.quickpath.mem_spare@motherboard/chip/memory-controller;
+    chip/memory-controller/dram-channel/dimm (1)->
+    ereport.cpu.intel.quickpath.mem_spare@chip/memory-controller;
 
-event ereport.cpu.intel.quickpath.mem_bad_id@motherboard/chip/memory-controller {within(1s)};
-event fault.cpu.intel.quickpath.mem_bad_id@motherboard/chip/memory-controller;
+event ereport.cpu.intel.quickpath.mem_bad_id@chip/memory-controller {within(1s)};
+event fault.cpu.intel.quickpath.mem_bad_id@chip/memory-controller;
 
-prop fault.cpu.intel.quickpath.mem_bad_id@motherboard/chip/memory-controller (1)->
-    ereport.cpu.intel.quickpath.mem_bad_id@motherboard/chip/memory-controller;
+prop fault.cpu.intel.quickpath.mem_bad_id@chip/memory-controller (1)->
+    ereport.cpu.intel.quickpath.mem_bad_id@chip/memory-controller;
 
-event ereport.cpu.intel.quickpath.mem_redundant@motherboard/chip/memory-controller {within(1s)};
+event ereport.cpu.intel.quickpath.mem_redundant@chip/memory-controller {within(1s)};
 engine serd.cpu.intel.quickpath.mem_redundant@CHIPDIMM, N=2, T=72h;
 event fault.cpu.intel.quickpath.mem_redundant@CHIPDIMM,
     engine=serd.cpu.intel.quickpath.mem_redundant@CHIPDIMM;
@@ -590,26 +590,26 @@
 prop error.cpu.intel.quickpath.mem_redundant@CHIPDIMM/rank
     { CONTAINS_RANK } (1)->
     ereport.cpu.intel.quickpath.mem_redundant@
-    motherboard/chip/memory-controller;
+    chip/memory-controller;
 
 #define	STATUS_UC	(payloadprop("error_uncorrected") == 1)
-event ereport.cpu.intel.quickpath.interconnect@motherboard/chip
+event ereport.cpu.intel.quickpath.interconnect@chip
     {within(1s)};
-event upset.cpu.intel.quickpath.interconnect@motherboard/chip;
+event upset.cpu.intel.quickpath.interconnect@chip;
 /* Diagnose corrected events to upsets */
-prop upset.cpu.intel.quickpath.interconnect@motherboard/chip
+prop upset.cpu.intel.quickpath.interconnect@chip
     { !STATUS_UC } (1)->
-    ereport.cpu.intel.quickpath.interconnect@motherboard/chip;
+    ereport.cpu.intel.quickpath.interconnect@chip;
 
-engine serd.cpu.intel.quickpath.interconnect@motherboard/chip,
+engine serd.cpu.intel.quickpath.interconnect@chip,
 	N=3, T=72h;
-event fault.cpu.intel.quickpath.interconnect@motherboard/chip,
-    engine=serd.cpu.intel.quickpath.interconnect@motherboard/chip;
+event fault.cpu.intel.quickpath.interconnect@chip,
+    engine=serd.cpu.intel.quickpath.interconnect@chip;
 
 /* Diagnose uncorrected events to faults */
-prop fault.cpu.intel.quickpath.interconnect@motherboard/chip
+prop fault.cpu.intel.quickpath.interconnect@chip
     { STATUS_UC } (0)->
-    ereport.cpu.intel.quickpath.interconnect@motherboard/chip;
+    ereport.cpu.intel.quickpath.interconnect@chip;
 
 
 /*
@@ -618,7 +618,7 @@
 /* MBox errors */
 #define EX_MEM_EVENT(leafclass, t) \
 	event ereport.cpu.intel.quickpath.leafclass@ \
-        motherboard/chip/memory-controller { within(t) }
+        chip/memory-controller { within(t) }
 
 EX_MEM_EVENT(mem_lnktrns, 1s);
 EX_MEM_EVENT(mem_lnkpers, 1s);
@@ -626,18 +626,18 @@
 EX_MEM_EVENT(mem_nbfbdlnkerr, 1s);
 EX_MEM_EVENT(mem_lnkcrcvld, 1s);
 
-engine serd.cpu.intel.quickpath.mem_link_ce@motherboard/chip/memory-controller,
+engine serd.cpu.intel.quickpath.mem_link_ce@chip/memory-controller,
       N=500, T=1week;
-event fault.cpu.intel.quickpath.mem_link_ce@motherboard/chip/memory-controller,
-      engine=serd.cpu.intel.quickpath.mem_link_ce@motherboard/chip/memory-controller,
+event fault.cpu.intel.quickpath.mem_link_ce@chip/memory-controller,
+      engine=serd.cpu.intel.quickpath.mem_link_ce@chip/memory-controller,
       retire=0, response=0;
 
-prop fault.cpu.intel.quickpath.mem_link_ce@motherboard/chip/memory-controller ->
-    ereport.cpu.intel.quickpath.mem_lnktrns@motherboard/chip/memory-controller,
-    ereport.cpu.intel.quickpath.mem_lnkpers@motherboard/chip/memory-controller,
-    ereport.cpu.intel.quickpath.mem_sbfbdlinkerr@motherboard/chip/memory-controller,
-    ereport.cpu.intel.quickpath.mem_nbfbdlnkerr@motherboard/chip/memory-controller,
-    ereport.cpu.intel.quickpath.mem_lnkcrcvld@motherboard/chip/memory-controller;
+prop fault.cpu.intel.quickpath.mem_link_ce@chip/memory-controller ->
+    ereport.cpu.intel.quickpath.mem_lnktrns@chip/memory-controller,
+    ereport.cpu.intel.quickpath.mem_lnkpers@chip/memory-controller,
+    ereport.cpu.intel.quickpath.mem_sbfbdlinkerr@chip/memory-controller,
+    ereport.cpu.intel.quickpath.mem_nbfbdlnkerr@chip/memory-controller,
+    ereport.cpu.intel.quickpath.mem_lnkcrcvld@chip/memory-controller;
 
 EX_MEM_EVENT(mem_lnkuncorr_uc, 1s);
 EX_MEM_EVENT(mem_lnkpers_uc, 1s);
@@ -645,30 +645,30 @@
 EX_MEM_EVENT(mem_nbfbdlnkerr_uc, 1s);
 EX_MEM_EVENT(mem_lnkcrcvld_uc, 1s);
 
-event fault.cpu.intel.quickpath.mem_link_ue@motherboard/chip/memory-controller,
+event fault.cpu.intel.quickpath.mem_link_ue@chip/memory-controller,
       retire=0;
 
-prop fault.cpu.intel.quickpath.mem_link_ue@motherboard/chip/memory-controller ->
-    ereport.cpu.intel.quickpath.mem_lnkuncorr_uc@motherboard/chip/memory-controller,
-    ereport.cpu.intel.quickpath.mem_lnkpers_uc@motherboard/chip/memory-controller,
-    ereport.cpu.intel.quickpath.mem_sbfbdlinkerr_uc@motherboard/chip/memory-controller,
-    ereport.cpu.intel.quickpath.mem_nbfbdlnkerr_uc@motherboard/chip/memory-controller,
-    ereport.cpu.intel.quickpath.mem_lnkcrcvld_uc@motherboard/chip/memory-controller;
+prop fault.cpu.intel.quickpath.mem_link_ue@chip/memory-controller ->
+    ereport.cpu.intel.quickpath.mem_lnkuncorr_uc@chip/memory-controller,
+    ereport.cpu.intel.quickpath.mem_lnkpers_uc@chip/memory-controller,
+    ereport.cpu.intel.quickpath.mem_sbfbdlinkerr_uc@chip/memory-controller,
+    ereport.cpu.intel.quickpath.mem_nbfbdlnkerr_uc@chip/memory-controller,
+    ereport.cpu.intel.quickpath.mem_lnkcrcvld_uc@chip/memory-controller;
 
 EX_MEM_EVENT(mem_ptrl_fsm_err, 1s);
 EX_MEM_EVENT(mem_errflw_fsm_fail, 1s);
 EX_MEM_EVENT(mem_vberr, 1s);
 
-engine serd.cpu.intel.quickpath.mem_controller_ce@motherboard/chip/memory-controller,
+engine serd.cpu.intel.quickpath.mem_controller_ce@chip/memory-controller,
       N=500, T=1week;
-event fault.cpu.intel.quickpath.mem_controller_ce@motherboard/chip/memory-controller,
-      engine=serd.cpu.intel.quickpath.mem_controller_ce@motherboard/chip/memory-controller,
+event fault.cpu.intel.quickpath.mem_controller_ce@chip/memory-controller,
+      engine=serd.cpu.intel.quickpath.mem_controller_ce@chip/memory-controller,
       retire=0, response=0;
 
-prop fault.cpu.intel.quickpath.mem_controller_ce@motherboard/chip/memory-controller ->
-    ereport.cpu.intel.quickpath.mem_ptrl_fsm_err@motherboard/chip/memory-controller,
-    ereport.cpu.intel.quickpath.mem_errflw_fsm_fail@motherboard/chip/memory-controller,
-    ereport.cpu.intel.quickpath.mem_vberr@motherboard/chip/memory-controller;
+prop fault.cpu.intel.quickpath.mem_controller_ce@chip/memory-controller ->
+    ereport.cpu.intel.quickpath.mem_ptrl_fsm_err@chip/memory-controller,
+    ereport.cpu.intel.quickpath.mem_errflw_fsm_fail@chip/memory-controller,
+    ereport.cpu.intel.quickpath.mem_vberr@chip/memory-controller;
 
 EX_MEM_EVENT(mem_ptrl_fsm_err_uc, 1s);
 EX_MEM_EVENT(mem_errflw_fsm_fail_uc, 1s);
@@ -676,27 +676,27 @@
 EX_MEM_EVENT(mem_vberr_uc, 1s);
 EX_MEM_EVENT(mem_fberr_uc, 1s);
 
-event fault.cpu.intel.quickpath.mem_controller_ue@motherboard/chip/memory-controller,
+event fault.cpu.intel.quickpath.mem_controller_ue@chip/memory-controller,
       retire=0;
 
-prop fault.cpu.intel.quickpath.mem_controller_ue@motherboard/chip/memory-controller ->
-    ereport.cpu.intel.quickpath.mem_ptrl_fsm_err_uc@motherboard/chip/memory-controller,
-    ereport.cpu.intel.quickpath.mem_errflw_fsm_fail_uc@motherboard/chip/memory-controller,
-    ereport.cpu.intel.quickpath.mem_mcpar_fsmerr_uc@motherboard/chip/memory-controller,
-    ereport.cpu.intel.quickpath.mem_vberr_uc@motherboard/chip/memory-controller,
-    ereport.cpu.intel.quickpath.mem_fberr_uc@motherboard/chip/memory-controller;
+prop fault.cpu.intel.quickpath.mem_controller_ue@chip/memory-controller ->
+    ereport.cpu.intel.quickpath.mem_ptrl_fsm_err_uc@chip/memory-controller,
+    ereport.cpu.intel.quickpath.mem_errflw_fsm_fail_uc@chip/memory-controller,
+    ereport.cpu.intel.quickpath.mem_mcpar_fsmerr_uc@chip/memory-controller,
+    ereport.cpu.intel.quickpath.mem_vberr_uc@chip/memory-controller,
+    ereport.cpu.intel.quickpath.mem_fberr_uc@chip/memory-controller;
 
 EX_MEM_EVENT(mem_scrubbing_uc, 1s);
 event fault.cpu.intel.quickpath.mem_scrubbing@
-    motherboard/chip/memory-controller/dram-channel/dimm/rank,
+    chip/memory-controller/dram-channel/dimm/rank,
     response=0;
 
 prop fault.cpu.intel.quickpath.mem_scrubbing@
-    motherboard/chip/memory-controller/dram-channel/dimm/rank[rank_num]
+    chip/memory-controller/dram-channel/dimm/rank[rank_num]
     { payloadprop_defined("rank") && rank_num == payloadprop("rank") &&
       (payloadprop_defined("physaddr") || payloadprop_defined("offset")) &&
       SET_ADDR && SET_OFFSET } (1)->
-    ereport.cpu.intel.quickpath.mem_scrubbing_uc@motherboard/chip/memory-controller;
+    ereport.cpu.intel.quickpath.mem_scrubbing_uc@chip/memory-controller;
 
 EX_MEM_EVENT(mem_ecc_uc, 12s);
 EX_MEM_EVENT(mem_even_parity_uc, 1s);
@@ -705,61 +705,61 @@
 EX_MEM_EVENT(mem_even_parity, 1s);
 
 event error.memory.intel.ex_dimm_ce@
-    motherboard/chip/memory-controller/dram-channel/dimm/rank;
+    chip/memory-controller/dram-channel/dimm/rank;
 
 prop fault.memory.intel.page_ue@
-    motherboard/chip/memory-controller/dram-channel/dimm/rank[rank_num]
+    chip/memory-controller/dram-channel/dimm/rank[rank_num]
     { payloadprop_defined("rank") && rank_num == payloadprop("rank") &&
       (payloadprop_defined("physaddr") || payloadprop_defined("offset")) &&
       SET_ADDR && SET_OFFSET } (0)->
-    ereport.cpu.intel.quickpath.mem_ecc_uc@motherboard/chip/memory-controller,
-    ereport.cpu.intel.quickpath.mem_even_parity_uc@motherboard/chip/memory-controller;
+    ereport.cpu.intel.quickpath.mem_ecc_uc@chip/memory-controller,
+    ereport.cpu.intel.quickpath.mem_even_parity_uc@chip/memory-controller;
 
 prop fault.memory.intel.page_ce@
-    motherboard/chip/memory-controller/dram-channel/dimm/rank[rank_num]
+    chip/memory-controller/dram-channel/dimm/rank[rank_num]
     { payloadprop_defined("rank") && rank_num == payloadprop("rank") &&
       (payloadprop_defined("physaddr") || payloadprop_defined("offset")) &&
       SET_ADDR && SET_OFFSET } (0)->
-    ereport.cpu.intel.quickpath.mem_ecc@motherboard/chip/memory-controller,
-    ereport.cpu.intel.quickpath.mem_even_parity@motherboard/chip/memory-controller;
+    ereport.cpu.intel.quickpath.mem_ecc@chip/memory-controller,
+    ereport.cpu.intel.quickpath.mem_even_parity@chip/memory-controller;
 
 prop error.memory.intel.dimm_ue_ex@
-    motherboard/chip/memory-controller/dram-channel/dimm/rank[rank_num]
+    chip/memory-controller/dram-channel/dimm/rank[rank_num]
     { payloadprop_defined("rank") && rank_num == payloadprop("rank") } (1)->
-    ereport.cpu.intel.quickpath.mem_ecc_uc@motherboard/chip/memory-controller,
-    ereport.cpu.intel.quickpath.mem_even_parity_uc@motherboard/chip/memory-controller;
+    ereport.cpu.intel.quickpath.mem_ecc_uc@chip/memory-controller,
+    ereport.cpu.intel.quickpath.mem_even_parity_uc@chip/memory-controller;
 
 prop fault.memory.intel.dimm_ce@
-    motherboard/chip/memory-controller/dram-channel/dimm
-    { !confprop_defined(motherboard/chip/memory-controller/dram-channel/dimm,
+    chip/memory-controller/dram-channel/dimm
+    { !confprop_defined(chip/memory-controller/dram-channel/dimm,
     "dimm-size") && setserdn(10) & setserdt(1week) } (0)->
     error.memory.intel.ex_dimm_ce@
-     motherboard/chip/memory-controller/dram-channel/dimm/rank;
+     chip/memory-controller/dram-channel/dimm/rank;
 prop error.memory.intel.ex_dimm_ce@
-    motherboard/chip/memory-controller/dram-channel/dimm/rank[rank_num]
+    chip/memory-controller/dram-channel/dimm/rank[rank_num]
     { payloadprop_defined("rank") && rank_num == payloadprop("rank") &&
-      !confprop_defined(motherboard/chip/memory-controller/dram-channel/dimm,
+      !confprop_defined(chip/memory-controller/dram-channel/dimm,
     "dimm-size") &&
     count(STAT_CPU_MEM_CE_PGFLTS) > 512 } (1)->
-    ereport.cpu.intel.quickpath.mem_ecc@motherboard/chip/memory-controller,
-    ereport.cpu.intel.quickpath.mem_even_parity@motherboard/chip/memory-controller;
+    ereport.cpu.intel.quickpath.mem_ecc@chip/memory-controller,
+    ereport.cpu.intel.quickpath.mem_even_parity@chip/memory-controller;
 
 #define	EX_CPU_MEM_DIMM_CE(dimm_size, n, t, fault_rate) \
 	prop fault.memory.intel.dimm_ce@ \
-	    motherboard/chip/memory-controller/dram-channel/dimm { \
-	    confprop(motherboard/chip/memory-controller/dram-channel/dimm, \
+	    chip/memory-controller/dram-channel/dimm { \
+	    confprop(chip/memory-controller/dram-channel/dimm, \
 	    "dimm-size") == dimm_size && \
 	    setserdn(n) & setserdt(t) } (0)-> \
 	    error.memory.intel.ex_dimm_ce@ \
-	    motherboard/chip/memory-controller/dram-channel/dimm/rank; \
+	    chip/memory-controller/dram-channel/dimm/rank; \
 	prop error.memory.intel.ex_dimm_ce@ \
-	    motherboard/chip/memory-controller/dram-channel/dimm/rank[rank_num] { \
+	    chip/memory-controller/dram-channel/dimm/rank[rank_num] { \
             payloadprop_defined("rank") && rank_num == payloadprop("rank") && \
-	    confprop(motherboard/chip/memory-controller/dram-channel/dimm, \
+	    confprop(chip/memory-controller/dram-channel/dimm, \
 	    "dimm-size") == dimm_size && \
 	    count(STAT_CPU_MEM_CE_PGFLTS) > fault_rate } (1)-> \
-            ereport.cpu.intel.quickpath.mem_ecc@motherboard/chip/memory-controller, \
-            ereport.cpu.intel.quickpath.mem_even_parity@motherboard/chip/memory-controller;
+            ereport.cpu.intel.quickpath.mem_ecc@chip/memory-controller, \
+            ereport.cpu.intel.quickpath.mem_even_parity@chip/memory-controller;
 
 EX_CPU_MEM_DIMM_CE("16G", 16, 1week, 2000)
 EX_CPU_MEM_DIMM_CE("8G", 8, 1week, 2000)
@@ -767,56 +767,56 @@
 EX_CPU_MEM_DIMM_CE("2G", 4, 2week, 1000)
 EX_CPU_MEM_DIMM_CE("1G", 4, 4week, 500)
 
-event upset.memory.intel.discard@motherboard/chip/memory-controller{within(1s)};
+event upset.memory.intel.discard@chip/memory-controller{within(1s)};
 
-prop upset.memory.intel.discard@motherboard/chip/memory-controller (0)->
-    ereport.cpu.intel.quickpath.mem_scrubbing_uc@motherboard/chip/memory-controller,
-    ereport.cpu.intel.quickpath.mem_ecc_uc@motherboard/chip/memory-controller,
-    ereport.cpu.intel.quickpath.mem_even_parity_uc@motherboard/chip/memory-controller,
-    ereport.cpu.intel.quickpath.mem_ecc@motherboard/chip/memory-controller,
-    ereport.cpu.intel.quickpath.mem_even_parity@motherboard/chip/memory-controller;
+prop upset.memory.intel.discard@chip/memory-controller (0)->
+    ereport.cpu.intel.quickpath.mem_scrubbing_uc@chip/memory-controller,
+    ereport.cpu.intel.quickpath.mem_ecc_uc@chip/memory-controller,
+    ereport.cpu.intel.quickpath.mem_even_parity_uc@chip/memory-controller,
+    ereport.cpu.intel.quickpath.mem_ecc@chip/memory-controller,
+    ereport.cpu.intel.quickpath.mem_even_parity@chip/memory-controller;
 
 EX_MEM_EVENT(mem_failover_mir, 1s);
-event fault.cpu.intel.quickpath.mem_failover_mir@motherboard/chip/memory-controller,
+event fault.cpu.intel.quickpath.mem_failover_mir@chip/memory-controller,
       retire=0;
 
-prop fault.cpu.intel.quickpath.mem_failover_mir@motherboard/chip/memory-controller ->
-    ereport.cpu.intel.quickpath.mem_failover_mir@motherboard/chip/memory-controller;
+prop fault.cpu.intel.quickpath.mem_failover_mir@chip/memory-controller ->
+    ereport.cpu.intel.quickpath.mem_failover_mir@chip/memory-controller;
 
 /*
  * RBox errors
  */
 #define EX_EVENT(leafclass, t) \
-	event ereport.cpu.intel.quickpath.leafclass@motherboard/chip { within(t) }
+	event ereport.cpu.intel.quickpath.leafclass@chip { within(t) }
 
-engine serd.cpu.intel.quickpath.bus_interconnect@motherboard/chip,
+engine serd.cpu.intel.quickpath.bus_interconnect@chip,
 	N=3, T=72h;
-event fault.cpu.intel.quickpath.bus_interconnect@motherboard/chip,
-    engine=serd.cpu.intel.quickpath.bus_interconnect@motherboard/chip,
+event fault.cpu.intel.quickpath.bus_interconnect@chip,
+    engine=serd.cpu.intel.quickpath.bus_interconnect@chip,
     retire=0;
 
 EX_EVENT(bus_retry_abort, 1s);
 EX_EVENT(bus_link_init_ce, 1s);
-event upset.cpu.intel.quickpath.discard@motherboard/chip;
+event upset.cpu.intel.quickpath.discard@chip;
 
-prop upset.cpu.intel.quickpath.discard@motherboard/chip (0)->
-    ereport.cpu.intel.quickpath.bus_retry_abort@motherboard/chip,
-    ereport.cpu.intel.quickpath.bus_link_init_ce@motherboard/chip;
+prop upset.cpu.intel.quickpath.discard@chip (0)->
+    ereport.cpu.intel.quickpath.bus_retry_abort@chip,
+    ereport.cpu.intel.quickpath.bus_link_init_ce@chip;
 
 EX_EVENT(bus_unknown, 1s);
 EX_EVENT(bus_single_ecc, 1s);
 EX_EVENT(bus_crc_flit, 1s);
 
-prop fault.cpu.intel.quickpath.bus_interconnect@motherboard/chip (0)->
-    ereport.cpu.intel.quickpath.bus_unknown@motherboard/chip,
-    ereport.cpu.intel.quickpath.bus_single_ecc@motherboard/chip,
-    ereport.cpu.intel.quickpath.bus_crc_flit@motherboard/chip;
+prop fault.cpu.intel.quickpath.bus_interconnect@chip (0)->
+    ereport.cpu.intel.quickpath.bus_unknown@chip,
+    ereport.cpu.intel.quickpath.bus_single_ecc@chip,
+    ereport.cpu.intel.quickpath.bus_crc_flit@chip;
 
 EX_EVENT(bus_unknown_external, 1s);
 EX_EVENT(bus_crc_flit_external, 1s);
-prop upset.cpu.intel.quickpath.discard@motherboard/chip (0)->
-    ereport.cpu.intel.quickpath.bus_unknown_external@motherboard/chip,
-    ereport.cpu.intel.quickpath.bus_crc_flit_external@motherboard/chip;
+prop upset.cpu.intel.quickpath.discard@chip (0)->
+    ereport.cpu.intel.quickpath.bus_unknown_external@chip,
+    ereport.cpu.intel.quickpath.bus_crc_flit_external@chip;
 
 EX_EVENT(bus_unknown_uc, 1s);
 EX_EVENT(bus_opr_poison_err, 1s);
@@ -828,17 +828,17 @@
 EX_EVENT(bus_hdr_double_ecc, 1s);
 EX_EVENT(bus_link_retry_err, 1s);
 
-prop fault.cpu.intel.quickpath.bus_interconnect@motherboard/chip
+prop fault.cpu.intel.quickpath.bus_interconnect@chip
     { setserdincrement(4) } (0)->
-    ereport.cpu.intel.quickpath.bus_unknown_uc@motherboard/chip,
-    ereport.cpu.intel.quickpath.bus_opr_poison_err@motherboard/chip,
-    ereport.cpu.intel.quickpath.bus_eot_parity@motherboard/chip,
-    ereport.cpu.intel.quickpath.bus_rta_parity@motherboard/chip,
-    ereport.cpu.intel.quickpath.bus_bad_sbu_route@motherboard/chip,
-    ereport.cpu.intel.quickpath.bus_bad_msg@motherboard/chip,
-    ereport.cpu.intel.quickpath.bus_bad_vn_credit@motherboard/chip,
-    ereport.cpu.intel.quickpath.bus_hdr_double_ecc@motherboard/chip,
-    ereport.cpu.intel.quickpath.bus_link_retry_err@motherboard/chip;
+    ereport.cpu.intel.quickpath.bus_unknown_uc@chip,
+    ereport.cpu.intel.quickpath.bus_opr_poison_err@chip,
+    ereport.cpu.intel.quickpath.bus_eot_parity@chip,
+    ereport.cpu.intel.quickpath.bus_rta_parity@chip,
+    ereport.cpu.intel.quickpath.bus_bad_sbu_route@chip,
+    ereport.cpu.intel.quickpath.bus_bad_msg@chip,
+    ereport.cpu.intel.quickpath.bus_bad_vn_credit@chip,
+    ereport.cpu.intel.quickpath.bus_hdr_double_ecc@chip,
+    ereport.cpu.intel.quickpath.bus_link_retry_err@chip;
 
 EX_EVENT(bus_unknown_uc_external, 1s);
 EX_EVENT(bus_opr_poison_err_external, 1s);
@@ -850,49 +850,49 @@
 EX_EVENT(bus_hdr_double_ecc_external, 1s);
 EX_EVENT(bus_link_retry_err_external, 1s);
  
-prop upset.cpu.intel.quickpath.discard@motherboard/chip (0)->
-    ereport.cpu.intel.quickpath.bus_unknown_uc_external@motherboard/chip,
-    ereport.cpu.intel.quickpath.bus_opr_poison_err_external@motherboard/chip,
-    ereport.cpu.intel.quickpath.bus_eot_parity_external@motherboard/chip,
-    ereport.cpu.intel.quickpath.bus_rta_parity_external@motherboard/chip,
-    ereport.cpu.intel.quickpath.bus_bad_sbu_route_external@motherboard/chip,
-    ereport.cpu.intel.quickpath.bus_bad_msg_external@motherboard/chip,
-    ereport.cpu.intel.quickpath.bus_bad_vn_credit_external@motherboard/chip,
-    ereport.cpu.intel.quickpath.bus_hdr_double_ecc_external@motherboard/chip,
-    ereport.cpu.intel.quickpath.bus_link_retry_err_external@motherboard/chip;
+prop upset.cpu.intel.quickpath.discard@chip (0)->
+    ereport.cpu.intel.quickpath.bus_unknown_uc_external@chip,
+    ereport.cpu.intel.quickpath.bus_opr_poison_err_external@chip,
+    ereport.cpu.intel.quickpath.bus_eot_parity_external@chip,
+    ereport.cpu.intel.quickpath.bus_rta_parity_external@chip,
+    ereport.cpu.intel.quickpath.bus_bad_sbu_route_external@chip,
+    ereport.cpu.intel.quickpath.bus_bad_msg_external@chip,
+    ereport.cpu.intel.quickpath.bus_bad_vn_credit_external@chip,
+    ereport.cpu.intel.quickpath.bus_hdr_double_ecc_external@chip,
+    ereport.cpu.intel.quickpath.bus_link_retry_err_external@chip;
 
 /*
  * CBox errors
  */
 EX_EVENT(llc_ewb_uc, 1s);
-event fault.cpu.intel.quickpath.llc_ewb@motherboard/chip,
+event fault.cpu.intel.quickpath.llc_ewb@chip,
       retire=0, response=0;
 
-prop fault.cpu.intel.quickpath.llc_ewb@motherboard/chip 
+prop fault.cpu.intel.quickpath.llc_ewb@chip 
     { (payloadprop_defined("physaddr") || payloadprop_defined("offset")) &&
     SET_ADDR && SET_OFFSET } (1)->
-    ereport.cpu.intel.quickpath.llc_ewb_uc@motherboard/chip;
+    ereport.cpu.intel.quickpath.llc_ewb_uc@chip;
 
-prop upset.cpu.intel.quickpath.discard@motherboard/chip (0)->
-    ereport.cpu.intel.quickpath.llc_ewb_uc@motherboard/chip;
+prop upset.cpu.intel.quickpath.discard@chip (0)->
+    ereport.cpu.intel.quickpath.llc_ewb_uc@chip;
 
 /*
  * SBox errors
  */
 EX_EVENT(system_cache_uc, 1s);
-event fault.cpu.intel.quickpath.system_cache@motherboard/chip,
+event fault.cpu.intel.quickpath.system_cache@chip,
       retire=0, response=0;
-prop fault.cpu.intel.quickpath.system_cache@motherboard/chip ->
-    ereport.cpu.intel.quickpath.system_cache_uc@motherboard/chip;
+prop fault.cpu.intel.quickpath.system_cache@chip ->
+    ereport.cpu.intel.quickpath.system_cache_uc@chip;
 
 /*
  * BBox errors
  */
 EX_EVENT(home_agent_uc, 1s);
-event fault.cpu.intel.quickpath.home_agent@motherboard/chip,
+event fault.cpu.intel.quickpath.home_agent@chip,
       retire=0, response=0;
-prop fault.cpu.intel.quickpath.home_agent@motherboard/chip ->
-    ereport.cpu.intel.quickpath.home_agent_uc@motherboard/chip;
+prop fault.cpu.intel.quickpath.home_agent@chip ->
+    ereport.cpu.intel.quickpath.home_agent_uc@chip;
 
 /*
  * UBox errors
@@ -900,18 +900,18 @@
 EX_EVENT(sys_cfg_cfa_ecc, 1s);
 EX_EVENT(sys_cfg_uc, 1s);
 
-engine serd.cpu.intel.quickpath.sys_cfg@motherboard/chip,
+engine serd.cpu.intel.quickpath.sys_cfg@chip,
       N=2, T=72h;
-event fault.cpu.intel.quickpath.sys_cfg@motherboard/chip,
-      engine=serd.cpu.intel.quickpath.sys_cfg@motherboard/chip,
+event fault.cpu.intel.quickpath.sys_cfg@chip,
+      engine=serd.cpu.intel.quickpath.sys_cfg@chip,
       retire=0, response=0;
 
-prop fault.cpu.intel.quickpath.sys_cfg@motherboard/chip (0)->
-    ereport.cpu.intel.quickpath.sys_cfg_cfa_ecc@motherboard/chip;
+prop fault.cpu.intel.quickpath.sys_cfg@chip (0)->
+    ereport.cpu.intel.quickpath.sys_cfg_cfa_ecc@chip;
 
-prop fault.cpu.intel.quickpath.sys_cfg@motherboard/chip
+prop fault.cpu.intel.quickpath.sys_cfg@chip
     { setserdincrement(3) } (0)->
-    ereport.cpu.intel.quickpath.sys_cfg_uc@motherboard/chip;
+    ereport.cpu.intel.quickpath.sys_cfg_uc@chip;
 
 /*
  * Handling poison errors
@@ -927,11 +927,11 @@
 
 prop fault.cpu.intel.has_poison@motherboard
     { payloadprop_defined("poison") && 1 == payloadprop("poison") } (1)->
-    ereport.cpu.intel.quickpath.mem_scrubbing_uc@motherboard/chip<>/memory-controller<>,
-    ereport.cpu.intel.quickpath.llc_ewb_uc@motherboard/chip<>,
-    ereport.cpu.intel.quickpath.system_cache_uc@motherboard/chip<>,
-    ereport.cpu.intel.quickpath.bus_opr_poison_err@motherboard/chip<>,
-    ereport.cpu.intel.quickpath.bus_opr_poison_err_external@motherboard/chip<>;
+    ereport.cpu.intel.quickpath.mem_scrubbing_uc@chip<>/memory-controller<>,
+    ereport.cpu.intel.quickpath.llc_ewb_uc@chip<>,
+    ereport.cpu.intel.quickpath.system_cache_uc@chip<>,
+    ereport.cpu.intel.quickpath.bus_opr_poison_err@chip<>,
+    ereport.cpu.intel.quickpath.bus_opr_poison_err_external@chip<>;
 
 prop fault.cpu.intel.discard_fatal@motherboard
     { count(stat.has_poison@motherboard[0]) > count(stat.discard_fatal@motherboard[0]) &&
--- a/usr/src/cmd/mdb/intel/modules/generic_cpu/gcpu.c	Tue Nov 03 17:06:24 2009 -0800
+++ b/usr/src/cmd/mdb/intel/modules/generic_cpu/gcpu.c	Tue Nov 03 21:14:05 2009 -0500
@@ -45,6 +45,9 @@
 	const struct cmi_mc_ops *cmih_mcops;	/* Memory-controller ops */
 	void *cmih_mcdata;			/* Memory-controller data */
 	uint64_t cmih_flags;
+	uint16_t cmih_smbiosid;			/* SMBIOS Type 4 struct ID */
+	uint_t cmih_smb_chipid;			/* smbios chipid */
+	nvlist_t *cmih_smb_bboard;		/* smbios bboard */
 } cmi_hdl_impl_t;
 
 typedef struct cmi_hdl_ent {
--- a/usr/src/cmd/smbios/smbios.c	Tue Nov 03 17:06:24 2009 -0800
+++ b/usr/src/cmd/smbios/smbios.c	Tue Nov 03 21:14:05 2009 -0500
@@ -2,9 +2,8 @@
  * CDDL HEADER START
  *
  * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
  *
  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  * or http://www.opensolaris.org/os/licensing.
@@ -21,12 +20,10 @@
  */
 
 /*
- * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
-#pragma ident	"%Z%%M%	%I%	%E% SMI"
-
 #include <sys/sysmacros.h>
 #include <sys/param.h>
 
@@ -266,6 +263,7 @@
 print_bboard(smbios_hdl_t *shp, id_t id, FILE *fp)
 {
 	smbios_bboard_t b;
+	int chdl_cnt;
 
 	(void) smbios_info_bboard(shp, id, &b);
 
@@ -276,12 +274,32 @@
 
 	desc_printf(smbios_bboard_type_desc(b.smbb_type),
 	    fp, "  Board Type: 0x%x", b.smbb_type);
+
+	chdl_cnt = b.smbb_contn;
+	if (chdl_cnt != 0) {
+		id_t *chdl;
+		uint16_t hdl;
+		int i, n, cnt;
+
+		chdl = alloca(chdl_cnt * sizeof (id_t));
+		cnt = smbios_info_contains(shp, id, chdl_cnt, chdl);
+		if (cnt > SMB_CONT_MAX)
+			return;
+		n = MIN(chdl_cnt, cnt);
+
+		oprintf(fp, "\n");
+		for (i = 0; i < n; i++) {
+			hdl = (uint16_t)chdl[i];
+			oprintf(fp, "  Contained Handle: %u\n", hdl);
+		}
+	}
 }
 
 static void
 print_chassis(smbios_hdl_t *shp, id_t id, FILE *fp)
 {
 	smbios_chassis_t c;
+	int elem_cnt;
 
 	(void) smbios_info_chassis(shp, id, &c);
 
@@ -302,7 +320,37 @@
 
 	oprintf(fp, "  Chassis Height: %uu\n", c.smbc_uheight);
 	oprintf(fp, "  Power Cords: %u\n", c.smbc_cords);
-	oprintf(fp, "  Element Records: %u\n", c.smbc_elems);
+
+	elem_cnt = c.smbc_elems;
+	oprintf(fp, "  Element Records: %u\n", elem_cnt);
+
+	if (elem_cnt > 0) {
+		id_t *elems;
+		uint8_t type;
+		int i, n, cnt;
+
+		elems = alloca(c.smbc_elems * sizeof (id_t));
+		cnt = smbios_info_contains(shp, id, elem_cnt, elems);
+		if (cnt > SMB_CONT_MAX)
+			return;
+		n = MIN(elem_cnt, cnt);
+
+		oprintf(fp, "\n");
+		for (i = 0; i < n; i++) {
+			type = (uint8_t)elems[i];
+			if (type & 0x80) {
+				/* SMBIOS structrure Type */
+				desc_printf(smbios_type_name(type & 0x7f), fp,
+				    "  Contained SMBIOS structure Type: %u",
+				    type & 0x80);
+			} else {
+				/* SMBIOS Base Board Type */
+				desc_printf(smbios_bboard_type_desc(type), fp,
+				    "  Contained SMBIOS Base Board Type: 0x%x",
+				    type);
+			}
+		}
+	}
 }
 
 static void
@@ -767,6 +815,109 @@
 }
 
 static int
+check_oem(smbios_hdl_t *shp)
+{
+	int i;
+	int cnt;
+	int rv;
+	id_t oem_id;
+	smbios_struct_t s;
+	const char **oem_str;
+
+	rv = smbios_lookup_type(shp, SMB_TYPE_OEMSTR, &s);
+	if (rv != 0) {
+		return (-1);
+	}
+
+	oem_id = s.smbstr_id;
+
+	cnt = smbios_info_strtab(shp, oem_id, 0, NULL);
+	if (cnt > 0) {
+		oem_str =  alloca(sizeof (char *) * cnt);
+		(void) smbios_info_strtab(shp, oem_id, cnt, oem_str);
+
+		for (i = 0; i < cnt; i++) {
+			if (strncmp(oem_str[i], SMB_PRMS1,
+			    strlen(SMB_PRMS1) + 1) == 0) {
+				return (0);
+			}
+		}
+	}
+
+	return (-1);
+}
+
+static void
+print_extprocessor(smbios_hdl_t *shp, id_t id, FILE *fp)
+{
+	int i;
+	smbios_processor_ext_t ep;
+
+	if (check_oem(shp) != 0)
+		return;
+
+	(void) smbios_info_extprocessor(shp, id, &ep);
+
+	oprintf(fp, "  Processor: %u\n", ep.smbpe_processor);
+	oprintf(fp, "  FRU: %u\n", ep.smbpe_fru);
+	oprintf(fp, "  Initial APIC ID count: %u\n\n", ep.smbpe_n);
+
+	for (i = 0; i < ep.smbpe_n; i++) {
+		oprintf(fp, "  Logical Strand %u: Initial APIC ID: %u\n", i,
+		    ep.smbpe_apicid[i]);
+	}
+}
+
+static void
+print_pciexrc(smbios_hdl_t *shp, id_t id, FILE *fp)
+{
+	smbios_pciexrc_t pcie;
+
+	if (check_oem(shp) != 0)
+		return;
+
+	(void) smbios_info_pciexrc(shp, id, &pcie);
+
+	oprintf(fp, "  Component ID: %u\n", pcie.smbpcie_bb);
+	oprintf(fp, "  BDF: 0x%x\n", pcie.smbpcie_bdf);
+}
+
+static void
+print_extmemarray(smbios_hdl_t *shp, id_t id, FILE *fp)
+{
+	smbios_memarray_ext_t em;
+
+	if (check_oem(shp) != 0)
+		return;
+
+	(void) smbios_info_extmemarray(shp, id, &em);
+
+	oprintf(fp, "  Physical Memory Array Handle: %u\n", em.smbmae_ma);
+	oprintf(fp, "  Component Parent Handle: %u\n", em.smbmae_comp);
+	oprintf(fp, "  BDF: 0x%x\n", em.smbmae_bdf);
+}
+
+static void
+print_extmemdevice(smbios_hdl_t *shp, id_t id, FILE *fp)
+{
+	int i;
+	smbios_memdevice_ext_t emd;
+
+	if (check_oem(shp) != 0)
+		return;
+
+	(void) smbios_info_extmemdevice(shp, id, &emd);
+
+	oprintf(fp, "  Memory Device Handle: %u\n", emd.smbmdeve_md);
+	oprintf(fp, "  DRAM Channel: %u\n", emd.smbmdeve_drch);
+	oprintf(fp, "  Number of Chip Selects: %u\n", emd.smbmdeve_ncs);
+
+	for (i = 0; i < emd.smbmdeve_ncs; i++) {
+		oprintf(fp, "  Chip Select: %u\n", emd.smbmdeve_cs[i]);
+	}
+}
+
+static int
 print_struct(smbios_hdl_t *shp, const smbios_struct_t *sp, void *fp)
 {
 	smbios_info_t info;
@@ -886,6 +1037,22 @@
 		oprintf(fp, "\n");
 		print_ipmi(shp, fp);
 		break;
+	case SUN_OEM_EXT_PROCESSOR:
+		oprintf(fp, "\n");
+		print_extprocessor(shp, sp->smbstr_id, fp);
+		break;
+	case SUN_OEM_PCIEXRC:
+		oprintf(fp, "\n");
+		print_pciexrc(shp, sp->smbstr_id, fp);
+		break;
+	case SUN_OEM_EXT_MEMARRAY:
+		oprintf(fp, "\n");
+		print_extmemarray(shp, sp->smbstr_id, fp);
+		break;
+	case SUN_OEM_EXT_MEMDEVICE:
+		oprintf(fp, "\n");
+		print_extmemdevice(shp, sp->smbstr_id, fp);
+		break;
 	default:
 		hex++;
 	}
--- a/usr/src/common/smbios/smb_info.c	Tue Nov 03 17:06:24 2009 -0800
+++ b/usr/src/common/smbios/smb_info.c	Tue Nov 03 21:14:05 2009 -0500
@@ -63,6 +63,7 @@
  * To simplify life for our clients, we factor these common things out into
  * smbios_info_t, which can be retrieved for any structure.  The following
  * table describes the mapping from a given structure to the smbios_info_t.
+ * Multiple SMBIOS stuctures' contained objects are also handled here.
  */
 static const struct smb_infospec {
 	uint8_t is_type;		/* structure type */
@@ -73,6 +74,9 @@
 	uint8_t is_asset;		/* asset tag offset */
 	uint8_t is_location;		/* location string offset */
 	uint8_t is_part;		/* part number offset */
+	uint8_t is_contc;		/* contained count */
+	uint8_t is_contsz;		/* contained size */
+	uint8_t is_contv;		/* contained objects */
 } _smb_infospecs[] = {
 	{ SMB_TYPE_SYSTEM,
 		offsetof(smb_system_t, smbsi_manufacturer),
@@ -81,6 +85,9 @@
 		offsetof(smb_system_t, smbsi_serial),
 		0,
 		0,
+		0,
+		0,
+		0,
 		0 },
 	{ SMB_TYPE_BASEBOARD,
 		offsetof(smb_bboard_t, smbbb_manufacturer),
@@ -89,7 +96,10 @@
 		offsetof(smb_bboard_t, smbbb_serial),
 		offsetof(smb_bboard_t, smbbb_asset),
 		offsetof(smb_bboard_t, smbbb_location),
-		0 },
+		0,
+		offsetof(smb_bboard_t, smbbb_cn),
+		SMB_CONT_WORD,
+		offsetof(smb_bboard_t, smbbb_cv) },
 	{ SMB_TYPE_CHASSIS,
 		offsetof(smb_chassis_t, smbch_manufacturer),
 		0,
@@ -97,7 +107,10 @@
 		offsetof(smb_chassis_t, smbch_serial),
 		offsetof(smb_chassis_t, smbch_asset),
 		0,
-		0 },
+		0,
+		offsetof(smb_chassis_t, smbch_cn),
+		SMB_CONT_BYTE,
+		offsetof(smb_chassis_t, smbch_cv) },
 	{ SMB_TYPE_PROCESSOR,
 		offsetof(smb_processor_t, smbpr_manufacturer),
 		0,
@@ -105,7 +118,10 @@
 		offsetof(smb_processor_t, smbpr_serial),
 		offsetof(smb_processor_t, smbpr_asset),
 		offsetof(smb_processor_t, smbpr_socket),
-		offsetof(smb_processor_t, smbpr_part) },
+		offsetof(smb_processor_t, smbpr_part),
+		0,
+		0,
+		0 },
 	{ SMB_TYPE_CACHE,
 		0,
 		0,
@@ -113,6 +129,9 @@
 		0,
 		0,
 		offsetof(smb_cache_t, smbca_socket),
+		0,
+		0,
+		0,
 		0 },
 	{ SMB_TYPE_PORT,
 		0,
@@ -121,6 +140,9 @@
 		0,
 		0,
 		offsetof(smb_port_t, smbpo_iref),
+		0,
+		0,
+		0,
 		0 },
 	{ SMB_TYPE_SLOT,
 		0,
@@ -129,6 +151,9 @@
 		0,
 		0,
 		offsetof(smb_slot_t, smbsl_name),
+		0,
+		0,
+		0,
 		0 },
 	{ SMB_TYPE_MEMDEVICE,
 		offsetof(smb_memdevice_t, smbmdev_manufacturer),
@@ -137,7 +162,10 @@
 		offsetof(smb_memdevice_t, smbmdev_serial),
 		offsetof(smb_memdevice_t, smbmdev_asset),
 		offsetof(smb_memdevice_t, smbmdev_dloc),
-		offsetof(smb_memdevice_t, smbmdev_part) },
+		offsetof(smb_memdevice_t, smbmdev_part),
+		0,
+		0,
+		0 },
 	{ SMB_TYPE_POWERSUP,
 		offsetof(smb_powersup_t, smbpsup_manufacturer),
 		offsetof(smb_powersup_t, smbpsup_devname),
@@ -145,7 +173,10 @@
 		offsetof(smb_powersup_t, smbpsup_serial),
 		offsetof(smb_powersup_t, smbpsup_asset),
 		offsetof(smb_powersup_t, smbpsup_loc),
-		offsetof(smb_powersup_t, smbpsup_part) },
+		offsetof(smb_powersup_t, smbpsup_part),
+		0,
+		0,
+		0 },
 	{ SMB_TYPE_EOT }
 };
 
@@ -240,6 +271,50 @@
 	return (n ? 0 : smb_set_errno(shp, ESMB_NOINFO));
 }
 
+/*
+ * Returns the actual number of contained objects.
+ *
+ * idc - number of contained objects
+ * idv - returned array of contained objects
+ */
+int
+smbios_info_contains(smbios_hdl_t *shp, id_t id, uint_t idc, id_t *idv)
+{
+	const smb_struct_t *stp = smb_lookup_id(shp, id);
+	const struct smb_infospec *isp;
+	id_t *cp;
+	uint_t size;
+	uint8_t cnt;
+	int i, n;
+
+	if (stp == NULL) {
+		return (-1); /* errno is set for us */
+	}
+
+	for (isp = _smb_infospecs; isp->is_type != SMB_TYPE_EOT; isp++) {
+		if (isp->is_type == stp->smbst_hdr->smbh_type)
+			break;
+	}
+	if (isp->is_type == SMB_TYPE_EOT)
+		return (smb_set_errno(shp, ESMB_TYPE));
+
+	size = isp->is_contsz;
+	cnt = *((uint8_t *)(uintptr_t)stp->smbst_hdr + isp->is_contc);
+	cp = (id_t *)((uintptr_t)stp->smbst_hdr + isp->is_contv);
+
+	n = MIN(cnt, idc);
+	for (i = 0; i < n; i++) {
+		if (size == SMB_CONT_WORD)
+			idv[i] = *((uint8_t *)(uintptr_t)cp + (i * 2));
+		else if (size == SMB_CONT_BYTE)
+			idv[i] = *((uint8_t *)(uintptr_t)cp + (i * 3));
+		else
+			return (smb_set_errno(shp, ESMB_INVAL));
+	}
+
+	return (cnt);
+}
+
 id_t
 smbios_info_bios(smbios_hdl_t *shp, smbios_bios_t *bp)
 {
@@ -324,14 +399,10 @@
 	smb_info_bcopy(stp->smbst_hdr, &bb, sizeof (bb));
 	bzero(bbp, sizeof (smbios_bboard_t));
 
-	/*
-	 * At present, we do not provide support for the contained object
-	 * handles portion of the Base Board structure, as none of the 2.3+
-	 * BIOSes commonly in use appear to implement it at present.
-	 */
 	bbp->smbb_chassis = bb.smbbb_chassis;
 	bbp->smbb_flags = bb.smbbb_flags;
 	bbp->smbb_type = bb.smbbb_type;
+	bbp->smbb_contn = bb.smbbb_cn;
 
 	return (0);
 }
@@ -351,11 +422,6 @@
 	smb_info_bcopy(stp->smbst_hdr, &ch, sizeof (ch));
 	bzero(chp, sizeof (smbios_chassis_t));
 
-	/*
-	 * At present, we do not provide support for the contained object
-	 * handles portion of the Chassis structure, as none of the 2.3+
-	 * BIOSes commonly in use appear to implement it at present.
-	 */
 	chp->smbc_oemdata = ch.smbch_oemdata;
 	chp->smbc_lock = (ch.smbch_type & SMB_CHT_LOCK) != 0;
 	chp->smbc_type = ch.smbch_type & ~SMB_CHT_LOCK;
@@ -366,6 +432,7 @@
 	chp->smbc_uheight = ch.smbch_uheight;
 	chp->smbc_cords = ch.smbch_cords;
 	chp->smbc_elems = ch.smbch_cn;
+	chp->smbc_elemlen = ch.smbch_cm;
 
 	return (0);
 }
@@ -912,3 +979,95 @@
 
 	return (smb_get_sn(shp, &psn, &csn) == SMB_ERR ? NULL : csn);
 }
+
+int
+smbios_info_extprocessor(smbios_hdl_t *shp, id_t id,
+    smbios_processor_ext_t *epp)
+{
+	const smb_struct_t *stp = smb_lookup_id(shp, id);
+	smb_processor_ext_t *exp;
+
+	if (stp == NULL)
+		return (-1); /* errno is set for us */
+
+	if (stp->smbst_hdr->smbh_type != SUN_OEM_EXT_PROCESSOR)
+		return (smb_set_errno(shp, ESMB_TYPE));
+
+	exp = (smb_processor_ext_t *)(uintptr_t)stp->smbst_hdr;
+	bzero(epp, sizeof (smbios_processor_ext_t));
+
+	epp->smbpe_processor = exp->smbpre_processor;
+	epp->smbpe_fru = exp->smbpre_fru;
+	epp->smbpe_n = exp->smbpre_n;
+	epp->smbpe_apicid = exp->smbpre_apicid;
+
+	return (0);
+}
+
+int
+smbios_info_pciexrc(smbios_hdl_t *shp, id_t id,
+    smbios_pciexrc_t *rcp)
+{
+	const smb_struct_t *stp = smb_lookup_id(shp, id);
+	smb_pciexrc_t rc;
+
+	if (stp == NULL)
+		return (-1); /* errno is set for us */
+
+	if (stp->smbst_hdr->smbh_type != SUN_OEM_PCIEXRC)
+		return (smb_set_errno(shp, ESMB_TYPE));
+
+	smb_info_bcopy(stp->smbst_hdr, &rc, sizeof (rc));
+	bzero(rcp, sizeof (smbios_pciexrc_t));
+
+	rcp->smbpcie_bb = rc.smbpciexrc_bboard;
+	rcp->smbpcie_bdf = rc.smbpciexrc_bdf;
+
+	return (0);
+}
+
+int
+smbios_info_extmemarray(smbios_hdl_t *shp, id_t id, smbios_memarray_ext_t *emap)
+{
+	const smb_struct_t *stp = smb_lookup_id(shp, id);
+	smb_memarray_ext_t exma;
+
+	if (stp == NULL)
+		return (-1); /* errno is set for us */
+
+	if (stp->smbst_hdr->smbh_type != SUN_OEM_EXT_MEMARRAY)
+		return (smb_set_errno(shp, ESMB_TYPE));
+
+	smb_info_bcopy(stp->smbst_hdr, &exma, sizeof (exma));
+	bzero(emap, sizeof (smbios_memarray_ext_t));
+
+	emap->smbmae_ma = exma.smbmarre_ma;
+	emap->smbmae_comp = exma.smbmarre_component;
+	emap->smbmae_bdf = exma.smbmarre_bdf;
+
+	return (0);
+}
+
+int
+smbios_info_extmemdevice(smbios_hdl_t *shp, id_t id,
+    smbios_memdevice_ext_t *emdp)
+{
+	const smb_struct_t *stp = smb_lookup_id(shp, id);
+	smb_memdevice_ext_t exmd;
+
+	if (stp == NULL)
+		return (-1); /* errno is set for us */
+
+	if (stp->smbst_hdr->smbh_type != SUN_OEM_EXT_MEMDEVICE)
+		return (smb_set_errno(shp, ESMB_TYPE));
+
+	smb_info_bcopy(stp->smbst_hdr, &exmd, sizeof (exmd));
+	bzero(emdp, sizeof (smbios_memdevice_ext_t));
+
+	emdp->smbmdeve_md = exmd.smbmdeve_mdev;
+	emdp->smbmdeve_drch = exmd.smbmdeve_dchan;
+	emdp->smbmdeve_ncs  = exmd.smbmdeve_ncs;
+	emdp->smbmdeve_cs = exmd.smbmdeve_cs;
+
+	return (0);
+}
--- a/usr/src/common/smbios/smb_open.c	Tue Nov 03 17:06:24 2009 -0800
+++ b/usr/src/common/smbios/smb_open.c	Tue Nov 03 21:14:05 2009 -0500
@@ -2,9 +2,8 @@
  * CDDL HEADER START
  *
  * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
  *
  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  * or http://www.opensolaris.org/os/licensing.
@@ -21,12 +20,10 @@
  */
 
 /*
- * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
-#pragma ident	"%Z%%M%	%I%	%E% SMI"
-
 #include <sys/smbios_impl.h>
 
 static const uint_t _smb_hashlen = 64;		/* hash length (must be Pof2) */
@@ -306,6 +303,20 @@
 }
 
 int
+smbios_lookup_type(smbios_hdl_t *shp, uint_t type, smbios_struct_t *sp)
+{
+	const smb_struct_t *stp = smb_lookup_type(shp, type);
+
+	if (stp == NULL)
+		return (-1); /* errno is set for us */
+
+	if (sp != NULL)
+		(void) smb_export(stp, sp);
+
+	return (0);
+}
+
+int
 smbios_iter(smbios_hdl_t *shp, smbios_struct_f *func, void *data)
 {
 	const smb_struct_t *sp = shp->sh_structs;
--- a/usr/src/lib/fm/topo/libtopo/common/mapfile-vers	Tue Nov 03 17:06:24 2009 -0800
+++ b/usr/src/lib/fm/topo/libtopo/common/mapfile-vers	Tue Nov 03 21:14:05 2009 -0500
@@ -121,6 +121,7 @@
 	topo_mod_unregister;
 	topo_mod_walk_init;
 	topo_mod_zalloc;
+	topo_mod_smbios;
 	topo_node_asru;
 	topo_node_asru_set;
 	topo_node_bind;
--- a/usr/src/lib/fm/topo/libtopo/common/topo_mod.map	Tue Nov 03 17:06:24 2009 -0800
+++ b/usr/src/lib/fm/topo/libtopo/common/topo_mod.map	Tue Nov 03 21:14:05 2009 -0500
@@ -66,6 +66,8 @@
 
 	topo_mod_walk_init = FUNCTION extern;
 
+	topo_mod_smbios = FUNCTION extern;
+
 	topo_method_register = FUNCTION extern;
 	topo_method_unregister = FUNCTION extern;
 	topo_method_unregister_all = FUNCTION extern;
--- a/usr/src/lib/fm/topo/maps/i86pc/Makefile	Tue Nov 03 17:06:24 2009 -0800
+++ b/usr/src/lib/fm/topo/maps/i86pc/Makefile	Tue Nov 03 21:14:05 2009 -0500
@@ -27,7 +27,7 @@
 CLASS = arch
 DTDFILE = topology.dtd.1
 TOPOFILE = i86pc-hc-topology.xml chip-hc-topology.xml psu-hc-topology.xml \
-fan-hc-topology.xml chassis-hc-topology.xml
+fan-hc-topology.xml i86pc-legacy-hc-topology.xml chassis-hc-topology.xml
 
 SRCDIR = ../i86pc
 
--- a/usr/src/lib/fm/topo/maps/i86pc/i86pc-hc-topology.xml	Tue Nov 03 17:06:24 2009 -0800
+++ b/usr/src/lib/fm/topo/maps/i86pc/i86pc-hc-topology.xml	Tue Nov 03 21:14:05 2009 -0500
@@ -27,131 +27,8 @@
 
 <topology name='i86pc' scheme='hc'>
 
-  <range name='motherboard' min='0' max='0'>
-    <node instance='0'>
-      <set type='product' setlist='Sun-Fire-X4100-Server|Sun-Fire-X4200-Server|Sun-Fire-X4100-M2|Sun-Fire-X4200-M2|Sun-Fire-X4140|Sun-Fire-X4240|Sun-Fire-X4440|Sun-Fire-X4500|Sun-Fire-X4540|Sun-Fire-X4600-M2'>
-        <fac-enum provider='fac_prov_ipmi' />
-        <propgroup name='protocol' version='1'
-            name-stability='Private' data-stability='Private' >
-            <propval name='label' type='string' value='MB' />
-        </propgroup>
-        <propgroup name='ipmi' version='1'
-            name-stability='Private' data-stability='Private' >
-            <propval name='entity_ref' type='string_array' >
-	        <propitem value='MB' />
-	        <propitem value='mb.fru' />
-	    </propval>
-        </propgroup>
-
-      </set>
-      <set type='product' setlist='SUN-FIRE-X4150|SUN-FIRE-X4250|SUN-FIRE-X4450'>
-        <fac-enum provider='fac_prov_ipmi' />
-        <propgroup name='protocol' version='1'
-            name-stability='Private' data-stability='Private' >
-            <propval name='label' type='string' value='MB' />
-        </propgroup>
-        <propgroup name='ipmi' version='1'
-            name-stability='Private' data-stability='Private' >
-            <propval name='entity_ref' type='string' value='MB' />
-        </propgroup>
-
-      </set>
-      <set type='product' setlist='default'>
-        <propgroup name='protocol' version='1'
-            name-stability='Private' data-stability='Private' >
-            <propval name='label' type='string' value='MB' />
-        </propgroup>
-      </set>
-    </node>
- 
-    <dependents grouping='children'>
-      <range name='chip' min='0' max='100'>
-        <enum-method name='chip' version='1' />
-	<propmap name='chip' />
-      </range>
-      <range name='hostbridge' min='0' max='254'>
-        <enum-method name='hostbridge' version='1' />
-      </range>
-    </dependents>
-    
-  </range>
-
   <range name='chassis' min='0' max='0'>
-    <propmap name='chassis' />
-    
-    <dependents grouping='children'>
-    
-    <set type='product' setlist='Sun-Fire-X4100-Server|Sun-Fire-X4200-Server|Sun-Fire-X4100-M2|Sun-Fire-X4200-M2|Sun-Fire-X4140|Sun-Fire-X4240|Sun-Fire-X4440'>
-       <range name='psu' min='0' max='100'>
-   	  <enum-method name='ipmi' version='1' />
-   	  <propmap name='psu' />
-       </range>
-       <range name='fanmodule' min='0' max='100'>
-          <propmap name='fan' />
-       </range>
-       <set type='product' setlist='Sun-Fire-X4200-M2'>
-	  <range name='bay' min='0' max='3'>
-             <propmap name='Sun-Fire-X4200-M2-disk' />
-          </range>
-       </set>
-       <set type='product' setlist='Sun-Fire-X4200-Server'>
-	  <range name='bay' min='0' max='3'>
-             <propmap name='Sun-Fire-X4200-Server-disk' />
-	  </range>
-       </set>
-       <set type='product' setlist='default'>
-	  <range name='bay' min='0' max='1024'>
-             <enum-method name='ses' version='1' />
-	  </range>
-       </set>
-    </set>
-
-    <set type='product' setlist='Sun-Fire-X4500|Sun-Fire-X4540|SUN-FIRE-X4150|SUN-FIRE-X4250|SUN-FIRE-X4450'>
-       <range name='psu' min='0' max='100'>
- 	  <propmap name='psu' />
-       </range>
-       <range name='fanmodule' min='0' max='100'>
-          <propmap name='fan' />
-       </range>
-       <set type='product' setlist='Sun-Fire-X4500'>
-	  <range name='bay' min='0' max='47'>
-              <propmap name='Sun-Fire-X4500-disk' />
-	  </range>
-       </set>
-       <set type='product' setlist='Sun-Fire-X4540'>
-	  <range name='bay' min='0' max='47'>
-             <propmap name='Sun-Fire-X4540-disk' />
-	  </range>
-       </set>
-    </set>
-      
-   <set type='product' setlist='Sun-Fire-X4600|Sun-Fire-X4600-M2'>
-       <range name='psu' min='0' max='100'>
-          <enum-method name='ipmi' version='1' />
-          <propmap name='psu' />
-       </range>
-       <range name='fan' min='0' max='3'>
-          <propmap name='fan' />
-       </range>
-       <range name='bay' min='0' max='3'>
-          <propmap name='Sun-Fire-X4600-M2-disk' />
-       </range>
-    </set>
-
-    <set type='product' setlist='default'>
-       <range name='psu' min='0' max='100'>
-   	  <enum-method name='ipmi' version='1' />
-       </range>
-       <range name='fan' min='0' max='100'>
-	  <enum-method name='ipmi' version='1' />
-       </range>
-       <range name='bay' min='0' max='1024'>
-          <enum-method name='ses' version='1' />
-       </range>
-    </set>
-
-    </dependents>
-
+    <enum-method name='x86pi' version='1' />
   </range>
 
   <range name='ses-enclosure' min='0' max='1024'>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/lib/fm/topo/maps/i86pc/i86pc-legacy-hc-topology.xml	Tue Nov 03 21:14:05 2009 -0500
@@ -0,0 +1,166 @@
+<?xml version="1.0"?>
+<!DOCTYPE topology SYSTEM "/usr/share/lib/xml/dtd/topology.dtd.1">
+<!--
+ Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
+ Use is subject to license terms.
+
+ CDDL HEADER START
+
+ The contents of this file are subject to the terms of the
+ Common Development and Distribution License (the "License").
+ You may not use this file except in compliance with the License.
+
+ You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ or http://www.opensolaris.org/os/licensing.
+ See the License for the specific language governing permissions
+ and limitations under the License.
+
+ When distributing Covered Code, include this CDDL HEADER in each
+ file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ If applicable, add the following below this CDDL HEADER, with the
+ fields enclosed by brackets "[]" replaced with your own identifying
+ information: Portions Copyright [yyyy] [name of copyright owner]
+
+ CDDL HEADER END
+
+-->
+
+<!--
+ This map file is loaded by the generic enumerator (x86pi.so) when
+ an FMA-compliant SMBIOS can't be found.
+-->
+
+<topology name='i86pc' scheme='hc'>
+
+  <range name='motherboard' min='0' max='0'>
+    <node instance='0'>
+      <set type='product' setlist='Sun-Fire-X4100-Server|Sun-Fire-X4200-Server|Sun-Fire-X4100-M2|Sun-Fire-X4200-M2|Sun-Fire-X4140|Sun-Fire-X4240|Sun-Fire-X4440|Sun-Fire-X4500|Sun-Fire-X4540|Sun-Fire-X4600-M2'>
+        <fac-enum provider='fac_prov_ipmi' />
+        <propgroup name='protocol' version='1'
+            name-stability='Private' data-stability='Private' >
+            <propval name='label' type='string' value='MB' />
+        </propgroup>
+        <propgroup name='ipmi' version='1'
+            name-stability='Private' data-stability='Private' >
+            <propval name='entity_ref' type='string_array' >
+	        <propitem value='MB' />
+	        <propitem value='mb.fru' />
+	    </propval>
+        </propgroup>
+
+      </set>
+      <set type='product' setlist='SUN-FIRE-X4150|SUN-FIRE-X4250|SUN-FIRE-X4450'>
+        <fac-enum provider='fac_prov_ipmi' />
+        <propgroup name='protocol' version='1'
+            name-stability='Private' data-stability='Private' >
+            <propval name='label' type='string' value='MB' />
+        </propgroup>
+        <propgroup name='ipmi' version='1'
+            name-stability='Private' data-stability='Private' >
+            <propval name='entity_ref' type='string' value='MB' />
+        </propgroup>
+
+      </set>
+      <set type='product' setlist='default'>
+        <propgroup name='protocol' version='1'
+            name-stability='Private' data-stability='Private' >
+            <propval name='label' type='string' value='MB' />
+        </propgroup>
+      </set>
+    </node>
+ 
+    <dependents grouping='children'>
+      <range name='chip' min='0' max='100'>
+        <enum-method name='chip' version='1' />
+	<propmap name='chip' />
+      </range>
+      <range name='hostbridge' min='0' max='254'>
+        <enum-method name='hostbridge' version='1' />
+      </range>
+    </dependents>
+    
+  </range>
+
+  <range name='chassis' min='0' max='0'>
+    <propmap name='chassis' />
+    
+    <dependents grouping='children'>
+    
+    <set type='product' setlist='Sun-Fire-X4100-Server|Sun-Fire-X4200-Server|Sun-Fire-X4100-M2|Sun-Fire-X4200-M2|Sun-Fire-X4140|Sun-Fire-X4240|Sun-Fire-X4440'>
+       <range name='psu' min='0' max='100'>
+   	  <enum-method name='ipmi' version='1' />
+   	  <propmap name='psu' />
+       </range>
+       <range name='fanmodule' min='0' max='100'>
+          <propmap name='fan' />
+       </range>
+       <set type='product' setlist='Sun-Fire-X4200-M2'>
+	  <range name='bay' min='0' max='3'>
+             <propmap name='Sun-Fire-X4200-M2-disk' />
+          </range>
+       </set>
+       <set type='product' setlist='Sun-Fire-X4200-Server'>
+	  <range name='bay' min='0' max='3'>
+             <propmap name='Sun-Fire-X4200-Server-disk' />
+	  </range>
+       </set>
+       <set type='product' setlist='default'>
+	  <range name='bay' min='0' max='1024'>
+             <enum-method name='ses' version='1' />
+	  </range>
+       </set>
+    </set>
+
+    <set type='product' setlist='Sun-Fire-X4500|Sun-Fire-X4540|SUN-FIRE-X4150|SUN-FIRE-X4250|SUN-FIRE-X4450'>
+       <range name='psu' min='0' max='100'>
+ 	  <propmap name='psu' />
+       </range>
+       <range name='fanmodule' min='0' max='100'>
+          <propmap name='fan' />
+       </range>
+       <set type='product' setlist='Sun-Fire-X4500'>
+	  <range name='bay' min='0' max='47'>
+              <propmap name='Sun-Fire-X4500-disk' />
+	  </range>
+       </set>
+       <set type='product' setlist='Sun-Fire-X4540'>
+	  <range name='bay' min='0' max='47'>
+             <propmap name='Sun-Fire-X4540-disk' />
+	  </range>
+       </set>
+    </set>
+      
+   <set type='product' setlist='Sun-Fire-X4600|Sun-Fire-X4600-M2'>
+       <range name='psu' min='0' max='100'>
+          <enum-method name='ipmi' version='1' />
+          <propmap name='psu' />
+       </range>
+       <range name='fan' min='0' max='3'>
+          <propmap name='fan' />
+       </range>
+       <range name='bay' min='0' max='3'>
+          <propmap name='Sun-Fire-X4600-M2-disk' />
+       </range>
+    </set>
+
+    <set type='product' setlist='default'>
+       <range name='psu' min='0' max='100'>
+   	  <enum-method name='ipmi' version='1' />
+       </range>
+       <range name='fan' min='0' max='100'>
+	  <enum-method name='ipmi' version='1' />
+       </range>
+       <range name='bay' min='0' max='1024'>
+          <enum-method name='ses' version='1' />
+       </range>
+    </set>
+
+    </dependents>
+
+  </range>
+
+  <range name='ses-enclosure' min='0' max='1024'>
+    <enum-method name='ses' version='1' />
+  </range>
+
+</topology>
--- a/usr/src/lib/fm/topo/modules/common/pcibus/did_props.c	Tue Nov 03 17:06:24 2009 -0800
+++ b/usr/src/lib/fm/topo/modules/common/pcibus/did_props.c	Tue Nov 03 21:14:05 2009 -0500
@@ -20,7 +20,7 @@
  */
 
 /*
- * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -129,15 +129,23 @@
 	{ NULL, &io_pgroup, TOPO_IO_MODULE, MODULEprop_set },
 	{ NULL, &pci_pgroup, TOPO_PCI_EXCAP, EXCAP_set },
 	{ NULL, &pci_pgroup, TOPO_PCI_BDF, BDF_set },
+	{ NULL, &protocol_pgroup, TOPO_PROP_ASRU, ASRU_set },
+	/*
+	 * These props need to be put at the end of table.  x86pi has its
+	 * own way to set them.
+	 */
 	{ NULL, &protocol_pgroup, TOPO_PROP_LABEL, label_set },
-	{ NULL, &protocol_pgroup, TOPO_PROP_FRU, FRU_set },
-	{ NULL, &protocol_pgroup, TOPO_PROP_ASRU, ASRU_set }
+	{ NULL, &protocol_pgroup, TOPO_PROP_FRU, FRU_set }
 };
 
 txprop_t ExHB_common_props[] = {
+	{ NULL, &protocol_pgroup, TOPO_PROP_ASRU, ASRU_set },
+	/*
+	 * These props need to be put at the end of table.  x86pi has its
+	 * own way to set them.
+	 */
 	{ NULL, &protocol_pgroup, TOPO_PROP_LABEL, label_set },
-	{ NULL, &protocol_pgroup, TOPO_PROP_FRU, FRU_set },
-	{ NULL, &protocol_pgroup, TOPO_PROP_ASRU, ASRU_set }
+	{ NULL, &protocol_pgroup, TOPO_PROP_FRU, FRU_set }
 };
 
 txprop_t IOB_common_props[] = {
@@ -150,9 +158,13 @@
 	{ NULL, &io_pgroup, TOPO_IO_DEV, DEVprop_set },
 	{ NULL, &io_pgroup, TOPO_IO_DRIVER, DRIVERprop_set },
 	{ NULL, &io_pgroup, TOPO_IO_MODULE, MODULEprop_set },
+	{ NULL, &protocol_pgroup, TOPO_PROP_ASRU, ASRU_set },
+	/*
+	 * These props need to be put at the end of table.  x86pi has its
+	 * own way to set them.
+	 */
 	{ NULL, &protocol_pgroup, TOPO_PROP_LABEL, label_set },
-	{ NULL, &protocol_pgroup, TOPO_PROP_FRU, FRU_set },
-	{ NULL, &protocol_pgroup, TOPO_PROP_ASRU, ASRU_set }
+	{ NULL, &protocol_pgroup, TOPO_PROP_FRU, FRU_set }
 };
 
 int Bus_propcnt = sizeof (Bus_common_props) / sizeof (txprop_t);
--- a/usr/src/lib/fm/topo/modules/i86pc/Makefile	Tue Nov 03 17:06:24 2009 -0800
+++ b/usr/src/lib/fm/topo/modules/i86pc/Makefile	Tue Nov 03 21:14:05 2009 -0500
@@ -20,12 +20,11 @@
 #
 
 #
-# Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
+# Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
 # Use is subject to license terms.
 #
-# ident	"%Z%%M%	%I%	%E% SMI"
 
-SUBDIRS = chip hostbridge pcibus
+SUBDIRS = chip hostbridge pcibus x86pi
 
 .PARALLEL: $(SUBDIRS)
 
--- a/usr/src/lib/fm/topo/modules/i86pc/chip/Makefile	Tue Nov 03 17:06:24 2009 -0800
+++ b/usr/src/lib/fm/topo/modules/i86pc/chip/Makefile	Tue Nov 03 21:14:05 2009 -0500
@@ -19,7 +19,7 @@
 # CDDL HEADER END
 #
 #
-# Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
+# Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
 # Use is subject to license terms.
 #
 
@@ -27,7 +27,7 @@
 ARCH = i86pc
 CLASS = arch
 MODULESRCS = chip.c chip_label.c chip_subr.c chip_amd.c chip_intel.c\
-chip_serial.c
+chip_serial.c chip_smbios.c
 
 include ../../Makefile.plugin
-LDLIBS += -lipmi -lfmd_agent -lumem
+LDLIBS += -lipmi -lfmd_agent -lumem -lsmbios
--- a/usr/src/lib/fm/topo/modules/i86pc/chip/chip.c	Tue Nov 03 17:06:24 2009 -0800
+++ b/usr/src/lib/fm/topo/modules/i86pc/chip/chip.c	Tue Nov 03 21:14:05 2009 -0500
@@ -143,7 +143,7 @@
 
 static tnode_t *
 create_node(topo_mod_t *mod, tnode_t *pnode, nvlist_t *auth, char *name,
-    topo_instance_t inst)
+    topo_instance_t inst, uint16_t smbios_id)
 {
 	nvlist_t *fmri;
 	tnode_t *cnode;
@@ -152,22 +152,57 @@
 		whinge(mod, NULL, "create_node: mkrsrc failed\n");
 		return (NULL);
 	}
+
+	if (FM_AWARE_SMBIOS(mod)) {
+		id_t phys_cpu_smbid;
+		int perr = 0;
+		const char *serial = NULL;
+		const char *part = NULL;
+		const char *rev = NULL;
+
+		phys_cpu_smbid = smbios_id;
+		serial = chip_serial_smbios_get(mod, phys_cpu_smbid);
+		part = chip_part_smbios_get(mod, phys_cpu_smbid);
+		rev = chip_rev_smbios_get(mod, phys_cpu_smbid);
+
+		perr += nvlist_add_string(fmri, FM_FMRI_HC_SERIAL_ID,
+		    serial);
+		perr += nvlist_add_string(fmri, FM_FMRI_HC_PART,
+		    part);
+		perr += nvlist_add_string(fmri, FM_FMRI_HC_REVISION,
+		    rev);
+
+		if (perr != 0)
+			whinge(mod, NULL,
+			    "create_node: nvlist_add_string failed\n");
+
+		topo_mod_strfree(mod, (char *)serial);
+		topo_mod_strfree(mod, (char *)part);
+		topo_mod_strfree(mod, (char *)rev);
+	}
+
 	cnode = topo_node_bind(mod, pnode, name, inst, fmri);
+
 	nvlist_free(fmri);
-	if (cnode == NULL)
-		whinge(mod, NULL, "create_node: node bind failed for %s %d\n",
-		    name, (int)inst);
+	if (cnode == NULL) {
+		whinge(mod, NULL, "create_node: node bind failed"
+		    " for %s %d\n", name, (int)inst);
+	}
 
 	return (cnode);
 }
 
 static int
-create_strand(topo_mod_t *mod, tnode_t *pnode, nvlist_t *cpu, nvlist_t *auth)
+create_strand(topo_mod_t *mod, tnode_t *pnode, nvlist_t *cpu,
+    nvlist_t *auth, uint16_t chip_smbiosid)
 {
 	tnode_t *strand;
 	int32_t strandid, cpuid;
-	int err, nerr = 0;
+	int err, perr, nerr = 0;
 	nvlist_t *fmri;
+	char *serial = NULL;
+	char *part = NULL;
+	char *rev = NULL;
 
 	if ((err = nvlist_lookup_int32(cpu, FM_PHYSCPU_INFO_STRAND_ID,
 	    &strandid)) != 0) {
@@ -183,19 +218,40 @@
 	}
 
 	if ((strand = create_node(mod, pnode, auth, STRAND_NODE_NAME,
-	    strandid)) == NULL)
+	    strandid, chip_smbiosid)) == NULL)
 		return (-1);
 
 	/*
 	 * Inherit FRU from core node, in native use cpu scheme ASRU,
 	 * in xpv, use hc scheme ASRU.
 	 */
-	(void) topo_node_fru_set(strand, NULL, 0, &err);
+	(void) topo_node_fru_set(strand, NULL, 0, &perr);
+	/*
+	 * From the inherited FRU, extract the Serial
+	 * number(if SMBIOS donates) and set it in the ASRU
+	 */
+	if (FM_AWARE_SMBIOS(mod)) {
+		char *val = NULL;
+
+		if (topo_prop_get_fmri(strand, TOPO_PGROUP_PROTOCOL,
+		    TOPO_PROP_RESOURCE, &fmri, &err) != 0)
+			whinge(mod, NULL,
+			    "create_strand: topo_prop_get_fmri failed\n");
+		if (nvlist_lookup_string(fmri, FM_FMRI_HC_SERIAL_ID, &val) != 0)
+			whinge(mod, NULL,
+			    "create_strand: nvlist_lookup_string failed: \n");
+		else
+			serial = topo_mod_strdup(mod, val);
+		nvlist_free(fmri);
+	}
 	if (is_xpv()) {
 		if (topo_node_resource(strand, &fmri, &err) == -1) {
 			whinge(mod, &nerr, "create_strand: "
 			    "topo_node_resource failed\n");
 		} else {
+			if (FM_AWARE_SMBIOS(mod))
+				(void) nvlist_add_string(fmri,
+				    FM_FMRI_HC_SERIAL_ID, serial);
 			(void) topo_node_asru_set(strand, fmri, 0, &err);
 			nvlist_free(fmri);
 		}
@@ -204,7 +260,7 @@
 			whinge(mod, &nerr, "create_strand: lookup cpuid "
 			    "failed\n");
 		} else {
-			if ((fmri = cpu_fmri_create(mod, cpuid, NULL, 0))
+			if ((fmri = cpu_fmri_create(mod, cpuid, serial, 0))
 			    != NULL) {
 				(void) topo_node_asru_set(strand, fmri,
 				    0, &err);
@@ -224,16 +280,55 @@
 	nerr -= add_nvlist_longprops(mod, strand, cpu, PGNAME(STRAND), NULL,
 	    STRAND_CHIP_ID, STRAND_CORE_ID, STRAND_CPU_ID, NULL);
 
+	if (FM_AWARE_SMBIOS(mod)) {
+		(void) topo_node_label_set(strand, NULL, &perr);
+
+		if (topo_node_resource(strand, &fmri, &perr) != 0) {
+			whinge(mod, &nerr, "create_strand: "
+			    "topo_node_resource failed\n");
+			perr = 0;
+		}
+
+		perr += nvlist_lookup_string(fmri,
+		    FM_FMRI_HC_PART, &part);
+		perr += nvlist_lookup_string(fmri,
+		    FM_FMRI_HC_REVISION, &rev);
+
+		if (perr != 0) {
+			whinge(mod, NULL,
+			    "create_strand: nvlist_lookup_string failed\n");
+			perr = 0;
+		}
+
+		perr += topo_prop_set_string(strand, PGNAME(STRAND),
+		    FM_FMRI_HC_SERIAL_ID, TOPO_PROP_IMMUTABLE, serial, &perr);
+		perr += topo_prop_set_string(strand, PGNAME(STRAND),
+		    FM_FMRI_HC_PART, TOPO_PROP_IMMUTABLE, part, &perr);
+		perr += topo_prop_set_string(strand, PGNAME(STRAND),
+		    FM_FMRI_HC_REVISION, TOPO_PROP_IMMUTABLE, rev, &perr);
+
+		if (perr != 0)
+			whinge(mod, NULL, "create_strand: topo_prop_set_string"
+			    "failed\n");
+
+		nvlist_free(fmri);
+		topo_mod_strfree(mod, serial);
+	}
+
 	return (err == 0 && nerr == 0 ? 0 : -1);
 }
 
 static int
-create_core(topo_mod_t *mod, tnode_t *pnode, nvlist_t *cpu, nvlist_t *auth)
+create_core(topo_mod_t *mod, tnode_t *pnode, nvlist_t *cpu,
+    nvlist_t *auth, uint16_t chip_smbiosid)
 {
 	tnode_t *core;
 	int32_t coreid, cpuid;
-	int err, nerr = 0;
+	int err, perr, nerr = 0;
 	nvlist_t *fmri;
+	char *serial = NULL;
+	char *part = NULL;
+	char *rev = NULL;
 
 	if ((err = nvlist_lookup_int32(cpu, FM_PHYSCPU_INFO_CORE_ID, &coreid))
 	    != 0) {
@@ -243,19 +338,40 @@
 	}
 	if ((core = topo_node_lookup(pnode, CORE_NODE_NAME, coreid)) == NULL) {
 		if ((core = create_node(mod, pnode, auth, CORE_NODE_NAME,
-		    coreid)) == NULL)
+		    coreid, chip_smbiosid)) == NULL)
 			return (-1);
 
 		/*
 		 * Inherit FRU from the chip node, for native, we use hc
 		 * scheme ASRU for the core node.
 		 */
-		(void) topo_node_fru_set(core, NULL, 0, &err);
+		(void) topo_node_fru_set(core, NULL, 0, &perr);
+		/*
+		 * From the inherited FRU, extract the Serial
+		 * number if SMBIOS donates and set it in the ASRU
+		 */
+		if (FM_AWARE_SMBIOS(mod)) {
+			char *val = NULL;
+
+			if (topo_node_resource(core, &fmri, &err) != 0)
+				whinge(mod, NULL,
+				    "create_core: topo_prop_get_fmri failed\n");
+			if (nvlist_lookup_string(fmri, FM_FMRI_HC_SERIAL_ID,
+			    &val) != 0)
+				whinge(mod, NULL, "create_core:"
+				    "nvlist_lookup_string failed\n");
+			else
+				serial = topo_mod_strdup(mod, val);
+			nvlist_free(fmri);
+		}
 		if (is_xpv()) {
 			if (topo_node_resource(core, &fmri, &err) == -1) {
 				whinge(mod, &nerr, "create_core: "
 				    "topo_node_resource failed\n");
 			} else {
+				if (FM_AWARE_SMBIOS(mod))
+					(void) nvlist_add_string(fmri,
+					    FM_FMRI_HC_SERIAL_ID, serial);
 				(void) topo_node_asru_set(core, fmri, 0, &err);
 				nvlist_free(fmri);
 			}
@@ -273,7 +389,7 @@
 			return (-1);
 	}
 
-	if (! is_xpv()) {
+	if (!is_xpv()) {
 		/*
 		 * In native mode, we're in favor of cpu scheme ASRU for
 		 * printing reason.  More work needs to be done to support
@@ -283,7 +399,7 @@
 			whinge(mod, &nerr, "create_core: lookup cpuid "
 			    "failed\n");
 		} else {
-			if ((fmri = cpu_fmri_create(mod, cpuid, NULL, 0))
+			if ((fmri = cpu_fmri_create(mod, cpuid, serial, 0))
 			    != NULL) {
 				(void) topo_node_asru_set(core, fmri, 0, &err);
 				nvlist_free(fmri);
@@ -294,7 +410,42 @@
 		}
 	}
 
-	err = create_strand(mod, core, cpu, auth);
+	if (FM_AWARE_SMBIOS(mod)) {
+		(void) topo_node_label_set(core, NULL, &perr);
+
+		if (topo_node_resource(core, &fmri, &perr) != 0) {
+			whinge(mod, &nerr, "create_core: "
+			    "topo_node_resource failed\n");
+			perr = 0;
+		}
+
+		perr += nvlist_lookup_string(fmri,
+		    FM_FMRI_HC_PART, &part);
+		perr += nvlist_lookup_string(fmri,
+		    FM_FMRI_HC_REVISION, &rev);
+
+		if (perr != 0) {
+			whinge(mod, NULL,
+			    "create_core: nvlist_lookup_string failed\n");
+			perr = 0;
+		}
+
+		perr += topo_prop_set_string(core, PGNAME(CORE),
+		    FM_FMRI_HC_SERIAL_ID, TOPO_PROP_IMMUTABLE, serial, &perr);
+		perr += topo_prop_set_string(core, PGNAME(CORE),
+		    FM_FMRI_HC_PART, TOPO_PROP_IMMUTABLE, part, &perr);
+		perr += topo_prop_set_string(core, PGNAME(CORE),
+		    FM_FMRI_HC_REVISION, TOPO_PROP_IMMUTABLE, rev, &perr);
+
+		if (perr != 0)
+			whinge(mod, NULL, "create_core: topo_prop_set_string"
+			    "failed\n");
+
+		nvlist_free(fmri);
+		topo_mod_strfree(mod, serial);
+	}
+
+	err = create_strand(mod, core, cpu, auth, chip_smbiosid);
 
 	return (err == 0 && nerr == 0 ? 0 : -1);
 }
@@ -307,14 +458,19 @@
 	tnode_t *chip;
 	int32_t chipid;
 	nvlist_t *fmri = NULL;
-	int err, nerr = 0;
+	int err, perr, nerr = 0;
 	int32_t fms[3];
 	const char *vendor;
 	boolean_t create_mc = B_FALSE;
+	uint16_t smbios_id;
 
+	/*
+	 * /dev/fm will export the chipid based on SMBIOS' ordering
+	 * of Type-4 structures, if SMBIOS meets FMA needs
+	 */
 	if ((err = nvlist_lookup_int32(cpu, FM_PHYSCPU_INFO_CHIP_ID, &chipid))
 	    != 0) {
-		whinge(mod, NULL, "create_chip: lookup chip_id failed: %s\n",
+		whinge(mod, &nerr, "create_chip: lookup chip_id failed: %s\n",
 		    strerror(err));
 		return (-1);
 	}
@@ -322,21 +478,37 @@
 	if (chipid < min || chipid > max)
 		return (-1);
 
+	if (FM_AWARE_SMBIOS(mod)) {
+		if ((err = nvlist_lookup_uint16(cpu,
+		    FM_PHYSCPU_INFO_SMBIOS_ID, &smbios_id)) != 0) {
+			whinge(mod, NULL,
+			    "create_chip: lookup smbios_id failed"
+			    ": enumerating x86pi & chip topology, but"
+			    " no Chip properties from SMBIOS"
+			    " - err msg : %s\n", strerror(err));
+			/*
+			 * Lets reset the module specific
+			 * data to NULL, overriding any
+			 * SMBIOS capability encoded earlier.
+			 * This will fail all subsequent
+			 * FM_AWARE_SMBIOS checks.
+			 */
+			topo_mod_setspecific(mod, NULL);
+		}
+	}
+
 	if ((chip = topo_node_lookup(pnode, CHIP_NODE_NAME, chipid)) == NULL) {
 		if ((chip = create_node(mod, pnode, auth, CHIP_NODE_NAME,
-		    chipid)) == NULL)
+		    chipid, smbios_id)) == NULL)
 			return (-1);
-
-		if (topo_method_register(mod, chip, chip_methods) < 0)
-			whinge(mod, &nerr, "create_chip: "
-			    "topo_method_register failed\n");
-
-		if (topo_node_resource(chip, &fmri, &err) == -1) {
-			whinge(mod, &nerr, "create_chip: "
-			    "topo_node_resource failed\n");
-		} else {
-			(void) topo_node_fru_set(chip, fmri, 0, &err);
-			nvlist_free(fmri);
+		/*
+		 * Do not register XML map methods if SMBIOS can provide
+		 * serial, part, revision & label
+		 */
+		if (!FM_AWARE_SMBIOS(mod)) {
+			if (topo_method_register(mod, chip, chip_methods) < 0)
+				whinge(mod, &nerr, "create_chip: "
+				    "topo_method_register failed\n");
 		}
 
 		(void) topo_pgroup_create(chip, &chip_pgroup, &err);
@@ -345,6 +517,83 @@
 		nerr -= add_nvlist_longprops(mod, chip, cpu, PGNAME(CHIP),
 		    fms, CHIP_FAMILY, CHIP_MODEL, CHIP_STEPPING, NULL);
 
+		if (FM_AWARE_SMBIOS(mod)) {
+			int fru = 0;
+			char *serial = NULL;
+			char *part = NULL;
+			char *rev = NULL;
+			char *label;
+
+			fru = chip_fru_smbios_get(mod, smbios_id);
+			/*
+			 * Chip is not a FRU, set the FRU fmri of parent node
+			 */
+			if (topo_node_resource(chip, &fmri, &perr) != 0)
+				whinge(mod, &nerr, "create_chip: "
+				    "topo_node_resource failed\n");
+			if (!fru) {
+				(void) topo_node_fru_set(chip, NULL, 0, &perr);
+				label = NULL;
+			} else {
+				label = (char *)chip_label_smbios_get(mod,
+				    pnode, smbios_id, NULL);
+
+				if (topo_node_fru_set(chip, fmri, 0, &perr)
+				    != 0) {
+					whinge(mod, NULL, "create_chip: "
+					    "topo_node_fru_set failed\n");
+					perr = 0;
+				}
+			}
+
+			perr += nvlist_lookup_string(fmri,
+			    FM_FMRI_HC_SERIAL_ID, &serial);
+			perr += nvlist_lookup_string(fmri,
+			    FM_FMRI_HC_PART, &part);
+			perr += nvlist_lookup_string(fmri,
+			    FM_FMRI_HC_REVISION, &rev);
+
+			if (perr != 0) {
+				whinge(mod, NULL,
+				    "create_chip: nvlist_lookup_string"
+				    "failed\n");
+				perr = 0;
+			}
+
+			perr += topo_prop_set_string(chip, PGNAME(CHIP),
+			    FM_FMRI_HC_SERIAL_ID, TOPO_PROP_IMMUTABLE,
+			    serial, &perr);
+			perr += topo_prop_set_string(chip, PGNAME(CHIP),
+			    FM_FMRI_HC_PART, TOPO_PROP_IMMUTABLE,
+			    part, &perr);
+			perr += topo_prop_set_string(chip, PGNAME(CHIP),
+			    FM_FMRI_HC_REVISION, TOPO_PROP_IMMUTABLE,
+			    rev, &perr);
+
+			if (perr != 0)
+				whinge(mod, NULL,
+				    "create_chip: topo_prop_set_string"
+				    "failed\n");
+
+			nvlist_free(fmri);
+
+			if (topo_node_label_set(chip, label, &perr)
+			    == -1) {
+				whinge(mod, NULL, "create_chip: "
+				    "topo_node_label_set failed\n");
+			}
+			topo_mod_strfree(mod, label);
+
+		} else {
+			if (topo_node_resource(chip, &fmri, &err) == -1) {
+				whinge(mod, &nerr, "create_chip: "
+				    "topo_node_resource failed\n");
+			} else {
+				(void) topo_node_fru_set(chip, fmri, 0, &perr);
+				nvlist_free(fmri);
+			}
+		}
+
 		if (topo_method_register(mod, chip, strands_retire_methods) < 0)
 			whinge(mod, &nerr, "create_chip: "
 			    "topo_method_register failed\n");
@@ -356,18 +605,46 @@
 		create_mc = B_TRUE;
 	}
 
-	err = create_core(mod, chip, cpu, auth);
+	if (FM_AWARE_SMBIOS(mod)) {
+		int status = 0;
+		/*
+		 * STATUS
+		 * CPU Socket Populated
+		 * CPU Socket Unpopulated
+		 * Populated : Enabled
+		 * Populated : Disabled by BIOS (Setup)
+		 * Populated : Disabled by BIOS (Error)
+		 * Populated : Idle
+		 *
+		 * Enumerate core & strand only for Populated : Enabled
+		 * Enumerate Off-Chip Memory Controller only for
+		 * Populated : Enabled
+		 */
+
+		status = chip_status_smbios_get(mod, (id_t)smbios_id);
+		if (!status) {
+			whinge(mod, NULL, "create_chip: "
+			    "CPU Socket is not populated or is disabled\n");
+			return (0);
+		}
+	}
+
+	err = create_core(mod, chip, cpu, auth, smbios_id);
 
 	/*
 	 * Create memory-controller node under a chip for architectures
 	 * that may have on-chip memory-controller(s).
+	 * If SMBIOS meets FMA needs, when Multi-Chip-Module is
+	 * addressed, mc instances should be derived from SMBIOS
 	 */
 	if (create_mc) {
 		if (strcmp(vendor, "AuthenticAMD") == 0)
-			amd_mc_create(mod, chip, MCT_NODE_NAME, auth,
+			amd_mc_create(mod, smbios_id, chip, MCT_NODE_NAME, auth,
 			    fms[0], fms[1], fms[2], &nerr);
-		else if (!mc_offchip)
-			onchip_mc_create(mod, chip, MCT_NODE_NAME, auth);
+		else if (!mc_offchip) {
+			onchip_mc_create(mod, smbios_id, chip,
+			    MCT_NODE_NAME, auth);
+		}
 	}
 
 	return (err == 0 && nerr == 0 ? 0 : -1);
@@ -415,7 +692,7 @@
 /*ARGSUSED*/
 static int
 chip_enum(topo_mod_t *mod, tnode_t *pnode, const char *name,
-    topo_instance_t min, topo_instance_t max, void *arg, void *notused)
+    topo_instance_t min, topo_instance_t max, void *arg, void *smbios_enabled)
 {
 	int rv = 0;
 	nvlist_t *auth = NULL;
@@ -446,6 +723,29 @@
 		}
 	}
 
+	/*
+	 * Set Chip Enumerator Module's private data with the value passed by
+	 * x86pi Enumerator, defining SMBIOS capabilities
+	 */
+	topo_mod_setspecific(mod, smbios_enabled);
+
+	if (FM_AWARE_SMBIOS(mod))
+		if (init_chip_smbios(mod) != 0) {
+			whinge(mod, NULL,
+			    "init_chip_smbios() failed, "
+			    " enumerating x86pi & chip topology, but no"
+			    " CPU & Memory properties will be"
+			    " derived from SMBIOS\n");
+			/*
+			 * Lets reset the module specific
+			 * data to NULL, overriding any
+			 * SMBIOS capability encoded earlier.
+			 * This will fail all subsequent
+			 * FM_AWARE_SMBIOS checks.
+			 */
+			topo_mod_setspecific(mod, NULL);
+		}
+
 	auth = topo_mod_auth(mod, pnode);
 
 	offchip_mc = mc_offchip_open();
--- a/usr/src/lib/fm/topo/modules/i86pc/chip/chip.h	Tue Nov 03 17:06:24 2009 -0800
+++ b/usr/src/lib/fm/topo/modules/i86pc/chip/chip.h	Tue Nov 03 21:14:05 2009 -0500
@@ -37,6 +37,21 @@
 
 #define	CHIP_VERSION		TOPO_VERSION
 
+/* Below should match the definitions in x86pi_impl.h */
+#define	X86PI_FULL		1
+#define	X86PI_NONE		2
+
+/*
+ * FM_AWARE_SMBIOS means SMBIOS meets FMA needs
+ * X86PI_FULL is defined as 1 in x86pi.so
+ * And passed from x86pi.so to chip.so as module
+ * private data
+ */
+#define	FM_AWARE_SMBIOS(mod)	\
+	(topo_mod_getspecific(mod) != NULL && \
+	    (*(int *)topo_mod_getspecific(mod) == X86PI_FULL))
+#define	IGNORE_ID	0xFFFF
+
 #define	CHIP_NODE_NAME		"chip"
 #define	CORE_NODE_NAME		"core"
 #define	STRAND_NODE_NAME	"strand"
@@ -161,19 +176,34 @@
 /*
  * Prototypes for chip_amd.c
  */
-extern void amd_mc_create(topo_mod_t *, tnode_t *, const char *, nvlist_t *,
-    int, int, int, int *);
+extern void amd_mc_create(topo_mod_t *, uint16_t, tnode_t *,
+    const char *, nvlist_t *, int, int, int, int *);
 
 /*
  * Prototypes for chip_intel.c
  */
 extern int mc_offchip_open(void);
 extern int mc_offchip_create(topo_mod_t *, tnode_t *, const char *, nvlist_t *);
-extern void onchip_mc_create(topo_mod_t *, tnode_t *, const char *, nvlist_t *);
+extern void onchip_mc_create(topo_mod_t *, uint16_t, tnode_t *,
+    const char *, nvlist_t *);
 
 extern char *get_fmtstr(topo_mod_t *, nvlist_t *);
 extern int store_prop_val(topo_mod_t *, char *, char *, nvlist_t **out);
 
+/*
+ * Prototypes for chip_smbios.c
+ */
+
+extern int init_chip_smbios(topo_mod_t *);
+extern int chip_status_smbios_get(topo_mod_t *, id_t);
+extern int chip_fru_smbios_get(topo_mod_t *, id_t);
+extern const char *chip_label_smbios_get(topo_mod_t *, tnode_t *, id_t, char *);
+extern const char *chip_serial_smbios_get(topo_mod_t *, id_t);
+extern const char *chip_part_smbios_get(topo_mod_t *, id_t);
+extern const char *chip_rev_smbios_get(topo_mod_t *, id_t);
+extern id_t memnode_to_smbiosid(uint16_t, const char *, uint64_t, void *);
+
+
 #ifdef __cplusplus
 }
 #endif
--- a/usr/src/lib/fm/topo/modules/i86pc/chip/chip_amd.c	Tue Nov 03 17:06:24 2009 -0800
+++ b/usr/src/lib/fm/topo/modules/i86pc/chip/chip_amd.c	Tue Nov 03 21:14:05 2009 -0500
@@ -98,6 +98,19 @@
 	{ NULL }
 };
 
+/*
+ * Serials, Labels are obtained from SMBIOS, so
+ * we leave out the related methods, any other
+ * methods that will be added to gen_cs_methods
+ * should be added to x86pi_gen_cs_methods too
+ */
+static const topo_method_t x86pi_gen_cs_methods[] = {
+	{ TOPO_METH_ASRU_COMPUTE, TOPO_METH_ASRU_COMPUTE_DESC,
+	    TOPO_METH_ASRU_COMPUTE_VERSION, TOPO_STABILITY_INTERNAL,
+	    mem_asru_compute },
+	{ NULL }
+};
+
 static const topo_method_t gen_cs_methods[] = {
 	{ TOPO_METH_ASRU_COMPUTE, TOPO_METH_ASRU_COMPUTE_DESC,
 	    TOPO_METH_ASRU_COMPUTE_VERSION, TOPO_STABILITY_INTERNAL,
@@ -127,8 +140,8 @@
  */
 /*ARGSUSED*/
 static int
-amd_generic_mc_create(topo_mod_t *mod, tnode_t *cnode, tnode_t *mcnode,
-    int family, int model, int stepping, nvlist_t *auth)
+amd_generic_mc_create(topo_mod_t *mod, uint16_t smbid, tnode_t *cnode,
+    tnode_t *mcnode, int family, int model, int stepping, nvlist_t *auth)
 {
 	int chan, cs;
 
@@ -176,6 +189,15 @@
 		(void) topo_prop_set_string(chnode, PGNAME(CHAN), "channel",
 		    TOPO_PROP_IMMUTABLE, chan == 0 ? "A" : "B", &err);
 
+		if (FM_AWARE_SMBIOS(mod)) {
+			if (topo_node_label_set(chnode, NULL, &err) == -1)
+				whinge(mod, NULL, "amd_generic_mc_create: "
+				    "topo_node_label_set\n");
+			if (topo_node_fru_set(chnode, NULL, 0, &err) != 0)
+				whinge(mod, NULL, "amd_generic_mc_create: "
+				    "topo_node_fru_set failed\n");
+		}
+
 		if (topo_node_range_create(mod, chnode, CS_NODE_NAME,
 		    0, MAX_CSNUM) < 0) {
 			whinge(mod, NULL, "amd_generic_mc_create: "
@@ -206,16 +228,76 @@
 			 * The topology does not represent pages (there are
 			 * too many) so when a page is faulted we generate
 			 * an ASRU to represent the individual page.
+			 * If SMBIOS meets FMA needs, derive labels & serials
+			 * for DIMMS and apply to chip-select nodes.
+			 * If deriving from SMBIOS, skip IPMI
 			 */
-			if (topo_method_register(mod, csnode,
-			    gen_cs_methods) < 0)
-				whinge(mod, NULL, "amd_generic_mc_create: "
-				    "method registration failed\n");
+			if (FM_AWARE_SMBIOS(mod)) {
+				if (topo_method_register(mod, csnode,
+				    x86pi_gen_cs_methods) < 0)
+					whinge(mod, NULL,
+					    "amd_generic_mc_create: "
+					    "method registration failed\n");
+			} else {
+				if (topo_method_register(mod, csnode,
+				    gen_cs_methods) < 0)
+					whinge(mod, NULL,
+					    "amd_generic_mc_create: method"
+					    "registration failed\n");
+			}
 
 			(void) topo_node_asru_set(csnode, fmri,
 			    TOPO_ASRU_COMPUTE, &err);
+			nvlist_free(fmri);
 
-			nvlist_free(fmri);
+			/*
+			 * If SMBIOS meets FMA needs, set DIMM as the FRU for
+			 * the chip-select node. Use the channel & chip-select
+			 * numbers to get the DIMM instance.
+			 * Send via inst : dram channel number
+			 * Receive via inst : dimm instance
+			 */
+			if (FM_AWARE_SMBIOS(mod)) {
+				int inst;
+				id_t dimm_smbid;
+				const char *serial;
+				const char *part;
+				const char *rev;
+				char *label;
+
+				(void) topo_pgroup_create(csnode,
+				    &cs_pgroup, &err);
+				inst = chan;
+				dimm_smbid = memnode_to_smbiosid(smbid,
+				    CS_NODE_NAME, cs, &inst);
+				serial = chip_serial_smbios_get(mod,
+				    dimm_smbid);
+				part = chip_part_smbios_get(mod,
+				    dimm_smbid);
+				rev = chip_rev_smbios_get(mod, dimm_smbid);
+				label = (char *)chip_label_smbios_get(mod,
+				    chnode, dimm_smbid, NULL);
+
+				(void) topo_prop_set_string(csnode, PGNAME(CS),
+				    FM_FMRI_HC_SERIAL_ID, TOPO_PROP_IMMUTABLE,
+				    serial, &err);
+				(void) topo_prop_set_string(csnode, PGNAME(CS),
+				    FM_FMRI_HC_PART, TOPO_PROP_IMMUTABLE,
+				    part, &err);
+				(void) topo_prop_set_string(csnode, PGNAME(CS),
+				    FM_FMRI_HC_REVISION, TOPO_PROP_IMMUTABLE,
+				    rev, &err);
+
+				/*
+				 * We apply DIMM labels to chip-select nodes,
+				 * FRU for chip-selects should be DIMMs, and
+				 * we do not derive dimm nodes for Family 0x10
+				 * so FRU fmri is NULL, but FRU Labels are set,
+				 * the FRU labels point to the DIMM.
+				 */
+				(void) topo_node_label_set(csnode, label, &err);
+				topo_mod_strfree(mod, label);
+			}
 		}
 	}
 
@@ -267,7 +349,6 @@
 	err = nvlist_unpack(buf, mcs.mcs_size, &nvl, 0);
 	topo_mod_free(mod, buf, mcs.mcs_size);
 
-
 	if (nvlist_lookup_uint8(nvl, MC_NVLIST_VERSTR, &ver) != 0) {
 		whinge(mod, NULL, "mc nvlist is not versioned\n");
 		nvlist_free(nvl);
@@ -339,8 +420,10 @@
 		}
 
 		nvlist_free(fmri);
-
-		(void) topo_node_fru_set(ranknode, pfmri, 0, &err);
+		if (FM_AWARE_SMBIOS(mod))
+			(void) topo_node_fru_set(ranknode, NULL, 0, &err);
+		else
+			(void) topo_node_fru_set(ranknode, pfmri, 0, &err);
 
 		/*
 		 * If a rank is faulted the asru is the associated
@@ -378,15 +461,20 @@
 }
 
 static int
-amd_dimm_create(topo_mod_t *mod, tnode_t *pnode, const char *name,
-    nvlist_t *mc, nvlist_t *auth)
+amd_dimm_create(topo_mod_t *mod, uint16_t chip_smbid, tnode_t *pnode,
+    const char *name, nvlist_t *mc, nvlist_t *auth)
 {
 	int i, err, nerr = 0;
+	int perr = 0;
 	nvpair_t *nvp;
 	tnode_t *dimmnode;
 	nvlist_t *fmri, **dimmarr = NULL;
 	uint64_t num;
 	uint_t ndimm;
+	id_t smbid;
+	const char *serial;
+	const char *part;
+	const char *rev;
 
 	if (nvlist_lookup_nvlist_array(mc, "dimmlist", &dimmarr, &ndimm) != 0) {
 		whinge(mod, NULL, "amd_dimm_create: dimmlist lookup failed\n");
@@ -412,6 +500,23 @@
 			whinge(mod, &nerr, "amd_dimm_create: mkrsrc failed\n");
 			continue;
 		}
+		if (FM_AWARE_SMBIOS(mod)) {
+			smbid = memnode_to_smbiosid(chip_smbid, DIMM_NODE_NAME,
+			    i, NULL);
+			serial = chip_serial_smbios_get(mod, smbid);
+			part = chip_part_smbios_get(mod, smbid);
+			rev = chip_rev_smbios_get(mod, smbid);
+			perr += nvlist_add_string(fmri, FM_FMRI_HC_SERIAL_ID,
+			    serial);
+			perr += nvlist_add_string(fmri, FM_FMRI_HC_PART,
+			    part);
+			perr += nvlist_add_string(fmri, FM_FMRI_HC_REVISION,
+			    rev);
+
+			if (perr != 0)
+				whinge(mod, NULL, "amd_dimm_create:"
+				    "nvlist_add_string failed\n");
+		}
 
 		if ((dimmnode = topo_node_bind(mod, pnode, name, num, fmri))
 		    == NULL) {
@@ -421,17 +526,44 @@
 			continue;
 		}
 
-		if (topo_method_register(mod, dimmnode, dimm_methods) < 0)
-			whinge(mod, &nerr, "amd_dimm_create: "
-			    "topo_method_register failed");
+		if (!FM_AWARE_SMBIOS(mod))
+			if (topo_method_register(mod,
+			    dimmnode, dimm_methods) < 0)
+				whinge(mod, &nerr, "amd_dimm_create: "
+				    "topo_method_register failed");
+
+		(void) topo_pgroup_create(dimmnode, &dimm_pgroup, &err);
+
+		if (FM_AWARE_SMBIOS(mod)) {
+			char *label;
+
+			nvlist_free(fmri);
+			(void) topo_node_resource(dimmnode,
+			    &fmri, &err);
+
+			label = (char *)chip_label_smbios_get(mod,
+			    pnode, smbid, NULL);
+			if (topo_node_label_set(dimmnode, label,
+			    &perr) == -1)
+				topo_mod_dprintf(mod, "Failed"
+				    "to set label\n");
+			topo_mod_strfree(mod, label);
+
+			(void) topo_prop_set_string(dimmnode, PGNAME(DIMM),
+			    FM_FMRI_HC_SERIAL_ID, TOPO_PROP_IMMUTABLE,
+			    serial, &err);
+			(void) topo_prop_set_string(dimmnode, PGNAME(DIMM),
+			    FM_FMRI_HC_PART, TOPO_PROP_IMMUTABLE,
+			    part, &err);
+			(void) topo_prop_set_string(dimmnode, PGNAME(DIMM),
+			    FM_FMRI_HC_REVISION, TOPO_PROP_IMMUTABLE,
+			    rev, &err);
+		}
 
 		(void) topo_node_asru_set(dimmnode, fmri, 0, &err);
 		(void) topo_node_fru_set(dimmnode, fmri, 0, &err);
-
 		nvlist_free(fmri);
 
-		(void) topo_pgroup_create(dimmnode, &dimm_pgroup, &err);
-
 		for (nvp = nvlist_next_nvpair(dimmarr[i], NULL); nvp != NULL;
 		    nvp = nvlist_next_nvpair(dimmarr[i], nvp)) {
 			if (nvpair_type(nvp) == DATA_TYPE_UINT64_ARRAY &&
@@ -587,14 +719,17 @@
 }
 
 void
-amd_mc_create(topo_mod_t *mod, tnode_t *pnode, const char *name, nvlist_t *auth,
-    int family, int model, int stepping, int *nerrp)
+amd_mc_create(topo_mod_t *mod, uint16_t smbid, tnode_t *pnode, const char *name,
+    nvlist_t *auth, int family, int model, int stepping, int *nerrp)
 {
 	tnode_t *mcnode;
 	nvlist_t *fmri;
 	nvpair_t *nvp;
 	nvlist_t *mc = NULL;
 	int i, err;
+	char *serial = NULL;
+	char *part = NULL;
+	char *rev = NULL;
 
 	/*
 	 * Return with no error for anything before AMD family 0xf - we
@@ -604,6 +739,13 @@
 	if (family < 0xf)
 		return;
 
+	if (FM_AWARE_SMBIOS(mod)) {
+		(void) topo_node_resource(pnode, &fmri, &err);
+		(void) nvlist_lookup_string(fmri, "serial", &serial);
+		(void) nvlist_lookup_string(fmri, "part", &part);
+		(void) nvlist_lookup_string(fmri, "revision", &rev);
+	}
+
 	if (mkrsrc(mod, pnode, name, 0, auth, &fmri) != 0) {
 		whinge(mod, nerrp, "mc_create: mkrsrc failed\n");
 		return;
@@ -615,6 +757,12 @@
 		return;
 	}
 
+	if (FM_AWARE_SMBIOS(mod)) {
+		(void) nvlist_add_string(fmri, "serial", serial);
+		(void) nvlist_add_string(fmri, "part", part);
+		(void) nvlist_add_string(fmri, "revision", rev);
+	}
+
 	if ((mcnode = topo_node_bind(mod, pnode, name, 0,
 	    fmri)) == NULL) {
 		nvlist_free(mc);
@@ -626,6 +774,11 @@
 	if (topo_node_fru_set(mcnode, NULL, 0, &err) < 0)
 		whinge(mod, nerrp, "mc_create: topo_node_fru_set failed\n");
 
+	if (FM_AWARE_SMBIOS(mod)) {
+		if (topo_node_label_set(mcnode, NULL, &err) == -1)
+			topo_mod_dprintf(mod, "Failed to set label\n");
+	}
+
 	nvlist_free(fmri);
 
 	if ((mc = amd_lookup_by_mcid(mod, topo_node_instance(pnode))) == NULL) {
@@ -636,7 +789,7 @@
 		 * (presumably newly-released) cpu model.  We fallback to
 		 * creating a generic maximal topology.
 		 */
-		if (amd_generic_mc_create(mod, pnode, mcnode,
+		if (amd_generic_mc_create(mod, smbid, pnode, mcnode,
 		    family, model, stepping, auth) != 0)
 			whinge(mod, nerrp,
 			    "mc_create: amd_generic_mc_create failed\n");
@@ -678,7 +831,7 @@
 
 	if (amd_dramchan_create(mod, mcnode, CHAN_NODE_NAME, auth) != 0 ||
 	    amd_cs_create(mod, mcnode, CS_NODE_NAME, mc, auth) != 0 ||
-	    amd_dimm_create(mod, mcnode, DIMM_NODE_NAME, mc, auth) != 0)
+	    amd_dimm_create(mod, smbid, mcnode, DIMM_NODE_NAME, mc, auth) != 0)
 		whinge(mod, nerrp, "mc_create: create children failed\n");
 
 	/*
--- a/usr/src/lib/fm/topo/modules/i86pc/chip/chip_intel.c	Tue Nov 03 17:06:24 2009 -0800
+++ b/usr/src/lib/fm/topo/modules/i86pc/chip/chip_intel.c	Tue Nov 03 21:14:05 2009 -0500
@@ -145,6 +145,9 @@
 
 		(void) topo_node_asru_set(rnode, fmri, TOPO_ASRU_COMPUTE, &err);
 
+		if (FM_AWARE_SMBIOS(mod))
+			topo_node_label_set(rnode, NULL, &err);
+
 		nvlist_free(fmri);
 
 		(void) topo_pgroup_create(rnode, &rank_pgroup, &err);
@@ -157,8 +160,8 @@
 }
 
 static void
-mc_add_dimms(topo_mod_t *mod, tnode_t *pnode, nvlist_t *auth,
-    nvlist_t **nvl, uint_t ndimms, int maxdimms, int maxranks)
+mc_add_dimms(topo_mod_t *mod, uint16_t chip_smbid, tnode_t *pnode,
+    nvlist_t *auth, nvlist_t **nvl, uint_t ndimms, int maxdimms, int maxranks)
 {
 	int i;
 	nvlist_t *fmri;
@@ -174,6 +177,7 @@
 	char *rev = NULL;
 	char *label = NULL;
 	char *name;
+	id_t smbid;
 
 	if (topo_node_range_create(mod, pnode, DIMM, 0,
 	    maxdimms ? maxdimms-1 : ndimms-1) < 0) {
@@ -204,6 +208,24 @@
 			}
 		}
 		fmri = NULL;
+
+		if (FM_AWARE_SMBIOS(mod)) {
+			int channum;
+
+			channum = topo_node_instance(pnode);
+			smbid = memnode_to_smbiosid(chip_smbid, DIMM_NODE_NAME,
+			    i, &channum);
+			if (serial == NULL)
+				serial = (char *)chip_serial_smbios_get(mod,
+				    smbid);
+			if (part == NULL)
+				part = (char *)chip_part_smbios_get(mod,
+				    smbid);
+			if (rev == NULL)
+				rev = (char *)chip_rev_smbios_get(mod,
+				    smbid);
+		}
+
 		fmri = topo_mod_hcfmri(mod, pnode, FM_HC_SCHEME_VERSION,
 		    DIMM, dimm_number, NULL, auth, part, rev, serial);
 		if (fmri == NULL) {
@@ -219,12 +241,11 @@
 			return;
 		}
 
-		if (topo_method_register(mod, dnode, dimm_methods) < 0)
-			whinge(mod, NULL, "mc_add_dimms: "
-			    "topo_method_register failed");
+		if (!FM_AWARE_SMBIOS(mod))
+			if (topo_method_register(mod, dnode, dimm_methods) < 0)
+				whinge(mod, NULL, "mc_add_dimms: "
+				    "topo_method_register failed");
 
-		(void) topo_node_fru_set(dnode, fmri, 0, &err);
-		nvlist_free(fmri);
 		(void) topo_pgroup_create(dnode, &dimm_pgroup, &err);
 
 		for (nvp = nvlist_next_nvpair(nvl[i], NULL); nvp != NULL;
@@ -237,8 +258,25 @@
 				    dnode);
 			}
 		}
-		if (label)
-			(void) topo_node_label_set(dnode, label, &err);
+
+		if (FM_AWARE_SMBIOS(mod)) {
+			nvlist_free(fmri);
+			(void) topo_node_resource(dnode, &fmri, &err);
+			/*
+			 * We will use a full absolute parent/child label
+			 */
+			label = (char *)chip_label_smbios_get(mod,
+			    pnode, smbid, label);
+		}
+
+		(void) topo_node_label_set(dnode, label, &err);
+
+		if (FM_AWARE_SMBIOS(mod))
+			topo_mod_strfree(mod, label);
+
+		(void) topo_node_fru_set(dnode, fmri, 0, &err);
+		(void) topo_node_asru_set(dnode, fmri, 0, &err);
+		nvlist_free(fmri);
 
 		if (nranks) {
 			mc_add_ranks(mod, dnode, auth, dimm_number, ranks_nvp,
@@ -248,8 +286,8 @@
 }
 
 static int
-mc_add_channel(topo_mod_t *mod, tnode_t *pnode, int channel, nvlist_t *auth,
-    nvlist_t *nvl, int maxdimms, int maxranks)
+mc_add_channel(topo_mod_t *mod, uint16_t chip_smbid, tnode_t *pnode,
+    int channel, nvlist_t *auth, nvlist_t *nvl, int maxdimms, int maxranks)
 {
 	tnode_t *mc_channel;
 	nvlist_t *fmri;
@@ -273,10 +311,14 @@
 	(void) topo_node_fru_set(mc_channel, NULL, 0, &err);
 	nvlist_free(fmri);
 	(void) topo_pgroup_create(mc_channel, &dimm_channel_pgroup, &err);
+
+	if (FM_AWARE_SMBIOS(mod))
+		(void) topo_node_label_set(mc_channel, NULL, &err);
+
 	if (nvlist_lookup_nvlist_array(nvl, MCINTEL_NVLIST_DIMMS, &dimm_nvl,
 	    &ndimms) == 0) {
-		mc_add_dimms(mod, mc_channel, auth, dimm_nvl, ndimms, maxdimms,
-		    maxranks);
+		mc_add_dimms(mod, chip_smbid, mc_channel, auth, dimm_nvl,
+		    ndimms, maxdimms, maxranks);
 	}
 	for (nvp = nvlist_next_nvpair(nvl, NULL); nvp != NULL;
 	    nvp = nvlist_next_nvpair(nvl, nvp)) {
@@ -286,12 +328,13 @@
 			    mc_channel);
 		}
 	}
+
 	return (0);
 }
 
 static int
-mc_nb_create(topo_mod_t *mod, tnode_t *pnode, const char *name, nvlist_t *auth,
-    nvlist_t *nvl)
+mc_nb_create(topo_mod_t *mod, uint16_t chip_smbid, tnode_t *pnode,
+    const char *name, nvlist_t *auth, nvlist_t *nvl)
 {
 	int err;
 	int i, j;
@@ -355,6 +398,9 @@
 		nvlist_free(fmri);
 		(void) topo_pgroup_create(mcnode, &mc_pgroup, &err);
 
+		if (FM_AWARE_SMBIOS(mod))
+			(void) topo_node_label_set(mcnode, NULL, &err);
+
 		if (topo_node_range_create(mod, mcnode, DRAMCHANNEL, channel,
 		    channel + nchannels - 1) < 0) {
 			whinge(mod, NULL,
@@ -362,8 +408,9 @@
 			return (-1);
 		}
 		for (j = 0; j < nchannels; j++) {
-			if (mc_add_channel(mod, mcnode, channel, auth,
-			    channel_nvl[channel], maxdimms, maxranks) < 0) {
+			if (mc_add_channel(mod, chip_smbid, mcnode, channel,
+			    auth, channel_nvl[channel], maxdimms,
+			    maxranks) < 0) {
 				return (-1);
 			}
 			channel++;
@@ -387,8 +434,8 @@
 }
 
 int
-mc_node_create(topo_mod_t *mod, tnode_t *pnode, const char *name,
-    nvlist_t *auth)
+mc_node_create(topo_mod_t *mod, uint16_t chip_smbid, tnode_t *pnode,
+    const char *name, nvlist_t *auth)
 {
 	mc_snapshot_info_t mcs;
 	void *buf = NULL;
@@ -421,23 +468,23 @@
 		return (NULL);
 	}
 
-	rc = mc_nb_create(mod, pnode, name, auth, nvl);
+	rc = mc_nb_create(mod, chip_smbid, pnode, name, auth, nvl);
 
 	nvlist_free(nvl);
 	return (rc);
 }
 
 void
-onchip_mc_create(topo_mod_t *mod, tnode_t *pnode, const char *name,
-    nvlist_t *auth)
+onchip_mc_create(topo_mod_t *mod, uint16_t chip_smbid, tnode_t *pnode,
+    const char *name, nvlist_t *auth)
 {
 	if (mc_onchip(topo_node_instance(pnode)))
-		(void) mc_node_create(mod, pnode, name, auth);
+		(void) mc_node_create(mod, chip_smbid, pnode, name, auth);
 }
 
 int
 mc_offchip_create(topo_mod_t *mod, tnode_t *pnode, const char *name,
     nvlist_t *auth)
 {
-	return (mc_node_create(mod, pnode, name, auth));
+	return (mc_node_create(mod, IGNORE_ID, pnode, name, auth));
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/lib/fm/topo/modules/i86pc/chip/chip_smbios.c	Tue Nov 03 21:14:05 2009 -0500
@@ -0,0 +1,590 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#include <unistd.h>
+#include <ctype.h>
+#include <strings.h>
+#include <sys/types.h>
+#include <sys/devfm.h>
+#include <libnvpair.h>
+#include <sys/smbios.h>
+#include <fm/topo_mod.h>
+#include <sys/fm/protocol.h>
+#include <sys/smbios_impl.h>
+
+#include "chip.h"
+
+#define	CPU_SLOTS	64
+#define	DIMM_SLOTS	512
+#define	MC_INSTANCES	128
+
+#define	MAXNAMELEN	256
+#define	LABEL		1
+
+#define	SKIP_CS		9999
+
+
+typedef struct cpu_smbios {
+	id_t cpu_id;
+	uint8_t status;
+	uint8_t fru;
+}csmb_t;
+
+typedef struct dimm_smbios {
+	id_t dimm_id;
+	id_t extdimm_id;
+	const char *bankloc;
+}dsmb_t;
+
+typedef struct mct_smbios {
+	id_t extmct_id;
+	id_t mct_id;
+	id_t p_id;
+}msmb_t;
+
+csmb_t cpusmb[CPU_SLOTS];
+dsmb_t dimmsmb[DIMM_SLOTS];
+msmb_t mctsmb[MC_INSTANCES];
+
+static int ncpu_ids = 0;
+static int bb_count = 0;
+static int ndimm_ids, nmct_ids = 0;
+
+static smbios_hdl_t *shp = NULL;
+static int fill_chip_smbios = 0;
+typedef int smbios_rec_f(topo_mod_t *, const smbios_struct_t *);
+
+static smbios_struct_t *
+smb_export(const smb_struct_t *stp, smbios_struct_t *sp)
+{
+	const smb_header_t *hdr;
+
+	if (stp == NULL)
+		return (NULL);
+
+	hdr = stp->smbst_hdr;
+	sp->smbstr_id = hdr->smbh_hdl;
+	sp->smbstr_type = hdr->smbh_type;
+	sp->smbstr_data = hdr;
+	sp->smbstr_size = (size_t)(stp->smbst_end - (uchar_t *)hdr);
+
+	return (sp);
+}
+
+static int
+extdimmslot_to_dimmslot(id_t chip_smbid, int channum, int csnum)
+{
+	smbios_memdevice_ext_t emd;
+	smbios_memdevice_t md;
+	int i, j, k;
+	int match = 0;
+
+	if (chip_smbid == IGNORE_ID && bb_count <= 1 && nmct_ids <= 1) {
+		for (i = 0; i < ndimm_ids; i++) {
+			(void) smbios_info_extmemdevice(shp,
+			    dimmsmb[i].extdimm_id, &emd);
+			if (emd.smbmdeve_drch == channum) {
+				if (csnum == SKIP_CS)
+					return (emd.smbmdeve_md);
+				for (k = 0; k < emd.smbmdeve_ncs; k++)
+					if (emd.smbmdeve_cs[k] == csnum)
+						return (emd.smbmdeve_md);
+			}
+		}
+	}
+
+	for (j = 0; j < nmct_ids; j++) {
+		if (mctsmb[j].p_id == chip_smbid) {
+			for (i = 0; i < ndimm_ids; i++) {
+				(void) smbios_info_extmemdevice(shp,
+				    dimmsmb[i].extdimm_id, &emd);
+				(void) smbios_info_memdevice(shp,
+				    emd.smbmdeve_md, &md);
+				if (md.smbmd_array == mctsmb[j].mct_id &&
+				    emd.smbmdeve_drch == channum) {
+					match = 1;
+					break;
+				}
+			}
+			if (match) {
+				if (csnum == SKIP_CS)
+					return (emd.smbmdeve_md);
+				for (k = 0; k < emd.smbmdeve_ncs; k++)
+					if (emd.smbmdeve_cs[k] == csnum)
+						return (emd.smbmdeve_md);
+			}
+		}
+	}
+
+	return (-1);
+}
+
+id_t
+memnode_to_smbiosid(uint16_t chip_smbid, const char *name, uint64_t nodeid,
+    void *data)
+{
+
+	if (strcmp(name, CS_NODE_NAME) == 0) {
+		int channum, csnum;
+		id_t dimmslot = -1;
+
+		if (data == NULL)
+			return (-1);
+		channum = *(int *)data;
+		csnum = nodeid;
+		/*
+		 * Set the DIMM Slot label to the Chip Select Node
+		 * Set the "data" to carry the DIMM instance
+		 */
+		dimmslot = extdimmslot_to_dimmslot(chip_smbid, channum, csnum);
+		if (dimmslot != -1 && dimmsmb[0].dimm_id != 0)
+			*((id_t *)data) = dimmslot % (dimmsmb[0].dimm_id);
+		else
+			*((id_t *)data) = -1;
+
+		return (dimmslot);
+
+	} else if (strcmp(name, DIMM_NODE_NAME) == 0) {
+		static int dimmnum = 0;
+
+		/*
+		 * On certain Intel Chips, topology does not have
+		 * chip-select nodes, it has the below layout
+		 * chip/memory-controller/dram-channel/dimm
+		 * so we check if channel instance is passed
+		 * and get the SMBIOS ID based on the channel
+		 */
+		if (data != NULL) {
+			int channum;
+			id_t dimmslot = -1;
+
+			channum = *(int *)data;
+			dimmslot = extdimmslot_to_dimmslot(chip_smbid,
+			    channum, SKIP_CS);
+
+			return (dimmslot);
+		}
+		dimmnum = nodeid;
+		return (dimmsmb[dimmnum].dimm_id);
+	}
+
+	return (-1);
+}
+
+
+int
+chip_get_smbstruct(topo_mod_t *mod, const smbios_struct_t *sp)
+{
+	smbios_processor_t p;
+	smbios_memdevice_t md;
+	smbios_processor_ext_t extp;
+	smbios_memarray_ext_t extma;
+
+	/*
+	 * We expect that the first SUN_OEM_EXT_XXX
+	 * that comes after a SMB_TYPE_XXX correspond
+	 * to each other in the SMBIOS ordering of the
+	 * records. And SUN_OEM_EXT_XXX always comes
+	 * after its SMB_TYPE_XXX record.
+	 */
+	switch (sp->smbstr_type) {
+	case SMB_TYPE_BASEBOARD:
+		bb_count++;
+		break;
+	case SMB_TYPE_MEMARRAY:
+		mctsmb[nmct_ids].mct_id = sp->smbstr_id;
+		break;
+	case SUN_OEM_EXT_MEMARRAY:
+		mctsmb[nmct_ids].extmct_id = sp->smbstr_id;
+		if (shp != NULL) {
+			if (smbios_info_extmemarray(shp,
+			    sp->smbstr_id, &extma) != 0) {
+				topo_mod_dprintf(mod, "chip_get_smbstruct : "
+				    "smbios_info_extmemarray()"
+				    "failed\n");
+				return (-1);
+			}
+		} else
+			return (-1);
+		if (extma.smbmae_ma == mctsmb[nmct_ids].mct_id)
+			mctsmb[nmct_ids].p_id = extma.smbmae_comp;
+		else
+			return (-1);
+
+		nmct_ids++;
+		break;
+	case SMB_TYPE_MEMDEVICE:
+		dimmsmb[ndimm_ids].dimm_id = sp->smbstr_id;
+		if (shp != NULL) {
+			if (smbios_info_memdevice(shp,
+			    sp->smbstr_id, &md) != 0)
+				return (-1);
+		} else
+			return (-1);
+		dimmsmb[ndimm_ids].bankloc = md.smbmd_bloc;
+		break;
+	/*
+	 * Every SMB_TYPE_MEMDEVICE SHOULD have a
+	 * corresponding SUN_OEM_EXT_MEMDEVICE
+	 */
+	case SUN_OEM_EXT_MEMDEVICE:
+		dimmsmb[ndimm_ids++].extdimm_id = sp->smbstr_id;
+		break;
+	case SMB_TYPE_PROCESSOR:
+		cpusmb[ncpu_ids].cpu_id = sp->smbstr_id;
+		if (shp != NULL) {
+			if (smbios_info_processor(shp,
+			    sp->smbstr_id, &p) != 0) {
+				topo_mod_dprintf(mod, "chip_get_smbstruct : "
+				    "smbios_info_processor()"
+				    "failed\n");
+				return (-1);
+			}
+		}
+		cpusmb[ncpu_ids].status = p.smbp_status;
+		break;
+	/*
+	 * Every SMB_TYPE_PROCESSOR SHOULD have a
+	 * corresponding SUN_OEM_EXT_PROCESSOR
+	 */
+	case SUN_OEM_EXT_PROCESSOR:
+		if (smbios_info_extprocessor(shp,
+		    sp->smbstr_id, &extp) != 0) {
+			topo_mod_dprintf(mod, "chip_get_smbstruct : "
+			    "smbios_info_extprocessor()"
+			    "failed\n");
+			return (-1);
+		}
+		cpusmb[ncpu_ids].fru = extp.smbpe_fru;
+		ncpu_ids++;
+		break;
+	}
+	return (0);
+}
+
+static int
+chip_smbios_iterate(topo_mod_t *mod, smbios_rec_f *func_iter)
+{
+	const smb_struct_t *sp = shp->sh_structs;
+	smbios_struct_t s;
+	int i, rv = 0;
+
+	for (i = 0; i < shp->sh_nstructs; i++, sp++) {
+		if (sp->smbst_hdr->smbh_type != SMB_TYPE_INACTIVE &&
+		    (rv = func_iter(mod, smb_export(sp, &s))) != 0)
+			break;
+	}
+	return (rv);
+}
+
+int
+init_chip_smbios(topo_mod_t *mod)
+{
+	if (shp == NULL) {
+		if ((shp = topo_mod_smbios(mod)) == NULL) {
+			whinge(mod, NULL, "init_chip_smbios: smbios "
+			    "handle get failed\n");
+			return (-1);
+		}
+	}
+
+	if (!fill_chip_smbios) {
+		if (chip_smbios_iterate(mod, chip_get_smbstruct) == -1)
+			return (-1);
+		fill_chip_smbios = 1;
+	}
+
+	return (0);
+}
+
+int
+chip_status_smbios_get(topo_mod_t *mod, id_t smb_id)
+{
+	/*
+	 * Type-4 Socket Status bit definitions per SMBIOS Version 2.6
+	 *
+	 * STATUS
+	 * CPU Socket Populated
+	 * CPU Socket Unpopulated
+	 * Populated : Enabled
+	 * Populated : Disabled by BIOS (Setup)
+	 * Populated : Disabled by BIOS (Error)
+	 * Populated : Idle
+	 */
+	uint8_t	enabled = 0x01;
+	uint8_t	populated = 0x40;
+
+	for (int i = 0; i < ncpu_ids; i++) {
+		if (smb_id == cpusmb[i].cpu_id) {
+			if (cpusmb[i].status  == (enabled | populated))
+				return (1);
+			else
+				return (0);
+		}
+	}
+
+	topo_mod_dprintf(mod, "topo_status_smbios_get() failed"
+	    " considering that Type 4 ID : %d is disabled", smb_id);
+	return (0);
+}
+
+int
+chip_fru_smbios_get(topo_mod_t *mod, id_t smb_id)
+{
+	/*
+	 * smbios_processor_ext_t->smbpe_fru : if set to 1
+	 * processor is a FRU
+	 */
+	uint8_t	fru = 1;
+
+	for (int i = 0; i < ncpu_ids; i++) {
+		if (smb_id == cpusmb[i].cpu_id) {
+			if (cpusmb[i].fru == fru)
+				return (1);
+			else
+				return (0);
+		}
+	}
+
+	topo_mod_dprintf(mod, "topo_fru_smbios_get() failed"
+	    " considering that Type 4 ID : %d is not a FRU", smb_id);
+	return (0);
+}
+
+/*
+ * This could be defined as topo_mod_strlen()
+ */
+size_t
+chip_strlen(const char *str)
+{
+	int len = 0;
+
+	if (str != NULL)
+		len = strlen(str);
+
+	return (len);
+}
+
+/*
+ * We clean Serials, Revisions, Part No. strings, to
+ * avoid getting lost when fmd synthesizes these
+ * strings. :, =, /, ' ' characters are replaced
+ * with character '-' any non-printable characters
+ * as seen with !isprint() is also replaced with '-'
+ * Labels are checked only for non-printable characters.
+ */
+static const char *
+chip_cleanup_smbios_str(topo_mod_t *mod, const char *begin, int str_type)
+{
+	char buf[MAXNAMELEN];
+	const char *end, *cp;
+	char *pp;
+	char c;
+	int i;
+
+	end = begin + strlen(begin);
+
+	while (begin < end && isspace(*begin))
+		begin++;
+	while (begin < end && isspace(*(end - 1)))
+		end--;
+
+	if (begin >= end)
+		return (NULL);
+
+	cp = begin;
+	for (i = 0; i < MAXNAMELEN - 1; i++) {
+		if (cp >= end)
+			break;
+		c = *cp;
+		if (str_type == LABEL) {
+			if (!isprint(c))
+				buf[i] = '-';
+			else
+				buf[i] = c;
+		} else {
+			if (c == ':' || c == '=' || c == '/' ||
+			    isspace(c) || !isprint(c))
+				buf[i] = '-';
+			else
+				buf[i] = c;
+		}
+		cp++;
+	}
+	buf[i] = 0;
+
+	pp = topo_mod_strdup(mod, buf);
+
+	if (str_type == LABEL)
+		topo_mod_strfree(mod, (char *)begin);
+
+	return (pp);
+}
+
+const char *
+chip_label_smbios_get(topo_mod_t *mod, tnode_t *pnode, id_t smb_id,
+    char *ksmbios_label)
+{
+	smbios_info_t c;
+	char *label = NULL;
+	char *buf = NULL;
+	const char *lsmbios_label = NULL;
+	int bufsz = 0;
+	char *delim = NULL, *blank = " ";
+	const char *dimm_bank = NULL;
+	const char *clean_label = NULL;
+	int err;
+
+	if (shp != NULL) {
+		/*
+		 * Get Parent FRU's label
+		 */
+		if (topo_prop_get_string(pnode, TOPO_PGROUP_PROTOCOL,
+		    TOPO_PROP_LABEL, &label, &err) == -1)
+			topo_mod_dprintf(mod, "Failed to get"
+			    " Label of Parent Node error : %d\n", err);
+
+		if (label != NULL)
+			label = (char *)chip_cleanup_smbios_str(mod,
+			    label, LABEL);
+
+		/*
+		 * On Intel the driver gets the label from ksmbios
+		 * so we check if we already have it, if not we
+		 * get it from libsmbios
+		 */
+		if (ksmbios_label == NULL && smb_id != -1) {
+			if (smbios_info_common(shp, smb_id, &c) != SMB_ERR) {
+				for (int i = 0; i < ndimm_ids; i++) {
+					if (smb_id == dimmsmb[i].dimm_id) {
+						dimm_bank = dimmsmb[i].bankloc;
+						break;
+					}
+				}
+				if (dimm_bank != NULL) {
+					bufsz += chip_strlen(blank) +
+					    chip_strlen(dimm_bank);
+				}
+				lsmbios_label = c.smbi_location;
+			}
+		} else
+			lsmbios_label = ksmbios_label;
+
+		if (label != NULL && lsmbios_label != NULL)
+			delim = "/";
+
+		bufsz += chip_strlen(label) + chip_strlen(delim) +
+		    chip_strlen(lsmbios_label) + 1;
+
+		buf = topo_mod_alloc(mod, bufsz);
+
+		if (buf != NULL) {
+			if (label != NULL) {
+				(void) strlcpy(buf, label, bufsz);
+				if (lsmbios_label != NULL) {
+					(void) strlcat(buf, delim, bufsz);
+					/*
+					 * If we are working on a DIMM
+					 * and we are deriving from libsmbios
+					 * smbi_location has the Device Locator.
+					 * add the Device Locator
+					 * add Bank Locator latter
+					 */
+					(void) strlcat(buf, lsmbios_label,
+					    bufsz);
+				}
+			} else if (lsmbios_label != NULL)
+				(void) strlcpy(buf, lsmbios_label,
+				    bufsz);
+
+			if (dimm_bank != NULL) {
+				(void) strlcat(buf, blank, bufsz);
+				(void) strlcat(buf, dimm_bank, bufsz);
+			}
+		}
+
+		clean_label = chip_cleanup_smbios_str(mod, buf, LABEL);
+		topo_mod_strfree(mod, label);
+
+		return (clean_label);
+	}
+
+	topo_mod_dprintf(mod, "Failed to get Label\n");
+	return (NULL);
+}
+
+
+const char *
+chip_serial_smbios_get(topo_mod_t *mod, id_t smb_id)
+{
+	smbios_info_t c;
+	const char *clean_serial = NULL;
+
+	if (shp != NULL && smb_id != -1)
+		if (smbios_info_common(shp, smb_id, &c) != SMB_ERR) {
+			clean_serial = chip_cleanup_smbios_str(mod,
+			    c.smbi_serial, 0);
+			return (clean_serial);
+		}
+
+	topo_mod_dprintf(mod, "Failed to get Serial \n");
+	return (NULL);
+}
+
+
+const char *
+chip_part_smbios_get(topo_mod_t *mod, id_t smb_id)
+{
+	smbios_info_t c;
+	const char *clean_part = NULL;
+
+	if (shp != NULL && smb_id != -1)
+		if (smbios_info_common(shp, smb_id, &c) != SMB_ERR) {
+			clean_part = chip_cleanup_smbios_str(mod,
+			    c.smbi_part, 0);
+			return (clean_part);
+		}
+
+	topo_mod_dprintf(mod, "Failed to get Part\n");
+	return (NULL);
+}
+
+const char *
+chip_rev_smbios_get(topo_mod_t *mod, id_t smb_id)
+{
+	smbios_info_t c;
+	const char *clean_rev = NULL;
+
+	if (shp != NULL && smb_id != -1)
+		if (smbios_info_common(shp, smb_id, &c) != SMB_ERR) {
+			clean_rev = chip_cleanup_smbios_str(mod,
+			    c.smbi_version, 0);
+			return (clean_rev);
+		}
+
+	topo_mod_dprintf(mod, "Failed to get Revision\n");
+	return (NULL);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/lib/fm/topo/modules/i86pc/x86pi/Makefile	Tue Nov 03 21:14:05 2009 -0500
@@ -0,0 +1,52 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
+# Use is subject to license terms.
+#
+
+MODULE	= x86pi
+ARCH	= i86pc
+CLASS	= arch
+
+TOPODIR		= ../../../libtopo/common
+
+UTILDIR		= ../../common/pcibus
+BRDIR		= ../../common/hostbridge
+UTILSRCS	= did.c did_hash.c did_props.c
+X86PISRCS	= x86pi.c x86pi_bboard.c x86pi_chassis.c \
+		  x86pi_generic.c x86pi_hostbridge.c x86pi_subr.c
+MODULESRCS	= $(X86PISRCS) $(UTILSRCS)
+
+include ../../Makefile.plugin
+
+LDLIBS += -lsmbios -ldevinfo -luutil
+
+CPPFLAGS += -I. -I$(ROOT)/usr/platform/i86pc/include -I$(TOPODIR)
+CPPFLAGS += -I$(UTILDIR) -I$(BRDIR)
+
+%.o: $(UTILDIR)/%.c
+	$(COMPILE.c) -o $@ $<
+	$(CTFCONVERT_O)
+
+%.ln: $(UTILDIR)/%.c
+	$(LINT.c) -c $<
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/lib/fm/topo/modules/i86pc/x86pi/x86pi.c	Tue Nov 03 21:14:05 2009 -0500
@@ -0,0 +1,462 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ */
+
+/*
+ * x86 Generic FMA Topology Enumerator
+ */
+
+
+#include <fcntl.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <strings.h>
+#include <sys/fcntl.h>
+#include <fm/topo_mod.h>
+#include <fm/topo_hc.h>
+#include <sys/systeminfo.h>
+#include <sys/smbios.h>
+#include <sys/smbios_impl.h>
+#include <sys/fm/protocol.h>
+#include <x86pi_impl.h>
+
+
+static int x86pi_enum_start(topo_mod_t *, x86pi_enum_t *);
+static int x86pi_enum_gentopo(topo_mod_t *, tnode_t *, smbios_hdl_t *);
+
+/*
+ * Entry point called by libtopo when enumeration is required
+ */
+static topo_enum_f x86pi_enum;	/* libtopo enumeration entry point */
+
+/*
+ * Declare the operations vector and information structure used during
+ * module registration
+ */
+static topo_modops_t x86pi_ops =
+	{ x86pi_enum, NULL };
+
+static topo_modinfo_t	x86pi_modinfo =
+	{ X86PI_DESC, X86PI_SCHEME, X86PI_VERSION, &x86pi_ops };
+
+/*
+ * Used to pass SMBIOS' FM compatibility to the
+ * chip enumerator
+ */
+int x86pi_smbios = 0;
+
+/*
+ * Called by libtopo when the topo module is loaded.
+ */
+int
+_topo_init(topo_mod_t *mod, topo_version_t version)
+{
+	int	result;
+	char	isa[MAXNAMELEN];
+
+	if (getenv("TOPOX86PIDBG") != NULL) {
+		/* Debugging is requested for this module */
+		topo_mod_setdebug(mod);
+	}
+	topo_mod_dprintf(mod, "module initializing.\n");
+
+	if (version != TOPO_VERSION) {
+		topo_mod_seterrno(mod, EMOD_VER_NEW);
+		topo_mod_dprintf(mod, "incompatible topo version %d\n",
+		    version);
+		return (-1);
+	}
+
+	/* Verify that this is a i86pc architecture machine */
+	(void) sysinfo(SI_MACHINE, isa, MAXNAMELEN);
+	if (strncmp(isa, "i86pc", MAXNAMELEN) != 0) {
+		topo_mod_dprintf(mod, "not i86pc architecture: %s\n", isa);
+		return (-1);
+	}
+
+	result = topo_mod_register(mod, &x86pi_modinfo, TOPO_VERSION);
+	if (result < 0) {
+		topo_mod_dprintf(mod, "registration failed: %s\n",
+		    topo_mod_errmsg(mod));
+		/* module errno already set */
+		return (-1);
+	}
+	topo_mod_dprintf(mod, "module ready.\n");
+	return (0);
+}
+
+
+/*
+ * Clean up any data used by the module before it is unloaded.
+ */
+void
+_topo_fini(topo_mod_t *mod)
+{
+	topo_mod_dprintf(mod, "module finishing.\n");
+
+	x86pi_hbr_enum_fini(mod);
+
+	/* Unregister from libtopo */
+	topo_mod_unregister(mod);
+}
+
+
+/*
+ * Enumeration entry point for the x86 Generic topology enumerator
+ */
+/* ARGSUSED */
+static int
+x86pi_enum(topo_mod_t *mod, tnode_t *t_parent, const char *name,
+    topo_instance_t min, topo_instance_t max, void *pi_private, void *data)
+{
+	int		result;
+	hrtime_t	starttime;
+	x86pi_enum_t	x86pi;
+
+	/* Begin enumeration */
+	starttime = gethrtime();
+	topo_mod_dprintf(mod, "enumeration starting.\n");
+
+	/*
+	 * Let's do some enumeration.
+	 */
+	bzero(&x86pi, sizeof (x86pi_enum_t));
+	x86pi.t_parent = t_parent;
+	result = x86pi_enum_start(mod, &x86pi);
+	if (result != 0) {
+		topo_mod_dprintf(mod, "Enumeration failed.\n");
+		return (-1);
+	}
+
+	/* Complete enumeration */
+	topo_mod_dprintf(mod, "enumeration complete in %lld ms.\n",
+	    ((gethrtime() - starttime)/MICROSEC));
+
+	/* All done */
+	return (result);
+}
+
+static int
+x86pi_enum_start(topo_mod_t *mod, x86pi_enum_t *x86pi)
+{
+	int		rv;
+	int		complvl = 0;
+	smbios_hdl_t	*shp;
+	char		*f = "x86pi_enum_start";
+
+	/*
+	 * Verify BIOS compliance.
+	 */
+	shp = x86pi_smb_open(mod);
+	if (shp == NULL) {
+		topo_mod_dprintf(mod, "%s: failed to open SMBIOS\n", f);
+		complvl = X86PI_NONE;
+	} else {
+		complvl = x86pi_check_comp(mod, shp);
+	}
+
+	topo_mod_dprintf(mod, "%s: SMBIOS x86pi compliance: %s\n", f,
+	    complvl == X86PI_FULL ? "FULL" : "NONE");
+
+	if (complvl == X86PI_NONE) {
+		/* fall back to legacy enumeration */
+		topo_mod_dprintf(mod,
+		    "%s: Calling legacy enumeration\n", f);
+
+		return (topo_mod_enummap(mod, x86pi->t_parent,
+		    "i86pc-legacy", FM_FMRI_SCHEME_HC));
+	}
+
+	x86pi->priv = (void *)shp;
+	x86pi_smbios = complvl;
+
+	if (x86pi_hbr_enum_init(mod) < 0) {
+		topo_mod_dprintf(mod, "%s: x86pi_hbr_enum_init() failed.\n", f);
+		return (-1);
+	}
+
+	/*
+	 * Create the topology.
+	 */
+	fac_done = 0;
+	rv = x86pi_enum_gentopo(mod, x86pi->t_parent, shp);
+	if (rv != 0) {
+		return (-1);
+	}
+	x86pi->mod = mod;
+
+	if (fac_done == 0) {
+		(void) topo_mod_enummap(mod, x86pi->t_parent, "chassis",
+		    FM_FMRI_SCHEME_HC);
+		(void) topo_mod_enummap(mod, x86pi->t_parent, "fan",
+		    FM_FMRI_SCHEME_HC);
+		(void) topo_mod_enummap(mod, x86pi->t_parent, "psu",
+		    FM_FMRI_SCHEME_HC);
+	}
+
+	/* All done */
+	topo_mod_dprintf(mod, "%s: done.\n", f);
+	return (rv);
+}
+
+/*
+ * Create the i86pc topology
+ *
+ * If either Type 2 or Type 3 structures have contained elements/handles,
+ * walk them creating the topo.
+ *
+ * If there are no contained elements/handles, build this topo:
+ *
+ *    Main Chassis
+ *      Motherboard
+ *        CMP Chip/Core/Strands
+ *          Memory Controllers/Memory Devices (DIMMs)
+ *        PCIE HostBrige
+ *          PCIE Root Complex
+ *
+ */
+static int
+x86pi_enum_gentopo(topo_mod_t *mod, tnode_t *t_parent, smbios_hdl_t *shp)
+{
+	int		rv;
+	int		nch, nbb, ncmp, i;
+	int		ch_smbid, bb_smbid;
+	tnode_t		*chassis_node = NULL;
+	tnode_t		*basebd_node = NULL;
+	smbs_cnt_t	*smbc;
+	tnode_t		*motherchassis_node = NULL;
+	tnode_t		*pnode = NULL;
+	id_t		psmbid;
+	int		notvisited;
+	int		bb_count, ch_count;
+	int		min, max;
+	int		ch_inst = 0;
+	topo_instance_t	 hbri = 0, rci = 0;
+	smbios_pciexrc_t hbr;
+	char		*f = "x86pi_enum_gentopo";
+
+	if (t_parent == NULL) {
+		topo_mod_dprintf(mod, "%s: NULL parent\n", f);
+		return (-1);
+	}
+
+	/*
+	 * "Chassis'"
+	 */
+	/* Type 3 structs */
+	stypes[SMB_TYPE_CHASSIS].type = SMB_TYPE_CHASSIS;
+	x86pi_smb_strcnt(shp, &stypes[SMB_TYPE_CHASSIS]);
+
+	ch_count = stypes[SMB_TYPE_CHASSIS].count;
+
+	for (nch = 0; nch < ch_count; nch++) {
+		topo_mod_dprintf(mod, "%s: found %d chassis\n", f,
+		    stypes[SMB_TYPE_CHASSIS].count);
+
+		ch_smbid = stypes[SMB_TYPE_CHASSIS].ids[nch].id;
+
+		/*
+		 * Expect SMBIOS to set the first Chassis Structure to be the
+		 * parent/mother of all chassis
+		 */
+		if (nch == 0)
+			motherchassis_node = chassis_node =
+			    x86pi_gen_chassis(mod, t_parent, shp,
+			    ch_smbid, ch_inst++);
+		else {
+			if (motherchassis_node != NULL)
+				chassis_node = x86pi_gen_chassis(mod,
+				    motherchassis_node, shp,
+				    ch_smbid, ch_inst++);
+			else
+				chassis_node = x86pi_gen_chassis(mod,
+				    t_parent, shp, ch_smbid, ch_inst++);
+		}
+
+		if (chassis_node == NULL) {
+			topo_mod_dprintf(mod,
+			    "%s: Failed to create chassis %d\n", f, nch);
+			continue;
+		}
+		stypes[SMB_TYPE_CHASSIS].ids[nch].node = chassis_node;
+	}
+
+	/*
+	 * "Base Board"
+	 */
+	/* Type 2 structs */
+	stypes[SMB_TYPE_BASEBOARD].type = SMB_TYPE_BASEBOARD;
+	x86pi_smb_strcnt(shp, &stypes[SMB_TYPE_BASEBOARD]);
+	bb_count = notvisited = stypes[SMB_TYPE_BASEBOARD].count;
+
+	for (nbb = 0; nbb < bb_count; nbb++) {
+		stypes[SMB_TYPE_BASEBOARD].ids[nbb].visited = 0;
+		stypes[SMB_TYPE_BASEBOARD].ids[nbb].con_by_id = 0;
+		stypes[SMB_TYPE_BASEBOARD].ids[nbb].node = NULL;
+	}
+	(void) x86pi_bb_contains(mod, shp);
+
+	min = 0;
+	nbb = 0;
+	do {
+		/*
+		 * We have reached end of the array due to the
+		 * parent-child relationship, without visiting all
+		 * baseboards! so re-iterate..
+		 * (or)
+		 * All baseboards are visited and their contained
+		 * processors are enumerated
+		 * (and/or)
+		 * More baseboards pending a visit
+		 */
+		if (nbb > bb_count && notvisited)
+			nbb = 0;
+		else if (nbb > bb_count && !notvisited)
+			break;
+		if (stypes[SMB_TYPE_BASEBOARD].ids[nbb].visited ==
+		    X86PI_VISITED) {
+			nbb++;
+			continue;
+		}
+
+		/*
+		 * Get the Top-most Parent Baseboard, irrespective
+		 * of its index in the array of Type-2s
+		 * If this Baseboard has no Baseboard parents
+		 * place it under the chassis that contains it
+		 */
+		bb_smbid = x86pi_bb_topparent(shp, nbb, &pnode, &psmbid);
+		if (bb_smbid == -1 || pnode == NULL) {
+			topo_mod_dprintf(mod,
+			    "Failed to get BaseBoard node (%d): parent\n",
+			    nbb);
+			return (-1);
+		}
+
+		if (stypes[SMB_TYPE_BASEBOARD].ids[nbb].id != bb_smbid) {
+			for (int i = 0; i < bb_count; i++) {
+				if (bb_smbid ==
+				    stypes[SMB_TYPE_BASEBOARD].ids[i].id) {
+					stypes[SMB_TYPE_BASEBOARD].ids[i].\
+					    visited = 1;
+					notvisited--;
+					break;
+				}
+			}
+		} else {
+			stypes[SMB_TYPE_BASEBOARD].ids[nbb].visited = 1;
+			notvisited--;
+		}
+
+		basebd_node = x86pi_gen_bboard(mod, pnode, shp,
+		    bb_smbid, nbb, psmbid);
+		if (basebd_node == NULL) {
+			topo_mod_dprintf(mod,
+			    "Failed to create BaseBoard node (%d)\n", nbb);
+			nbb++;
+			continue;
+		}
+
+		stypes[SMB_TYPE_BASEBOARD].ids[nbb].node = basebd_node;
+		/*
+		 * Look for contained handles here and if there are
+		 * make sure the chip handle below is part of it.
+		 */
+		ncmp = x86pi_bb_getchips(mod, shp, nbb, bb_count);
+		if (ncmp > 0) {
+			max = min + ncmp - 1;
+			/* make sure the chip enum is loaded */
+			topo_mod_dprintf(mod, "%s: loading chip enum\n", f);
+
+			if (topo_mod_load(mod, CHIP, TOPO_VERSION) == NULL) {
+				topo_mod_dprintf(mod,
+				    "%s: Failed to load %s module: %s\n", f,
+				    CHIP, topo_strerror(topo_mod_errno(mod)));
+			} else {
+				/* create node range */
+				topo_mod_dprintf(mod,
+				    "%s: chip range %d to %d\n",
+				    f, min, max);
+				rv = topo_node_range_create(mod, basebd_node,
+				    CHIP, min, max);
+				if (rv != 0) {
+					topo_mod_dprintf(mod,
+					    "%s: Failed to create node range: "
+					    "%s\n", f,
+					    topo_strerror(topo_mod_errno(mod)));
+				} else {
+					/* call the chip enumerator */
+					topo_mod_dprintf(mod, "%s: calling"
+					    " chip enum\n", f);
+					rv =
+					    topo_mod_enumerate(mod, basebd_node,
+					    CHIP, CHIP, min, max,
+					    &x86pi_smbios);
+					min = max + 1;
+					if (rv != 0)
+						topo_mod_dprintf(mod, "%s:%s"
+						    "enumeration failed: \n",
+						    f, CHIP);
+				}
+			}
+		}
+
+		/* enumerate the hostbridge node */
+		rv = topo_node_range_create(mod, basebd_node, HOSTBRIDGE,
+		    0, 255);
+		if (rv != 0) {
+			topo_mod_dprintf(mod,
+			    "%s: Failed to create %s range: %s\n",
+			    f, HOSTBRIDGE, topo_mod_errmsg(mod));
+			continue;
+		}
+
+		smbc = &stypes[SUN_OEM_PCIEXRC];
+		smbc->type = SUN_OEM_PCIEXRC;
+		x86pi_smb_strcnt(shp, smbc);
+		for (i = 0; i < smbc->count; i++) {
+			if (smbios_info_pciexrc(shp, smbc->ids[i].id,
+			    &hbr) != 0) {
+				topo_mod_dprintf(mod,
+				    "smbios_info_pciexrc failed: "
+				    "id = %d\n", (int)smbc->ids[i].id);
+				continue;
+			}
+
+			if (hbr.smbpcie_bb != bb_smbid)
+				continue;
+			rv = x86pi_gen_hbr(mod, basebd_node, shp,
+			    smbc->ids[i].id, hbri, &rci);
+			if (rv != 0)
+				topo_mod_dprintf(mod,
+				    "couldn't create hostbridge=%d\n", hbri);
+			hbri++;
+		}
+		nbb++;
+
+	} while (notvisited);
+
+	return (0);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/lib/fm/topo/modules/i86pc/x86pi/x86pi_bboard.c	Tue Nov 03 21:14:05 2009 -0500
@@ -0,0 +1,370 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ */
+
+/*
+ * Create Base Board (MB) topology node from SMBIOS Type 2 structure
+ */
+
+#include <sys/types.h>
+#include <strings.h>
+#include <fm/topo_mod.h>
+#include <fm/topo_hc.h>
+#include <sys/systeminfo.h>
+#include <sys/smbios_impl.h>
+#include <sys/smbios.h>
+#include <x86pi_impl.h>
+
+/* base baoed type values to hc-canonical-name */
+static const struct x86pi_bb_name {
+	int type;
+	const char *name;
+} x86pi_bb_names[] = {
+	{ SMB_BBT_SBLADE,	"systemboard" },
+	{ SMB_BBT_PROC,		"cpuboard" },
+	{ SMB_BBT_IO,		"ioboard" },
+	{ SMB_BBT_MEM,		"memboard" },
+	{ SMB_BBT_DAUGHTER,	"systemboard" },
+	{ SMB_BBT_MOTHER,	"motherboard" },
+	{ SMB_BBT_PROCMEM,	"systemboard" },
+	{ SMB_BBT_PROCIO,	"systemboard" },
+	{ SMB_BBT_INTER,	"systemboard" },
+	{ 0x00 }
+};
+
+tnode_t *
+x86pi_gen_bboard(topo_mod_t *mod, tnode_t *t_parent, smbios_hdl_t *shp,
+    int smb_id, int instance, int psmb_id)
+{
+	int		rv;
+	smbios_info_t	ip;
+	smbios_bboard_t	bb;
+	smbios_struct_t	sp;
+	x86pi_hcfmri_t	bb_hcfmri;
+	tnode_t		*bb_node;
+	const struct x86pi_bb_name *bbnp;
+	static int	cpuboard = 0;
+	static int	memboard = 0;
+	static int	ioboard = 0;
+	static int	systemboard = 0;
+	static int	motherboard = 0;
+	char		*f = "x86pi_gen_bboard";
+
+	topo_mod_dprintf(mod, "%s\n", f);
+
+	/* SMBIOS Base Board struct */
+	rv = smbios_info_bboard(shp, smb_id, &bb);
+	if (rv != 0) {
+		topo_mod_dprintf(mod, "%s: smbios_info_bboard() failed\n", f);
+		return (NULL);
+	}
+	(void) smbios_lookup_id(shp, psmb_id, &sp);
+	if (sp.smbstr_type == SMB_TYPE_CHASSIS &&
+	    bb.smbb_chassis != psmb_id) {
+		topo_mod_dprintf(mod, "%s: base board (%d) does not belong to "
+		    "chassis (%d)\n", f, smb_id, psmb_id);
+		return (NULL);
+	}
+
+	/* SMBIOS Base Board strings */
+	rv = smbios_info_common(shp, smb_id, &ip);
+	if (rv != 0) {
+		return (NULL);
+	}
+
+	/*
+	 * populate string entries
+	 *
+	 * We don't set "product" because it may contain characters
+	 * unacceptable by fmri.   topo_mod_auth() will set the product-id
+	 * for us and call topo_cleanup_auth_str() when necessary.
+	 */
+	bb_hcfmri.serial_number = x86pi_cleanup_smbios_str(mod,
+	    ip.smbi_serial, 0);
+	bb_hcfmri.version = x86pi_cleanup_smbios_str(mod, ip.smbi_version, 0);
+	/* asset tag string contains the part number */
+	bb_hcfmri.part_number = x86pi_cleanup_smbios_str(mod,
+	    ip.smbi_asset, 0);
+	bb_hcfmri.location = x86pi_cleanup_smbios_str(mod, ip.smbi_location, 0);
+
+	/* determine the hc-name */
+	for (bbnp = x86pi_bb_names; bbnp->type != 0x00; bbnp++) {
+		if (bbnp->type == bb.smbb_type) {
+			switch (bbnp->type) {
+				case SMB_BBT_PROC :
+					instance = cpuboard++;
+					break;
+				case SMB_BBT_IO :
+					instance = ioboard++;
+					break;
+				case SMB_BBT_MEM :
+					instance = memboard++;
+					break;
+				case SMB_BBT_MOTHER :
+					instance = motherboard++;
+					break;
+				default :
+					/*
+					 * Enumerate any other baseboard type
+					 * as systemboard.
+					 *
+					 * SMB_BBT_UNKNOWN
+					 * SMB_BBT_OTHER
+					 * SMB_BBT_SBLADE
+					 * SMB_BBT_CSWITCH
+					 * SMB_BBT_SMM
+					 * SMB_BBT_DAUGHTER
+					 * SMB_BBT_PROCMEM
+					 * SMB_BBT_PROCIO
+					 * SMB_BBT_INTER
+					 */
+					instance = systemboard++;
+					break;
+			}
+			break;
+		}
+	}
+
+	bb_hcfmri.instance = instance;
+	if (bbnp->type != 0x00)
+		bb_hcfmri.hc_name = topo_mod_strdup(mod, bbnp->name);
+	else
+		bb_hcfmri.hc_name = topo_mod_strdup(mod, "NULL");
+
+	topo_mod_dprintf(mod, "%s: S/N (%s)\n", f, bb_hcfmri.serial_number);
+	topo_mod_dprintf(mod, "%s: version/N (%s)\n", f, bb_hcfmri.version);
+	topo_mod_dprintf(mod, "%s: Part/N (%s)\n", f, bb_hcfmri.part_number);
+	topo_mod_dprintf(mod, "%s: location (%s)\n", f, bb_hcfmri.location);
+	topo_mod_dprintf(mod, "%s: instance (%d)\n", f, bb_hcfmri.instance);
+	topo_mod_dprintf(mod, "%s: hc_name (%s)\n", f, bb_hcfmri.hc_name);
+
+	rv = x86pi_enum_generic(mod, &bb_hcfmri, t_parent, t_parent, &bb_node,
+	    X86PI_ENUM_FRU);
+	if (rv != 0) {
+		topo_mod_dprintf(mod, "%s: failed to create tnode %d\n", f,
+		    instance);
+		bb_node = NULL;
+	}
+
+	/* free up strings */
+	if (bb_hcfmri.hc_name != NULL) {
+		topo_mod_strfree(mod, (char *)bb_hcfmri.hc_name);
+	}
+	if (bb_hcfmri.part_number != NULL) {
+		topo_mod_strfree(mod, (char *)bb_hcfmri.part_number);
+	}
+	if (bb_hcfmri.serial_number != NULL) {
+		topo_mod_strfree(mod, (char *)bb_hcfmri.serial_number);
+	}
+	if (bb_hcfmri.version != NULL) {
+		topo_mod_strfree(mod, (char *)bb_hcfmri.version);
+	}
+	if (bb_hcfmri.location != NULL) {
+		topo_mod_strfree(mod, (char *)bb_hcfmri.location);
+	}
+
+	return (bb_node);
+}
+
+
+int
+x86pi_bb_getchips(topo_mod_t *mod, smbios_hdl_t *shp, int index, int nboards)
+{
+	id_t		*cid;
+	int		count;
+	int		ncmp = 0;
+	smbios_struct_t	sp;
+	smbs_cnt_t	*smbc = NULL;
+
+	cid = stypes[SMB_TYPE_BASEBOARD].ids[index].con_ids;
+	count = stypes[SMB_TYPE_BASEBOARD].ids[index].con_cnt;
+
+	for (int i = 0; i < count; i++) {
+		(void) smbios_lookup_id(shp, cid[i], &sp);
+		if (sp.smbstr_type == SMB_TYPE_PROCESSOR) {
+			ncmp++;
+		}
+	}
+
+	/*
+	 * If there are missing SMB_TYPE_PROCESSOR structures
+	 * contained within SMB_TYPE_BASEBOARD, and if the
+	 * system has only one baseboard we enumerate
+	 * all processors under it.
+	 */
+	smbc = &stypes[SMB_TYPE_PROCESSOR];
+	smbc->type = SMB_TYPE_PROCESSOR;
+	x86pi_smb_strcnt(shp, smbc);
+
+	if (nboards == 1) {
+		if (ncmp != stypes[SMB_TYPE_PROCESSOR].count)
+			ncmp = stypes[SMB_TYPE_PROCESSOR].count;
+	} else {
+		if (ncmp == 0) {
+			topo_mod_dprintf(mod, "failed to get processors"
+			    " (or) no processors are contained"
+			    " within baseboard instance %d, unable to"
+			    " enumerate chips\n", index);
+		}
+	}
+
+	return (ncmp);
+}
+
+
+id_t
+x86pi_bb_topparent(smbios_hdl_t *shp, int index, tnode_t **pnode, id_t *psmbid)
+{
+
+	id_t	top_bb_smbid = -1;
+	id_t	smb_id;
+	int	bb_count, ch_count;
+	smbios_struct_t	sp;
+
+	smb_id = stypes[SMB_TYPE_BASEBOARD].ids[index].con_by_id;
+	(void) smbios_lookup_id(shp, smb_id, &sp);
+
+	if (sp.smbstr_type == SMB_TYPE_CHASSIS) {
+		top_bb_smbid = stypes[SMB_TYPE_BASEBOARD].ids[index].id;
+		*psmbid = smb_id;
+		ch_count = stypes[SMB_TYPE_CHASSIS].count;
+		for (int i = 0; i < ch_count; i++)
+			if (stypes[SMB_TYPE_CHASSIS].ids[i].id == *psmbid)
+				*pnode = stypes[SMB_TYPE_CHASSIS].ids[i].node;
+
+		return (top_bb_smbid);
+
+	} else if (sp.smbstr_type == SMB_TYPE_BASEBOARD) {
+		bb_count = stypes[SMB_TYPE_BASEBOARD].count;
+		for (int i = 0; i < bb_count; i++) {
+			if (stypes[SMB_TYPE_BASEBOARD].ids[i].id == smb_id) {
+				if (stypes[SMB_TYPE_BASEBOARD].ids[i].visited
+				    == X86PI_VISITED) {
+					top_bb_smbid =
+					    stypes[SMB_TYPE_BASEBOARD].\
+					    ids[index].id;
+					*pnode =
+					    stypes[SMB_TYPE_BASEBOARD].ids[i].\
+					    node;
+					*psmbid =
+					    stypes[SMB_TYPE_BASEBOARD].ids[i].\
+					    id;
+					break;
+				}
+				top_bb_smbid = x86pi_bb_topparent(shp,
+				    i, pnode, psmbid);
+				break;
+			}
+		}
+	}
+
+	return (top_bb_smbid);
+}
+
+
+id_t
+x86pi_bb_chassis(smbios_hdl_t *shp, id_t bb_smbid)
+{
+	smbios_bboard_t	bb;
+	int		rv;
+
+	rv = smbios_info_bboard(shp, bb_smbid, &bb);
+	if (rv != 0)
+		return (-1);
+
+	return (bb.smbb_chassis);
+}
+
+
+int
+x86pi_bb_contains(topo_mod_t *mod, smbios_hdl_t *shp)
+{
+	int		rv;
+	id_t		smb_id;
+	smbios_bboard_t	bb;
+	int		bb_count = 0;
+	uint_t		cont_cnt = 0;
+	smbios_struct_t	sp;
+
+	bb_count = stypes[SMB_TYPE_BASEBOARD].count;
+	for (int i = 0; i < bb_count; i++) {
+		smb_id = stypes[SMB_TYPE_BASEBOARD].ids[i].id;
+		/* SMBIOS Base Board struct */
+		rv = smbios_info_bboard(shp, smb_id, &bb);
+		if (rv != 0)
+			return (-1);
+		/* Set Baseboard - Chassis Relationship */
+		if (stypes[SMB_TYPE_BASEBOARD].ids[i].con_by_id == 0) {
+			stypes[SMB_TYPE_BASEBOARD].ids[i].con_by_id =
+			    rv = x86pi_bb_chassis(shp, smb_id);
+			if (rv == -1) {
+				topo_mod_dprintf(mod, " failed to get"
+				    " the chassis handle\n");
+				return (rv);
+			}
+		}
+
+		/* SMBIOS contained object handles */
+		cont_cnt = bb.smbb_contn;
+		if (cont_cnt > 0) {
+			id_t *cont_hdl;
+			uint16_t hdl;
+
+			/* allocate space for and get contained handles */
+			cont_hdl = topo_mod_alloc(mod, cont_cnt *
+			    sizeof (id_t));
+			rv = smbios_info_contains(shp, smb_id, cont_cnt,
+			    cont_hdl);
+			if (rv > SMB_CONT_MAX) {
+				topo_mod_free(mod, cont_hdl, cont_cnt *
+				    sizeof (id_t));
+				return (-1);
+			}
+			cont_cnt = MIN(rv, cont_cnt);
+
+			/* attach contained handles */
+			stypes[SMB_TYPE_BASEBOARD].ids[i].con_cnt = cont_cnt;
+			for (int j = 0; j < cont_cnt; j++) {
+				hdl = (uint16_t)cont_hdl[j];
+				topo_mod_dprintf(mod, "id %d contained handle"
+				    " %d: %d\n", i, j, hdl);
+				stypes[SMB_TYPE_BASEBOARD].ids[i].\
+				    con_ids[j] = hdl;
+				(void) smbios_lookup_id(shp, hdl, &sp);
+				if (sp.smbstr_type == SMB_TYPE_BASEBOARD) {
+					for (int k = 0; k < bb_count; k++)
+						if (stypes[SMB_TYPE_BASEBOARD].\
+						    ids[k].id == hdl)
+							stypes[\
+							    SMB_TYPE_BASEBOARD\
+							    ].ids[k].con_by_id =
+							    smb_id;
+				}
+			}
+			topo_mod_free(mod, cont_hdl, cont_cnt * sizeof (id_t));
+		}
+	}
+	return (0);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/lib/fm/topo/modules/i86pc/x86pi/x86pi_chassis.c	Tue Nov 03 21:14:05 2009 -0500
@@ -0,0 +1,116 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ */
+
+/*
+ * Create chassis topology node from SMBIOS Type 3 structure
+ */
+
+#include <sys/types.h>
+#include <strings.h>
+#include <fm/topo_mod.h>
+#include <fm/topo_hc.h>
+#include <sys/systeminfo.h>
+#include <sys/smbios_impl.h>
+#include <x86pi_impl.h>
+
+
+tnode_t *
+x86pi_gen_chassis(topo_mod_t *mod, tnode_t *t_parent, smbios_hdl_t *shp,
+    int smb_id, int instance)
+{
+	int			rv;
+	smbios_info_t		ip;
+	smbios_chassis_t	ch;
+	x86pi_hcfmri_t		ch_hcfmri;
+	tnode_t			*ch_node;
+	char			*f = "x86pi_gen_chassis";
+
+
+	/* init fmri struct */
+	bzero(&ch_hcfmri, sizeof (x86pi_hcfmri_t));
+
+	/* grab SMBIOS strings */
+	rv = smbios_info_common(shp, smb_id, &ip);
+	if (rv != 0) {
+		return (NULL);
+	}
+
+	/* grab SMBIOS type 3 struct */
+	rv = smbios_info_chassis(shp, smb_id, &ch);
+	if (rv != 0) {
+		return (NULL);
+	}
+
+	/* populate string entries */
+	ch_hcfmri.serial_number = x86pi_cleanup_smbios_str(mod,
+	    ip.smbi_serial, 0);
+	ch_hcfmri.version = x86pi_cleanup_smbios_str(mod, ip.smbi_version, 0);
+	ch_hcfmri.manufacturer = x86pi_cleanup_smbios_str(mod,
+	    ip.smbi_manufacturer, 0);
+
+	/* set hc_name and instance */
+	ch_hcfmri.hc_name = topo_mod_strdup(mod, "chassis");
+	ch_hcfmri.instance = instance;
+
+	topo_mod_dprintf(mod, "%s: instance (%d)\n", f, ch_hcfmri.instance);
+	topo_mod_dprintf(mod, "%s: hc name (%s)\n", f, ch_hcfmri.hc_name);
+	topo_mod_dprintf(mod, "%s: Serial Number (%s)\n",
+	    f, ch_hcfmri.serial_number);
+	topo_mod_dprintf(mod, "%s: Version (%s)\n", f, ch_hcfmri.version);
+	topo_mod_dprintf(mod, "%s: Manufacturer (%s)\n",
+	    f, ch_hcfmri.manufacturer);
+
+	/* create topo node */
+	if (!instance) {
+		/* First Chassis SMBIOS Record is Chassis topo instance 0 */
+		rv = x86pi_enum_generic(mod, &ch_hcfmri, t_parent, NULL,
+		    &ch_node, 0);
+	} else {
+		rv = x86pi_enum_generic(mod, &ch_hcfmri, t_parent, t_parent,
+		    &ch_node, 0);
+	}
+	if (rv != 0) {
+		topo_mod_dprintf(mod, "%s: failed to create %d tnode\n", f,
+		    instance);
+		return (NULL);
+	}
+
+	/* free up strings */
+	if (ch_hcfmri.serial_number != NULL) {
+		topo_mod_strfree(mod, (char *)ch_hcfmri.serial_number);
+	}
+	if (ch_hcfmri.version != NULL) {
+		topo_mod_strfree(mod, (char *)ch_hcfmri.version);
+	}
+	if (ch_hcfmri.manufacturer != NULL) {
+		topo_mod_strfree(mod, (char *)ch_hcfmri.manufacturer);
+	}
+	if (ch_hcfmri.hc_name != NULL) {
+		topo_mod_strfree(mod, (char *)ch_hcfmri.hc_name);
+	}
+
+	return (ch_node);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/lib/fm/topo/modules/i86pc/x86pi/x86pi_generic.c	Tue Nov 03 21:14:05 2009 -0500
@@ -0,0 +1,211 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ */
+
+/*
+ * Create a generic topology node.
+ */
+#include <sys/types.h>
+#include <strings.h>
+#include <sys/fm/protocol.h>
+#include <fm/topo_mod.h>
+#include <fm/topo_hc.h>
+#include <x86pi_impl.h>
+
+#define	_ENUM_NAME	"enum_generic"
+#define	_FAC_PROV	"fac_prov_ipmi"
+
+/*
+ * Create a generic topo node based on the hcfmri strcuture passed in.
+ */
+int
+x86pi_enum_generic(topo_mod_t *mod, x86pi_hcfmri_t *hcfmri,
+    tnode_t *t_bindparent, tnode_t *t_fmriparent, tnode_t **t_node, int flag)
+{
+	int		rv;
+	int		err;
+	nvlist_t	*out;
+	nvlist_t	*fmri;
+	nvlist_t	*auth;
+
+	topo_mod_dprintf(mod, "%s adding entry for type (%s)\n",
+	    _ENUM_NAME, hcfmri->hc_name);
+
+	if (t_bindparent == NULL) {
+		topo_mod_dprintf(mod,
+		    "%s called with NULL parent for type %s\n",
+		    _ENUM_NAME, hcfmri->hc_name);
+		return (-1);
+	}
+
+	/* Create the FMRI for this node */
+	auth = topo_mod_auth(mod, t_bindparent);
+	fmri = topo_mod_hcfmri(mod, t_fmriparent, FM_HC_SCHEME_VERSION,
+	    hcfmri->hc_name, hcfmri->instance, NULL, auth,
+	    hcfmri->part_number, hcfmri->version, hcfmri->serial_number);
+
+	nvlist_free(auth);
+
+	if (fmri == NULL) {
+		topo_mod_dprintf(mod,
+		    "%s failed to create %s fmri : %s\n", _ENUM_NAME,
+		    hcfmri->hc_name, topo_strerror(topo_mod_errno(mod)));
+		return (-1);
+	}
+
+	rv = topo_node_range_create(mod, t_bindparent, hcfmri->hc_name, 0, 4);
+	if (rv != 0 && topo_mod_errno(mod) != EMOD_NODE_DUP) {
+		topo_mod_dprintf(mod, "%s range create failed for node %s\n",
+		    _ENUM_NAME, hcfmri->hc_name);
+	}
+
+	/* Bind this node to the parent */
+	*t_node = x86pi_node_bind(mod, t_bindparent, hcfmri, fmri, flag);
+	nvlist_free(fmri);
+	if (*t_node == NULL) {
+		topo_mod_dprintf(mod,
+		    "%s failed to bind %s node instance %d: %s\n",
+		    _ENUM_NAME, hcfmri->hc_name, hcfmri->instance,
+		    topo_strerror(topo_mod_errno(mod)));
+		return (-1);
+	}
+
+	/* call IPMI facility provider to register fac methods */
+	if (topo_mod_load(mod, _FAC_PROV, TOPO_VERSION) == NULL) {
+		topo_mod_dprintf(mod,
+		    "%s: Failed to load %s module: %s\n", _ENUM_NAME, _FAC_PROV,
+		    topo_mod_errmsg(mod));
+		return (-1);
+	}
+
+	rv = topo_mod_enumerate(mod, *t_node, _FAC_PROV, _FAC_PROV, 0, 0, NULL);
+	if (rv != 0) {
+		topo_mod_dprintf(mod,
+		    "%s: %s failed: %s\n", _ENUM_NAME, _FAC_PROV,
+		    topo_mod_errmsg(mod));
+		return (-1);
+	}
+
+	/* invoke fac_prov_ipmi_enum method */
+	if (topo_method_supported(*t_node, TOPO_METH_FAC_ENUM, 0)) {
+		if (topo_method_invoke(*t_node, TOPO_METH_FAC_ENUM, 0, NULL,
+		    &out, &err) != 0) {
+			/* log the error and drive on */
+			topo_mod_dprintf(mod,
+			    "%s: TOPO_METH_FAC_ENUM failed\n", _ENUM_NAME);
+		} else {
+			fac_done = 1;
+		}
+	}
+
+	topo_mod_dprintf(mod, "%s added (%s) node\n", _ENUM_NAME,
+	    topo_node_name(*t_node));
+
+	return (0);
+}
+
+
+tnode_t *
+x86pi_node_bind(topo_mod_t *mod, tnode_t *t_parent, x86pi_hcfmri_t *hcfmri,
+    nvlist_t *fmri, int flag)
+{
+	int	result;
+	tnode_t	*t_node;
+	char	*f = "x86pi_node_bind";
+
+	if (t_parent == NULL) {
+		topo_mod_dprintf(mod,
+		    "%s: NULL parent for %s node instance %d\n",
+		    f, hcfmri->hc_name, hcfmri->instance);
+		return (NULL);
+	}
+
+	/* Bind this node to the parent */
+	t_node = topo_node_bind(mod, t_parent, hcfmri->hc_name,
+	    hcfmri->instance, fmri);
+	if (t_node == NULL) {
+		topo_mod_dprintf(mod,
+		    "%s: failed to bind %s node instance %d: %s\n",
+		    f, hcfmri->hc_name, (uint32_t)hcfmri->instance,
+		    topo_strerror(topo_mod_errno(mod)));
+		return (NULL);
+	}
+	topo_mod_dprintf(mod, "%s: bound %s node instance %d type %s\n",
+	    f, hcfmri->hc_name, hcfmri->instance, hcfmri->hc_name);
+
+	/*
+	 * We have bound the node.  Now decorate it with an appropriate
+	 * FRU and label (which may be inherited from the parent).
+	 */
+	result = x86pi_set_frufmri(mod, hcfmri, t_parent, t_node, flag);
+	if (result != 0) {
+		/*
+		 * Though we have failed to set the FRU FMRI we still continue.
+		 * The module errno is set by the called routine, so we report
+		 * the problem and move on.
+		 */
+		topo_mod_dprintf(mod,
+		    "%s: failed to set FRU FMRI for %s node\n",
+		    f, hcfmri->hc_name);
+	}
+
+	result = x86pi_set_label(mod, hcfmri->location, hcfmri->hc_name,
+	    t_node);
+	if (result != 0) {
+		/*
+		 * Though we have failed to set the label, we still continue.
+		 * The module errno is set by the called routine, so we report
+		 * the problem and move on.
+		 */
+		topo_mod_dprintf(mod, "%s: no label for %s node\n",
+		    f, hcfmri->hc_name);
+	}
+
+	result = x86pi_set_auth(mod, hcfmri, t_parent, t_node);
+	if (result != 0) {
+		/*
+		 * Though we have failed to set the authority, we still
+		 * continue. The module errno is set by the called routine, so
+		 * we report the problem and move on.
+		 */
+		topo_mod_dprintf(mod,
+		    "%s: no authority information for %s node\n",
+		    f, hcfmri->hc_name);
+	}
+
+	result = x86pi_set_system(mod, t_node);
+	if (result != 0) {
+		/*
+		 * Though we have failed to set the system group, we still
+		 * continue. The module errno is set by the called routine, so
+		 * we report the problem and move on.
+		 */
+		topo_mod_dprintf(mod,
+		    "%s: no system information for %s node\n",
+		    f, hcfmri->hc_name);
+	}
+
+	return (t_node);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/lib/fm/topo/modules/i86pc/x86pi/x86pi_hostbridge.c	Tue Nov 03 21:14:05 2009 -0500
@@ -0,0 +1,290 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ */
+
+/*
+ * i86pc Generic hostbridge/pciex/pci enumerator
+ *
+ * hostbridge/pciexrc/pcibus topo nodes are created per SMBIOS type 138
+ * (SUN_OEM_PCIEXRC) records.   Each type 138 record can either represent
+ * a hostbridge or a pciexrc/pcibus determined by whether it points to
+ * a baseboard record or another type 138 record.
+ *
+ * x86pi_gen_hbr() is called when a new hostbridge node needs to be created..
+ * It then searches all the type 138 records that connected to it.  For each
+ * of the records, bdf is compared to find a matching di_node.  If the
+ * di_node is a pciex root port, a pciexrc (bad name!) node will be created.
+ * When pciexrc creation is done, or the di_node is a pcibus, in either
+ * case the pcibus module will loaded to enumerate pciexbus/pcibus etc.
+ *
+ * The enumeration uses did routines heavily, which requires a did hash
+ * pointer stored in x86pi's module-specific area.
+ */
+
+#include <sys/types.h>
+#include <strings.h>
+#include <fm/topo_mod.h>
+#include <fm/topo_hc.h>
+#include <sys/systeminfo.h>
+#include <sys/smbios_impl.h>
+#include <sys/fm/protocol.h>
+#include <x86pi_impl.h>
+#include <did.h>
+#include <did_impl.h>
+#include <did_props.h>
+#include <hostbridge.h>
+
+#define	PCI_ENUM	"pcibus"
+#define	PCI_ENUMR_VERS	1
+#define	MAX_HB_BUSES	255
+
+extern txprop_t RC_common_props[], HB_common_props[], ExHB_common_props[];
+extern int RC_propcnt, HB_propcnt, ExHB_propcnt;
+
+static topo_mod_t *pcimp = NULL;
+
+int
+x86pi_hbr_enum_init(topo_mod_t *mod)
+{
+	did_hash_t *tab = (did_hash_t *)topo_mod_getspecific(mod);
+	const char *f = "x86pi_hbr_enum_init";
+
+	if (tab == NULL && did_hash_init(mod) < 0) {
+		topo_mod_dprintf(mod, "%s: did_hash_init() failed.\n", f);
+		return (-1);
+	}
+
+	if (pcimp == NULL &&
+	    (pcimp = topo_mod_load(mod, PCI_ENUM, PCI_ENUMR_VERS))
+	    == NULL) {
+		topo_mod_dprintf(mod,
+		    "%s: %s enumerator could not load %s.\n",
+		    f, HOSTBRIDGE, PCI_ENUM);
+		did_hash_fini(mod);
+		return (-1);
+	}
+
+	return (0);
+}
+
+void
+x86pi_hbr_enum_fini(topo_mod_t *mod)
+{
+	did_hash_fini(mod);
+	if (pcimp != NULL) {
+		topo_mod_unload(pcimp);
+		pcimp = NULL;
+	}
+}
+
+static uint16_t
+x86pi_bdf(topo_mod_t *mod, di_node_t node)
+{
+	int *val;
+
+	if (di_prop_lookup_ints(DDI_DEV_T_ANY, node, "reg", &val) < 0) {
+		topo_mod_dprintf(mod, "couldn't get \"reg\" prop: %s.\n",
+		    strerror(errno));
+		return ((uint16_t)-1);
+	}
+
+	return (uint16_t)((*val & PCI_REG_BDFR_M) >> PCI_REG_FUNC_SHIFT);
+}
+
+static int
+pciex_process(topo_mod_t *mod, tnode_t *tn_hbr, di_node_t rcn,
+    topo_instance_t rci)
+{
+	did_t		*did;
+	int		rv;
+	tnode_t		*tn_rc;
+	x86pi_hcfmri_t	hcfmri = {0};
+	tnode_t		*tn_bb = topo_node_parent(tn_hbr);
+	const char	*f = "pciexrc_process";
+
+	if ((did = did_create(mod, rcn, topo_node_instance(tn_bb),
+	    topo_node_instance(tn_hbr), rci, TRUST_BDF)) == NULL)
+		return (NULL);
+
+	did_markrc(did);
+
+	/*
+	 * Let did set the hostbridge properties excluding FRU and label.
+	 */
+	(void) did_props_set(tn_hbr, did, ExHB_common_props, ExHB_propcnt - 2);
+
+	if (topo_node_range_create(mod, tn_hbr, PCIEX_ROOT, 0,
+	    MAX_HB_BUSES) != 0 && topo_mod_errno(mod) != EMOD_NODE_DUP) {
+		topo_mod_dprintf(mod,
+		    "%s: create child range for %s failed: %s\n",
+		    f, PCIEX_ROOT, topo_mod_errmsg(mod));
+		return (-1);
+	}
+
+	hcfmri.hc_name = PCIEX_ROOT;
+	hcfmri.instance = rci;
+	rv = x86pi_enum_generic(mod, &hcfmri, tn_hbr, tn_hbr, &tn_rc, 0);
+	if (rv != 0) {
+		topo_mod_dprintf(mod, "%s: failed to create %s = %d\n",
+		    f, PCIEX_ROOT, rci);
+		return (-1);
+	}
+
+	/*
+	 * pcibus enumerator requires di_node_t be set in node specific
+	 */
+	topo_node_setspecific(tn_rc, rcn);
+
+	/*
+	 * Let did set the RC properties excluding FRU, and label.
+	 */
+	if (did_props_set(tn_rc, did, RC_common_props, RC_propcnt - 2) < 0) {
+		topo_mod_dprintf(mod, "%s: did_props_set failed for %s = %d\n",
+		    f, PCIEX_ROOT, rci);
+		topo_node_unbind(tn_rc);
+		return (-1);
+	}
+
+	if (topo_node_range_create(mod, tn_rc, PCIEX_BUS, 0,
+	    MAX_HB_BUSES) != 0 && topo_mod_errno(mod) != EMOD_NODE_DUP) {
+		topo_mod_dprintf(mod,
+		    "%s: create child range for %s failed: %s\n",
+		    f, PCIEX_BUS, topo_mod_errmsg(mod));
+		return (-1);
+	}
+
+	return (topo_mod_enumerate(mod, tn_rc, PCI_BUS, PCIEX_BUS,
+	    0, MAX_HB_BUSES, did));
+}
+
+static int
+pci_process(topo_mod_t *mod, tnode_t *tn_hbr, di_node_t bn)
+{
+	did_t *did;
+	tnode_t *tn_bb = topo_node_parent(tn_hbr);
+
+	if ((did = did_create(mod, bn, topo_node_instance(tn_bb),
+	    topo_node_instance(tn_hbr), NO_RC, TRUST_BDF)) == NULL)
+		return (-1);
+
+	/*
+	 * Let did set the hostbridge properties excluding FRU and label.
+	 */
+	(void) did_props_set(tn_hbr, did, HB_common_props, HB_propcnt - 2);
+
+	if (topo_node_range_create(mod, tn_hbr, PCI_BUS, 0,
+	    MAX_HB_BUSES) != 0 && topo_mod_errno(mod) != EMOD_NODE_DUP) {
+		topo_mod_dprintf(mod, "create child range for %s failed: %s\n",
+		    PCI_BUS, topo_mod_errmsg(mod));
+		return (-1);
+	}
+
+	return (topo_mod_enumerate(mod, tn_hbr, PCI_BUS, PCI_BUS,
+	    0, MAX_HB_BUSES, did));
+}
+
+static int
+x86pi_gen_pci_pciexrc(topo_mod_t *mod, tnode_t *tn_hbr, uint16_t bdf,
+    topo_instance_t *rcip)
+{
+	di_node_t devtree, pnode, cnode;
+
+	topo_mod_dprintf(mod, "creating pci/pciexrc node bdf = %#x\n",
+	    (int)bdf);
+
+	devtree = topo_mod_devinfo(mod);
+	if (devtree == DI_NODE_NIL) {
+		topo_mod_dprintf(mod, "devinfo init failed.\n");
+		return (-1);
+	}
+
+	for (pnode = di_drv_first_node(PCI, devtree);
+	    pnode != DI_NODE_NIL; pnode = di_drv_next_node(pnode))
+		if (x86pi_bdf(mod, pnode) == bdf)
+			return (pci_process(mod, tn_hbr, pnode));
+
+	pnode = di_drv_first_node(NPE, devtree);
+	while (pnode != DI_NODE_NIL) {
+		for (cnode = di_child_node(pnode); cnode != DI_NODE_NIL;
+		    cnode = di_sibling_node(cnode)) {
+			if (di_driver_name(cnode) == NULL ||
+			    x86pi_bdf(mod, cnode) != bdf)
+				continue;
+
+			if (strcmp(di_driver_name(cnode), PCI_PCI) == 0)
+				return (pci_process(mod, tn_hbr, cnode));
+
+			if (strcmp(di_driver_name(cnode), PCIEB) == 0)
+				return (pciex_process(mod, tn_hbr,
+				    cnode, (*rcip)++));
+
+			topo_mod_dprintf(mod, "no matching driver found: "
+			    "bdf = %#x\n", (int)bdf);
+		}
+		pnode = di_drv_next_node(pnode);
+	}
+
+	topo_mod_dprintf(mod, "no matching bdf found: bdf = %#x\n", (int)bdf);
+
+	return (0);
+}
+
+int
+x86pi_gen_hbr(topo_mod_t *mod, tnode_t *tn_bb, smbios_hdl_t *shp,
+    int hbr_smbid, topo_instance_t hbri, topo_instance_t *rcip)
+{
+	x86pi_hcfmri_t	hcfmri = {0};
+	tnode_t		*tn_hbr;
+	smbs_cnt_t	*smbc = &stypes[SUN_OEM_PCIEXRC];
+	smbios_pciexrc_t smb_rc;
+	int		i, rv, err = 0;
+	const char	*f = "x86pi_gen_hbr";
+
+	hcfmri.hc_name = HOSTBRIDGE;
+	hcfmri.instance = hbri;
+
+	/* create and bind the "hostbridge" node */
+	rv = x86pi_enum_generic(mod, &hcfmri, tn_bb, tn_bb, &tn_hbr, 0);
+	if (rv != 0) {
+		topo_mod_dprintf(mod, "%s: failed to create %s = %d\n",
+		    f, HOSTBRIDGE, hbri);
+		return (topo_mod_seterrno(mod, EMOD_PARTIAL_ENUM));
+	}
+
+	/*
+	 * Walk the smbios records and create the pci/pciexrc nodes
+	 */
+	for (i = 0; i < smbc->count; i++) {
+		if (smbios_info_pciexrc(shp, smbc->ids[i].id, &smb_rc) != 0)
+			topo_mod_dprintf(mod,
+			    "%s: failed: id = %d\n", f, (int)smbc->ids[i].id);
+		else if (smb_rc.smbpcie_bb == hbr_smbid &&
+		    x86pi_gen_pci_pciexrc(mod, tn_hbr, smb_rc.smbpcie_bdf,
+		    rcip) != 0)
+			err++;
+	}
+
+	return (err == 0 ? 0 : topo_mod_seterrno(mod, EMOD_PARTIAL_ENUM));
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/lib/fm/topo/modules/i86pc/x86pi/x86pi_impl.h	Tue Nov 03 21:14:05 2009 -0500
@@ -0,0 +1,206 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#ifndef _X86PI_IMPL_H
+#define	_X86PI_IMPL_H
+
+/*
+ * i86pc Generic Enumerator private interfaces
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <smbios.h>
+#include <ctype.h>
+
+
+/*
+ * Table showing the relationship between hc-canonical names and the
+ * SMBIOS tables/values.
+ *
+ * **************************************************************************
+ * | hc-name             | SMB Table | Offset - Name            | Value     |
+ * --------------------------------------------------------------------------
+ * --------------------------------------------------------------------------
+ * | "motherboard"       | Type 2    | 0x0D - Board Type        | 0x0A      |
+ * --------------------------------------------------------------------------
+ * | "cpuboard"          | Type 2    | 0x0D - Board Type        | 0x06      |
+ * --------------------------------------------------------------------------
+ * | "memboard"          | Type 2    | 0x0D - Board Type        | 0x08      |
+ * --------------------------------------------------------------------------
+ * | "ioboard"           | Type 2    | 0x0D - Board Type        | 0x07      |
+ * --------------------------------------------------------------------------
+ * | "systemboard"       | Type 2    | 0x0D - Board Type        | 0x03,0x09,|
+ * |                     |           |                          | 0x0B,0x0C |
+ * --------------------------------------------------------------------------
+ * | "hostbridge"        | Type 138  |                                      |
+ * --------------------------------------------------------------------------
+ * | "pciexrc"           | Type 138  |                                      |
+ * **************************************************************************
+ */
+
+
+/* Definitions used when registering the enumerator with libtopo */
+#define	X86PI_DESC	"i86pc Generic Topology Enumerator"
+#define	X86PI_SCHEME	"hc"
+#define	X86PI_VERSION	TOPO_VERSION
+
+/*
+ * Solaris FMA Compliance level for SMBIOS.
+ * The same X86PI_* definitions are used in chip.h
+ * please keep them in sync
+ */
+#define	X86PI_FULL	1
+#define	X86PI_NONE	2
+
+/* used in traversing contained bboards */
+#define	X86PI_VISITED	1
+
+#define	LABEL		1
+
+/* Flags used by x86pi_enum_generic */
+#define	X86PI_ENUM_FRU	0x0001	/* Indicates a FRU */
+
+/* max allowed contained count */
+#define	SMB_MAX_ID	0x40
+
+/* indication of successful fac node creation */
+int fac_done;
+
+/*
+ * Count and smbios struct id(s) for each smbios struct type.
+ */
+typedef struct smbs_con_ids {
+	id_t id;			/* smbios struct id */
+	id_t con_cnt;			/* containee count */
+	id_t con_ids[SMB_MAX_ID];	/* containee ids */
+	id_t con_by_id;			/* container id */
+	int visited;			/* visit flag */
+	tnode_t *node;
+} smbs_con_ids_t;
+
+typedef struct smbs_cnt {
+	int type;		/* SMBIOS stucture type */
+	int count;		/* number of table entries */
+	smbs_con_ids_t ids[SMB_MAX_ID]; /* SMBIOS table entry id(s) */
+} smbs_cnt_t;
+
+smbs_cnt_t stypes[SMB_TYPE_OEM_HI]; /* one for each struct */
+
+/*
+ * The enumerator needs to pass some state in to the function that walks
+ * the PRI graph.  This structure contains the necessary information.
+ */
+struct x86pi_enum_s {
+	topo_mod_t	*mod;		/* Topo module handle */
+	tnode_t		*t_parent;	/* "Chassis" parent */
+	uint32_t	force;		/* force legacy */
+	void		*priv;		/* Private data */
+};
+typedef struct x86pi_enum_s x86pi_enum_t;
+
+/*
+ * x86gentopo hcfmri info structure.
+ *
+ * Available unformed SMBIOS strings:
+ *  smbi_manufacturer
+ *  smbi_product
+ *  smbi_version
+ *  smbi_serial
+ *  smbi_asset
+ *  smbi_location
+ *  smbi_part
+ *
+ */
+struct x86pi_hcfmri_info_s {
+	int		instance;
+	int		rev;
+
+	const char	*hc_name;
+	const char	*manufacturer;
+	const char	*product;
+	const char	*version;
+	const char	*serial_number;
+	const char	*asset_tag;
+	const char	*location;
+	const char	*part_number;
+};
+typedef struct x86pi_hcfmri_info_s x86pi_hcfmri_t;
+
+/*
+ * Prototypes
+ */
+
+/* SMBIOS */
+smbios_hdl_t *x86pi_smb_open(topo_mod_t *);
+void x86pi_smb_strcnt(smbios_hdl_t *, smbs_cnt_t *);
+int x86pi_check_comp(topo_mod_t *, smbios_hdl_t *);
+
+/* Node generation */
+tnode_t *x86pi_gen_chassis(topo_mod_t *, tnode_t *, smbios_hdl_t *, int, int);
+tnode_t *x86pi_gen_bboard(topo_mod_t *, tnode_t *, smbios_hdl_t *, int, int,
+    int);
+int x86pi_gen_cmp(topo_mod_t *, tnode_t *, smbios_hdl_t *, int, int, int);
+int x86pi_gen_core(topo_mod_t *, tnode_t *, int, int, int);
+int x86pi_gen_strand(topo_mod_t *, tnode_t *, int, int, int);
+int x86pi_gen_memarray(topo_mod_t *, tnode_t *, smbios_hdl_t *, int, int);
+void x86pi_gen_memdev(topo_mod_t *, tnode_t *, smbios_hdl_t *, int, int, int);
+int x86pi_gen_hbr(topo_mod_t *, tnode_t *, smbios_hdl_t *, int,
+    topo_instance_t, topo_instance_t *);
+
+/* support routines */
+int x86pi_enum_generic(topo_mod_t *, x86pi_hcfmri_t *, tnode_t *, tnode_t *,
+    tnode_t **, int);
+tnode_t *x86pi_node_bind(topo_mod_t *, tnode_t *, x86pi_hcfmri_t *, nvlist_t *,
+    int);
+void x86pi_hcfmri_info_fini(topo_mod_t *, x86pi_hcfmri_t *);
+
+/* get/set info */
+char *x86pi_get_serverid(topo_mod_t *);
+int x86pi_set_frufmri(topo_mod_t *, x86pi_hcfmri_t *, tnode_t *, tnode_t *,
+    int);
+int x86pi_set_label(topo_mod_t *, const char *, const char *, tnode_t *);
+int x86pi_set_auth(topo_mod_t *, x86pi_hcfmri_t *, tnode_t *, tnode_t *);
+int x86pi_set_system(topo_mod_t *, tnode_t *);
+
+/* hostbridge */
+int x86pi_hbr_enum_init(topo_mod_t *);
+void x86pi_hbr_enum_fini(topo_mod_t *);
+
+/* base board */
+id_t x86pi_bb_topparent(smbios_hdl_t *, int, tnode_t **, id_t *);
+int x86pi_bb_contains(topo_mod_t *, smbios_hdl_t *);
+int x86pi_bb_getchips(topo_mod_t *, smbios_hdl_t *, int, int);
+
+const char *x86pi_cleanup_smbios_str(topo_mod_t *, const char *, int);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _X86PI_IMPL_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/lib/fm/topo/modules/i86pc/x86pi/x86pi_subr.c	Tue Nov 03 21:14:05 2009 -0500
@@ -0,0 +1,653 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ */
+
+/*
+ *  Subroutines used by the i86pc Generic Topology Enumerator
+ */
+
+#include <sys/types.h>
+#include <strings.h>
+#include <deflt.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <fm/topo_mod.h>
+#include <fm/topo_hc.h>
+#include <sys/devfm.h>
+#include <sys/systeminfo.h>
+#include <sys/fm/protocol.h>
+#include <sys/utsname.h>
+#include <sys/smbios.h>
+#include <sys/smbios_impl.h>
+#include <x86pi_impl.h>
+
+
+static const topo_pgroup_info_t sys_pgroup = {
+	TOPO_PGROUP_SYSTEM,
+	TOPO_STABILITY_PRIVATE,
+	TOPO_STABILITY_PRIVATE,
+	1
+};
+
+static const topo_pgroup_info_t auth_pgroup = {
+	FM_FMRI_AUTHORITY,
+	TOPO_STABILITY_PRIVATE,
+	TOPO_STABILITY_PRIVATE,
+	1
+};
+
+
+/*
+ * Free hcfmri strings.
+ */
+void
+x86pi_hcfmri_info_fini(topo_mod_t *mod, x86pi_hcfmri_t *hc)
+{
+	if (hc->hc_name != NULL)
+		topo_mod_strfree(mod, (char *)hc->hc_name);
+	if (hc->manufacturer != NULL)
+		topo_mod_strfree(mod, (char *)hc->manufacturer);
+	if (hc->product != NULL)
+		topo_mod_strfree(mod, (char *)hc->product);
+	if (hc->version != NULL)
+		topo_mod_strfree(mod, (char *)hc->version);
+	if (hc->serial_number != NULL)
+		topo_mod_strfree(mod, (char *)hc->serial_number);
+	if (hc->asset_tag != NULL)
+		topo_mod_strfree(mod, (char *)hc->asset_tag);
+	if (hc->location != NULL)
+		topo_mod_strfree(mod, (char *)hc->location);
+	if (hc->part_number != NULL)
+		topo_mod_strfree(mod, (char *)hc->part_number);
+}
+
+
+/*
+ * Get the server hostname (the ID as far as the topo authority is
+ * concerned) from sysinfo and return a copy to the caller.
+ *
+ * The string must be freed with topo_mod_strfree()
+ */
+char *
+x86pi_get_serverid(topo_mod_t *mod)
+{
+	int result;
+	char hostname[MAXNAMELEN];
+
+	topo_mod_dprintf(mod, "x86pi_get_serverid\n");
+
+	result = sysinfo(SI_HOSTNAME, hostname, sizeof (hostname));
+	/* Everything is freed up and it's time to return the platform-id */
+	if (result == -1) {
+		return (NULL);
+	}
+	topo_mod_dprintf(mod, "x86pi_get_serverid: hostname = %s\n", hostname);
+
+	return (topo_mod_strdup(mod, hostname));
+}
+
+
+/*
+ * Get copy of SMBIOS.
+ */
+smbios_hdl_t *
+x86pi_smb_open(topo_mod_t *mod)
+{
+	smbios_hdl_t *smb_hdl;
+	char *f = "x86pi_smb_open";
+
+	topo_mod_dprintf(mod, "%s\n", f);
+
+	smb_hdl = topo_mod_smbios(mod);
+	if (smb_hdl == NULL) {
+		topo_mod_dprintf(mod, "%s: failed to load SMBIOS\n", f);
+		return (NULL);
+	}
+
+	return (smb_hdl);
+}
+
+
+/*
+ * Go through the smbios structures looking for a type. Fill in
+ * the structure count as well as the id(s) of the struct types.
+ */
+void
+x86pi_smb_strcnt(smbios_hdl_t *shp, smbs_cnt_t *stype)
+{
+	const smb_struct_t *sp = shp->sh_structs;
+	int nstructs = shp->sh_nstructs;
+	int i, cnt;
+
+	for (i = 0, cnt = 0; i < nstructs; i++, sp++) {
+		if (sp->smbst_hdr->smbh_type == stype->type) {
+			stype->ids[cnt].node = NULL;
+			stype->ids[cnt].id = sp->smbst_hdr->smbh_hdl;
+			cnt++;
+		}
+	}
+
+	stype->count = cnt;
+}
+
+
+/*
+ * Calculate the authority information for a node.  Inherit the data if
+ * possible, but always create an appropriate property group.
+ */
+int
+x86pi_set_auth(topo_mod_t *mod, x86pi_hcfmri_t *hcfmri, tnode_t *t_parent,
+    tnode_t *t_node)
+{
+	int 		result;
+	int		err;
+	int		is_chassis = 0;
+	int		chassis_instance = 0;
+	nvlist_t	*auth;
+	char		*val = NULL;
+	char		*prod = NULL;
+	char		*psn = NULL;
+	char		*csn = NULL;
+	char		*server = NULL;
+	char		*f = "x86pi_set_auth";
+
+	if (mod == NULL || t_parent == NULL || t_node == NULL) {
+		return (-1);
+	}
+
+	result = topo_pgroup_create(t_node, &auth_pgroup, &err);
+	if (result != 0 && err != ETOPO_PROP_DEFD) {
+		/*
+		 * We failed to create the property group and it was not
+		 * already defined.  Set the err code and return failure.
+		 */
+		topo_mod_seterrno(mod, err);
+		return (-1);
+	}
+
+	/* Get the authority information already available from the parent */
+	auth = topo_mod_auth(mod, t_parent);
+
+	/* Determnine if this is a chassis node and set it's instance */
+	if ((strlen(hcfmri->hc_name) == strlen(CHASSIS)) &&
+	    strncmp(hcfmri->hc_name, CHASSIS, strlen(CHASSIS)) == 0) {
+		is_chassis = 1;
+		chassis_instance = hcfmri->instance;
+	}
+
+	/*
+	 * Set the authority data, inheriting it if possible, but creating it
+	 * if necessary.
+	 */
+
+	/* product-id */
+	result = topo_prop_inherit(t_node, FM_FMRI_AUTHORITY,
+	    FM_FMRI_AUTH_PRODUCT, &err);
+	if (result != 0 && err != ETOPO_PROP_DEFD) {
+		result = nvlist_lookup_string(auth, FM_FMRI_AUTH_PRODUCT,
+		    &prod);
+		if (result != 0 || prod == NULL) {
+			/*
+			 * No product information in the parent node or auth
+			 * list. Use the product information in the hcfrmi
+			 * struct.
+			 */
+			prod = (char *)hcfmri->product;
+			if (prod == NULL) {
+				topo_mod_dprintf(mod, "%s: product name not "
+				    "found for %s node\n", f, hcfmri->hc_name);
+			}
+		}
+
+		/*
+		 * We continue even if the product information is not available
+		 * to enumerate as much as possible.
+		 */
+		if (prod != NULL) {
+			result = topo_prop_set_string(t_node, FM_FMRI_AUTHORITY,
+			    FM_FMRI_AUTH_PRODUCT, TOPO_PROP_IMMUTABLE, prod,
+			    &err);
+			if (result != 0) {
+				/* Preserve the error and continue */
+				topo_mod_seterrno(mod, err);
+				topo_mod_dprintf(mod, "%s: failed to set "
+				    "property %s (%d) : %s\n", f,
+				    FM_FMRI_AUTH_PRODUCT, err,
+				    topo_strerror(err));
+			}
+		}
+	}
+
+	/* product-sn */
+	result = topo_prop_inherit(t_node, FM_FMRI_AUTHORITY,
+	    FM_FMRI_AUTH_PRODUCT_SN, &err);
+	if (result != 0 && err != ETOPO_PROP_DEFD) {
+		result = nvlist_lookup_string(auth, FM_FMRI_AUTH_PRODUCT_SN,
+		    &psn);
+		if (result != 0 || psn == NULL) {
+			/*
+			 * No product-sn information in the parent node or auth
+			 * list.
+			 */
+			topo_mod_dprintf(mod, "%s: psn not found\n", f);
+		} else {
+			/*
+			 * We continue even if the product-sn information is
+			 * not available to enumerate as much as possible.
+			 */
+			result = topo_prop_set_string(t_node, FM_FMRI_AUTHORITY,
+			    FM_FMRI_AUTH_PRODUCT_SN, TOPO_PROP_IMMUTABLE, psn,
+			    &err);
+			if (result != 0) {
+				/* Preserve the error and continue */
+				topo_mod_seterrno(mod, err);
+				topo_mod_dprintf(mod, "%s: failed to "
+				    "set property %s (%d) : %s\n", f,
+				    FM_FMRI_AUTH_PRODUCT_SN, err,
+				    topo_strerror(err));
+			}
+		}
+	}
+
+	/* chassis-id */
+	if (is_chassis == 0 || (is_chassis == 1 && chassis_instance == 0)) {
+		/* either not a chassis node, or chassis #0 */
+		result = topo_prop_inherit(t_node, FM_FMRI_AUTHORITY,
+		    FM_FMRI_AUTH_CHASSIS, &err);
+	} else {
+		/* chassis 'n' in a >1 chassis system */
+		result = err = -1;
+	}
+	if (result != 0 && err != ETOPO_PROP_DEFD) {
+		if (is_chassis == 0) {
+			result = nvlist_lookup_string(auth,
+			    FM_FMRI_AUTH_CHASSIS, &csn);
+			if (result != 0 || csn == NULL) {
+				/*
+				 * No chassis information in the parent
+				 * node or auth list.
+				 */
+				topo_mod_dprintf(mod,
+				    "%s: csn name not found\n", f);
+			}
+		} else {
+			/*
+			 * So as not to blindly set the chassis-id to
+			 * chassis #0's serial number.
+			 */
+			csn = val = topo_mod_strdup(mod, hcfmri->serial_number);
+		}
+
+		/*
+		 * We continue even if the chassis information is not available
+		 * to enumerate as much as possible.
+		 */
+		if (csn != NULL) {
+			if (is_chassis == 1)
+				result = topo_prop_set_string(t_node,
+				    FM_FMRI_AUTHORITY, FM_FMRI_AUTH_CHASSIS,
+				    TOPO_PROP_MUTABLE, csn, &err);
+			else
+				result = topo_prop_set_string(t_node,
+				    FM_FMRI_AUTHORITY, FM_FMRI_AUTH_CHASSIS,
+				    TOPO_PROP_IMMUTABLE, csn, &err);
+
+			if (result != 0) {
+				/* Preserve the error and continue */
+				topo_mod_seterrno(mod, err);
+				topo_mod_dprintf(mod, "%s: failed to "
+				    "set property %s (%d) : %s\n", f,
+				    FM_FMRI_AUTH_CHASSIS, err,
+				    topo_strerror(err));
+			}
+		}
+
+		if (val != NULL) {
+			topo_mod_strfree(mod, val);
+			val = NULL;
+		}
+	}
+
+	/* server-id */
+	result = topo_prop_inherit(t_node, FM_FMRI_AUTHORITY,
+	    FM_FMRI_AUTH_SERVER, &err);
+	if (result != 0 && err != ETOPO_PROP_DEFD) {
+		result = nvlist_lookup_string(auth, FM_FMRI_AUTH_SERVER,
+		    &server);
+		if (result != 0 || server == NULL) {
+			/*
+			 * No server information in the parent node or auth
+			 * list.  Find the server information in hostname.
+			 */
+			server = val = x86pi_get_serverid(mod);
+			if (server == NULL) {
+				topo_mod_dprintf(mod, "%s: server "
+				    "name not found for %s node\n", f,
+				    hcfmri->hc_name);
+			}
+		}
+
+		/*
+		 * We continue even if the server information is not available
+		 * to enumerate as much as possible.
+		 */
+		if (server != NULL) {
+			result = topo_prop_set_string(t_node, FM_FMRI_AUTHORITY,
+			    FM_FMRI_AUTH_SERVER, TOPO_PROP_IMMUTABLE, server,
+			    &err);
+			if (result != 0) {
+				/* Preserve the error and continue */
+				topo_mod_seterrno(mod, err);
+				topo_mod_dprintf(mod, "%s: failed to "
+				    "set property %s (%d) : %s\n", f,
+				    FM_FMRI_AUTH_SERVER, err,
+				    topo_strerror(err));
+			}
+		}
+
+		if (val != NULL)
+			topo_mod_strfree(mod, val);
+	}
+
+	nvlist_free(auth);
+
+	return (0);
+}
+
+
+/*
+ * Calculate a generic FRU for the given node.  If the node is not a FRU,
+ * then inherit the FRU data from the nodes parent.
+ */
+int
+x86pi_set_frufmri(topo_mod_t *mod, x86pi_hcfmri_t *hcfmri, tnode_t *t_parent,
+    tnode_t *t_node, int flag)
+{
+	int		result;
+	int		err;
+
+	nvlist_t	*auth = NULL;
+	nvlist_t	*frufmri = NULL;
+
+	if (t_node == NULL || mod == NULL) {
+		return (-1);
+	}
+
+	/*
+	 * Determine if this node is a FRU
+	 */
+	if (!(flag & X86PI_ENUM_FRU)) {
+		/* This node is not a FRU.  Inherit from parent and return */
+		topo_node_fru_set(t_node, NULL, 0, &result);
+		return (0);
+	}
+
+	/*
+	 * This node is a FRU.  Create an FMRI.
+	 */
+	auth	= topo_mod_auth(mod, t_parent);
+	frufmri	= topo_mod_hcfmri(mod, t_parent, FM_HC_SCHEME_VERSION,
+	    hcfmri->hc_name, hcfmri->instance, NULL, auth,
+	    hcfmri->part_number, hcfmri->version, hcfmri->serial_number);
+	if (frufmri == NULL) {
+		topo_mod_dprintf(mod, "failed to create FRU: %s\n",
+		    topo_strerror(topo_mod_errno(mod)));
+	}
+	nvlist_free(auth);
+
+	/* Set the FRU, whether NULL or not */
+	result = topo_node_fru_set(t_node, frufmri, 0, &err);
+	if (result != 0)  {
+		topo_mod_seterrno(mod, err);
+	}
+	nvlist_free(frufmri);
+
+	return (result);
+}
+
+
+/*
+ * Set the label for a topo node.
+ */
+int
+x86pi_set_label(topo_mod_t *mod, const char *label, const char *name,
+    tnode_t *t_node)
+{
+	int	result;
+	int	err;
+
+	if (mod == NULL) {
+		return (-1);
+	}
+
+	/*
+	 * Set the label for this topology node.
+	 * Note that a NULL label will inherit the label from topology
+	 * node's parent.
+	 */
+	result = topo_node_label_set(t_node, (char *)label, &err);
+	if (result != 0) {
+		topo_mod_seterrno(mod, err);
+		topo_mod_dprintf(mod, "x86pi_set_label: failed with label %s "
+		    "on %s node: %s\n", (label == NULL ? "NULL" : label),
+		    name, topo_strerror(err));
+	}
+
+	return (result);
+}
+
+
+/*
+ * Calculate the system information for a node.  Inherit the data if
+ * possible, but always create an appropriate property group.
+ */
+int
+x86pi_set_system(topo_mod_t *mod, tnode_t *t_node)
+{
+	int		result;
+	int		err;
+	struct utsname	uts;
+	char		isa[MAXNAMELEN];
+
+	if (mod == NULL || t_node == NULL) {
+		return (-1);
+	}
+
+	result = topo_pgroup_create(t_node, &sys_pgroup, &err);
+	if (result != 0 && err != ETOPO_PROP_DEFD) {
+		/*
+		 * We failed to create the property group and it was not
+		 * already defined.  Set the err code and return failure.
+		 */
+		topo_mod_seterrno(mod, err);
+		return (-1);
+	}
+
+	result = topo_prop_inherit(t_node, TOPO_PGROUP_SYSTEM, TOPO_PROP_ISA,
+	    &err);
+	if (result != 0 && err != ETOPO_PROP_DEFD) {
+		isa[0] = '\0';
+		result = sysinfo(SI_ARCHITECTURE, isa, sizeof (isa));
+		if (result == -1) {
+			/* Preserve the error and continue */
+			topo_mod_dprintf(mod, "x86pi_set_system: failed to "
+			    "read SI_ARCHITECTURE: %d\n", errno);
+		}
+		if (strnlen(isa, MAXNAMELEN) > 0) {
+			result = topo_prop_set_string(t_node,
+			    TOPO_PGROUP_SYSTEM, TOPO_PROP_ISA,
+			    TOPO_PROP_IMMUTABLE, isa, &err);
+			if (result != 0) {
+				/* Preserve the error and continue */
+				topo_mod_seterrno(mod, err);
+				topo_mod_dprintf(mod,
+				    "x86pi_set_auth: failed to "
+				    "set property %s (%d) : %s\n",
+				    TOPO_PROP_ISA, err, topo_strerror(err));
+			}
+		}
+	}
+
+	result = topo_prop_inherit(t_node, TOPO_PGROUP_SYSTEM,
+	    TOPO_PROP_MACHINE, &err);
+	if (result != 0 && err != ETOPO_PROP_DEFD) {
+		result = uname(&uts);
+		if (result == -1) {
+			/* Preserve the error and continue */
+			topo_mod_seterrno(mod, errno);
+			topo_mod_dprintf(mod, "x86pi_set_system: failed to "
+			    "read uname: %d\n", errno);
+		}
+		if (strnlen(uts.machine, sizeof (uts.machine)) > 0) {
+			result = topo_prop_set_string(t_node,
+			    TOPO_PGROUP_SYSTEM, TOPO_PROP_MACHINE,
+			    TOPO_PROP_IMMUTABLE, uts.machine, &err);
+			if (result != 0) {
+				/* Preserve the error and continue */
+				topo_mod_seterrno(mod, err);
+				topo_mod_dprintf(mod,
+				    "x86pi_set_auth: failed to "
+				    "set property %s (%d) : %s\n",
+				    TOPO_PROP_MACHINE, err, topo_strerror(err));
+			}
+		}
+	}
+
+	return (0);
+}
+
+/*
+ * All the checks for compatibility are done within the kernel where the
+ * ereport generators are. They'll determine first if there's a problem
+ * and the topo enum will follow suit. The /dev/fm ioclt returns the value
+ * of the x86gentopo_legacy kernel variable which determines if this platform
+ * will provide an x86 generic topo or legacy topo enumeration.
+ */
+/* ARGSUSED */
+int
+x86pi_check_comp(topo_mod_t *mod, smbios_hdl_t *shp)
+{
+	int rv;
+	int fd;
+	int32_t legacy;
+	nvlist_t *nvl = NULL;
+	fm_ioc_data_t fid;
+	char *ibuf = NULL, *obuf = NULL;
+	size_t insz = 0, outsz = 0;
+	char *f = "x86pi_check_comp";
+
+	/* open /dev/fm */
+	fd = open("/dev/fm", O_RDONLY);
+	if (fd < 0) {
+		topo_mod_dprintf(mod, "%s: failed to open /dev/fm.\n", f);
+		return (X86PI_NONE);
+	}
+
+	/* set up buffers and ioctl data structure */
+	outsz = FM_IOC_MAXBUFSZ;
+	obuf = topo_mod_alloc(mod, outsz);
+	if (obuf == NULL) {
+		perror("umem_alloc");
+		return (X86PI_NONE);
+	}
+
+	fid.fid_version = 1;
+	fid.fid_insz = insz;
+	fid.fid_inbuf = ibuf;
+	fid.fid_outsz = outsz;
+	fid.fid_outbuf = obuf;
+
+	/* send the ioctl to /dev/fm to retrieve legacy variable */
+	rv = ioctl(fd, FM_IOC_GENTOPO_LEGACY, &fid);
+	if (rv < 0) {
+		topo_mod_dprintf(mod, "%s: ioctl to /dev/fm failed", f);
+		perror("fm_ioctl");
+		(void) close(fd);
+		return (X86PI_NONE);
+	}
+	(void) close(fd);
+
+	(void) nvlist_unpack(fid.fid_outbuf, fid.fid_outsz, &nvl, 0);
+	(void) nvlist_lookup_int32(nvl, FM_GENTOPO_LEGACY, &legacy);
+
+	nvlist_free(nvl);
+	topo_mod_free(mod, obuf, outsz);
+
+	if (legacy == 1) {
+		/* legacy kernel variable set; will do the same */
+		return (X86PI_NONE);
+	}
+
+	/* legacy kernel variable not set; generic topo enum */
+	return (X86PI_FULL);
+}
+
+const char *
+x86pi_cleanup_smbios_str(topo_mod_t *mod, const char *begin, int str_type)
+{
+	char buf[MAXNAMELEN];
+	const char *end, *cp;
+	char *pp;
+	char c;
+	int i;
+
+	end = begin + strlen(begin);
+
+	while (begin < end && isspace(*begin))
+		begin++;
+	while (begin < end && isspace(*(end - 1)))
+		end--;
+
+	if (begin >= end)
+		return (NULL);
+
+	cp = begin;
+	for (i = 0; i < MAXNAMELEN - 1; i++) {
+		if (cp >= end)
+			break;
+		c = *cp;
+		if (str_type == LABEL) {
+			if (!isprint(c))
+				buf[i] = '-';
+			else
+				buf[i] = c;
+		} else {
+			if (c == ':' || c == '=' || c == '/' ||
+			    isspace(c) || !isprint(c))
+				buf[i] = '-';
+			else
+				buf[i] = c;
+		}
+		cp++;
+	}
+	buf[i] = 0;
+
+	pp = topo_mod_strdup(mod, buf);
+
+	if (str_type == LABEL)
+		topo_mod_strfree(mod, (char *)begin);
+
+	return (pp);
+}
--- a/usr/src/lib/libsmbios/common/mapfile-vers	Tue Nov 03 17:06:24 2009 -0800
+++ b/usr/src/lib/libsmbios/common/mapfile-vers	Tue Nov 03 21:14:05 2009 -0500
@@ -81,26 +81,32 @@
 	smbios_info_cache;
 	smbios_info_chassis;
 	smbios_info_common;
+	smbios_info_contains;
 	smbios_info_eventlog;
 	smbios_info_hwsec;
 	smbios_info_ipmi;
 	smbios_info_lang;
 	smbios_info_memarray;
+	smbios_info_extmemarray;
 	smbios_info_memarrmap;
 	smbios_info_memdevice;
+	smbios_info_extmemdevice;
 	smbios_info_memdevmap;
 	smbios_info_obdevs;
 	smbios_info_port;
 	smbios_info_processor;
+	smbios_info_extprocessor;
 	smbios_info_slot;
 	smbios_info_smbios;
 	smbios_info_strtab;
 	smbios_info_system;
+	smbios_info_pciexrc;
 	smbios_ipmi_flag_desc;
 	smbios_ipmi_flag_name;
 	smbios_ipmi_type_desc;
 	smbios_iter;
 	smbios_lookup_id;
+	smbios_lookup_type;
 	smbios_memarray_ecc_desc;
 	smbios_memarray_loc_desc;
 	smbios_memarray_use_desc;
--- a/usr/src/pkgdefs/SUNWfmd/prototype_i386	Tue Nov 03 17:06:24 2009 -0800
+++ b/usr/src/pkgdefs/SUNWfmd/prototype_i386	Tue Nov 03 21:14:05 2009 -0500
@@ -82,11 +82,13 @@
 f none usr/platform/i86pc/lib/fm/topo/plugins/chip.so 555 root bin
 f none usr/platform/i86pc/lib/fm/topo/plugins/hostbridge.so 555 root bin
 f none usr/platform/i86pc/lib/fm/topo/plugins/pcibus.so 555 root bin
+f none usr/platform/i86pc/lib/fm/topo/plugins/x86pi.so 555 root bin
 d none usr/platform/i86pc/lib/fm/topo/maps 755 root bin
 f none usr/platform/i86pc/lib/fm/topo/maps/chassis-hc-topology.xml 444 root bin
 f none usr/platform/i86pc/lib/fm/topo/maps/chip-hc-topology.xml 444 root bin
 f none usr/platform/i86pc/lib/fm/topo/maps/fan-hc-topology.xml 444 root bin
 f none usr/platform/i86pc/lib/fm/topo/maps/i86pc-hc-topology.xml 444 root bin
+f none usr/platform/i86pc/lib/fm/topo/maps/i86pc-legacy-hc-topology.xml 444 root bin
 f none usr/platform/i86pc/lib/fm/topo/maps/psu-hc-topology.xml 444 root bin
 f none usr/platform/i86pc/lib/fm/topo/maps/Sun-Fire-X4200-M2-disk-hc-topology.xml 444 root bin
 f none usr/platform/i86pc/lib/fm/topo/maps/Sun-Fire-X4200-Server-disk-hc-topology.xml 444 root bin
--- a/usr/src/uts/common/io/devfm.c	Tue Nov 03 17:06:24 2009 -0800
+++ b/usr/src/uts/common/io/devfm.c	Tue Nov 03 21:14:05 2009 -0500
@@ -19,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -44,6 +44,7 @@
 #if defined(__x86)
 extern int fm_ioctl_physcpu_info(int, nvlist_t *, nvlist_t **);
 extern int fm_ioctl_cpu_retire(int, nvlist_t *, nvlist_t **);
+extern int fm_ioctl_gentopo_legacy(int, nvlist_t *, nvlist_t **);
 #endif /* __x86 */
 
 static int fm_ioctl_versions(int, nvlist_t *, nvlist_t **);
@@ -73,6 +74,7 @@
 	{ FM_PAGE_OP_VERSION, 1 },
 	{ FM_CPU_OP_VERSION, 1 },
 	{ FM_CPU_INFO_VERSION, 1 },
+	{ FM_TOPO_LEGACY_VERSION, 1 },
 	{ NULL, 0 }
 };
 
@@ -93,6 +95,8 @@
 	    fm_ioctl_cpu_retire },
 	{ FM_IOC_CPU_UNRETIRE, B_TRUE, FM_CPU_OP_VERSION,
 	    fm_ioctl_cpu_retire },
+	{ FM_IOC_GENTOPO_LEGACY, B_FALSE, FM_TOPO_LEGACY_VERSION,
+	    fm_ioctl_gentopo_legacy },
 #endif	/* __x86 */
 	{ -1, B_FALSE, NULL, NULL },
 };
--- a/usr/src/uts/common/os/fm.c	Tue Nov 03 17:06:24 2009 -0800
+++ b/usr/src/uts/common/os/fm.c	Tue Nov 03 21:14:05 2009 -0500
@@ -1269,3 +1269,102 @@
 	uprintf("Killed process %d (%s) in contract id %d "
 	    "due to hardware error\n", p->p_pid, p->p_user.u_comm, ct_id);
 }
+
+void
+fm_fmri_hc_create(nvlist_t *fmri, int version, const nvlist_t *auth,
+    nvlist_t *snvl, nvlist_t *bboard, int npairs, ...)
+{
+	nv_alloc_t *nva = nvlist_lookup_nv_alloc(fmri);
+	nvlist_t *pairs[HC_MAXPAIRS];
+	nvlist_t **hcl;
+	uint_t n;
+	int i, j;
+	va_list ap;
+	char *hcname, *hcid;
+
+	if (!fm_fmri_hc_set_common(fmri, version, auth))
+		return;
+
+	/*
+	 * copy the bboard nvpairs to the pairs array
+	 */
+	if (nvlist_lookup_nvlist_array(bboard, FM_FMRI_HC_LIST, &hcl, &n)
+	    != 0) {
+		atomic_add_64(&erpt_kstat_data.fmri_set_failed.value.ui64, 1);
+		return;
+	}
+
+	for (i = 0; i < n; i++) {
+		if (nvlist_lookup_string(hcl[i], FM_FMRI_HC_NAME,
+		    &hcname) != 0) {
+			atomic_add_64(
+			    &erpt_kstat_data.fmri_set_failed.value.ui64, 1);
+			return;
+		}
+		if (nvlist_lookup_string(hcl[i], FM_FMRI_HC_ID, &hcid) != 0) {
+			atomic_add_64(
+			    &erpt_kstat_data.fmri_set_failed.value.ui64, 1);
+			return;
+		}
+
+		pairs[i] = fm_nvlist_create(nva);
+		if (nvlist_add_string(pairs[i], FM_FMRI_HC_NAME, hcname) != 0 ||
+		    nvlist_add_string(pairs[i], FM_FMRI_HC_ID, hcid) != 0) {
+			for (j = 0; j <= i; j++) {
+				if (pairs[j] != NULL)
+					fm_nvlist_destroy(pairs[j],
+					    FM_NVA_RETAIN);
+			}
+			atomic_add_64(
+			    &erpt_kstat_data.fmri_set_failed.value.ui64, 1);
+			return;
+		}
+	}
+
+	/*
+	 * create the pairs from passed in pairs
+	 */
+	npairs = MIN(npairs, HC_MAXPAIRS);
+
+	va_start(ap, npairs);
+	for (i = n; i < npairs + n; i++) {
+		const char *name = va_arg(ap, const char *);
+		uint32_t id = va_arg(ap, uint32_t);
+		char idstr[11];
+		(void) snprintf(idstr, sizeof (idstr), "%u", id);
+		pairs[i] = fm_nvlist_create(nva);
+		if (nvlist_add_string(pairs[i], FM_FMRI_HC_NAME, name) != 0 ||
+		    nvlist_add_string(pairs[i], FM_FMRI_HC_ID, idstr) != 0) {
+			for (j = 0; j <= i; j++) {
+				if (pairs[j] != NULL)
+					fm_nvlist_destroy(pairs[j],
+					    FM_NVA_RETAIN);
+			}
+			atomic_add_64(
+			    &erpt_kstat_data.fmri_set_failed.value.ui64, 1);
+			return;
+		}
+	}
+	va_end(ap);
+
+	/*
+	 * Create the fmri hc list
+	 */
+	if (nvlist_add_nvlist_array(fmri, FM_FMRI_HC_LIST, pairs,
+	    npairs + n) != 0) {
+		atomic_add_64(&erpt_kstat_data.fmri_set_failed.value.ui64, 1);
+		return;
+	}
+
+	for (i = 0; i < npairs + n; i++) {
+			fm_nvlist_destroy(pairs[i], FM_NVA_RETAIN);
+	}
+
+	if (snvl != NULL) {
+		if (nvlist_add_nvlist(fmri, FM_FMRI_HC_SPECIFIC, snvl) != 0) {
+			atomic_add_64(
+			    &erpt_kstat_data.fmri_set_failed.value.ui64, 1);
+			return;
+		}
+	}
+}
--- a/usr/src/uts/common/sys/devfm.h	Tue Nov 03 17:06:24 2009 -0800
+++ b/usr/src/uts/common/sys/devfm.h	Tue Nov 03 21:14:05 2009 -0500
@@ -19,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -40,6 +40,7 @@
 #define	FM_PAGE_OP_VERSION	"page-operation-version"
 #define	FM_CPU_OP_VERSION	"cpu-operation-version"
 #define	FM_CPU_INFO_VERSION	"cpu-info-version"
+#define	FM_TOPO_LEGACY_VERSION	"topo-legacy-version"
 
 /*
  * FMA driver ioctl interfaces
@@ -55,6 +56,7 @@
 #define	FM_IOC_CPU_RETIRE	(FM_IOC | 6)
 #define	FM_IOC_CPU_STATUS	(FM_IOC | 7)
 #define	FM_IOC_CPU_UNRETIRE	(FM_IOC | 8)
+#define	FM_IOC_GENTOPO_LEGACY	(FM_IOC | 9)
 #endif	/* __x86 */
 
 /*
@@ -87,6 +89,7 @@
 #define	FM_CPU_RETIRE_CORE_ID	"core_id"
 #define	FM_CPU_RETIRE_STRAND_ID	"strand_id"
 #define	FM_CPU_RETIRE_OLDSTATUS	"oldstatus"
+#define	FM_GENTOPO_LEGACY	"gentopolegacy"
 
 /*
  * Properties set by FM_PHYSCPU_INFO
@@ -95,9 +98,21 @@
 #define	FM_PHYSCPU_INFO_FAMILY		"family"
 #define	FM_PHYSCPU_INFO_MODEL		"model"
 #define	FM_PHYSCPU_INFO_STEPPING	"stepping"
+
+/*
+ * When Multi-Chip-Module(MCM) support is added
+ * chip_id should map to the processor package
+ * and not the die in the processor package.
+ * This is for FMA; kernel's perception of
+ * chip_id could differ for MCM.
+ */
 #define	FM_PHYSCPU_INFO_CHIP_ID		"chip_id"
+
 #define	FM_PHYSCPU_INFO_CORE_ID		"core_id"
 #define	FM_PHYSCPU_INFO_STRAND_ID	"strand_id"
+#define	FM_PHYSCPU_INFO_STRAND_APICID	"strand_initial_apicid"
+#define	FM_PHYSCPU_INFO_SMBIOS_ID	"smbios_id"
+#define	FM_PHYSCPU_INFO_CHIP_ROOTS	"chip_roots"
 #define	FM_PHYSCPU_INFO_CHIP_REV	"chip_rev"
 #define	FM_PHYSCPU_INFO_SOCKET_TYPE	"socket_type"
 #define	FM_PHYSCPU_INFO_CPU_ID		"cpuid"
--- a/usr/src/uts/common/sys/fm/protocol.h	Tue Nov 03 17:06:24 2009 -0800
+++ b/usr/src/uts/common/sys/fm/protocol.h	Tue Nov 03 21:14:05 2009 -0500
@@ -323,6 +323,8 @@
 extern void fm_authority_set(nvlist_t *, int, const char *, const char *,
     const char *, const char *);
 extern void fm_fmri_zfs_set(nvlist_t *, int, uint64_t, uint64_t);
+extern void fm_fmri_hc_create(nvlist_t *, int, const nvlist_t *, nvlist_t *,
+    nvlist_t *, int, ...);
 
 extern uint64_t fm_ena_increment(uint64_t);
 extern uint64_t fm_ena_generate(uint64_t, uchar_t);
--- a/usr/src/uts/common/sys/smbios.h	Tue Nov 03 17:06:24 2009 -0800
+++ b/usr/src/uts/common/sys/smbios.h	Tue Nov 03 21:14:05 2009 -0500
@@ -126,6 +126,10 @@
 #define	SMB_TYPE_EOT		127	/* end of table */
 
 #define	SMB_TYPE_OEM_LO		128	/* start of OEM-specific type range */
+#define	SUN_OEM_EXT_PROCESSOR	132	/* processor extended info */
+#define	SUN_OEM_PCIEXRC		138	/* PCIE RootComplex/RootPort info */
+#define	SUN_OEM_EXT_MEMARRAY	144	/* phys memory array extended info */
+#define	SUN_OEM_EXT_MEMDEVICE	145	/* memory device extended info */
 #define	SMB_TYPE_OEM_HI		256	/* end of OEM-specific type range */
 
 /*
@@ -160,6 +164,10 @@
 	uint8_t smbv_minor;		/* version minor number */
 } smbios_version_t;
 
+#define	SMB_CONT_BYTE	1		/* contained elements are byte size */
+#define	SMB_CONT_WORD	2		/* contained elements are word size */
+#define	SMB_CONT_MAX	255		/* maximum contained objects */
+
 /*
  * SMBIOS Bios Information.  See DSP0134 Section 3.3.1 for more information.
  * smbb_romsize is converted from the implementation format into bytes.
@@ -261,6 +269,7 @@
 	id_t smbb_chassis;		/* chassis containing this board */
 	uint8_t smbb_flags;		/* flags (see below) */
 	uint8_t smbb_type;		/* board type (see below) */
+	uint8_t smbb_contn;		/* number of contained object hdls */
 } smbios_bboard_t;
 
 #define	SMB_BBFL_MOTHERBOARD	0x01	/* board is a motherboard */
@@ -286,8 +295,6 @@
 /*
  * SMBIOS Chassis description.  See DSP0134 Section 3.3.4 for more information.
  * We move the lock bit of the type field into smbc_lock for easier processing.
- * NOTE: We do not currently export the contained element data for each chassis
- * as this seems useless: see DSP0134 3.3.4.4.  It can be added if necessary.
  */
 typedef struct smbios_chassis {
 	uint32_t smbc_oemdata;		/* OEM-specific data */
@@ -299,7 +306,8 @@
 	uint8_t smbc_security;		/* security status */
 	uint8_t smbc_uheight;		/* enclosure height in U's */
 	uint8_t smbc_cords;		/* number of power cords */
-	uint8_t smbc_elems;		/* number of element records */
+	uint8_t smbc_elems;		/* number of element records (n) */
+	uint8_t smbc_elemlen;		/* length of contained element (m) */
 } smbios_chassis_t;
 
 #define	SMB_CHT_OTHER		0x01	/* other */
@@ -1071,6 +1079,43 @@
 #define	SMB_IPMI_F_INTREDGE	0x08	/* intr is edge triggered (else lvl) */
 
 /*
+ * SMBIOS OEM-specific (Type 132) Processor Extended Information.
+ */
+typedef struct smbios_processor_ext {
+	uint16_t smbpe_processor;	/* extending processor handle */
+	uint8_t smbpe_fru;		/* FRU indicaor */
+	uint8_t smbpe_n;		/* number of APIC IDs */
+	uint16_t *smbpe_apicid;		/* strand Inital APIC IDs */
+} smbios_processor_ext_t;
+
+/*
+ * SMBIOS OEM-specific (Type 138) PCI-Express RC/RP Information.
+ */
+typedef struct smbios_pciexrc {
+	uint16_t smbpcie_bb;		/* base board handle */
+	uint16_t smbpcie_bdf;		/* Bus/Dev/Funct (PCI) */
+} smbios_pciexrc_t;
+
+/*
+ * SMBIOS OEM-specific (Type 144) Memory Array Extended Information.
+ */
+typedef struct smbios_memarray_ext {
+	uint16_t smbmae_ma;		/* memory array handle */
+	uint16_t smbmae_comp;		/* component parent handle */
+	uint16_t smbmae_bdf;		/* Bus/Dev/Funct (PCI) */
+} smbios_memarray_ext_t;
+
+/*
+ * SMBIOS OEM-specific (Type 145) Memory Device Extended Information.
+ */
+typedef struct smbios_memdevice_ext {
+	uint16_t smbmdeve_md;		/* memory device handle */
+	uint8_t smbmdeve_drch;		/* DRAM channel */
+	uint8_t smbmdeve_ncs;		/* number of chip selects */
+	uint8_t *smbmdeve_cs;		/* array of chip select numbers */
+} smbios_memdevice_ext_t;
+
+/*
  * SMBIOS Interfaces.  An SMBIOS image can be opened by either providing a file
  * pathname, device pathname, file descriptor, or raw memory buffer.  Once an
  * image is opened the functions below can be used to iterate over the various
@@ -1123,15 +1168,19 @@
 extern const char *smbios_errmsg(int);
 
 extern int smbios_lookup_id(smbios_hdl_t *, id_t, smbios_struct_t *);
+extern int smbios_lookup_type(smbios_hdl_t *, uint_t, smbios_struct_t *);
 extern int smbios_iter(smbios_hdl_t *, smbios_struct_f *, void *);
 
 extern void smbios_info_smbios(smbios_hdl_t *, smbios_entry_t *);
 extern int smbios_info_common(smbios_hdl_t *, id_t, smbios_info_t *);
+extern int smbios_info_contains(smbios_hdl_t *, id_t, uint_t, id_t *);
 extern id_t smbios_info_bios(smbios_hdl_t *, smbios_bios_t *);
 extern id_t smbios_info_system(smbios_hdl_t *, smbios_system_t *);
 extern int smbios_info_bboard(smbios_hdl_t *, id_t, smbios_bboard_t *);
 extern int smbios_info_chassis(smbios_hdl_t *, id_t, smbios_chassis_t *);
 extern int smbios_info_processor(smbios_hdl_t *, id_t, smbios_processor_t *);
+extern int smbios_info_extprocessor(smbios_hdl_t *, id_t,
+    smbios_processor_ext_t *);
 extern int smbios_info_cache(smbios_hdl_t *, id_t, smbios_cache_t *);
 extern int smbios_info_port(smbios_hdl_t *, id_t, smbios_port_t *);
 extern int smbios_info_slot(smbios_hdl_t *, id_t, smbios_slot_t *);
@@ -1140,12 +1189,17 @@
 extern id_t smbios_info_lang(smbios_hdl_t *, smbios_lang_t *);
 extern id_t smbios_info_eventlog(smbios_hdl_t *, smbios_evlog_t *);
 extern int smbios_info_memarray(smbios_hdl_t *, id_t, smbios_memarray_t *);
+extern int smbios_info_extmemarray(smbios_hdl_t *, id_t,
+    smbios_memarray_ext_t *);
 extern int smbios_info_memarrmap(smbios_hdl_t *, id_t, smbios_memarrmap_t *);
 extern int smbios_info_memdevice(smbios_hdl_t *, id_t, smbios_memdevice_t *);
+extern int smbios_info_extmemdevice(smbios_hdl_t *, id_t,
+    smbios_memdevice_ext_t *);
 extern int smbios_info_memdevmap(smbios_hdl_t *, id_t, smbios_memdevmap_t *);
 extern id_t smbios_info_hwsec(smbios_hdl_t *, smbios_hwsec_t *);
 extern id_t smbios_info_boot(smbios_hdl_t *, smbios_boot_t *);
 extern id_t smbios_info_ipmi(smbios_hdl_t *, smbios_ipmi_t *);
+extern int smbios_info_pciexrc(smbios_hdl_t *, id_t, smbios_pciexrc_t *);
 
 extern const char *smbios_psn(smbios_hdl_t *);
 extern const char *smbios_csn(smbios_hdl_t *);
--- a/usr/src/uts/common/sys/smbios_impl.h	Tue Nov 03 17:06:24 2009 -0800
+++ b/usr/src/uts/common/sys/smbios_impl.h	Tue Nov 03 21:14:05 2009 -0500
@@ -2,9 +2,8 @@
  * CDDL HEADER START
  *
  * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
  *
  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  * or http://www.opensolaris.org/os/licensing.
@@ -21,7 +20,7 @@
  */
 
 /*
- * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -36,8 +35,6 @@
 #ifndef	_SYS_SMBIOS_IMPL_H
 #define	_SYS_SMBIOS_IMPL_H
 
-#pragma ident	"%Z%%M%	%I%	%E% SMI"
-
 #include <sys/smbios.h>
 #include <sys/sysmacros.h>
 
@@ -360,6 +357,35 @@
 	uint16_t smbpsup_iprobe;	/* current probe handle */
 } smb_powersup_t;
 
+typedef struct smb_processor_ext {
+	smb_header_t smbpre_hdr;	/* structure header */
+	uint16_t smbpre_processor;	/* processor handle */
+	uint8_t smbpre_fru;		/* FRU indicator */
+	uint8_t smbpre_n;		/* number of APIC IDs */
+	uint16_t smbpre_apicid[1];	/* strand initial apic id */
+} smb_processor_ext_t;
+
+typedef struct smb_pciexrc {
+	smb_header_t smbpciexrc_hdr;	/* structure header */
+	uint16_t smbpciexrc_bboard;	/* base board handle */
+	uint16_t smbpciexrc_bdf;	/* PCI Bus/Dev/Func */
+} smb_pciexrc_t;
+
+typedef struct smb_memarray_ext {
+	smb_header_t smbmarre_hdr;	/* structure header */
+	uint16_t smbmarre_ma;		/* memory array handle */
+	uint16_t smbmarre_component;	/* component parent handle */
+	uint16_t smbmarre_bdf;		/* PCI bus/dev/funct */
+} smb_memarray_ext_t;
+
+typedef struct smb_memdevice_ext {
+	smb_header_t smbmdeve_hdr;	/* structure header */
+	uint16_t smbmdeve_mdev;		/* memory device handle */
+	uint8_t smbmdeve_dchan;		/* DRAM channel */
+	uint8_t smbmdeve_ncs;		/* number of chip select */
+	uint8_t smbmdeve_cs[1];		/* chip selects */
+} smb_memdevice_ext_t;
+
 #pragma pack()
 
 typedef struct smb_struct {
--- a/usr/src/uts/i86pc/cpu/amd_opteron/ao_mca.c	Tue Nov 03 17:06:24 2009 -0800
+++ b/usr/src/uts/i86pc/cpu/amd_opteron/ao_mca.c	Tue Nov 03 21:14:05 2009 -0500
@@ -20,7 +20,7 @@
  */
 
 /*
- * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -48,6 +48,7 @@
 #include <sys/fm/util.h>
 #include <sys/fm/protocol.h>
 #include <sys/fm/cpu/AMD.h>
+#include <sys/fm/smb/fmsmb.h>
 #include <sys/acpi/acpi.h>
 #include <sys/acpi/acpi_pci.h>
 #include <sys/acpica.h>
@@ -60,6 +61,8 @@
 
 int ao_mca_smi_disable = 1;		/* attempt to disable SMI polling */
 
+extern int x86gentopo_legacy;	/* x86 generic topology support */
+
 struct ao_ctl_init {
 	uint32_t ctl_revmask;	/* rev(s) to which this applies */
 	uint64_t ctl_bits;	/* mca ctl reg bitmask to set */
@@ -617,9 +620,11 @@
 }
 
 static nvlist_t *
-ao_ereport_create_resource_elem(nv_alloc_t *nva, mc_unum_t *unump, int dimmnum)
+ao_ereport_create_resource_elem(cmi_hdl_t hdl, nv_alloc_t *nva,
+    mc_unum_t *unump, int dimmnum)
 {
 	nvlist_t *nvl, *snvl;
+	nvlist_t *board_list = NULL;
 
 	if ((nvl = fm_nvlist_create(nva)) == NULL)	/* freed by caller */
 		return (NULL);
@@ -632,12 +637,31 @@
 	(void) nvlist_add_uint64(snvl, FM_FMRI_HC_SPECIFIC_OFFSET,
 	    unump->unum_offset);
 
-	fm_fmri_hc_set(nvl, FM_HC_SCHEME_VERSION, NULL, snvl, 5,
-	    "motherboard", unump->unum_board,
-	    "chip", unump->unum_chip,
-	    "memory-controller", unump->unum_mc,
-	    "dimm", unump->unum_dimms[dimmnum],
-	    "rank", unump->unum_rank);
+	if (!x86gentopo_legacy) {
+		board_list = cmi_hdl_smb_bboard(hdl);
+
+		if (board_list == NULL) {
+			fm_nvlist_destroy(nvl,
+			    nva ? FM_NVA_RETAIN : FM_NVA_FREE);
+			fm_nvlist_destroy(snvl,
+			    nva ? FM_NVA_RETAIN : FM_NVA_FREE);
+			return (NULL);
+		}
+
+		fm_fmri_hc_create(nvl, FM_HC_SCHEME_VERSION, NULL, snvl,
+		    board_list, 4,
+		    "chip", cmi_hdl_smb_chipid(hdl),
+		    "memory-controller", unump->unum_mc,
+		    "dimm", unump->unum_dimms[dimmnum],
+		    "rank", unump->unum_rank);
+	} else {
+		fm_fmri_hc_set(nvl, FM_HC_SCHEME_VERSION, NULL, snvl, 5,
+		    "motherboard", unump->unum_board,
+		    "chip", unump->unum_chip,
+		    "memory-controller", unump->unum_mc,
+		    "dimm", unump->unum_dimms[dimmnum],
+		    "rank", unump->unum_rank);
+	}
 
 	fm_nvlist_destroy(snvl, nva ? FM_NVA_RETAIN : FM_NVA_FREE);
 
@@ -645,7 +669,8 @@
 }
 
 static void
-ao_ereport_add_resource(nvlist_t *payload, nv_alloc_t *nva, mc_unum_t *unump)
+ao_ereport_add_resource(cmi_hdl_t hdl, nvlist_t *payload, nv_alloc_t *nva,
+    mc_unum_t *unump)
 {
 
 	nvlist_t *elems[MC_UNUM_NDIMM];
@@ -656,7 +681,7 @@
 		if (unump->unum_dimms[i] == MC_INVALNUM)
 			break;
 
-		if ((elems[nelems] = ao_ereport_create_resource_elem(nva,
+		if ((elems[nelems] = ao_ereport_create_resource_elem(hdl, nva,
 		    unump, i)) == NULL)
 			break;
 
@@ -711,7 +736,7 @@
 		    cmi_mc_patounum(addr, aed->aed_addrvalid_hi,
 		    aed->aed_addrvalid_lo, synd, syndtype, &unum) ==
 		    CMI_SUCCESS)
-			ao_ereport_add_resource(ereport, nva, &unum);
+			ao_ereport_add_resource(hdl, ereport, nva, &unum);
 	}
 }
 
--- a/usr/src/uts/i86pc/cpu/authenticamd/authamd_main.c	Tue Nov 03 17:06:24 2009 -0800
+++ b/usr/src/uts/i86pc/cpu/authenticamd/authamd_main.c	Tue Nov 03 21:14:05 2009 -0500
@@ -44,6 +44,8 @@
 #include <sys/mc_amd.h>
 #include <sys/fm/protocol.h>
 #include <sys/fm/cpu/GENAMD.h>
+#include <sys/fm/smb/fmsmb.h>
+#include <sys/fm/util.h>
 #include <sys/nvpair.h>
 #include <sys/controlregs.h>
 #include <sys/pghw.h>
@@ -53,6 +55,8 @@
 
 #include "authamd.h"
 
+extern int x86gentopo_legacy; /* x86 generic topo support */
+
 int authamd_ms_support_disable = 0;
 
 #define	AUTHAMD_F_REVS_BCDE \
@@ -982,6 +986,7 @@
 	nvlist_t *nvl;
 	int nelems = 0;
 	int i, chan, cs;
+	nvlist_t *board_list = NULL;
 
 	if ((msl = mslogout) == NULL)
 		return;
@@ -997,12 +1002,25 @@
 			elems[nelems] = nvl;
 			counts[nelems++] = msl->aal_eccerrcnt[chan][cs];
 
-			fm_fmri_hc_set(nvl, FM_HC_SCHEME_VERSION, NULL, NULL, 5,
-			    "motherboard", 0,
-			    "chip", authamd->amd_shared->acs_chipid,
-			    "memory-controller", 0,
-			    "dram-channel", chan,
-			    "chip-select", cs);
+			if (!x86gentopo_legacy) {
+				board_list = cmi_hdl_smb_bboard(hdl);
+				if (board_list == NULL)
+					continue;
+				fm_fmri_hc_create(nvl, FM_HC_SCHEME_VERSION,
+				    NULL, NULL, board_list, 4,
+				    "chip", cmi_hdl_smb_chipid(hdl),
+				    "memory-controller", 0,
+				    "dram-channel", chan,
+				    "chip-select", cs);
+			} else {
+				fm_fmri_hc_set(nvl, FM_HC_SCHEME_VERSION,
+				    NULL, NULL, 5,
+				    "motherboard", 0,
+				    "chip", authamd->amd_shared->acs_chipid,
+				    "memory-controller", 0,
+				    "dram-channel", chan,
+				    "chip-select", cs);
+			}
 		}
 	}
 
--- a/usr/src/uts/i86pc/cpu/generic_cpu/gcpu_mca.c	Tue Nov 03 17:06:24 2009 -0800
+++ b/usr/src/uts/i86pc/cpu/generic_cpu/gcpu_mca.c	Tue Nov 03 21:14:05 2009 -0500
@@ -43,11 +43,14 @@
 #include <sys/errorq.h>
 #include <sys/mca_x86.h>
 #include <sys/fm/cpu/GMCA.h>
+#include <sys/fm/smb/fmsmb.h>
 #include <sys/sysevent.h>
 #include <sys/ontrap.h>
 
 #include "gcpu.h"
 
+extern int x86gentopo_legacy;	/* x86 generic topology support */
+
 /*
  * Clear to log telemetry found at initialization.  While processor docs
  * say you should process this telemetry on all but Intel family 0x6
@@ -501,16 +504,28 @@
 static nvlist_t *
 gcpu_fmri_create(cmi_hdl_t hdl, nv_alloc_t *nva)
 {
-	nvlist_t *nvl;
+	nvlist_t *nvl, *fmri;
 
 	if ((nvl = fm_nvlist_create(nva)) == NULL)
 		return (NULL);
 
-	fm_fmri_hc_set(nvl, FM_HC_SCHEME_VERSION, NULL, NULL, 4,
-	    "motherboard", 0,
-	    "chip", cmi_hdl_chipid(hdl),
-	    "core", cmi_hdl_coreid(hdl),
-	    "strand", cmi_hdl_strandid(hdl));
+	if (!x86gentopo_legacy) {
+		fmri = cmi_hdl_smb_bboard(hdl);
+		if (fmri == NULL)
+			return (NULL);
+
+		fm_fmri_hc_create(nvl, FM_HC_SCHEME_VERSION,
+		    NULL, NULL, fmri, 3,
+		    "chip", cmi_hdl_smb_chipid(hdl),
+		    "core", cmi_hdl_coreid(hdl),
+		    "strand", cmi_hdl_strandid(hdl));
+	} else {
+		fm_fmri_hc_set(nvl, FM_HC_SCHEME_VERSION, NULL, NULL, 4,
+		    "motherboard", 0,
+		    "chip", cmi_hdl_chipid(hdl),
+		    "core", cmi_hdl_coreid(hdl),
+		    "strand", cmi_hdl_strandid(hdl));
+	}
 
 	return (nvl);
 }
--- a/usr/src/uts/i86pc/cpu/genuineintel/gintel_main.c	Tue Nov 03 17:06:24 2009 -0800
+++ b/usr/src/uts/i86pc/cpu/genuineintel/gintel_main.c	Tue Nov 03 21:14:05 2009 -0500
@@ -38,6 +38,10 @@
 #include <sys/mc_intel.h>
 #include <sys/pci_cfgspace.h>
 #include <sys/fm/protocol.h>
+#include <sys/fm/util.h>
+#include <sys/fm/smb/fmsmb.h>
+
+extern int x86gentopo_legacy;
 
 int gintel_ms_support_disable = 0;
 int gintel_error_action_return = 0;
@@ -249,6 +253,36 @@
 	}
 }
 
+static nvlist_t *
+gintel_gentopo_ereport_detector(cmi_hdl_t hdl, cms_cookie_t mscookie,
+    nv_alloc_t *nva)
+{
+	nvlist_t *nvl = (nvlist_t *)NULL;
+	nvlist_t *board_list = (nvlist_t *)NULL;
+
+	if (mscookie) {
+		board_list = cmi_hdl_smb_bboard(hdl);
+
+		if (board_list == NULL)
+			return (NULL);
+
+		if ((nvl = fm_nvlist_create(nva)) == NULL)
+			return (NULL);
+
+		if ((uintptr_t)mscookie & GINTEL_ERROR_QUICKPATH) {
+			fm_fmri_hc_create(nvl, FM_HC_SCHEME_VERSION,
+			    NULL, NULL, board_list, 1,
+			    "chip", cmi_hdl_smb_chipid(hdl));
+		} else {
+			fm_fmri_hc_create(nvl, FM_HC_SCHEME_VERSION,
+			    NULL, NULL, board_list, 2,
+			    "chip", cmi_hdl_smb_chipid(hdl),
+			    "memory-controller", 0);
+		}
+	}
+	return (nvl);
+}
+
 /*ARGSUSED*/
 nvlist_t *
 gintel_ereport_detector(cmi_hdl_t hdl, int bankno, cms_cookie_t mscookie,
@@ -256,6 +290,11 @@
 {
 	nvlist_t *nvl = (nvlist_t *)NULL;
 
+	if (!x86gentopo_legacy) {
+		nvl = gintel_gentopo_ereport_detector(hdl, mscookie, nva);
+		return (nvl);
+	}
+
 	if (mscookie) {
 		if ((nvl = fm_nvlist_create(nva)) == NULL)
 			return (NULL);
@@ -274,6 +313,62 @@
 }
 
 static nvlist_t *
+gintel_gentopo_ereport_create_resource_elem(cmi_hdl_t hdl, nv_alloc_t *nva,
+    mc_unum_t *unump)
+{
+	nvlist_t *nvl, *snvl;
+	nvlist_t *board_list = NULL;
+
+	board_list = cmi_hdl_smb_bboard(hdl);
+	if (board_list == NULL) {
+		return (NULL);
+	}
+
+	if ((nvl = fm_nvlist_create(nva)) == NULL)	/* freed by caller */
+		return (NULL);
+
+	if ((snvl = fm_nvlist_create(nva)) == NULL) {
+		fm_nvlist_destroy(nvl, nva ? FM_NVA_RETAIN : FM_NVA_FREE);
+		return (NULL);
+	}
+
+	(void) nvlist_add_uint64(snvl, FM_FMRI_HC_SPECIFIC_OFFSET,
+	    unump->unum_offset);
+
+	if (unump->unum_chan == -1) {
+		fm_fmri_hc_create(nvl, FM_HC_SCHEME_VERSION, NULL, snvl,
+		    board_list, 2,
+		    "chip", cmi_hdl_smb_chipid(hdl),
+		    "memory-controller", unump->unum_mc);
+	} else if (unump->unum_cs == -1) {
+		fm_fmri_hc_create(nvl, FM_HC_SCHEME_VERSION, NULL, snvl,
+		    board_list, 3,
+		    "chip", cmi_hdl_smb_chipid(hdl),
+		    "memory-controller", unump->unum_mc,
+		    "dram-channel", unump->unum_chan);
+	} else if (unump->unum_rank == -1) {
+		fm_fmri_hc_create(nvl, FM_HC_SCHEME_VERSION, NULL, snvl,
+		    board_list, 4,
+		    "chip", cmi_hdl_smb_chipid(hdl),
+		    "memory-controller", unump->unum_mc,
+		    "dram-channel", unump->unum_chan,
+		    "dimm", unump->unum_cs);
+	} else {
+		fm_fmri_hc_create(nvl, FM_HC_SCHEME_VERSION, NULL, snvl,
+		    board_list, 5,
+		    "chip", cmi_hdl_smb_chipid(hdl),
+		    "memory-controller", unump->unum_mc,
+		    "dram-channel", unump->unum_chan,
+		    "dimm", unump->unum_cs,
+		    "rank", unump->unum_rank);
+	}
+
+	fm_nvlist_destroy(snvl, nva ? FM_NVA_RETAIN : FM_NVA_FREE);
+
+	return (nvl);
+}
+
+static nvlist_t *
 gintel_ereport_create_resource_elem(nv_alloc_t *nva, mc_unum_t *unump)
 {
 	nvlist_t *nvl, *snvl;
@@ -400,7 +495,15 @@
 				    TCODE_OFFSET_RAS(unum.unum_offset), NULL);
 			}
 		}
-		resource = gintel_ereport_create_resource_elem(nva, &unum);
+
+		if (!x86gentopo_legacy) {
+			resource = gintel_gentopo_ereport_create_resource_elem(
+			    hdl, nva, &unum);
+		} else {
+			resource = gintel_ereport_create_resource_elem(nva,
+			    &unum);
+		}
+
 		fm_payload_set(ereport, FM_EREPORT_PAYLOAD_NAME_RESOURCE,
 		    DATA_TYPE_NVLIST_ARRAY, 1, &resource, NULL);
 		fm_nvlist_destroy(resource, nva ? FM_NVA_RETAIN:FM_NVA_FREE);
--- a/usr/src/uts/i86pc/os/cmi.c	Tue Nov 03 17:06:24 2009 -0800
+++ b/usr/src/uts/i86pc/os/cmi.c	Tue Nov 03 21:14:05 2009 -0500
@@ -20,7 +20,7 @@
  */
 
 /*
- * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -112,6 +112,7 @@
 extern void cmi_hdl_setmc(cmi_hdl_t, const struct cmi_mc_ops *, void *);
 extern void cmi_hdl_inj_begin(cmi_hdl_t);
 extern void cmi_hdl_inj_end(cmi_hdl_t);
+extern void cmi_read_smbios(cmi_hdl_t);
 
 #define	HDL2CMI(hdl)		cmi_hdl_getcmi(hdl)
 
@@ -475,6 +476,8 @@
 
 	cms_init(hdl);
 
+	cmi_read_smbios(hdl);
+
 	mutex_exit(&cmi_load_lock);
 
 	return (hdl);
--- a/usr/src/uts/i86pc/os/cmi_hw.c	Tue Nov 03 17:06:24 2009 -0800
+++ b/usr/src/uts/i86pc/os/cmi_hw.c	Tue Nov 03 21:14:05 2009 -0500
@@ -48,6 +48,18 @@
 #include <sys/trap.h>
 #include <sys/mca_x86.h>
 #include <sys/processor.h>
+#include <sys/cmn_err.h>
+#include <sys/nvpair.h>
+#include <sys/fm/util.h>
+#include <sys/fm/protocol.h>
+#include <sys/fm/smb/fmsmb.h>
+#include <sys/cpu_module_impl.h>
+
+/*
+ * Variable which determines if the SMBIOS supports x86 generic topology; or
+ * if legacy topolgy enumeration will occur.
+ */
+extern int x86gentopo_legacy;
 
 /*
  * Outside of this file consumers use the opaque cmi_hdl_t.  This
@@ -70,6 +82,9 @@
 	const struct cmi_mc_ops *cmih_mcops;	/* Memory-controller ops */
 	void *cmih_mcdata;			/* Memory-controller data */
 	uint64_t cmih_flags;			/* See CMIH_F_* below */
+	uint16_t cmih_smbiosid;			/* SMBIOS Type 4 struct ID */
+	uint_t cmih_smb_chipid;			/* SMBIOS factored chipid */
+	nvlist_t *cmih_smb_bboard;		/* SMBIOS bboard nvlist */
 } cmi_hdl_impl_t;
 
 #define	IMPLHDL(ophdl)	((cmi_hdl_impl_t *)ophdl)
@@ -92,6 +107,7 @@
 	uint_t (*cmio_chipid)(cmi_hdl_impl_t *);
 	uint_t (*cmio_coreid)(cmi_hdl_impl_t *);
 	uint_t (*cmio_strandid)(cmi_hdl_impl_t *);
+	uint_t (*cmio_strand_apicid)(cmi_hdl_impl_t *);
 	uint32_t (*cmio_chiprev)(cmi_hdl_impl_t *);
 	const char *(*cmio_chiprevstr)(cmi_hdl_impl_t *);
 	uint32_t (*cmio_getsockettype)(cmi_hdl_impl_t *);
@@ -108,6 +124,9 @@
 	cmi_errno_t (*cmio_msrinterpose)(cmi_hdl_impl_t *, uint_t, uint64_t);
 	void (*cmio_int)(cmi_hdl_impl_t *, int);
 	int (*cmio_online)(cmi_hdl_impl_t *, int, int *);
+	uint16_t (*cmio_smbiosid) (cmi_hdl_impl_t *);
+	uint_t (*cmio_smb_chipid)(cmi_hdl_impl_t *);
+	nvlist_t *(*cmio_smb_bboard)(cmi_hdl_impl_t *);
 };
 
 static const struct cmi_hdl_ops cmi_hdl_ops;
@@ -602,6 +621,30 @@
 	return (hdl->cmih_strandid);
 }
 
+static uint_t
+ntv_strand_apicid(cmi_hdl_impl_t *hdl)
+{
+	return (cpuid_get_apicid(HDLPRIV(hdl)));
+}
+
+static uint16_t
+ntv_smbiosid(cmi_hdl_impl_t *hdl)
+{
+	return (hdl->cmih_smbiosid);
+}
+
+static uint_t
+ntv_smb_chipid(cmi_hdl_impl_t *hdl)
+{
+	return (hdl->cmih_smb_chipid);
+}
+
+static nvlist_t *
+ntv_smb_bboard(cmi_hdl_impl_t *hdl)
+{
+	return (hdl->cmih_smb_bboard);
+}
+
 static uint32_t
 ntv_chiprev(cmi_hdl_impl_t *hdl)
 {
@@ -858,6 +901,30 @@
 	return (hdl->cmih_strandid);
 }
 
+static uint_t
+xpv_strand_apicid(cmi_hdl_impl_t *hdl)
+{
+	return (xen_physcpu_initial_apicid(HDLPRIV(hdl)));
+}
+
+static uint16_t
+xpv_smbiosid(cmi_hdl_impl_t *hdl)
+{
+	return (hdl->cmih_smbiosid);
+}
+
+static uint_t
+xpv_smb_chipid(cmi_hdl_impl_t *hdl)
+{
+	return (hdl->cmih_smb_chipid);
+}
+
+static nvlist_t *
+xpv_smb_bboard(cmi_hdl_impl_t *hdl)
+{
+	return (hdl->cmih_smb_bboard);
+}
+
 extern uint32_t _cpuid_chiprev(uint_t, uint_t, uint_t, uint_t);
 
 static uint32_t
@@ -1186,6 +1253,51 @@
 }
 
 void
+cmi_read_smbios(cmi_hdl_t ophdl)
+{
+
+	uint_t strand_apicid;
+	uint_t chip_inst;
+	uint16_t smb_id;
+	int rc = 0;
+
+	cmi_hdl_impl_t *hdl = IMPLHDL(ophdl);
+
+	/* set x86gentopo compatibility */
+	fm_smb_fmacompat();
+
+#ifndef __xpv
+	strand_apicid = ntv_strand_apicid(hdl);
+#else
+	strand_apicid = xpv_strand_apicid(hdl);
+#endif
+
+	if (!x86gentopo_legacy) {
+		/*
+		 * If fm_smb_chipinst() or fm_smb_bboard() fails,
+		 * topo reverts to legacy mode
+		 */
+		rc = fm_smb_chipinst(strand_apicid, &chip_inst, &smb_id);
+		if (rc == 0) {
+			hdl->cmih_smb_chipid = chip_inst;
+			hdl->cmih_smbiosid = smb_id;
+		} else {
+#ifdef DEBUG
+			cmn_err(CE_NOTE, "cmi reads smbios chip info failed");
+#endif /* DEBUG */
+			return;
+		}
+
+		hdl->cmih_smb_bboard  = fm_smb_bboard(strand_apicid);
+#ifdef DEBUG
+		if (hdl->cmih_smb_bboard == NULL)
+			cmn_err(CE_NOTE,
+			    "cmi reads smbios base boards info failed");
+#endif /* DEBUG */
+	}
+}
+
+void
 cmi_hdl_hold(cmi_hdl_t ophdl)
 {
 	cmi_hdl_impl_t *hdl = IMPLHDL(ophdl);
@@ -1398,11 +1510,15 @@
 CMI_HDL_OPFUNC(chipid, uint_t)
 CMI_HDL_OPFUNC(coreid, uint_t)
 CMI_HDL_OPFUNC(strandid, uint_t)
+CMI_HDL_OPFUNC(strand_apicid, uint_t)
 CMI_HDL_OPFUNC(chiprev, uint32_t)
 CMI_HDL_OPFUNC(chiprevstr, const char *)
 CMI_HDL_OPFUNC(getsockettype, uint32_t)
 CMI_HDL_OPFUNC(getsocketstr, const char *)
 CMI_HDL_OPFUNC(logical_id, id_t)
+CMI_HDL_OPFUNC(smbiosid, uint16_t)
+CMI_HDL_OPFUNC(smb_chipid, uint_t)
+CMI_HDL_OPFUNC(smb_bboard, nvlist_t *)
 
 boolean_t
 cmi_hdl_is_cmt(cmi_hdl_t ophdl)
@@ -1730,6 +1846,7 @@
 	xpv_chipid,		/* cmio_chipid */
 	xpv_coreid,		/* cmio_coreid */
 	xpv_strandid,		/* cmio_strandid */
+	xpv_strand_apicid,	/* cmio_strand_apicid */
 	xpv_chiprev,		/* cmio_chiprev */
 	xpv_chiprevstr,		/* cmio_chiprevstr */
 	xpv_getsockettype,	/* cmio_getsockettype */
@@ -1741,7 +1858,10 @@
 	xpv_wrmsr,		/* cmio_wrmsr */
 	xpv_msrinterpose,	/* cmio_msrinterpose */
 	xpv_int,		/* cmio_int */
-	xpv_online		/* cmio_online */
+	xpv_online,		/* cmio_online */
+	xpv_smbiosid,		/* cmio_smbiosid */
+	xpv_smb_chipid,		/* cmio_smb_chipid */
+	xpv_smb_bboard		/* cmio_smb_bboard */
 
 #else	/* __xpv */
 
@@ -1756,6 +1876,7 @@
 	ntv_chipid,		/* cmio_chipid */
 	ntv_coreid,		/* cmio_coreid */
 	ntv_strandid,		/* cmio_strandid */
+	ntv_strand_apicid,	/* cmio_strandid */
 	ntv_chiprev,		/* cmio_chiprev */
 	ntv_chiprevstr,		/* cmio_chiprevstr */
 	ntv_getsockettype,	/* cmio_getsockettype */
@@ -1767,6 +1888,9 @@
 	ntv_wrmsr,		/* cmio_wrmsr */
 	ntv_msrinterpose,	/* cmio_msrinterpose */
 	ntv_int,		/* cmio_int */
-	ntv_online		/* cmio_online */
+	ntv_online,		/* cmio_online */
+	ntv_smbiosid,		/* cmio_smbiosid */
+	ntv_smb_chipid,		/* cmio_smb_chipid */
+	ntv_smb_bboard		/* cmio_smb_bboard */
 #endif
 };
--- a/usr/src/uts/i86pc/os/startup.c	Tue Nov 03 17:06:24 2009 -0800
+++ b/usr/src/uts/i86pc/os/startup.c	Tue Nov 03 21:14:05 2009 -0500
@@ -1545,6 +1545,18 @@
 	 */
 	setup_ddi();
 
+#ifdef __xpv
+	if (DOMAIN_IS_INITDOMAIN(xen_info))
+#endif
+	{
+		/*
+		 * Load the System Management BIOS into the global ksmbios
+		 * handle, if an SMBIOS is present on this system.
+		 */
+		ksmbios = smbios_open(NULL, SMB_VERSION, ksmbios_flags, NULL);
+	}
+
+
 	/*
 	 * Set up the CPU module subsystem for the boot cpu in the native
 	 * case, and all physical cpu resource in the xpv dom0 case.
@@ -2186,12 +2198,6 @@
 	if (DOMAIN_IS_INITDOMAIN(xen_info))
 #endif
 	{
-		/*
-		 * Load the System Management BIOS into the global ksmbios
-		 * handle, if an SMBIOS is present on this system.
-		 */
-		ksmbios = smbios_open(NULL, SMB_VERSION, ksmbios_flags, NULL);
-
 #if defined(__xpv)
 		xpv_panic_init();
 #else
--- a/usr/src/uts/i86xpv/os/xen_machdep.c	Tue Nov 03 17:06:24 2009 -0800
+++ b/usr/src/uts/i86xpv/os/xen_machdep.c	Tue Nov 03 21:14:05 2009 -0500
@@ -1275,6 +1275,12 @@
 }
 
 id_t
+xen_physcpu_initial_apicid(xen_mc_lcpu_cookie_t cookie)
+{
+	return (COOKIE2XCP(cookie)->mc_clusterid);
+}
+
+id_t
 xen_physcpu_logical_id(xen_mc_lcpu_cookie_t cookie)
 {
 	return (COOKIE2XCP(cookie)->mc_cpunr);
--- a/usr/src/uts/intel/Makefile.files	Tue Nov 03 17:06:24 2009 -0800
+++ b/usr/src/uts/intel/Makefile.files	Tue Nov 03 21:14:05 2009 -0500
@@ -45,6 +45,7 @@
 	desctbls_asm.o	\
 	exception.o	\
 	float.o		\
+	fmsmb.o		\
 	fpu.o		\
 	i86_subr.o	\
 	lock_prim.o	\
--- a/usr/src/uts/intel/io/devfm_machdep.c	Tue Nov 03 17:06:24 2009 -0800
+++ b/usr/src/uts/intel/io/devfm_machdep.c	Tue Nov 03 21:14:05 2009 -0500
@@ -19,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -28,6 +28,7 @@
 #include <sys/time.h>
 
 #include <sys/fm/protocol.h>
+#include <sys/fm/smb/fmsmb.h>
 #include <sys/devfm.h>
 
 #include <sys/cpu_module.h>
@@ -52,6 +53,8 @@
 	int	nhdl;		/* handles saved */
 } fm_cmi_walk_t;
 
+extern int x86gentopo_legacy;
+
 int
 fm_get_paddr(nvlist_t *nvl, uint64_t *paddr)
 {
@@ -145,7 +148,33 @@
 static void
 populate_cpu(nvlist_t **nvlp, cmi_hdl_t hdl)
 {
+	uint_t	fm_chipid;
+	uint16_t smbios_id;
+
 	(void) nvlist_alloc(nvlp, NV_UNIQUE_NAME, KM_SLEEP);
+
+	/*
+	 * If SMBIOS satisfies FMA Topology needs, gather
+	 * more information on the chip's physical roots
+	 * like /chassis=x/motherboard=y/cpuboard=z and
+	 * set the chip_id to match the SMBIOS' Type 4
+	 * ordering & this has to match the ereport's chip
+	 * resource instance derived off of SMBIOS.
+	 * Multi-Chip-Module support should set the chipid
+	 * in terms of the processor package rather than
+	 * the die/node in the processor package, for FM.
+	 */
+
+	if (!x86gentopo_legacy) {
+		smbios_id = cmi_hdl_smbiosid(hdl);
+		fm_chipid = cmi_hdl_smb_chipid(hdl);
+		(void) nvlist_add_nvlist(*nvlp, FM_PHYSCPU_INFO_CHIP_ROOTS,
+		    cmi_hdl_smb_bboard(hdl));
+		(void) nvlist_add_uint16(*nvlp, FM_PHYSCPU_INFO_SMBIOS_ID,
+		    (uint16_t)smbios_id);
+	} else
+		fm_chipid = cmi_hdl_chipid(hdl);
+
 	fm_payload_set(*nvlp,
 	    FM_PHYSCPU_INFO_VENDOR_ID, DATA_TYPE_STRING,
 	    cmi_hdl_vendorstr(hdl),
@@ -156,11 +185,13 @@
 	    FM_PHYSCPU_INFO_STEPPING, DATA_TYPE_INT32,
 	    (int32_t)cmi_hdl_stepping(hdl),
 	    FM_PHYSCPU_INFO_CHIP_ID, DATA_TYPE_INT32,
-	    (int32_t)cmi_hdl_chipid(hdl),
+	    (int32_t)fm_chipid,
 	    FM_PHYSCPU_INFO_CORE_ID, DATA_TYPE_INT32,
 	    (int32_t)cmi_hdl_coreid(hdl),
 	    FM_PHYSCPU_INFO_STRAND_ID, DATA_TYPE_INT32,
 	    (int32_t)cmi_hdl_strandid(hdl),
+	    FM_PHYSCPU_INFO_STRAND_APICID, DATA_TYPE_INT32,
+	    (int32_t)cmi_hdl_strand_apicid(hdl),
 	    FM_PHYSCPU_INFO_CHIP_REV, DATA_TYPE_STRING,
 	    cmi_hdl_chiprevstr(hdl),
 	    FM_PHYSCPU_INFO_SOCKET_TYPE, DATA_TYPE_UINT32,
@@ -257,3 +288,30 @@
 
 	return (rc);
 }
+
+/*
+ * Retrun the value of x86gentopo_legacy variable as an nvpair.
+ *
+ * The caller is responsible for freeing the nvlist.
+ */
+/* ARGSUSED */
+int
+fm_ioctl_gentopo_legacy(int cmd, nvlist_t *invl, nvlist_t **onvlp)
+{
+	nvlist_t *nvl;
+
+	if (cmd != FM_IOC_GENTOPO_LEGACY) {
+		return (ENOTTY);
+	}
+
+	/*
+	 * Inform the caller of the intentions of the ereport generators to
+	 * generate either a "generic" or "legacy" x86 topology.
+	 */
+
+	(void) nvlist_alloc(&nvl, NV_UNIQUE_NAME, KM_SLEEP);
+	(void) nvlist_add_int32(nvl, FM_GENTOPO_LEGACY, x86gentopo_legacy);
+	*onvlp = nvl;
+
+	return (0);
+}
--- a/usr/src/uts/intel/io/mc-amd/mcamd.h	Tue Nov 03 17:06:24 2009 -0800
+++ b/usr/src/uts/intel/io/mc-amd/mcamd.h	Tue Nov 03 21:14:05 2009 -0500
@@ -20,7 +20,7 @@
  */
 
 /*
- * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -209,6 +209,8 @@
 	size_t mc_snapshotsz;			/* packed nvlist buffer size */
 	uint_t mc_snapshotgen;			/* snapshot generation number */
 	int mc_csdiscontig;			/* chip-selects discontiguous */
+	uint_t smb_chipid;			/* smbios chip instance */
+	nvlist_t *smb_bboard;			/* smbios chip's parent */
 };
 
 typedef struct mcamd_hdl {
--- a/usr/src/uts/intel/io/mc-amd/mcamd_drv.c	Tue Nov 03 17:06:24 2009 -0800
+++ b/usr/src/uts/intel/io/mc-amd/mcamd_drv.c	Tue Nov 03 21:14:05 2009 -0500
@@ -47,11 +47,16 @@
 #include <sys/pci_cfgspace.h>
 #include <sys/mc.h>
 #include <sys/mc_amd.h>
+#include <sys/smbios.h>
+#include <sys/pci.h>
 #include <mcamd.h>
 #include <mcamd_dimmcfg.h>
 #include <mcamd_pcicfg.h>
 #include <mcamd_api.h>
 #include <sys/fm/cpu/AMD.h>
+#include <sys/fm/smb/fmsmb.h>
+#include <sys/fm/protocol.h>
+#include <sys/fm/util.h>
 
 /*
  * Set to prevent mc-amd from attaching.
@@ -1270,6 +1275,41 @@
 	ddi_fm_handler_register(dip, mc_fm_handle, NULL);
 }
 
+static void
+mc_read_smbios(mc_t *mc, dev_info_t *dip)
+{
+
+	uint16_t bdf;
+	pci_regspec_t *pci_rp;
+	uint32_t phys_hi;
+	int m;
+	uint_t chip_inst;
+	int rc = 0;
+
+	if (ddi_getlongprop(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS, "reg",
+	    (caddr_t)&pci_rp, &m) == DDI_SUCCESS) {
+		phys_hi = pci_rp->pci_phys_hi;
+		bdf = (uint16_t)(PCI_REG_BDFR_G(phys_hi) >>
+		    PCI_REG_FUNC_SHIFT);
+
+		rc = fm_smb_mc_chipinst(bdf, &chip_inst);
+		if (rc == 0) {
+			mc->smb_chipid = chip_inst;
+		} else {
+#ifdef DEBUG
+			cmn_err(CE_NOTE, "mc reads smbios chip info failed");
+#endif /* DEBUG */
+			return;
+		}
+		mc->smb_bboard = fm_smb_mc_bboards(bdf);
+#ifdef DEBUG
+		if (mc->smb_bboard == NULL)
+			cmn_err(CE_NOTE,
+			    "mc reads smbios base boards info failed");
+#endif /* DEBUG */
+	}
+}
+
 /*ARGSUSED*/
 static int
 mc_create_cb(cmi_hdl_t whdl, void *arg1, void *arg2, void *arg3)
@@ -1287,7 +1327,7 @@
 }
 
 static mc_t *
-mc_create(chipid_t chipid)
+mc_create(chipid_t chipid, dev_info_t *dip)
 {
 	mc_t *mc;
 	cmi_hdl_t hdl = NULL;
@@ -1315,6 +1355,8 @@
 	mc->mc_revname = cmi_hdl_chiprevstr(hdl);
 	mc->mc_socket = cmi_hdl_getsockettype(hdl);
 
+	mc_read_smbios(mc, dip);
+
 	if (mc_list == NULL)
 		mc_list = mc;
 	if (mc_last != NULL)
@@ -1552,7 +1594,7 @@
 
 	/* Integrate this memory controller device into existing set */
 	if (mc == NULL) {
-		mc = mc_create(chipid);
+		mc = mc_create(chipid, dip);
 
 		if (mc == NULL) {
 			/*
--- a/usr/src/uts/intel/io/mc-amd/mcamd_subr.c	Tue Nov 03 17:06:24 2009 -0800
+++ b/usr/src/uts/intel/io/mc-amd/mcamd_subr.c	Tue Nov 03 21:14:05 2009 -0500
@@ -20,7 +20,7 @@
  */
 
 /*
- * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -35,14 +35,19 @@
 #include <sys/varargs.h>
 #include <sys/fm/util.h>
 #include <sys/fm/cpu/AMD.h>
+#include <sys/fm/smb/fmsmb.h>
 #include <sys/fm/protocol.h>
 #include <sys/mc.h>
+#include <sys/smbios.h>
+#include <sys/smbios_impl.h>
 
 #include <mcamd.h>
 #include <mcamd_off.h>
 
 int mcamd_debug = 0; /* see mcamd_api.h for MCAMD_DBG_* values */
 
+extern int x86gentopo_legacy;
+
 struct mc_offmap {
 	int mcom_code;
 	uint_t mcom_offset;
@@ -557,7 +562,8 @@
 }
 
 static void
-mc_ereport_dimm_resource(mc_unum_t *unump, nvlist_t *elems[], int *nump)
+mc_ereport_dimm_resource(mc_unum_t *unump, nvlist_t *elems[], int *nump,
+    mc_t *mc)
 {
 	int i;
 
@@ -566,24 +572,44 @@
 			break;
 
 		elems[(*nump)++] = fm_nvlist_create(NULL);
-		fm_fmri_hc_set(elems[i], FM_HC_SCHEME_VERSION, NULL, NULL, 5,
-		    "motherboard",  unump->unum_board,
-		    "chip", unump->unum_chip,
-		    "memory-controller", unump->unum_mc,
-		    "dimm", unump->unum_dimms[i],
-		    "rank", unump->unum_rank);
+
+		if (!x86gentopo_legacy && mc->smb_bboard != NULL) {
+			fm_fmri_hc_create(elems[i], FM_HC_SCHEME_VERSION,
+			    NULL, NULL, mc->smb_bboard, 4,
+			    "chip", mc->smb_chipid,
+			    "memory-controller", unump->unum_mc,
+			    "dimm", unump->unum_dimms[i],
+			    "rank", unump->unum_rank);
+		} else {
+			fm_fmri_hc_set(elems[i], FM_HC_SCHEME_VERSION,
+			    NULL, NULL, 5,
+			    "motherboard",  unump->unum_board,
+			    "chip", unump->unum_chip,
+			    "memory-controller", unump->unum_mc,
+			    "dimm", unump->unum_dimms[i],
+			    "rank", unump->unum_rank);
+		}
 	}
 }
 
 static void
-mc_ereport_cs_resource(mc_unum_t *unump, nvlist_t *elems[], int *nump)
+mc_ereport_cs_resource(mc_unum_t *unump, nvlist_t *elems[], int *nump, mc_t *mc)
 {
 	elems[0] = fm_nvlist_create(NULL);
-	fm_fmri_hc_set(elems[0], FM_HC_SCHEME_VERSION, NULL, NULL, 4,
-	    "motherboard",  unump->unum_board,
-	    "chip", unump->unum_chip,
-	    "memory-controller", unump->unum_mc,
-	    "chip-select", unump->unum_cs);
+
+	if (!x86gentopo_legacy && mc->smb_bboard != NULL) {
+		fm_fmri_hc_create(elems[0], FM_HC_SCHEME_VERSION, NULL, NULL,
+		    mc->smb_bboard, 3,
+		    "chip", mc->smb_chipid,
+		    "memory-controller", unump->unum_mc,
+		    "chip-select", unump->unum_cs);
+	} else {
+		fm_fmri_hc_set(elems[0], FM_HC_SCHEME_VERSION, NULL, NULL, 4,
+		    "motherboard",  unump->unum_board,
+		    "chip", unump->unum_chip,
+		    "memory-controller", unump->unum_mc,
+		    "chip-select", unump->unum_cs);
+	}
 	*nump = 1;
 }
 
@@ -595,16 +621,16 @@
  * topology node.
  */
 static void
-mc_ereport_add_resource(nvlist_t *payload, mc_unum_t *unump)
+mc_ereport_add_resource(nvlist_t *payload, mc_unum_t *unump, mc_t *mc)
 {
 	nvlist_t *elems[MC_UNUM_NDIMM];
 	int nelems = 0;
 	int i;
 
 	if (unump->unum_dimms[0] != MC_INVALNUM)
-		mc_ereport_dimm_resource(unump, elems, &nelems);
+		mc_ereport_dimm_resource(unump, elems, &nelems, mc);
 	else if (unump->unum_cs != MC_INVALNUM)
-		mc_ereport_cs_resource(unump, elems, &nelems);
+		mc_ereport_cs_resource(unump, elems, &nelems, mc);
 
 	if (nelems > 0) {
 		fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_RESOURCE,
@@ -616,11 +642,12 @@
 }
 
 static void
-mc_ereport_add_payload(nvlist_t *ereport, uint64_t members, mc_unum_t *unump)
+mc_ereport_add_payload(nvlist_t *ereport, uint64_t members, mc_unum_t *unump,
+    mc_t *mc)
 {
 	if (members & FM_EREPORT_PAYLOAD_FLAG_RESOURCE &&
 	    unump != NULL)
-		mc_ereport_add_resource(ereport, unump);
+		mc_ereport_add_resource(ereport, unump, mc);
 }
 
 static nvlist_t *
@@ -628,10 +655,17 @@
 {
 	nvlist_t *nvl = fm_nvlist_create(NULL);
 
-	fm_fmri_hc_set(nvl, FM_HC_SCHEME_VERSION, NULL, NULL, 3,
-	    "motherboard", 0,
-	    "chip", mc->mc_props.mcp_num,
-	    "memory-controller", 0);
+	if (!x86gentopo_legacy && mc->smb_bboard != NULL) {
+		fm_fmri_hc_create(nvl, FM_HC_SCHEME_VERSION, NULL, NULL,
+		    mc->smb_bboard, 2,
+		    "chip", mc->smb_chipid,
+		    "memory-controller", 0);
+	} else {
+		fm_fmri_hc_set(nvl, FM_HC_SCHEME_VERSION, NULL, NULL, 3,
+		    "motherboard", 0,
+		    "chip", mc->mc_props.mcp_num,
+		    "memory-controller", 0);
+	}
 
 	return (nvl);
 }
@@ -668,7 +702,7 @@
 	    fm_ena_generate(gethrtime(), FM_ENA_FMT1), detector, NULL);
 	fm_nvlist_destroy(detector, FM_NVA_FREE);
 
-	mc_ereport_add_payload(ereport, payload, unump);
+	mc_ereport_add_payload(ereport, payload, unump, mc);
 
 	(void) fm_ereport_post(ereport, EVCH_TRYHARD);
 	fm_nvlist_destroy(ereport, FM_NVA_FREE);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/uts/intel/os/fmsmb.c	Tue Nov 03 21:14:05 2009 -0500
@@ -0,0 +1,1129 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/nvpair.h>
+#include <sys/cmn_err.h>
+#include <sys/fm/util.h>
+#include <sys/fm/protocol.h>
+#include <sys/smbios.h>
+#include <sys/smbios_impl.h>
+
+/*
+ * Variable used to determine if the x86 generic topology enumerator will
+ * revert to legacy enumeration. I.E. Big Kill Switch... tunable via
+ * /etc/system
+ */
+int x86gentopo_legacy = 0;
+
+#define	MC		0
+#define	PROC		1
+#define	MAX_PAIRS	20
+#define	MAX_CONT	40
+
+typedef struct bbindex  {
+	int count;
+	uint16_t index[MAX_PAIRS];
+} bbindex_t;
+
+/*
+ * the enum values come from DMTF
+ */
+typedef enum baseb {
+	BB_BAD = 0,		/* There is no bb value 0 */
+	BB_UNKNOWN,		/* Unknown */
+	BB_OTHER,		/* Other */
+	BB_BLADE,		/* Server Blade */
+	BB_CONNSW,		/* Connectivity Switch */
+	BB_SMM,			/* System Management Module */
+	BB_PROCMOD,		/* Processor Module */
+	BB_IOMOD,		/* I/O Module */
+	BB_MEMMOD,		/* Memory Module */
+	BB_DBOARD,		/* Daughter Board */
+	BB_MBOARD,		/* Motherboard */
+	BB_PROCMMOD,		/* Processor/Memory Module */
+	BB_PROCIOMOD,		/* Processor/IO Module */
+	BB_ICONNBD		/* Interconnect Board */
+} bbd_t;
+
+static struct bboard_type {
+	bbd_t		baseb;
+	const char	*name;
+} bbd_type[] = {
+	{BB_BAD,		NULL},
+	{BB_UNKNOWN,		"unknown"},
+	{BB_OTHER,		"other"},
+	{BB_BLADE,		"systemboard"},
+	{BB_CONNSW,		"connswitch"},
+	{BB_SMM,		"smmodule"},
+	{BB_PROCMOD,		"cpuboard"},
+	{BB_IOMOD,		"ioboard"},
+	{BB_MEMMOD,		"memboard"},
+	{BB_DBOARD,		"systemboard"},
+	{BB_MBOARD,		"motherboard"},
+	{BB_PROCMMOD,		"systemboard"},
+	{BB_PROCIOMOD,		"systemboard"},
+	{BB_ICONNBD,		"systemboard"}
+};
+
+typedef struct smbs_con_ids {
+	int id;
+	int inst;
+	int cont_count;
+	uint16_t **cont_ids;
+	int cont_by_id;
+	int visited;
+} smbs_con_ids_t;
+
+typedef struct smbs_cnt {
+	int type;			/* SMBIOS stucture type */
+	int count;			/* number of table entries */
+	smbs_con_ids_t **ids;		/* SMBIOS table entry id(s) */
+} smbs_cnt_t;
+
+/*
+ * dynamically allocate the storage for the smbs_cnt_t
+ */
+static smbs_cnt_t *
+smb_create_strcnt(int count)
+{
+	smbs_cnt_t *types = NULL;
+	int i, j;
+
+	types = kmem_zalloc(sizeof (smbs_cnt_t), KM_SLEEP);
+
+	types->ids = (smbs_con_ids_t **)kmem_zalloc(
+	    count * sizeof (smbs_con_ids_t *), KM_SLEEP);
+
+	for (i = 0; i < count; i++) {
+		types->ids[i] = (smbs_con_ids_t *)kmem_zalloc(
+		    sizeof (smbs_con_ids_t), KM_SLEEP);
+	}
+
+	for (i = 0; i < count; i++) {
+		types->ids[i]->cont_ids = (uint16_t **)kmem_zalloc(
+		    MAX_CONT * sizeof (uint16_t *), KM_SLEEP);
+	}
+
+	for (i = 0; i < count; i++) {
+		for (j = 0; j < MAX_CONT; j++) {
+			types->ids[i]->cont_ids[j] = (uint16_t *)kmem_zalloc(
+			    sizeof (uint16_t), KM_SLEEP);
+		}
+	}
+	return (types);
+}
+
+/*
+ * free the smbs_cnt_t memory
+ */
+static void
+smb_free_strcnt(smbs_cnt_t *types, int count)
+{
+	int i, j;
+
+	if (types == NULL)
+		return;
+
+	for (i = 0; i < count; i++) {
+		for (j = 0; j < MAX_CONT; j++) {
+			if (types->ids[i]->cont_ids[j] != NULL)
+				kmem_free(types->ids[i]->cont_ids[j],
+				    sizeof (uint16_t));
+		}
+	}
+
+	for (i = 0; i < count; i++) {
+		if (types->ids[i]->cont_ids != NULL)
+			kmem_free(types->ids[i]->cont_ids,
+			    MAX_CONT * sizeof (uint16_t *));
+	}
+
+	for (i = 0; i < count; i++) {
+		if (types->ids[i] != NULL)
+			kmem_free(types->ids[i], sizeof (smbs_con_ids_t));
+	}
+
+	if (types->ids != NULL)
+		kmem_free(types->ids, count * sizeof (smbs_con_ids_t *));
+
+	if (types != NULL)
+		kmem_free(types, sizeof (smbs_cnt_t));
+
+}
+
+/*
+ * count number of the structure type in the ksmbios
+ */
+static int
+smb_cnttypes(smbios_hdl_t *shp, int type)
+{
+	const smb_struct_t *sp = shp->sh_structs;
+	int nstructs = shp->sh_nstructs;
+	int i;
+	int cnt = 0;
+
+	for (i = 0, cnt = 0; i < nstructs; i++, sp++) {
+		if (sp->smbst_hdr->smbh_type == type)
+			cnt++;
+	}
+	return (cnt);
+}
+
+static void
+smb_strcnt(smbios_hdl_t *shp, smbs_cnt_t *stype)
+{
+	const smb_struct_t *sp = shp->sh_structs;
+	int nstructs = shp->sh_nstructs;
+	smbios_bboard_t bb;
+	int i, cnt;
+	int mb_cnt = 0;
+	int cpub_cnt = 0;
+	int sysb_cnt = 0;
+	int memb_cnt = 0;
+	int iob_cnt = 0;
+	int inst = 0;
+	int rc = 0;
+
+	for (i = 0, cnt = 0; i < nstructs; i++, sp++) {
+		if (sp->smbst_hdr->smbh_type == stype->type) {
+			stype->ids[cnt]->id = sp->smbst_hdr->smbh_hdl;
+			stype->ids[cnt]->inst = cnt;
+			stype->ids[cnt]->visited = 0;
+			stype->ids[cnt]->cont_by_id = -1;
+			if (stype->type == SMB_TYPE_BASEBOARD) {
+				rc = smbios_info_bboard(shp,
+				    stype->ids[cnt]->id, &bb);
+				if (rc == 0) {
+					switch (bb.smbb_type) {
+						case SMB_BBT_PROC :
+							inst = cpub_cnt++;
+							break;
+						case SMB_BBT_IO :
+							inst = iob_cnt++;
+							break;
+						case SMB_BBT_MEM :
+							inst = memb_cnt++;
+							break;
+						case SMB_BBT_MOTHER :
+							inst = mb_cnt++;
+							break;
+						default:
+							/*
+							 * SMB_BBT_UNKNOWN
+							 * SMB_BBT_OTHER
+							 * SMB_BBT_SBLADE
+							 * SMB_BBT_CSWITCH
+							 * SMB_BBT_SMM
+							 * SMB_BBT_DAUGHTER
+							 * SMB_BBT_PROCMEM
+							 * SMB_BBT_PROCIO
+							 * SMB_BBT_INTER
+							 */
+							inst = sysb_cnt++;
+							break;
+					}
+					stype->ids[cnt]->inst = inst;
+				}
+			}
+			cnt++;
+		}
+	}
+	stype->count = cnt;
+}
+
+/*
+ * Go through the smbios structures looking for type 2. Fill in
+ * the cont_id and cont_by_id for each type 2
+ *
+ */
+static void
+smb_bb_contains(smbios_hdl_t *shp, smbs_cnt_t *stype)
+{
+	int i, j, cnt, c;
+	uint_t cont_count;
+	const smb_struct_t *spt;
+	smbios_bboard_t smb_bb;
+	uint16_t bb_id, cont_id;
+	uint_t cont_len;
+	id_t *cont_hdl = NULL;
+	int rc;
+
+	for (cnt = 0; cnt < stype->count; cnt++) {
+		bb_id = stype->ids[cnt]->id;
+		(void) smbios_info_bboard(shp, stype->ids[cnt]->id, &smb_bb);
+		cont_count = (uint_t)smb_bb.smbb_contn;
+		if (cont_count == 0) {
+			continue;
+		}
+
+		cont_len = sizeof (id_t);
+		cont_hdl = kmem_zalloc(cont_count * cont_len, KM_SLEEP);
+		if (cont_hdl == NULL)
+			continue;
+
+		rc = smbios_info_contains(shp, stype->ids[cnt]->id,
+		    cont_count, cont_hdl);
+		if (rc > SMB_CONT_MAX) {
+			kmem_free(cont_hdl, cont_count * cont_len);
+			continue;
+		}
+		cont_count = MIN(rc, cont_count);
+
+		/*
+		 * fill in the type 2 and type 4 ids which are
+		 * contained in this type 2
+		 */
+		c = 0;
+		for (j = 0; j < cont_count; j++) {
+			cont_id = (uint16_t)cont_hdl[j];
+			spt = smb_lookup_id(shp, cont_id);
+			if (spt->smbst_hdr->smbh_type == SMB_TYPE_BASEBOARD ||
+			    spt->smbst_hdr->smbh_type == SMB_TYPE_PROCESSOR) {
+				*stype->ids[cnt]->cont_ids[c] = cont_id;
+				c++;
+			}
+
+			if (spt->smbst_hdr->smbh_type == SMB_TYPE_BASEBOARD) {
+				for (i = 0; i < stype->count; i++) {
+					if (stype->ids[i]->id == cont_id) {
+						stype->ids[i]->cont_by_id =
+						    bb_id;
+					}
+				}
+			}
+
+		}
+		stype->ids[cnt]->cont_count = c;
+		if (cont_hdl != NULL)
+			kmem_free(cont_hdl, cont_count * cont_len);
+	}
+}
+
+/*
+ * Verify SMBIOS structures for x86 generic topology.
+ *
+ * Return (0) on success.
+ */
+static int
+fm_smb_check(smbios_hdl_t *shp)
+{
+	int i;
+	int bb_cnt = 0;
+	int pr_cnt = 0;
+	int expr_cnt = 0;
+	int ma_cnt = 0;
+	int exma_cnt = 0;
+	int mdev_cnt = 0;
+	int exmdev_cnt = 0;
+	uint16_t bb_id;
+	uint16_t pr_id, expr_id;
+	uint16_t ma_id, exma_id;
+	uint16_t mdev_id, exmdev_id;
+	smbios_bboard_t bb;
+	smbios_processor_ext_t exproc;
+	smbios_memarray_ext_t exma;
+	smbios_memdevice_ext_t exmdev;
+	smbs_cnt_t *bb_stype;
+	smbs_cnt_t *pr_stype, *expr_stype;
+	smbs_cnt_t *ma_stype, *exma_stype;
+	smbs_cnt_t *mdev_stype, *exmdev_stype;
+
+	/*
+	 * Verify the existance of the requuired extended OEM-Specific
+	 * structures and they coincide with the structures they extend
+	 * (e.g. the number of extended processor structures equal the
+	 * number of processor structures).
+	 */
+	pr_cnt = smb_cnttypes(shp, SMB_TYPE_PROCESSOR);
+	expr_cnt = smb_cnttypes(shp, SUN_OEM_EXT_PROCESSOR);
+	ma_cnt = smb_cnttypes(shp, SMB_TYPE_MEMARRAY);
+	exma_cnt = smb_cnttypes(shp, SUN_OEM_EXT_MEMARRAY);
+	mdev_cnt = smb_cnttypes(shp, SMB_TYPE_MEMDEVICE);
+	exmdev_cnt = smb_cnttypes(shp, SUN_OEM_EXT_MEMDEVICE);
+	if (expr_cnt == 0 || exma_cnt == 0 || exmdev_cnt == 0 ||
+	    expr_cnt != pr_cnt || exma_cnt != ma_cnt ||
+	    exmdev_cnt != mdev_cnt) {
+#ifdef	DEBUG
+		cmn_err(CE_NOTE, "Structure mismatch: ext_proc (%d) "
+		    "proc (%d) ext_ma (%d) ma (%d) ext_mdev (%d) mdev (%d)\n",
+		    expr_cnt, pr_cnt, exma_cnt, ma_cnt, exmdev_cnt,
+		    mdev_cnt);
+#endif	/* DEBUG */
+		return (-1);
+	}
+
+	/*
+	 * Verify the OEM-Specific structrures are correctly
+	 * linked to the SMBIOS structure types they extend.
+	 */
+
+	/* allocate processor stypes */
+	pr_stype = smb_create_strcnt(pr_cnt);
+	expr_stype = smb_create_strcnt(expr_cnt);
+
+	/* fill in stypes */
+	pr_stype->type = SMB_TYPE_PROCESSOR;
+	smb_strcnt(shp, pr_stype);
+	expr_stype->type = SUN_OEM_EXT_PROCESSOR;
+	smb_strcnt(shp, expr_stype);
+
+	/* verify the ext proc struct belong to the proc struct */
+	for (i = 0; i < pr_cnt; i++) {
+		pr_id = pr_stype->ids[i]->id;
+		expr_id = expr_stype->ids[i]->id;
+		(void) smbios_info_extprocessor(shp, expr_id, &exproc);
+		if (exproc.smbpe_processor != pr_id) {
+#ifdef	DEBUG
+			cmn_err(CE_NOTE, "Processor struct linkage (%d)", i);
+#endif	/* DEBUG */
+			smb_free_strcnt(pr_stype, pr_cnt);
+			smb_free_strcnt(expr_stype, expr_cnt);
+			return (-1);
+		}
+	}
+
+	/* free stypes */
+	smb_free_strcnt(pr_stype, pr_cnt);
+	smb_free_strcnt(expr_stype, expr_cnt);
+
+	/* allocate memory array stypes */
+	ma_stype = smb_create_strcnt(ma_cnt);
+	exma_stype = smb_create_strcnt(exma_cnt);
+
+	/* fill in stypes */
+	ma_stype->type = SMB_TYPE_MEMARRAY;
+	smb_strcnt(shp, ma_stype);
+	exma_stype->type = SUN_OEM_EXT_MEMARRAY;
+	smb_strcnt(shp, exma_stype);
+
+	/* verify linkage from ext memarray struct to memarray struct */
+	for (i = 0; i < ma_cnt; i++) {
+		ma_id = ma_stype->ids[i]->id;
+		exma_id = exma_stype->ids[i]->id;
+		(void) smbios_info_extmemarray(shp, exma_id, &exma);
+		if (exma.smbmae_ma != ma_id) {
+#ifdef	DEBUG
+			cmn_err(CE_NOTE, "Memory Array struct linkage (%d)", i);
+#endif	/* DEBUG */
+			smb_free_strcnt(ma_stype, ma_cnt);
+			smb_free_strcnt(exma_stype, exma_cnt);
+			return (-1);
+		}
+	}
+
+	/* free stypes */
+	smb_free_strcnt(ma_stype, ma_cnt);
+	smb_free_strcnt(exma_stype, exma_cnt);
+
+	/* allocate memory device stypes */
+	mdev_stype = smb_create_strcnt(mdev_cnt);
+	exmdev_stype = smb_create_strcnt(exmdev_cnt);
+
+	/* fill in stypes */
+	mdev_stype->type = SMB_TYPE_MEMDEVICE;
+	smb_strcnt(shp, mdev_stype);
+	exmdev_stype->type = SUN_OEM_EXT_MEMDEVICE;
+	smb_strcnt(shp, exmdev_stype);
+
+	/* verify linkage */
+	for (i = 0; i < mdev_cnt; i++) {
+		mdev_id = mdev_stype->ids[i]->id;
+		exmdev_id = exmdev_stype->ids[i]->id;
+		(void) smbios_info_extmemdevice(shp, exmdev_id, &exmdev);
+		if (exmdev.smbmdeve_md != mdev_id) {
+#ifdef	DEBUG
+			cmn_err(CE_NOTE, "Memory Device struct linkage (%d)",
+			    i);
+#endif	/* DEBUG */
+			smb_free_strcnt(mdev_stype, mdev_cnt);
+			smb_free_strcnt(exmdev_stype, exmdev_cnt);
+			return (-1);
+		}
+	}
+
+	/* free stypes */
+	smb_free_strcnt(mdev_stype, mdev_cnt);
+	smb_free_strcnt(exmdev_stype, exmdev_cnt);
+
+	/*
+	 * Verify the presece of contained handles if there are more
+	 * than one Type-2 (Base Board) structures.
+	 */
+	bb_cnt = smb_cnttypes(shp, SMB_TYPE_BASEBOARD);
+	if (bb_cnt > 1) {
+		/* allocate base board stypes */
+		bb_stype = smb_create_strcnt(bb_cnt);
+
+		/* fill in stypes */
+		bb_stype->type = SMB_TYPE_BASEBOARD;
+		smb_strcnt(shp, bb_stype);
+
+		/* verify contained handles */
+		for (i = 0; i < bb_cnt; i++) {
+			bb_id = bb_stype->ids[i]->id;
+			(void) smbios_info_bboard(shp, bb_id, &bb);
+			if (bb.smbb_contn == 0) {
+#ifdef	DEBUG
+				cmn_err(CE_NOTE, "No contained hanldes (%d)",
+				    i);
+#endif	/* DEBUG */
+				smb_free_strcnt(bb_stype, bb_cnt);
+				return (-1);
+			}
+		}
+
+		/* free stypes */
+		smb_free_strcnt(bb_stype, bb_cnt);
+	}
+
+	return (0);
+}
+
+void
+fm_smb_fmacompat()
+{
+	int i, j;
+	int id;
+	int cnt;
+	const char **oem_strings = NULL;
+	smbs_cnt_t *oemstypes;
+	smbios_hdl_t *shp;
+	int strcnt;
+	int compat = 0;
+
+	/* check for BKS */
+	if (x86gentopo_legacy == 1) {
+#ifdef DEBUG
+		cmn_err(CE_NOTE, "forced legacy x86 topology enumeration");
+#endif /* DEBUG */
+		return;
+	}
+
+	shp = ksmbios;
+	if (shp == NULL) {
+		goto bad;
+	}
+
+	/* OEM strings (Type 11) */
+	strcnt = smb_cnttypes(shp, SMB_TYPE_OEMSTR);
+	if (strcnt == 0)
+		goto bad;
+
+	oemstypes = smb_create_strcnt(strcnt);
+	if (oemstypes == NULL)
+		goto bad;
+
+	oemstypes->type = SMB_TYPE_OEMSTR;
+	smb_strcnt(shp, oemstypes);
+
+	for (i = 0; i < oemstypes->count; i++) {
+		id = oemstypes->ids[i]->id;
+		cnt = smbios_info_strtab(shp, id, 0, NULL);
+		if (cnt > 0) {
+			oem_strings = kmem_zalloc(sizeof (char *) * cnt,
+			    KM_SLEEP);
+			(void) smbios_info_strtab(shp, id, cnt, oem_strings);
+
+			for (j = 0; j < cnt; j++) {
+				if (strncmp(oem_strings[j], SMB_PRMS1,
+				    strlen(SMB_PRMS1) + 1) == 0) {
+					kmem_free(oem_strings,
+					    sizeof (char *) * cnt);
+					smb_free_strcnt(oemstypes, strcnt);
+					compat = 1;
+					break;
+				}
+			}
+		}
+	}
+
+	if (compat == 0) {
+		/* didn't find x86pi magic cookie */
+		if (oem_strings != NULL)
+			kmem_free(oem_strings, sizeof (char *) * cnt);
+		smb_free_strcnt(oemstypes, strcnt);
+		goto bad;
+	}
+
+	/* sanity check SMBIOS structures */
+	if (fm_smb_check(shp) == 0)
+		return;
+
+bad:
+	/* not compatible with x86gentopo; revert to legacy enumeration */
+#ifdef	DEBUG
+	cmn_err(CE_NOTE, "SMBIOS is not compatible with x86 generic topology.");
+	cmn_err(CE_NOTE, "Invoking legacy x86 topology enumeration.");
+#endif	/* DEBUG */
+	x86gentopo_legacy = 1;
+}
+
+static int
+find_matching_apic(smbios_hdl_t *shp, uint16_t proc_id, uint_t strand_apicid)
+{
+	uint16_t ext_id;
+	int i, j;
+	smbios_processor_ext_t ep;
+	smbs_cnt_t *pstypes;
+	int strcnt;
+
+	strcnt = smb_cnttypes(shp, SUN_OEM_EXT_PROCESSOR);
+	if (strcnt == 0)
+		return (0);
+
+	pstypes = smb_create_strcnt(strcnt);
+	if (pstypes == NULL)
+		return (0);
+
+	pstypes->type = SUN_OEM_EXT_PROCESSOR;
+	smb_strcnt(shp, pstypes);
+	for (i = 0; i < pstypes->count; i++) {
+		ext_id = pstypes->ids[i]->id;
+		(void) smbios_info_extprocessor(shp, ext_id, &ep);
+		if (ep.smbpe_processor == proc_id) {
+			for (j = 0; j < ep.smbpe_n; j++) {
+				if (ep.smbpe_apicid[j] == strand_apicid) {
+					smb_free_strcnt(pstypes, strcnt);
+					return (1);
+				}
+			}
+		}
+	}
+	smb_free_strcnt(pstypes, strcnt);
+	return (0);
+}
+
+/*
+ * go throught the type 2 structure contained_ids looking for
+ * the type 4 which  has strand_apicid == this strand_apicid
+ */
+static int
+find_matching_proc(smbios_hdl_t *shp, uint_t strand_apicid,
+    uint16_t bb_id, uint16_t proc_hdl, int is_proc)
+{
+	int n;
+	const smb_struct_t *sp;
+	smbios_bboard_t bb;
+	uint_t cont_count, cont_len;
+	uint16_t cont_id;
+	id_t *cont_hdl = NULL;
+	int rc;
+
+
+	(void) smbios_info_bboard(shp, bb_id, &bb);
+	cont_count = (uint_t)bb.smbb_contn;
+	if (cont_count == 0)
+		return (0);
+
+	cont_len = sizeof (id_t);
+	cont_hdl = kmem_zalloc(cont_count * cont_len, KM_SLEEP);
+	if (cont_hdl == NULL)
+		return (0);
+
+	rc = smbios_info_contains(shp, bb_id, cont_count, cont_hdl);
+	if (rc > SMB_CONT_MAX) {
+		kmem_free(cont_hdl, cont_count * cont_len);
+		return (0);
+	}
+	cont_count = MIN(rc, cont_count);
+
+	for (n = 0; n < cont_count; n++) {
+		cont_id = (uint16_t)cont_hdl[n];
+		sp = smb_lookup_id(shp, cont_id);
+		if (sp->smbst_hdr->smbh_type == SMB_TYPE_PROCESSOR) {
+			if (is_proc) {
+				if (find_matching_apic(shp, cont_id,
+				    strand_apicid)) {
+					kmem_free(cont_hdl,
+					    cont_count * cont_len);
+					return (1);
+				}
+			} else {
+				if (cont_id == proc_hdl) {
+					kmem_free(cont_hdl,
+					    cont_count * cont_len);
+					return (1);
+				}
+			}
+		}
+	}
+	if (cont_hdl != NULL)
+		kmem_free(cont_hdl, cont_count * cont_len);
+
+	return (0);
+}
+
+void
+get_bboard_index(smbs_cnt_t *bbstypes, uint_t bb_id, bbindex_t *bb_idx)
+{
+	int curr_id, tmp_id;
+	int i, j, nb;
+	bbindex_t tmp_idx;
+
+	for (i = 0; i < MAX_PAIRS; i++)
+		tmp_idx.index[i] = 0;
+
+	tmp_idx.count = 0;
+
+	curr_id = bb_id;
+	for (nb = bbstypes->count-1, i = 0; nb >= 0; nb--) {
+		tmp_id = bbstypes->ids[nb]->id;
+		if (tmp_id == curr_id) {
+			tmp_idx.index[i] = nb;
+			tmp_idx.count++;
+			curr_id = bbstypes->ids[nb]->cont_by_id;
+			if (curr_id == -1)
+				break;
+			i++;
+		}
+	}
+
+	for (i = tmp_idx.count - 1, j = 0; i >= 0; i--) {
+		bb_idx->index[j] = tmp_idx.index[i];
+		j++;
+	}
+
+	bb_idx->count = tmp_idx.count;
+}
+
+int
+get_chassis_inst(smbios_hdl_t *shp, uint16_t *chassis_inst,
+    uint16_t bb_id, int *chcnt)
+{
+	int ch_strcnt;
+	smbs_cnt_t *chstypes;
+	uint16_t chassis_id, tmp_id;
+	smbios_bboard_t bb;
+	int rc = 0;
+	int i;
+
+	rc = smbios_info_bboard(shp, bb_id, &bb);
+	if (rc != 0) {
+		return (-1);
+	}
+
+	chassis_id = bb.smbb_chassis;
+
+	ch_strcnt = smb_cnttypes(shp, SMB_TYPE_CHASSIS);
+
+	if (ch_strcnt == 0)
+		return (-1);
+
+	chstypes = smb_create_strcnt(ch_strcnt);
+	if (chstypes == NULL)
+		return (-1);
+
+	chstypes->type = SMB_TYPE_CHASSIS;
+	smb_strcnt(shp, chstypes);
+
+	for (i = 0; i < chstypes->count; i++) {
+		tmp_id = chstypes->ids[i]->id;
+		if (tmp_id == chassis_id) {
+			*chassis_inst = chstypes->ids[i]->inst;
+			if (chstypes->ids[i]->inst != 0)
+				*chcnt = 2;
+			else
+				*chcnt = 1;
+			smb_free_strcnt(chstypes, ch_strcnt);
+			return (0);
+		}
+	}
+
+	smb_free_strcnt(chstypes, ch_strcnt);
+	return (-1);
+}
+
+int
+smb_get_bb_fmri(smbios_hdl_t *shp, nvlist_t *fmri,  uint_t parent,
+    smbs_cnt_t *bbstypes)
+{
+	int rc = 0;
+	int i, j, n, cnt;
+	int id, index;
+	nvlist_t *pairs[MAX_PAIRS];
+	smbios_bboard_t bb;
+	uint16_t chassis_inst, mch_inst;
+	char name[40];
+	char idstr[11];
+	bbindex_t bb_idx;
+	uint16_t bbid;
+	int chcnt = 0;
+
+	for (n = 0; n < MAX_PAIRS; n++) {
+		bb_idx.index[n] = 0;
+		pairs[n] = NULL;
+	}
+	bb_idx.count = 0;
+
+	get_bboard_index(bbstypes, parent, &bb_idx);
+
+	index = bb_idx.index[0];
+	bbid = bbstypes->ids[index]->id;
+
+	rc = get_chassis_inst(shp, &chassis_inst, bbid, &chcnt);
+
+	if (rc != 0) {
+		return (rc);
+	}
+
+	if ((bb_idx.count + chcnt) > MAX_PAIRS) {
+		return (-1);
+	}
+
+	i = 0;
+	if (chcnt > 1) {
+		/*
+		 * create main chassis pair
+		 */
+		pairs[i] = fm_nvlist_create(NULL);
+		if (pairs[i] == NULL) {
+			return (-1);
+		}
+		mch_inst = 0;
+		(void) snprintf(idstr, sizeof (idstr), "%u", mch_inst);
+		if ((nvlist_add_string(pairs[i], FM_FMRI_HC_NAME,
+		    "chassis") != 0) ||
+		    (nvlist_add_string(pairs[i], FM_FMRI_HC_ID, idstr)) != 0) {
+			fm_nvlist_destroy(pairs[i], FM_NVA_FREE);
+			return (-1);
+		}
+		i++;
+	}
+
+	/*
+	 * create chassis pair
+	 */
+	pairs[i] = fm_nvlist_create(NULL);
+	if (pairs[i] == NULL) {
+		for (n = 0; n < MAX_PAIRS; n++) {
+			if (pairs[n] != NULL)
+				fm_nvlist_destroy(pairs[n], FM_NVA_FREE);
+		}
+		return (-1);
+	}
+	(void) snprintf(idstr, sizeof (idstr), "%u", chassis_inst);
+	if ((nvlist_add_string(pairs[i], FM_FMRI_HC_NAME, "chassis") != 0) ||
+	    (nvlist_add_string(pairs[i], FM_FMRI_HC_ID, idstr) != 0)) {
+		for (n = 0; n < MAX_PAIRS; n++) {
+			if (pairs[n] != NULL)
+				fm_nvlist_destroy(pairs[n], FM_NVA_FREE);
+		}
+		return (-1);
+	}
+
+	for (j = 0, i = chcnt, cnt = chcnt; j < bb_idx.count; j++) {
+		index = bb_idx.index[j];
+		bbid = bbstypes->ids[index]->id;
+		rc =  smbios_info_bboard(shp, bbid, &bb);
+		if (rc != 0) {
+			rc = -1;
+			break;
+		}
+
+		pairs[i] = fm_nvlist_create(NULL);
+		if (pairs[i] == NULL) {
+			rc = -1;
+			break;
+		}
+
+		id = bbstypes->ids[index]->inst;
+		(void) snprintf(idstr, sizeof (idstr), "%u", id);
+		(void) strncpy(name, bbd_type[bb.smbb_type].name,
+		    sizeof (name));
+		cnt++;
+
+		if (nvlist_add_string(pairs[i], FM_FMRI_HC_NAME, name) != 0 ||
+		    nvlist_add_string(pairs[i], FM_FMRI_HC_ID, idstr)
+		    != 0) {
+			rc = -1;
+			break;
+		}
+		i++;
+	}
+
+	if (rc != -1) {
+		if (nvlist_add_nvlist_array(fmri, FM_FMRI_HC_LIST,
+		    pairs, cnt) != 0) {
+			rc = -1;
+		}
+	}
+
+	for (n = 0; n < cnt; n++) {
+		if (pairs[n] != NULL)
+			fm_nvlist_destroy(pairs[n], FM_NVA_FREE);
+	}
+
+	return (rc);
+}
+
+/*
+ * pass in strand_apic id
+ * return chip's bboards list which has strand_apicid == passed
+ * in strand_apic id
+ */
+static nvlist_t *
+smb_bboard(uint_t strand_apicid, uint16_t proc_hdl, int is_proc)
+{
+	smbios_hdl_t *shp;
+	smbs_cnt_t *bbstypes;
+	int nb;
+	int bb_smbid;
+	nvlist_t *fmri = NULL;
+	int rc = 0;
+	int bb_strcnt;
+
+	if (x86gentopo_legacy)
+		return (NULL);
+
+	shp = ksmbios;
+	if (shp == NULL) {
+		goto bad;
+	}
+
+	/*
+	 * Type 2 structs : "base board"
+	 */
+	bb_strcnt = smb_cnttypes(shp, SMB_TYPE_BASEBOARD);
+	if (bb_strcnt == 0) {
+		goto bad;
+	}
+
+	bbstypes = smb_create_strcnt(bb_strcnt);
+	if (bbstypes == NULL)  {
+		goto bad;
+	}
+
+	bbstypes->type = SMB_TYPE_BASEBOARD;
+	smb_strcnt(shp, bbstypes);
+	smb_bb_contains(shp, bbstypes);
+
+	for (nb = 0; nb < bbstypes->count; nb++) {
+		if (bbstypes->ids[nb]->visited) {
+			continue;
+		}
+
+		bbstypes->ids[nb]->visited = 1;
+		bb_smbid = bbstypes->ids[nb]->id;
+
+		/*
+		 * check if there is a matching  processor under
+		 * this board. If found, find base board(s) of this proc
+		 * If proc is not in contained handle of a base board and
+		 * there is only one base board in the system, treat that base
+		 * board as the parent of the proc
+		 */
+		if (find_matching_proc(shp, strand_apicid,
+		    bb_smbid, proc_hdl, is_proc) || (bbstypes->count == 1)) {
+			fmri = fm_nvlist_create(NULL);
+			if (fmri == NULL) {
+				smb_free_strcnt(bbstypes, bb_strcnt);
+				goto bad;
+			}
+			/*
+			 * find parent by walking the cont_by_id
+			 */
+			rc = smb_get_bb_fmri(shp, fmri, bb_smbid, bbstypes);
+			smb_free_strcnt(bbstypes, bb_strcnt);
+			if (rc == 0) {
+				return (fmri);
+			} else
+				goto bad;
+		}
+
+	}
+
+	smb_free_strcnt(bbstypes, bb_strcnt);
+bad:
+	/* revert to legacy enumeration */
+	x86gentopo_legacy = 1;
+
+	return (NULL);
+}
+
+nvlist_t *
+fm_smb_bboard(uint_t strand_apicid)
+{
+	return (smb_bboard(strand_apicid, 0, PROC));
+}
+
+int
+fm_smb_chipinst(uint_t strand_apicid, uint_t *chip_inst, uint16_t *smbiosid)
+{
+	int n;
+	smbios_hdl_t *shp;
+	uint16_t proc_id;
+	smbs_cnt_t *pstypes;
+	int strcnt;
+
+	if (x86gentopo_legacy)
+		return (-1);
+
+	shp = ksmbios;
+	if (shp == NULL) {
+		goto bad;
+	}
+
+	strcnt = smb_cnttypes(shp, SMB_TYPE_PROCESSOR);
+	if (strcnt == 0)
+		goto bad;
+
+	pstypes = smb_create_strcnt(strcnt);
+	if (pstypes == NULL)
+		goto bad;
+
+	pstypes->type = SMB_TYPE_PROCESSOR;
+	smb_strcnt(shp, pstypes);
+	for (n = 0; n < pstypes->count; n++) {
+		proc_id = pstypes->ids[n]->id;
+		if (find_matching_apic(shp, proc_id, strand_apicid)) {
+			*chip_inst = pstypes->ids[n]->inst;
+			*smbiosid = pstypes->ids[n]->id;
+			smb_free_strcnt(pstypes, strcnt);
+			return (0);
+		}
+	}
+	smb_free_strcnt(pstypes, strcnt);
+bad:
+	/* revert to legacy enumerarion */
+	x86gentopo_legacy = 1;
+
+	return (-1);
+}
+
+nvlist_t *
+fm_smb_mc_bboards(uint_t bdf)
+{
+
+	int i;
+	smbios_hdl_t *shp;
+	uint16_t ext_id;
+	smbios_memarray_ext_t em;
+	nvlist_t *fmri = NULL;
+	smbs_cnt_t *mastypes;
+	int strcnt;
+
+	if (x86gentopo_legacy)
+		return (NULL);
+
+	shp = ksmbios;
+	if (shp == NULL) {
+		goto bad;
+	}
+
+	strcnt = smb_cnttypes(shp, SUN_OEM_EXT_MEMARRAY);
+	if (strcnt == 0)
+		goto bad;
+
+	mastypes = smb_create_strcnt(strcnt);
+	if (mastypes == NULL)
+		goto bad;
+
+	mastypes->type = SUN_OEM_EXT_MEMARRAY;
+	smb_strcnt(shp, mastypes);
+	for (i = 0; i < mastypes->count; i++) {
+		ext_id = mastypes->ids[i]->id;
+		(void) smbios_info_extmemarray(shp, ext_id, &em);
+		if (em.smbmae_bdf == bdf) {
+			fmri = smb_bboard(0, em.smbmae_comp, MC);
+			smb_free_strcnt(mastypes, strcnt);
+			return (fmri);
+		}
+	}
+	smb_free_strcnt(mastypes, strcnt);
+bad:
+	/* revert to legacy enumerarion */
+	x86gentopo_legacy = 1;
+
+	return (NULL);
+}
+
+int
+fm_smb_mc_chipinst(uint_t bdf, uint_t *chip_inst) {
+
+	int i, j;
+	smbios_hdl_t *shp;
+	smbios_memarray_ext_t em;
+	uint16_t ext_id, proc_id;
+	smbs_cnt_t *mastypes;
+	smbs_cnt_t *pstypes;
+	int ma_strcnt, p_strcnt;
+
+	if (x86gentopo_legacy)
+		return (-1);
+
+	shp = ksmbios;
+	if (shp == NULL) {
+		goto bad;
+	}
+
+	ma_strcnt = smb_cnttypes(shp, SUN_OEM_EXT_MEMARRAY);
+	if (ma_strcnt == 0)
+		goto bad;
+
+	mastypes = smb_create_strcnt(ma_strcnt);
+	if (mastypes == NULL)
+		goto bad;
+
+	mastypes->type = SUN_OEM_EXT_MEMARRAY;
+	smb_strcnt(shp, mastypes);
+	for (i = 0; i < mastypes->count; i++) {
+		ext_id = mastypes->ids[i]->id;
+		(void) smbios_info_extmemarray(shp, ext_id, &em);
+		    if (em.smbmae_bdf == bdf) {
+			p_strcnt = smb_cnttypes(shp, SMB_TYPE_PROCESSOR);
+			if (p_strcnt == 0) {
+				smb_free_strcnt(mastypes, ma_strcnt);
+				goto bad;
+			}
+
+			pstypes = smb_create_strcnt(p_strcnt);
+			if (pstypes == NULL) {
+				smb_free_strcnt(mastypes, ma_strcnt);
+				goto bad;
+			}
+
+			pstypes->type = SMB_TYPE_PROCESSOR;
+			smb_strcnt(shp, pstypes);
+			for (j = 0; j < pstypes->count; j++) {
+				proc_id = pstypes->ids[j]->id;
+				if (proc_id == em.smbmae_comp) {
+					*chip_inst = pstypes->ids[j]->inst;
+					smb_free_strcnt(mastypes, ma_strcnt);
+					smb_free_strcnt(pstypes, p_strcnt);
+					return (0);
+				}
+			}
+		}
+	}
+	smb_free_strcnt(mastypes, ma_strcnt);
+	smb_free_strcnt(pstypes, p_strcnt);
+bad:
+	/* revert to legacy enumeration */
+	x86gentopo_legacy = 1;
+
+	return (-1);
+}
--- a/usr/src/uts/intel/sys/cpu_module.h	Tue Nov 03 17:06:24 2009 -0800
+++ b/usr/src/uts/intel/sys/cpu_module.h	Tue Nov 03 21:14:05 2009 -0500
@@ -153,12 +153,16 @@
 extern uint_t cmi_hdl_dieid(cmi_hdl_t);
 extern uint_t cmi_hdl_coreid(cmi_hdl_t);
 extern uint_t cmi_hdl_strandid(cmi_hdl_t);
+extern uint_t cmi_hdl_strand_apicid(cmi_hdl_t);
 extern boolean_t cmi_hdl_is_cmt(cmi_hdl_t);
 extern uint32_t cmi_hdl_chiprev(cmi_hdl_t);
 extern const char *cmi_hdl_chiprevstr(cmi_hdl_t);
 extern uint32_t cmi_hdl_getsockettype(cmi_hdl_t);
 extern const char *cmi_hdl_getsocketstr(cmi_hdl_t);
 extern id_t cmi_hdl_logical_id(cmi_hdl_t);
+extern uint16_t cmi_hdl_smbiosid(cmi_hdl_t);
+extern uint_t cmi_hdl_smb_chipid(cmi_hdl_t);
+extern nvlist_t *cmi_hdl_smb_bboard(cmi_hdl_t);
 
 extern int cmi_hdl_online(cmi_hdl_t, int, int *);
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/uts/intel/sys/fm/smb/fmsmb.h	Tue Nov 03 21:14:05 2009 -0500
@@ -0,0 +1,52 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#ifndef	_SYS_FM_SMB_FMSMB_H
+#define	_SYS_FM_SMB_FMSMB_H
+
+
+#ifdef	__cplusplus
+extern "C" {
+#endif
+
+#include <sys/nvpair.h>
+
+#ifdef _KERNEL
+#include <sys/systm.h>
+
+extern nvlist_t *fm_smb_bboard(uint_t);
+extern nvlist_t *fm_smb_mc_bboards(uint_t);
+extern int fm_smb_chipinst(uint_t, uint_t *, uint16_t *);
+extern int fm_smb_mc_chipinst(uint_t, uint_t *);
+extern void fm_smb_fmacompat();
+
+#endif  /* _KERNEL */
+
+#ifdef	__cplusplus
+}
+#endif
+
+#endif /* _SYS_FM_SMB_FMSMB_H */
--- a/usr/src/uts/intel/sys/hypervisor.h	Tue Nov 03 17:06:24 2009 -0800
+++ b/usr/src/uts/intel/sys/hypervisor.h	Tue Nov 03 21:14:05 2009 -0500
@@ -132,6 +132,7 @@
 extern id_t xen_physcpu_chipid(xen_mc_lcpu_cookie_t);
 extern id_t xen_physcpu_coreid(xen_mc_lcpu_cookie_t);
 extern id_t xen_physcpu_strandid(xen_mc_lcpu_cookie_t);
+extern id_t xen_physcpu_initial_apicid(xen_mc_lcpu_cookie_t);
 extern boolean_t xen_physcpu_is_cmt(xen_mc_lcpu_cookie_t);
 extern id_t xen_physcpu_logical_id(xen_mc_lcpu_cookie_t);
 extern uint64_t xen_physcpu_mcg_cap(xen_mc_lcpu_cookie_t);