summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorDean Sanner <dsanner@us.ibm.com>2013-01-03 10:16:18 -0600
committerA. Patrick Williams III <iawillia@us.ibm.com>2013-08-09 13:43:19 -0500
commit97bd69daf028bec2f7d7f4fbd8feb49486fb4577 (patch)
tree3168aba491fb1cbdd181c40c3e3947410a47e28e /src
parent7b0dcb2cc3a80cb09aa2af5d4cd2f2673c7146a6 (diff)
downloadtalos-hostboot-97bd69daf028bec2f7d7f4fbd8feb49486fb4577.tar.gz
talos-hostboot-97bd69daf028bec2f7d7f4fbd8feb49486fb4577.zip
Basic devtree support
Simple devtree support for Sapphire in SPless mode Change-Id: I4a70bfc5cd3eb3dbd1b443869c046c789f98cc95 Reviewed-on: http://gfw160.austin.ibm.com:8080/gerrit/3739 Tested-by: Jenkins Server Reviewed-by: Daniel M. Crowell <dcrowell@us.ibm.com> Reviewed-by: A. Patrick Williams III <iawillia@us.ibm.com>
Diffstat (limited to 'src')
-rw-r--r--src/include/kernel/misc.H2
-rw-r--r--src/include/sys/misc.h5
-rw-r--r--src/include/usr/devtree/devtree_reasoncodes.H43
-rw-r--r--src/include/usr/devtree/devtreeif.H51
-rw-r--r--src/include/usr/hbotcompid.H10
-rw-r--r--src/include/usr/initservice/initserviceif.H5
-rw-r--r--src/include/usr/intr/interrupt.H40
-rw-r--r--src/include/usr/isteps/istep21list.H1
-rw-r--r--src/kernel/misc.C5
-rw-r--r--src/kernel/shutdown.S47
-rw-r--r--src/kernel/syscall.C1
-rw-r--r--src/lib/syscall_misc.C8
-rw-r--r--src/makefile3
-rw-r--r--src/usr/devtree/bld_devtree.C427
-rw-r--r--src/usr/devtree/devtree.C711
-rw-r--r--src/usr/devtree/devtree.H332
-rw-r--r--src/usr/devtree/makefile35
-rw-r--r--src/usr/hwpf/hwp/start_payload/start_payload.C46
-rw-r--r--src/usr/initservice/baseinitsvc/initservice.C11
-rw-r--r--src/usr/initservice/baseinitsvc/initservice.H49
-rw-r--r--src/usr/intr/intrrp.C18
-rw-r--r--src/usr/intr/intrrp.H32
-rw-r--r--src/usr/makefile2
-rw-r--r--src/usr/targeting/common/xmltohb/attribute_types.xml6
24 files changed, 1788 insertions, 102 deletions
diff --git a/src/include/kernel/misc.H b/src/include/kernel/misc.H
index 544df7c88..42cfd3fa0 100644
--- a/src/include/kernel/misc.H
+++ b/src/include/kernel/misc.H
@@ -45,6 +45,8 @@ namespace KernelMisc
extern uint64_t g_payload_base;
/** @brief Address from base of payload entry-point. */
extern uint64_t g_payload_entry;
+ /** @brief Address from base of payload data pointer. */
+ extern uint64_t g_payload_data;
/** @fn in_kernel_mode
* @brief Determine if the code is currently in kernel mode or not.
diff --git a/src/include/sys/misc.h b/src/include/sys/misc.h
index f3e89e4e7..a73398efa 100644
--- a/src/include/sys/misc.h
+++ b/src/include/sys/misc.h
@@ -95,10 +95,13 @@ extern "C"
* @param[in] i_payload_base The base address (target HRMOR) of the payload.
* @param[in] i_payload_entry The offset from base address of the payload
* entry-point.
+ * @param[in] i_payload_data Data pointer fo the payload. For standalone
+ * Saphire this is the devtree
*/
extern "C" void shutdown(uint64_t i_status,
uint64_t i_payload_base,
- uint64_t i_payload_entry);
+ uint64_t i_payload_entry,
+ uint64_t i_payload_data);
#endif
/** @enum ProcessorCoreType
diff --git a/src/include/usr/devtree/devtree_reasoncodes.H b/src/include/usr/devtree/devtree_reasoncodes.H
new file mode 100644
index 000000000..c996ebca3
--- /dev/null
+++ b/src/include/usr/devtree/devtree_reasoncodes.H
@@ -0,0 +1,43 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/include/usr/devtree/devtree_reasoncodes.H $ */
+/* */
+/* IBM CONFIDENTIAL */
+/* */
+/* COPYRIGHT International Business Machines Corp. 2012,2013 */
+/* */
+/* p1 */
+/* */
+/* Object Code Only (OCO) source materials */
+/* Licensed Internal Code Source Materials */
+/* IBM HostBoot Licensed Internal Code */
+/* */
+/* The source code for this program is not published or otherwise */
+/* divested of its trade secrets, irrespective of what has been */
+/* deposited with the U.S. Copyright Office. */
+/* */
+/* Origin: 30 */
+/* */
+/* IBM_PROLOG_END_TAG */
+#ifndef __DEVTREE_REASONCODES_H
+#define __DEVTREE_REASONCODES_H
+
+#include <hbotcompid.H>
+
+namespace DEVTREE
+{
+ enum DevtreeModuleId
+ {
+ MOD_DEVTREE_INVALID = 0x00, /**< Zero is invalid module id */
+ MOD_DEVTREE_BLD_MEM = 0x01,
+ };
+
+ enum DevtreeReasonCode
+ {
+ RC_ATTR_MEMSIZE_GET_FAIL = DEVTREE_COMP_ID | 0x01,
+ RC_ATTR_MEMBASE_GET_FAIL = DEVTREE_COMP_ID | 0x02,
+ };
+};
+
+#endif
diff --git a/src/include/usr/devtree/devtreeif.H b/src/include/usr/devtree/devtreeif.H
new file mode 100644
index 000000000..e6c068e88
--- /dev/null
+++ b/src/include/usr/devtree/devtreeif.H
@@ -0,0 +1,51 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/include/usr/devtree/devtreeif.H $ */
+/* */
+/* IBM CONFIDENTIAL */
+/* */
+/* COPYRIGHT International Business Machines Corp. 2012,2013 */
+/* */
+/* p1 */
+/* */
+/* Object Code Only (OCO) source materials */
+/* Licensed Internal Code Source Materials */
+/* IBM HostBoot Licensed Internal Code */
+/* */
+/* The source code for this program is not published or otherwise */
+/* divested of its trade secrets, irrespective of what has been */
+/* deposited with the U.S. Copyright Office. */
+/* */
+/* Origin: 30 */
+/* */
+/* IBM_PROLOG_END_TAG */
+#ifndef __DEVTREE_IF_H
+#define __DEVTREE_IF_H
+
+#include <errl/errlentry.H>
+
+
+namespace DEVTREE
+{
+
+ /**
+ * @brief Build flattened dev tree for Sapphire
+ *
+ * @return errlHndl_t NULL on success
+ */
+ errlHndl_t build_flatdevtree( void );
+
+ /**
+ * @brief Get the address of the flattened dev tree for Sapphire
+ *
+ * @return uint64_t - Address if valid, else NULL
+ */
+ uint64_t get_flatdevtree_phys_addr( void );
+
+
+
+
+}; // end namespace DEVTREE
+
+#endif
diff --git a/src/include/usr/hbotcompid.H b/src/include/usr/hbotcompid.H
index 0484715f1..994aac1de 100644
--- a/src/include/usr/hbotcompid.H
+++ b/src/include/usr/hbotcompid.H
@@ -265,6 +265,7 @@ const char KERNEL_COMP_NAME[] = "kernel";
//@{
const compId_t IBSCOM_COMP_ID = 0x1C00;
const char IBSCOM_COMP_NAME[] = "ibscom";
+//@}
/** @name VPD
@@ -291,7 +292,6 @@ const compId_t IPC_COMP_ID = 0x1F00;
const char IPC_COMP_NAME[] = "ipc";
//@}
-
/** @name HSVC
* Host Services component
* For the code running under PHYP
@@ -300,6 +300,14 @@ const char IPC_COMP_NAME[] = "ipc";
const compId_t HSVC_COMP_ID = 0x2000;
const char HSVC_COMP_NAME[] = "hsvc";
+/** @name DEVTREE
+ * DEVTREE component
+ */
+//@{
+const compId_t DEVTREE_COMP_ID = 0x2100;
+const char DEVTREE_COMP_NAME[] = "devtree";
+//@}
+
/** @name RESERVED
* Reserved component ID. x3100 is the component ID
* of FipS ERRL component. Due to our use of
diff --git a/src/include/usr/initservice/initserviceif.H b/src/include/usr/initservice/initserviceif.H
index f09433e15..77db81ea4 100644
--- a/src/include/usr/initservice/initserviceif.H
+++ b/src/include/usr/initservice/initserviceif.H
@@ -84,6 +84,7 @@ bool unregisterShutdownEvent(msg_q_t i_msgQ);
* payload.
* @param[in] i_payload_entry - The offset from base address of the
* payload entry-point.
+ * @param[in] i_payload_data - Pointer to payload data (if needed)
*
* @return Nothing
*
@@ -91,8 +92,8 @@ bool unregisterShutdownEvent(msg_q_t i_msgQ);
*/
void doShutdown ( uint64_t i_status,
uint64_t i_payload_base = 0,
- uint64_t i_payload_entry = 0 ) NO_RETURN;
-
+ uint64_t i_payload_entry = 0,
+ uint64_t i_payload_data = 0) NO_RETURN;
}
#endif
diff --git a/src/include/usr/intr/interrupt.H b/src/include/usr/intr/interrupt.H
index cf129712a..f41f8ccf6 100644
--- a/src/include/usr/intr/interrupt.H
+++ b/src/include/usr/intr/interrupt.H
@@ -33,6 +33,37 @@ namespace TARGETING
namespace INTR
{
+ /**
+ * cpu PIR register
+ */
+ struct PIR_t
+ {
+ union
+ {
+ uint32_t word;
+ struct
+ {
+ //P8:
+ uint32_t reserved:19; //!< zeros
+ uint32_t nodeId:3; //!< node (0-3)
+ uint32_t chipId:3; //!< chip pos on node (0-5)
+ uint32_t coreId:4; //!< Core number (1-6,9-14)?
+ uint32_t threadId:3; //!< Thread number (0-7)
+ } PACKED;
+ };
+ PIR_t(uint32_t i_word = 0) : word(i_word) {}
+
+ PIR_t operator= (uint32_t i_word)
+ {
+ word = i_word;
+ return word;
+ }
+
+ bool operator< (const PIR_t& r) const
+ {
+ return word < r.word;
+ }
+ };
/**
* External Interrupt Types (XISR)
@@ -165,6 +196,15 @@ namespace INTR
*/
errlHndl_t enablePsiIntr(TARGETING::Target * i_target);
+ /**
+ * Return the interrupt presenter for requested target/thread
+ * @param[in] i_ex The target EX
+ * @param[in] i_thread Which thread on EX (0-7)
+ * @return 64 bit address for the interrupt present addr
+ */
+ uint64_t getIntpAddr(const TARGETING::Target * i_ex,
+ uint8_t i_thread);
+
};
#endif
diff --git a/src/include/usr/isteps/istep21list.H b/src/include/usr/isteps/istep21list.H
index 0d0f6108a..7b4bfb8e1 100644
--- a/src/include/usr/isteps/istep21list.H
+++ b/src/include/usr/isteps/istep21list.H
@@ -107,6 +107,7 @@ const DepModInfo g_istep21Dependancies = {
{
DEP_LIB(libstart_payload.so),
DEP_LIB(libruntime.so),
+ DEP_LIB(libdevtree.so),
{ 0 },
}
};
diff --git a/src/kernel/misc.C b/src/kernel/misc.C
index 542e34c64..9e19674ad 100644
--- a/src/kernel/misc.C
+++ b/src/kernel/misc.C
@@ -38,7 +38,8 @@
#include <kernel/hbdescriptor.H>
extern "C"
- void kernel_shutdown(size_t, uint64_t, uint64_t, uint64_t) NO_RETURN;
+ void kernel_shutdown(size_t, uint64_t, uint64_t, uint64_t,
+ uint64_t) NO_RETURN;
extern HB_Descriptor kernel_hbDescriptor;
@@ -47,6 +48,7 @@ namespace KernelMisc
uint64_t g_payload_base = 0;
uint64_t g_payload_entry = 0;
+ uint64_t g_payload_data = 0;
void shutdown()
{
@@ -139,6 +141,7 @@ namespace KernelMisc
kernel_shutdown(CpuManager::getCpuCount(),
g_payload_base,
g_payload_entry,
+ g_payload_data,
l_lowestPIR);
}
}
diff --git a/src/kernel/shutdown.S b/src/kernel/shutdown.S
index bb7657318..74492f37d 100644
--- a/src/kernel/shutdown.S
+++ b/src/kernel/shutdown.S
@@ -1,25 +1,25 @@
-# IBM_PROLOG_BEGIN_TAG
-# This is an automatically generated prolog.
+# IBM_PROLOG_BEGIN_TAG
+# This is an automatically generated prolog.
#
-# $Source: src/kernel/shutdown.S $
+# $Source: src/kernel/shutdown.S $
#
-# IBM CONFIDENTIAL
+# IBM CONFIDENTIAL
#
-# COPYRIGHT International Business Machines Corp. 2012
+# COPYRIGHT International Business Machines Corp. 2012,2013
#
-# p1
+# p1
#
-# Object Code Only (OCO) source materials
-# Licensed Internal Code Source Materials
-# IBM HostBoot Licensed Internal Code
+# Object Code Only (OCO) source materials
+# Licensed Internal Code Source Materials
+# IBM HostBoot Licensed Internal Code
#
-# The source code for this program is not published or other-
-# wise divested of its trade secrets, irrespective of what has
-# been deposited with the U.S. Copyright Office.
+# The source code for this program is not published or otherwise
+# divested of its trade secrets, irrespective of what has been
+# deposited with the U.S. Copyright Office.
#
-# Origin: 30
+# Origin: 30
#
-# IBM_PROLOG_END_TAG
+# IBM_PROLOG_END_TAG
.include "kernel/ppcconsts.S"
#define KERNEL_BARRIER(addr, count, temp) \
@@ -64,7 +64,8 @@
;// @param[in] r3 - CPU count - Number of active CPUs.
;// @param[in] r4 - Payload Base
;// @param[in] r5 - Payload Entry
- ;// @param[in] r6 - Last thread to enter payload.
+ ;// @param[in] r6 - Payload Data
+ ;// @param[in] r7 - Last thread to enter payload.
;//
.global kernel_shutdown
kernel_shutdown:
@@ -72,16 +73,16 @@ kernel_shutdown:
li r10, 1
rotldi r10, r10, 63
;// Retrieve existing HRMOR.
- mfspr r7, HRMOR
+ mfspr r0, HRMOR
;// Determine physical address of shutdown_barrier.
lis r8, kernel_shutdown_barriers@h
ori r8, r8, kernel_shutdown_barriers@l
- or r8, r8, r7 ;// Apply HRMOR.
+ or r8, r8, r0 ;// Apply HRMOR.
or r8, r8, r10 ;// Apply EA[0] = 1.
;// Determine physical address of EA[0]=1 mode instruction.
lis r9, kernel_shutdown_ea0_1_mode@h
ori r9, r9, kernel_shutdown_ea0_1_mode@l
- or r9, r9, r7 ;// Apply HRMOR.
+ or r9, r9, r0 ;// Apply HRMOR.
or r9, r9, r10 ;// Apply EA[0] = 1.
;// Jump to enter EA[0] = 1
mtlr r9
@@ -110,11 +111,11 @@ kernel_shutdown_ea0_1_mode:
KERNEL_BARRIER(r8, r3, r11)
;// "Barrier" 4:
- ;// Increment counter as leaving, except PIR == r6 waits.
+ ;// Increment counter as leaving, except PIR == r7 waits.
addi r8, r8, 8
- ;// Check for PIR == r6.
+ ;// Check for PIR == r7.
mfspr r10, PIR
- cmp cr0, r10, r6
+ cmp cr0, r10, r7
beq 3f
;// Increment thread count.
1:
@@ -130,10 +131,12 @@ kernel_shutdown_ea0_1_mode:
;// Save MSR, move to HSRR1.
mfmsr r10
mtspr HSRR1, r10
+ ;// Move payload data to r3
+ mr r3,r6
;// Jump to entry point. Causes HSRR0 -> NIA, HSSR1 -> MSR.
hrfid
- ;// PIR == r6 waits here for all others to leave.
+ ;// PIR == r7 waits here for all others to leave.
3:
subi r3, r3, 1
1:
diff --git a/src/kernel/syscall.C b/src/kernel/syscall.C
index 1c9b62ab6..be2b51d59 100644
--- a/src/kernel/syscall.C
+++ b/src/kernel/syscall.C
@@ -650,6 +650,7 @@ namespace Systemcalls
uint64_t status = static_cast<uint64_t>(TASK_GETARG0(t));
KernelMisc::g_payload_base = static_cast<uint64_t>(TASK_GETARG1(t));
KernelMisc::g_payload_entry = static_cast<uint64_t>(TASK_GETARG2(t));
+ KernelMisc::g_payload_data = static_cast<uint64_t>(TASK_GETARG3(t));
CpuManager::requestShutdown(status);
TASK_SETRTN(t, 0);
}
diff --git a/src/lib/syscall_misc.C b/src/lib/syscall_misc.C
index f2b50bb01..c972292f9 100644
--- a/src/lib/syscall_misc.C
+++ b/src/lib/syscall_misc.C
@@ -30,12 +30,14 @@ using namespace Systemcalls;
void shutdown(uint64_t i_status,
uint64_t i_payload_base,
- uint64_t i_payload_entry)
+ uint64_t i_payload_entry,
+ uint64_t i_payload_data)
{
- _syscall3(MISC_SHUTDOWN,
+ _syscall4(MISC_SHUTDOWN,
reinterpret_cast<void*>(i_status),
reinterpret_cast<void*>(i_payload_base),
- reinterpret_cast<void*>(i_payload_entry));
+ reinterpret_cast<void*>(i_payload_entry),
+ reinterpret_cast<void*>(i_payload_data));
}
ProcessorCoreType cpu_core_type()
diff --git a/src/makefile b/src/makefile
index 98c1301ef..fb8c225a9 100644
--- a/src/makefile
+++ b/src/makefile
@@ -57,7 +57,8 @@ EXTENDED_MODULES = targeting ecmddatabuffer fapi hwp plat \
core_activate dram_initialization edi_ei_initialization \
establish_system_smp occ\
nest_chiplets start_payload thread_activate slave_sbe \
- attn runtime ibscom dump tod_init secureboot_ext
+ attn runtime ibscom dump tod_init secureboot_ext \
+ devtree
TESTCASE_MODULES = cxxtest testtrace testerrl testdevicefw testsyslib \
testscom testxscom testtargeting testinitservice testkernel \
diff --git a/src/usr/devtree/bld_devtree.C b/src/usr/devtree/bld_devtree.C
new file mode 100644
index 000000000..85d2d0773
--- /dev/null
+++ b/src/usr/devtree/bld_devtree.C
@@ -0,0 +1,427 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/usr/devtree/bld_devtree.C $ */
+/* */
+/* IBM CONFIDENTIAL */
+/* */
+/* COPYRIGHT International Business Machines Corp. 2013 */
+/* */
+/* p1 */
+/* */
+/* Object Code Only (OCO) source materials */
+/* Licensed Internal Code Source Materials */
+/* IBM HostBoot Licensed Internal Code */
+/* */
+/* The source code for this program is not published or otherwise */
+/* divested of its trade secrets, irrespective of what has been */
+/* deposited with the U.S. Copyright Office. */
+/* */
+/* Origin: 30 */
+/* */
+/* IBM_PROLOG_END_TAG */
+/* $IBMCopyrightBlock:
+ IBM Confidential
+
+ OCO Source Materials
+
+ 5733-907
+
+ (C) Copyright IBM Corp. 2011
+
+ The source code for this program is not published or other-
+ wise divested of its trade secrets, irrespective of what has
+ been deposited with the U.S. Copyright Office.
+$ */
+
+#include <trace/interface.H>
+#include <errl/errlentry.H>
+#include <targeting/common/target.H>
+#include <targeting/common/targetservice.H>
+#include <targeting/common/utilFilter.H>
+#include <devtree/devtree_reasoncodes.H>
+#include <devtree/devtreeif.H>
+#include "devtree.H"
+#include <sys/mmio.h> //THIRTYTWO_GB
+#include <intr/interrupt.H>
+
+
+trace_desc_t *g_trac_devtree = NULL;
+TRAC_INIT(&g_trac_devtree, "DEVTREE", 4096);
+
+namespace DEVTREE
+{
+using namespace TARGETING;
+
+enum BuildConstants
+{
+ DEVTREE_DATA_ADDR =0xFF00000, /* 256MB - 1MB*/
+ DEVTREE_SPACE_SIZE =0x10000, /*64KB*/
+ XSCOM_NODE_SHIFT =38, /*Node pos is 25, so 63-25=38*/
+ XSCOM_CHIP_SHIFT =35, /*Chip pos is 28, so 63-28=35*/
+ CHIPID_NODE_SHIFT =3, /*CHIPID is NNNCCC, shift 3*/
+ PHB0_MASK =0x80,
+ MAX_PHBs = 3, /*Max PHBs per chip is 3*/
+};
+
+
+errlHndl_t bld_fdt_cpu(devTree * i_dt)
+{
+ errlHndl_t errhdl = NULL;
+ const char* cpuNodeName = "PowerPC,POWER8";
+ const char* cpuIntrName = "interrupt-controller";
+ const char* xscomNodeName = "xscom";
+ const char* todNodeName = "chiptod";
+ const char* pciNodeName = "pbcq";
+ const char* lpcNodeName = "lpc";
+ const uint32_t THREADPERCORE = 8;
+
+ /* Find the / node and add a cpus node under it. */
+ dtOffset_t rootNode = i_dt->findNode("/");
+ dtOffset_t cpusNode = i_dt->addNode(rootNode, "cpus");
+
+ // Grab a system object to work with
+ TARGETING::Target* sys = NULL;
+ TARGETING::targetService().getTopLevelTarget(sys);
+ uint64_t l_xscomBaseAddr =
+ sys->getAttr<TARGETING::ATTR_XSCOM_BASE_ADDRESS>();
+
+
+ /* Add the # address & size cell properties to /cpus. */
+ i_dt->addPropertyCell32(cpusNode, "#address-cells", 1);
+ i_dt->addPropertyCell32(cpusNode, "#size-cells", 0);
+
+ uint32_t segmentSizes[4] = { 0x1c, 0x28, 0xffffffff, 0xffffffff };
+ uint32_t segmentPageSizes[] =
+ {
+ 12, 0x0, 3, /* 4k SLB page size, L,LP = 0,x1, 3 page size encodings */
+ 12, 0x0, /* 4K PTE page size, L,LP = 0,x0 */
+ 16, 0x7, /* 64K PTE page size, L,LP = 1,x7 */
+ 24, 0x38, /* 16M PTE page size, L,LP = 1,x38 */
+ 16, 0x110, 2, /* 64K SLB page size, L,LP = 1,x1, 2 page size encodings*/
+ 16, 0x1, /* 64K PTE page size, L,LP = 1,x1 */
+ 24, 0x8, /* 16M PTE page size, L,LP = 1,x8 */
+ 20, 0x130, 1, /* 1M SLB page size, L,LP = 1,x3, 1 page size encoding */
+ 20, 0x2, /* 1M PTE page size, L,LP = 1,x2 */
+ 24, 0x100, 1, /* 16M SLB page size, L,LP = 1,x0, 1 page size encoding */
+ 24, 0x0, /* 16M PTE page size, L,LP = 1,x0 */
+ 34, 0x120, 1, /* 16G SLB page size, L,LP = 1,x2, 1 page size encoding */
+ 34, 0x3 /* 16G PTE page size, L,LP = 1,x3 */
+ };
+
+
+ // Get all functional proc chip targets
+ TARGETING::TargetHandleList l_cpuTargetList;
+ getAllChips(l_cpuTargetList, TYPE_PROC);
+
+ for ( size_t proc = 0; (!errhdl) && (proc < l_cpuTargetList.size()); proc++)
+ {
+ const TARGETING::Target * l_pProc = l_cpuTargetList[proc];
+
+ uint32_t l_fabId = l_pProc->getAttr<TARGETING::ATTR_FABRIC_NODE_ID>();
+ uint32_t l_procPos = l_pProc->getAttr<TARGETING::ATTR_FABRIC_CHIP_ID>();
+ uint32_t l_chipid = (l_fabId << CHIPID_NODE_SHIFT) + l_procPos;
+
+ /* Find calculate the Xscom addr for this chip and add it */
+ uint64_t l_xscomAddr = l_xscomBaseAddr +
+ (static_cast<uint64_t>(l_chipid) << XSCOM_CHIP_SHIFT);
+
+ dtOffset_t xscomNode = i_dt->addNode(rootNode, xscomNodeName,
+ l_xscomAddr);
+
+ uint64_t xscom_prop[2] = { l_xscomAddr, THIRTYTWO_GB};
+ i_dt->addPropertyCells64(xscomNode, "reg", xscom_prop, 2);
+ const char* xscom_compatStrs[] = {"ibm,xscom","ibm,power8-xscom",NULL};
+ i_dt->addPropertyCell32(xscomNode, "#address-cells", 1);
+ i_dt->addPropertyCell32(xscomNode, "#size-cells", 1);
+ i_dt->addPropertyCell32(xscomNode, "ibm,chip-id", l_chipid);
+ i_dt->addPropertyStrings(xscomNode, "compatible", xscom_compatStrs);
+
+
+ /*ChipTod*/
+ uint32_t l_todInfo = 0x40000; /*Chip tod Scom addr*/
+ dtOffset_t todNode = i_dt->addNode(xscomNode, todNodeName, l_todInfo);
+ const char* tod_compatStrs[] = {"ibm,power-chiptod",
+ "ibm,power8-chiptod", NULL};
+ i_dt->addPropertyStrings(todNode, "compatible", tod_compatStrs);
+ uint32_t tod_prop[2] = { l_todInfo, 0x34 }; //# of scoms in range
+ i_dt->addPropertyCells32(todNode, "reg", tod_prop, 2);
+
+ if(l_chipid == 0x0) //Master chip
+ {
+ i_dt->addProperty(todNode, "primary"); //TODO -- get from ATTR
+
+ uint32_t l_lpcInfo = 0xB0020; /*ECCB FW addr*/
+ dtOffset_t lpcNode = i_dt->addNode(xscomNode,lpcNodeName,l_lpcInfo);
+ i_dt->addPropertyString(lpcNode, "compatible", "ibm,power8-lpc");
+ uint32_t lpc_prop[2] = { l_lpcInfo, 0x4 }; //# of scoms in range
+ i_dt->addPropertyCells32(lpcNode, "reg", lpc_prop, 2);
+ }
+
+ /*PCIE*/
+ uint8_t l_phbActive =
+ l_pProc->getAttr<TARGETING::ATTR_PROC_PCIE_PHB_ACTIVE>();
+ //TARGETING::ATTR_PROC_PCIE_LANE_EQUALIZATION_type l_laneEq =
+ // l_pProc->getAttr<TARGETING::ATTR_PROC_PCIE_LANE_EQUALIZATION>();
+ uint32_t l_laneEq[] = {0,0,0,0};
+
+ TRACFCOMP( g_trac_devtree, "Chip %X PHB Active mask %X",
+ l_chipid, l_phbActive);
+
+ for(uint32_t l_phb =0; l_phb < MAX_PHBs; l_phb++)
+ {
+ if(!(l_phbActive & (PHB0_MASK>>l_phb)))
+ {
+ continue;
+ }
+
+ TRACFCOMP( g_trac_devtree, "Adding PHB %d", l_phb);
+
+ /*PHB is active, add to Xscom map*/
+ uint32_t l_peInfo = 0x02012000 + (l_phb * 0x400);
+ uint32_t l_pciInfo = 0x09012000 + (l_phb * 0x400);
+ uint32_t l_spciInfo = 0x09013c00 + (l_phb * 0x40);
+ dtOffset_t pcieNode = i_dt->addNode(xscomNode,pciNodeName,l_peInfo);
+ const char* pcie_compatStrs[] = {"ibm,power8-pbcq", NULL};
+ i_dt->addPropertyStrings(pcieNode, "compatible", pcie_compatStrs);
+ uint32_t pcie_prop[6] = { l_peInfo, 0x20, //# of scoms in range
+ l_pciInfo, 0x5, //# of scoms in range
+ l_spciInfo, 0x15}; //# of scoms in range
+ i_dt->addPropertyCells32(pcieNode, "reg", pcie_prop, 6);
+ i_dt->addPropertyCell32(pcieNode, "ibm,phb-index", l_phb);
+ i_dt->addPropertyCell32(pcieNode, "ibm,lane-eq", l_laneEq[l_phb]);
+ }
+
+ TARGETING::TargetHandleList l_exlist;
+ getChildChiplets( l_exlist, l_pProc, TYPE_CORE );
+ for (size_t core = 0; core < l_exlist.size(); core++)
+ {
+ const TARGETING::Target * l_ex = l_exlist[core];
+ if(l_ex->getAttr<TARGETING::ATTR_HWAS_STATE>().functional != true)
+ {
+ continue; //Not functional
+ }
+
+ /* TODO -- need to add cache info */
+
+ /* Add a dev node for each cpu core. The unit address is the
+ *interrupt server number of the first thread of the core.
+ */
+
+ /* Proc ID Reg is N NNCC CPPP PTTT Where
+ NNN is node number
+ CCC is Chip
+ PPPP is the core number
+ TTT is Thread num
+ */
+ uint32_t l_coreNum = l_ex->getAttr<TARGETING::ATTR_CHIP_UNIT>();
+ INTR::PIR_t pir(0);
+ pir.nodeId = l_fabId;
+ pir.chipId = l_procPos;
+ pir.coreId = l_coreNum;
+
+ TRACFCOMP( g_trac_devtree, "Added pir[%x] node %d proc %d core %d",
+ pir.word, l_fabId, l_procPos, l_coreNum );
+
+ cpusNode = i_dt->findNode("/cpus");
+ dtOffset_t cpuNode = i_dt->addNode(cpusNode, cpuNodeName,
+ pir.word);
+ i_dt->addPropertyString(cpuNode, "device_type", "cpu");
+ i_dt->addPropertyString(cpuNode, "status", "okay");
+ i_dt->addPropertyCell32(cpuNode, "reg", pir.word);
+ i_dt->addPropertyCell32(cpuNode, "d-cache-size", 0x10000);
+ i_dt->addPropertyCell32(cpuNode, "i-cache-size", 0x8000);
+ i_dt->addPropertyCell32(cpuNode, "d-cache-line-size", 128);
+ i_dt->addPropertyCell32(cpuNode, "i-cache-line-size", 128);
+ i_dt->addPropertyCell32(cpuNode, "ibm,dfp", 1);
+ i_dt->addPropertyCell32(cpuNode, "ibm,vmx", 2);
+ i_dt->addPropertyCell32(cpuNode, "timebase-frequency", 512000000);
+ i_dt->addPropertyCell32(cpuNode, "clock-frequency", 2000000000);
+ i_dt->addPropertyCell32(cpuNode, "ibm,pir", pir.word);
+ i_dt->addPropertyCell32(cpuNode, "ibm,chip-id", l_chipid);
+ i_dt->addPropertyCells32(cpuNode, "ibm,processor-segment-sizes",
+ segmentSizes,
+ sizeof(segmentSizes) / sizeof(uint32_t));
+ i_dt->addPropertyCells32(cpuNode, "ibm,segment-page-sizes",
+ segmentPageSizes,
+ sizeof(segmentPageSizes)/sizeof(uint32_t));
+ i_dt->addPropertyCell32(cpuNode, "ibm,slb-size", 32);
+
+ uint32_t interruptServerNum[THREADPERCORE];
+ for(size_t i = 0; i < THREADPERCORE ; i++)
+ {
+ pir.threadId = i;
+ interruptServerNum[i] = pir.word;
+ }
+
+ i_dt->addPropertyCells32(cpuNode, "ibm,ppc-interrupt-server#s",
+ interruptServerNum, THREADPERCORE);
+
+ //IBASE ADDRESS
+ uint64_t l_ibase = INTR::getIntpAddr(l_ex, 0);
+
+ rootNode = i_dt->findNode("/");
+ dtOffset_t intNode = i_dt->addNode(rootNode, cpuIntrName, l_ibase);
+ const char* intr_compatStrs[] = {"ibm,ppc-xicp", "ibm,power8-xicp",
+ NULL};
+ i_dt->addPropertyStrings(intNode, "compatible", intr_compatStrs);
+ uint32_t int_serv[2] = { interruptServerNum[0], THREADPERCORE};
+ i_dt->addPropertyCells32(intNode, "ibm,interrupt-server-ranges",
+ int_serv, 2);
+ i_dt->addPropertyCell32(intNode, "#address-cells", 0);
+ i_dt->addPropertyCell32(intNode, "#interrupt-cells", 1);
+ i_dt->addPropertyString(intNode, "device_type",
+ "PowerPC-External-Interrupt-Presentation");
+ uint64_t intr_prop[THREADPERCORE][2];
+ for(size_t i=0; i < THREADPERCORE; i++)
+ {
+ intr_prop[i][0] = INTR::getIntpAddr(l_ex, i);
+ intr_prop[i][1] = 0x1000;
+ }
+ i_dt->addPropertyCells64(intNode, "reg",
+ reinterpret_cast<uint64_t*>(intr_prop),
+ sizeof(intr_prop) / sizeof(uint64_t));
+
+ /* TODO add associativity*/
+ }
+ }
+
+ return errhdl;
+}
+
+errlHndl_t bld_fdt_mem(devTree * i_dt)
+{
+ errlHndl_t errhdl = NULL;
+ bool rc;
+
+ do
+ {
+
+ /* Find the / node and add a memory node(s) under it. */
+ dtOffset_t rootNode = i_dt->findNode("/");
+
+ // Grab a system object to work with
+ TARGETING::Target* sys = NULL;
+ TARGETING::targetService().getTopLevelTarget(sys);
+
+ // Get all functional proc chip targets
+ TARGETING::TargetHandleList l_cpuTargetList;
+ getAllChips(l_cpuTargetList, TYPE_PROC);
+
+ for ( size_t proc = 0;
+ (!errhdl) && (proc < l_cpuTargetList.size()); proc++ )
+ {
+ const TARGETING::Target * l_pProc = l_cpuTargetList[proc];
+
+ uint64_t l_bases[8] = {0,};
+ uint64_t l_sizes[8] = {0,};
+ rc = l_pProc->tryGetAttr<TARGETING::ATTR_PROC_MEM_BASES>(l_bases);
+ if(!rc)
+ {
+ /*@
+ * @errortype
+ * @reasoncode DEVTREE::RC_ATTR_MEMBASE_GET_FAIL
+ * @moduleid DEVTREE::MOD_DEVTREE_BLD_MEM
+ * @userdata1 Return code from ATTR_GET
+ * @userdata2 Attribute Id that failed
+ * @devdesc Error retrieving attribute
+ */
+ errhdl=new ERRORLOG::ErrlEntry(ERRORLOG::ERRL_SEV_UNRECOVERABLE,
+ MOD_DEVTREE_BLD_MEM,
+ RC_ATTR_MEMBASE_GET_FAIL,
+ rc,
+ ATTR_PROC_MEM_BASES);
+ break;
+ }
+
+ rc = l_pProc->tryGetAttr<TARGETING::ATTR_PROC_MEM_SIZES>(l_sizes);
+ if(!rc)
+ {
+ /*@
+ * @errortype
+ * @reasoncode DEVTREE::RC_ATTR_MEMSIZE_GET_FAIL
+ * @moduleid DEVTREE::MOD_DEVTREE_BLD_MEM
+ * @userdata1 Return code from ATTR_GET
+ * @userdata2 Attribute Id that failed
+ * @devdesc Error retrieving attribute
+ */
+ errhdl=new ERRORLOG::ErrlEntry(ERRORLOG::ERRL_SEV_UNRECOVERABLE,
+ MOD_DEVTREE_BLD_MEM,
+ RC_ATTR_MEMSIZE_GET_FAIL,
+ rc,
+ ATTR_PROC_MEM_SIZES);
+ break;
+ }
+
+ for (size_t i=0; i< 8; i++)
+ {
+ if(l_sizes[i]) //non zero means that there is memory present
+ {
+ dtOffset_t memNode = i_dt->addNode(rootNode, "memory",
+ l_bases[i]);
+ i_dt->addPropertyString(memNode, "device_type","memory");
+ uint64_t propertyCells[2] = {l_bases[i],l_sizes[i]};
+ i_dt->addPropertyCells64(memNode, "reg", propertyCells, 2);
+
+ /*TODO -- add core affinity*/
+
+ /*TODO -- add VPD*/
+ }
+ }
+ }
+ }while(0);
+ return errhdl;
+}
+
+errlHndl_t bld_fdt_io(devTree * i_dt)
+{
+ errlHndl_t errhdl = NULL;
+
+
+
+ return errhdl;
+}
+
+errlHndl_t build_flatdevtree( void )
+{
+ errlHndl_t errhdl = NULL;
+ devTree * dt = &Singleton<devTree>::instance();
+
+ do
+ {
+
+ TRACFCOMP( g_trac_devtree, "---devtree init---" );
+ dt->initialize(DEVTREE_DATA_ADDR, DEVTREE_SPACE_SIZE);
+
+ TRACFCOMP( g_trac_devtree, "---devtree cpu ---" );
+ errhdl = bld_fdt_cpu(dt);
+ if(errhdl)
+ {
+ break;
+ }
+
+ TRACFCOMP( g_trac_devtree, "---devtree mem ---" );
+ errhdl = bld_fdt_mem(dt);
+ if(errhdl)
+ {
+ break;
+ }
+
+ TRACFCOMP( g_trac_devtree, "---devtree io ---" );
+ errhdl = bld_fdt_io(dt);
+ if(errhdl)
+ {
+ break;
+ }
+ }while(0);
+
+ return errhdl;
+}
+
+
+uint64_t get_flatdevtree_phys_addr()
+{
+ return Singleton<devTree>::instance().getBlobPhys();
+}
+
+}
diff --git a/src/usr/devtree/devtree.C b/src/usr/devtree/devtree.C
new file mode 100644
index 000000000..562bf876c
--- /dev/null
+++ b/src/usr/devtree/devtree.C
@@ -0,0 +1,711 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/usr/devtree/devtree.C $ */
+/* */
+/* IBM CONFIDENTIAL */
+/* */
+/* COPYRIGHT International Business Machines Corp. 2013 */
+/* */
+/* p1 */
+/* */
+/* Object Code Only (OCO) source materials */
+/* Licensed Internal Code Source Materials */
+/* IBM HostBoot Licensed Internal Code */
+/* */
+/* The source code for this program is not published or otherwise */
+/* divested of its trade secrets, irrespective of what has been */
+/* deposited with the U.S. Copyright Office. */
+/* */
+/* Origin: 30 */
+/* */
+/* IBM_PROLOG_END_TAG */
+/* $IBMCopyrightBlock:
+ IBM Confidential
+
+ OCO Source Materials
+
+ 5733-907
+
+ (C) Copyright IBM Corp. 2011
+
+ The source code for this program is not published or other-
+ wise divested of its trade secrets, irrespective of what has
+ been deposited with the U.S. Copyright Office.
+$ */
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+#include "devtree.H"
+#include <sys/mm.h>
+#include <limits.h>
+
+extern trace_desc_t *g_trac_devtree;
+
+namespace DEVTREE
+{
+
+uint64_t devTree::getBlobPhys()
+{
+ return mPhysAddr;
+}
+
+uint32_t devTree::getSize()
+{
+ return mHeader->totalSize;
+}
+
+void devTree::initialize(uint64_t i_addr, size_t i_maxSize)
+{
+ /* Initialize the device tree header. */
+ mMaxSize = i_maxSize;
+ mPhysAddr = i_addr;
+ mSpace= static_cast<char*>
+ (mm_block_map(reinterpret_cast<void*>(mPhysAddr),
+ mMaxSize));
+ memset(mSpace, 0, mMaxSize);
+ mNextPhandle = 1;
+
+ TRACFCOMP( g_trac_devtree, "FDT located @ v:%p p:0x%x", mSpace, mPhysAddr);
+
+ mHeader->magicNumber = DT_MAGIC;
+ mHeader->totalSize = sizeof(*mHeader) + (sizeof(dtReserveEntry_t) * 2);
+ mHeader->offsetStruct = mHeader->totalSize;
+ mHeader->offsetStrings = mHeader->totalSize;
+ mHeader->offsetReservedMemMap = sizeof(*mHeader);
+ mHeader->version = DT_CUR_VERSION;
+ mHeader->lastCompatVersion = DT_COMPAT_VERSION;
+ mHeader->bootCpuId = 0;
+ mHeader->sizeStrings = 0;
+ mHeader->sizeStruct = 0;
+
+ /* Create the initial root node. */
+ uint32_t* curWord = getStructSectionAtOffset(0);
+ *curWord++ = DT_BEGIN_NODE;
+ *curWord++ = 0;
+ *curWord++ = DT_END_NODE;
+ *curWord = DT_END;
+
+ /* Adjust offsets and sizes to account for the root node we just added*/
+ uint32_t structSizeAdded = sizeof(uint32_t) * 4;
+ mHeader->offsetStrings += structSizeAdded;
+ mHeader->sizeStruct += structSizeAdded;
+ mHeader->totalSize += structSizeAdded;
+
+ /* Setup the memory reserve map to include the region that
+ Hostboot places the SLW and OCC images*/
+ dtReserveEntry* reserveMemMap = (dtReserveEntry*)
+ (mSpace + mHeader->offsetReservedMemMap);
+ reserveMemMap->address = 0x0A000000; /*160MB-192MB*/;
+ reserveMemMap->size = MEGABYTE * 32;
+
+ /* Add the standard root node properties. */
+ dtOffset_t rootNode = findNode("/");
+ addPropertyCell32(rootNode, "#address-cells", 2);
+ addPropertyCell32(rootNode, "#size-cells", 2);
+ addPropertyString(rootNode, "compatible", "ibm,powernv");
+
+ addPropertyString(rootNode, "model", "P8_Sim");
+
+ addNode(rootNode, "chosen");
+
+ // Add the initial vpd and location code nodes.
+ addProperty(rootNode, "ibm,vpd");
+ addProperty(rootNode, "ibm,loc-code");
+}
+
+void devTree::setBootCpu(uint32_t pir)
+{
+ mHeader->bootCpuId = pir;
+}
+
+dtOffset_t devTree::findNode(const char* nodePath)
+{
+ /* Get structure section and start out with the name of first node*/
+ uint32_t* curWord = getStructSectionAtOffset(0);
+ dtOffset_t curOffset = 0;
+
+ if(strlen(nodePath) == 1)
+ {
+ if(nodePath[0] == '/')
+ {
+ return 0;
+ }
+ else
+ {
+ return DT_INVALID_OFFSET;
+ }
+ }
+
+ nodePath++;
+ int nodeNestLevel = 0;
+ curWord += 2;
+ curOffset += 8;
+ do
+ {
+ nodeNestLevel = 0;
+ /* Figure out how long the name of the current portion
+ of the path we're looking for is. */
+ int currentPathLength = 0;
+ while(nodePath[currentPathLength] &&
+ (nodePath[currentPathLength] != '/'))
+ {
+ currentPathLength++;
+ }
+ int done = 0;
+ do
+ {
+ switch(*curWord)
+ {
+ case DT_BEGIN_NODE:
+ {
+ if(nodeNestLevel == 0)
+ {
+ if(memcmp(curWord+1, nodePath, currentPathLength) == 0)
+ {
+ if(nodePath[currentPathLength] == NULL)
+ {
+ return curOffset;
+ }
+ else
+ {
+ done = 1;
+ }
+ }
+ }
+
+ nodeNestLevel++;
+
+ /* Figure out how far to advance to get past this node entry
+ Start by skipping over the node name. */
+ int nodeSkipWords = getNodeTagAndNameWords(curOffset);
+ curWord += nodeSkipWords;
+ curOffset += nodeSkipWords * 4;
+ }
+ break;
+
+ case DT_END_NODE:
+ {
+ if(nodeNestLevel == 0)
+ {
+ return DT_INVALID_OFFSET;
+ }
+ else
+ {
+ nodeNestLevel--;
+ /* Skip over the node end tag. */
+ curWord++;
+ curOffset += 4;
+ }
+ }
+ break;
+
+ case DT_PROP:
+ {
+ /* Skip over the property. */
+ curWord++;
+ int propSkiWords = ((*curWord + 3) / 4) + 2;
+ curWord += propSkiWords;
+ curOffset += (propSkiWords + 1) * 4;
+ }
+ break;
+
+ case DT_NOP:
+ {
+ curWord++;
+ curOffset += 4;
+ }
+ break;
+
+ case DT_END:
+ return DT_INVALID_OFFSET;
+ break;
+
+ default:
+ return DT_INVALID_OFFSET;
+ break;
+ }
+ }
+ while(!done);
+ nodePath += currentPathLength + 1;
+ }
+ while(*nodePath != NULL);
+
+ /* We should never get here. */
+ return DT_INVALID_OFFSET;
+}
+
+dtOffset_t devTree::addNode(dtOffset_t parentNodeOffset, const char* nodeName)
+{
+ uint32_t* curWord = getStructSectionAtOffset(parentNodeOffset);
+ int skipWords = getNodeTagAndNameWords(parentNodeOffset);
+
+ curWord += skipWords;
+ dtOffset_t newNodeOffset = parentNodeOffset + (skipWords * 4);
+
+ /* There is a FDT rule that nodes must be after properties
+ so skip over any properties. */
+ while(*curWord == DT_PROP)
+ {
+ int propertyWords = getPropertyWords(newNodeOffset);
+ curWord += propertyWords;
+ newNodeOffset += propertyWords * 4;
+ }
+
+ size_t newNodeNameLength = strlen(nodeName);
+ int newNodeNameWords = (newNodeNameLength + 4) / 4;
+ insertStructSpace(newNodeOffset, newNodeNameWords + 2);
+
+ *curWord++ = DT_BEGIN_NODE;
+ for(int i = 0; i < newNodeNameWords; ++i)
+ {
+ *curWord = 0;
+ memcpy(curWord, nodeName + (i * 4),
+ newNodeNameLength < 4 ? newNodeNameLength : 4);
+ if(newNodeNameLength < 4)
+ {
+ newNodeNameLength = 0;
+ }
+ else
+ {
+ newNodeNameLength -= 4;
+ }
+ curWord++;
+ }
+
+ *curWord = DT_END_NODE;
+
+ /* Always tack on a pHandle to each new node*/
+ uint32_t newPhandle = mNextPhandle++;
+ addPropertyCell32(newNodeOffset, "phandle", newPhandle);
+
+ return newNodeOffset;
+}
+
+dtOffset_t devTree::addNode(dtOffset_t parentNodeOffset,
+ const char* nodeName, uint64_t unitAddress)
+{
+ char nodeNameWithUnitAddress[1024];
+ sprintf(nodeNameWithUnitAddress, "%s@%lx", nodeName, unitAddress);
+ return addNode(parentNodeOffset, nodeNameWithUnitAddress);
+}
+
+void devTree::addProperty(dtOffset_t parentNodeOffset, const char* propertyName)
+{
+ uint32_t* curWord = getStructSectionAtOffset(parentNodeOffset);
+ int skipWords = getNodeTagAndNameWords(parentNodeOffset);
+
+ curWord += skipWords;
+ dtOffset_t newPropertyOffset = parentNodeOffset + (skipWords * 4);
+ insertStructSpace(newPropertyOffset, 3);
+
+ *curWord++ = DT_PROP;
+ *curWord++ = 0;
+ *curWord++ = addString(propertyName);
+}
+
+void devTree::addPropertyString(dtOffset_t parentNodeOffset,
+ const char* propertyName,
+ const char* propertyData)
+{
+ uint32_t* curWord = getStructSectionAtOffset(parentNodeOffset);
+ int skipWords = getNodeTagAndNameWords(parentNodeOffset);
+
+ curWord += skipWords;
+ dtOffset_t newPropertyOffset = parentNodeOffset + (skipWords * 4);
+ size_t newPropertyDataLength = strlen(propertyData);
+ int newPropertyDataWords = (newPropertyDataLength + 4) / 4;
+ insertStructSpace(newPropertyOffset, newPropertyDataWords + 3);
+
+ *curWord++ = DT_PROP;
+ *curWord++ = newPropertyDataLength + 1;
+ *curWord++ = addString(propertyName);
+
+ for(int i = 0; i < newPropertyDataWords; ++i)
+ {
+ *curWord = 0;
+ memcpy(curWord, propertyData + (i * 4),
+ newPropertyDataLength < 4 ? newPropertyDataLength : 4);
+ if(newPropertyDataLength < 4)
+ {
+ newPropertyDataLength = 0;
+ }
+ else
+ {
+ newPropertyDataLength -= 4;
+ }
+ curWord++;
+ }
+}
+
+void devTree::addPropertyBytes(dtOffset_t parentNodeOffset,
+ const char* propertyName,
+ const uint8_t* propertyData,
+ uint32_t numBytes)
+{
+ uint32_t* curWord = getStructSectionAtOffset(parentNodeOffset);
+ int skipWords = getNodeTagAndNameWords(parentNodeOffset);
+
+ curWord += skipWords;
+ dtOffset_t newPropertyOffset = parentNodeOffset + (skipWords * 4);
+ size_t newPropertyDataLength = numBytes;
+ int newPropertyDataWords = (newPropertyDataLength + 3) / 4;
+ insertStructSpace(newPropertyOffset, newPropertyDataWords + 3);
+
+ *curWord++ = DT_PROP;
+ *curWord++ = newPropertyDataLength;
+ *curWord++ = addString(propertyName);
+
+ for(int i = 0; i < newPropertyDataWords; ++i)
+ {
+ *curWord = 0;
+ memcpy(curWord, propertyData + (i * 4),
+ newPropertyDataLength < 4 ? newPropertyDataLength : 4);
+ if(newPropertyDataLength < 4)
+ {
+ newPropertyDataLength = 0;
+ }
+ else
+ {
+ newPropertyDataLength -= 4;
+ }
+ curWord++;
+ }
+}
+
+void devTree::addPropertyStrings(dtOffset_t parentNodeOffset,
+ const char* propertyName,
+ const char** propertyData)
+{
+ uint32_t* curWord = getStructSectionAtOffset(parentNodeOffset);
+ int skipWords = getNodeTagAndNameWords(parentNodeOffset);
+
+ size_t totalDataSize = 0;
+ int numStrings = 0;
+ /* Figure out the total size of the data in the property. */
+ for(int stringIndex = 0;
+ propertyData[stringIndex] && *propertyData[stringIndex]; stringIndex++)
+ {
+ totalDataSize += strlen(propertyData[stringIndex]) + 1;
+ numStrings++;
+ }
+
+ curWord += skipWords;
+ dtOffset_t newPropertyOffset = parentNodeOffset + (skipWords * 4);
+ size_t newPropertyDataLength = totalDataSize;
+ int newPropertyDataWords = (newPropertyDataLength + 3) / 4;
+ insertStructSpace(newPropertyOffset, newPropertyDataWords + 3);
+
+ *curWord++ = DT_PROP;
+ *curWord++ = newPropertyDataLength ;
+ *curWord++ = addString(propertyName);
+
+ for(int i = 0; i < newPropertyDataWords; ++i)
+ {
+ *(curWord + i) = 0;
+ }
+
+ char* target = (char*)curWord;
+ for(int stringIndex = 0; stringIndex < numStrings; stringIndex++)
+ {
+ size_t curStringLen = strlen(propertyData[stringIndex]);
+ memcpy(target, propertyData[stringIndex], curStringLen);
+ target += curStringLen + 1;
+ }
+}
+
+void devTree::addPropertyCell32(dtOffset_t parentNodeOffset,
+ const char* propertyName,
+ const uint32_t cell)
+{
+ uint32_t cells[1] = { cell };
+ addPropertyCells32(parentNodeOffset, propertyName, cells, 1);
+}
+
+void devTree::addPropertyCell64(dtOffset_t parentNodeOffset,
+ const char* propertyName,
+ const uint64_t cell)
+{
+ uint64_t cells[1] = { cell };
+ addPropertyCells64(parentNodeOffset, propertyName, cells, 1);
+}
+
+void devTree::addPropertyCells32(dtOffset_t parentNodeOffset,
+ const char* propertyName,
+ uint32_t cells[], uint32_t numCells)
+{
+ uint32_t* curWord = getStructSectionAtOffset(parentNodeOffset);
+ int skipWords = getNodeTagAndNameWords(parentNodeOffset);
+
+ curWord += skipWords;
+ dtOffset_t newPropertyOffset = parentNodeOffset + (skipWords * 4);
+ int newPropertyDataLength = numCells * 4;
+ int newPropertyDataWords = numCells;
+ insertStructSpace(newPropertyOffset, newPropertyDataWords + 3);
+
+ *curWord++ = DT_PROP;
+ *curWord++ = newPropertyDataLength;
+ *curWord++ = addString(propertyName);
+
+ for(uint32_t i = 0; i < numCells; ++i)
+ {
+ *curWord++ = cells[i];
+ }
+}
+
+void devTree::addPropertyCells64(dtOffset_t parentNodeOffset,
+ const char* propertyName,
+ uint64_t cells[], uint32_t numCells)
+{
+ uint32_t* curWord = getStructSectionAtOffset(parentNodeOffset);
+ int skipWords = getNodeTagAndNameWords(parentNodeOffset);
+
+ curWord += skipWords;
+ dtOffset_t newPropertyOffset = parentNodeOffset + (skipWords * 4);
+ int newPropertyDataLength = numCells * 8;
+ int newPropertyDataWords = numCells * 2;
+ insertStructSpace(newPropertyOffset, newPropertyDataWords + 3);
+
+ *curWord++ = DT_PROP;
+ *curWord++ = newPropertyDataLength;
+ *curWord++ = addString(propertyName);
+
+ for(uint32_t i = 0; i < numCells; ++i)
+ {
+ *curWord++ = cells[i] >> 32;
+ *curWord++ = cells[i];
+ }
+}
+
+int devTree::getNodeTagAndNameWords(dtOffset_t nodeOffset)
+{
+ size_t nodeNameAndTagWords = 1;
+ uint32_t* curWord = getStructSectionAtOffset(nodeOffset);
+ nodeNameAndTagWords += (strlen((char*)(curWord + 1)) + 4) / 4;
+ return nodeNameAndTagWords;
+}
+
+void devTree::insertStructSpace(uint32_t offset, int numNewWords)
+{
+ uint32_t* firstWord = getStructSectionAtOffset(0);
+ int numCurrentWords = mHeader->sizeStruct / 4;
+ /* Mode the string section out of the way first. */
+ shiftStringsSection(numNewWords * 4);
+ /* Now insert space into the struct section. */
+ assert((mHeader->totalSize + (numNewWords * 4)) < mMaxSize);
+ mHeader->sizeStruct += numNewWords * 4;
+ mHeader->totalSize += numNewWords * 4;
+
+ uint32_t* srcWord = firstWord + numCurrentWords - 1;
+ uint32_t* tgtWord = firstWord + numCurrentWords + numNewWords - 1;
+ int numCopyWords = numCurrentWords - (offset / 4);
+ while(numCopyWords--)
+ {
+ *tgtWord = *srcWord;
+ tgtWord--;
+ srcWord--;
+ };
+}
+
+void devTree::shiftStringsSection(int shiftSize)
+{
+ /* We always move it forward so copy it from the end to the beginning. */
+ uint32_t stringSectionSize = mHeader->sizeStrings;
+ char* src = mSpace + mHeader->offsetStrings;
+ char* tgt = src + shiftSize;
+
+ memmove(tgt, src, stringSectionSize);
+
+ mHeader->offsetStrings += shiftSize;
+
+ /* Clear out the area we just shifted out of so that it's easier to
+ debug the blob. */
+ memset(src, 0, shiftSize);
+}
+
+int devTree::getPropertyWords(int propertyOffset)
+{
+ int propertyWords = 3;
+ uint32_t* curWord = getStructSectionAtOffset(propertyOffset);
+ curWord++; /* Skip over the DT_PROP tag */
+ propertyWords += (*curWord + 3) / 4;
+ return propertyWords;
+}
+
+dtOffset_t devTree::addString(const char *string)
+{
+ dtOffset_t stringOffset = 0;
+ size_t stringSize = strlen(string) + 1;
+ char* stringSection = mSpace + mHeader->offsetStrings;
+ uint32_t stringSectionSize = mHeader->sizeStrings;
+
+ /* Search for the string as long as we know it could still be there. */
+ while(stringSize <= (stringSectionSize - stringOffset))
+ {
+ if(memcmp(stringSection, string, stringSize) == 0)
+ {
+ return stringOffset;
+ }
+ else
+ {
+ size_t curStringLength = strlen(stringSection) + 1;
+ stringOffset += curStringLength;
+ stringSection += curStringLength;
+ }
+ }
+
+ /* We didn't find a string to reuse so tack this one on the end. */
+ stringOffset = mHeader->sizeStrings;
+ memcpy(mSpace + mHeader->offsetStrings + stringOffset, string, stringSize);
+ assert((mHeader->totalSize + stringSize) < mMaxSize);
+ mHeader->sizeStrings += stringSize;
+ mHeader->totalSize += stringSize;
+ return stringOffset;
+}
+
+bool devTree::locateStringOffset(const char* string, uint32_t& stringOffset)
+{
+ bool foundStringOffset = false;
+ stringOffset = 0;
+ size_t stringSize = strlen(string) + 1;
+ char* stringSection = mSpace + mHeader->offsetStrings;
+ uint32_t stringSectionSize = mHeader->sizeStrings;
+
+ /* Search for the string as long as we know it could still be there. */
+ while(stringSize <= (stringSectionSize - stringOffset))
+ {
+ if(memcmp(stringSection, string, stringSize) == 0)
+ {
+ foundStringOffset = true;
+ break;
+ }
+ else
+ {
+ size_t curStringLength = strlen(stringSection) + 1;
+ stringOffset += curStringLength;
+ stringSection += curStringLength;
+ }
+ }
+
+ return foundStringOffset;
+}
+
+void* devTree::findProperty(dtOffset_t nodeOffset, const char* propertyName)
+{
+ uint32_t nameOffset = 0;
+ void *propertyData = NULL;
+
+ if(locateStringOffset(propertyName, nameOffset))
+ {
+ uint32_t* curWord = getStructSectionAtOffset(nodeOffset);
+ int skipWords = getNodeTagAndNameWords(nodeOffset);
+
+ curWord += skipWords;
+ dtOffset_t curOffset = nodeOffset + (skipWords * 4);
+
+ while(*curWord == DT_PROP)
+ {
+ /* Check if this is the property we are searching for. */
+ if(*(curWord + 2) == nameOffset)
+ {
+ /* It is, we found it. */
+ return (void*)(curWord + 3);
+ }
+ else
+ {
+ int propertyWords = getPropertyWords(curOffset);
+ curWord += propertyWords;
+ curOffset += propertyWords * 4;
+ }
+ }
+ }
+
+ return propertyData;
+}
+
+uint32_t devTree::getPhandle(dtOffset_t nodeOffset)
+{
+ uint32_t* phandlePtr = (uint32_t*) findProperty(nodeOffset, "phandle");
+ if(phandlePtr)
+ {
+ return *phandlePtr;
+ }
+
+ /* We didn't find a phandle, so we need to add one. */
+ uint32_t newPhandle = mNextPhandle++;
+ addPropertyCell32(nodeOffset, "phandle", newPhandle);
+ return newPhandle;
+}
+
+void devTree::appendPropertyBytes(dtOffset_t parentNode,
+ const char* propertyName,
+ const uint8_t* propertyData,
+ uint32_t numBytes)
+{
+ uint32_t nameOffset = 0;
+
+ if(locateStringOffset(propertyName, nameOffset))
+ {
+ uint32_t* curWord = getStructSectionAtOffset(parentNode);
+ int skipWords = getNodeTagAndNameWords(parentNode);
+
+ curWord += skipWords;
+ dtOffset_t curOffset = parentNode + (skipWords * 4);
+
+ while(*curWord == DT_PROP)
+ {
+ /* Check if this is the property we are searching for. */
+ if(*(curWord + 2) == nameOffset)
+ {
+ /* It is, we found it. */
+ uint32_t curPropertyDataLength = *(curWord + 1);
+ *(curWord + 1) = curPropertyDataLength + numBytes;
+ uint8_t* newDataLocation = ((uint8_t*)(curWord + 3))
+ + curPropertyDataLength;
+ uint32_t curPropertyDataWords = (curPropertyDataLength + 3) / 4;
+ uint32_t newPropertyDataWords = (curPropertyDataLength
+ + numBytes + 3) / 4;
+ uint32_t propertyDataWordsToAdd = newPropertyDataWords
+ - curPropertyDataWords;
+ if(propertyDataWordsToAdd)
+ {
+ uint32_t insertOffset =curOffset +
+ ((3 + curPropertyDataWords) * 4);
+ insertStructSpace(insertOffset, propertyDataWordsToAdd);
+ }
+ memcpy(newDataLocation, propertyData, numBytes);
+ break;
+ }
+ else
+ {
+ int propertyWords = getPropertyWords(curOffset);
+ curWord += propertyWords;
+ curOffset += propertyWords * 4;
+ }
+ }
+ }
+}
+
+
+/********************
+Internal Methods
+********************/
+
+/**
+ * @brief Constructor
+*/
+devTree::devTree()
+:mSpace(NULL), mMaxSize(0)
+{
+ //Nothing right now...
+}
+
+/**
+ * @brief Destructor
+ */
+devTree::~devTree()
+{
+ mm_block_unmap(mSpace);
+}
+
+}
diff --git a/src/usr/devtree/devtree.H b/src/usr/devtree/devtree.H
new file mode 100644
index 000000000..1056ed304
--- /dev/null
+++ b/src/usr/devtree/devtree.H
@@ -0,0 +1,332 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/usr/devtree/devtree.H $ */
+/* */
+/* IBM CONFIDENTIAL */
+/* */
+/* COPYRIGHT International Business Machines Corp. 2013 */
+/* */
+/* p1 */
+/* */
+/* Object Code Only (OCO) source materials */
+/* Licensed Internal Code Source Materials */
+/* IBM HostBoot Licensed Internal Code */
+/* */
+/* The source code for this program is not published or otherwise */
+/* divested of its trade secrets, irrespective of what has been */
+/* deposited with the U.S. Copyright Office. */
+/* */
+/* Origin: 30 */
+/* */
+/* IBM_PROLOG_END_TAG */
+/* $IBMCopyrightBlock:
+ IBM Confidential
+
+ OCO Source Materials
+
+ 5733-907
+
+ (C) Copyright IBM Corp. 2011
+
+ The source code for this program is not published or other-
+ wise divested of its trade secrets, irrespective of what has
+ been deposited with the U.S. Copyright Office.
+$ */
+#include <devtree/devtreeif.H>
+
+#ifndef _DEVTREE_H
+#define _DEVTREE_H
+
+namespace DEVTREE
+{
+typedef size_t dtOffset_t;
+
+
+ /**
+ * The devtree class that does the actual work of
+ * generating and manipulating the devtree
+ *
+ */
+ class devTree
+ {
+ public:
+
+ /**
+ * Initialize the FDT at address and size
+ * @param[in] i_addr Physical address to place FDT at
+ * @param[in] i_maxSize Size of FDT
+ */
+ void initialize(uint64_t i_addr, size_t i_maxSize);
+
+ /**
+ * Find given node (e.g. "/lpc") in the FDT
+ * @param[in] nodePath NULL terminated string of the path
+ * @return dtOffset_t into FDT of node location
+ */
+ dtOffset_t findNode(const char* nodePath);
+
+ /**
+ * Find and return a pointer to a property within a node
+ * @param[in] nodeOffset Offset into FDT to start looking
+ * @param[in] propertyName NULL terminated string of the property
+ to get
+ * @return void* pointer to dtOffset_t into FDT of node location
+ */
+ void* findProperty(dtOffset_t nodeOffset, const char* propertyName);
+
+ /**
+ * Add a new node under the parent node
+ * @param[in] parentNode Offset to parent node
+ * @param[in] nodeName NULL terminated string of node to add
+ * @return dtOffset_t into FDT of node location
+ */
+ dtOffset_t addNode(dtOffset_t parentNode, const char* nodeName);
+
+ /**
+ * Add a new node under the parent node with address
+ * @param[in] parentNode Offset to parent node
+ * @param[in] nodeName NULL terminated string of node to add
+ * @param[in] unitAddress Address of the node
+ * @return dtOffset_t into FDT of node location
+ */
+ dtOffset_t addNode(dtOffset_t parentNode, const char* nodeName,
+ uint64_t unitAddress);
+
+ /**
+ * Add a property to a node with no data
+ * @param[in] parentNode Offset to node to add property to
+ * @param[in] propertyName NULL terminated string of property name
+ */
+ void addProperty(dtOffset_t parentNode, const char* propertyName);
+
+ /**
+ * Add a property to a node with free form bytes
+ * @param[in] parentNode Offset to node to add property to
+ * @param[in] propertyName NULL terminated string of property name
+ * @param[in] propertyData Data to add
+ * @param[in] numBytes Number of data bytes
+ */
+ void addPropertyBytes(dtOffset_t parentNode, const char* propertyName,
+ const uint8_t* propertyData, uint32_t numBytes);
+
+ /**
+ * Add a property to a node with string data
+ * @param[in] parentNode Offset to node to add property to
+ * @param[in] propertyName NULL terminated string of property name
+ * @param[in] propertyData NULL terminated string data
+ */
+ void addPropertyString(dtOffset_t parentNode, const char* propertyName,
+ const char* propertyData);
+
+ /**
+ * Add a property to a node with array of strings
+ * @param[in] parentNode Offset to node to add property to
+ * @param[in] propertyName NULL terminated string of property name
+ * @param[in] propertyData NULL terminated array of strings, last
+ * string must be NULL
+ */
+ void addPropertyStrings(dtOffset_t parentNode, const char* propertyName,
+ const char** propertyData);
+
+ /**
+ * Add a property to a node with a 32 bit "cell" (aka uint32_t data)
+ * @param[in] parentNode Offset to node to add property to
+ * @param[in] propertyName NULL terminated string of property name
+ * @param[in] cell Data to add
+ */
+ void addPropertyCell32(dtOffset_t parentNode, const char* propertyName,
+ const uint32_t cell);
+
+ /**
+ * Add a property to a node with a 64 bit "cell" (aka uint64_t data)
+ * @param[in] parentNode Offset to node to add property to
+ * @param[in] propertyName NULL terminated string of property name
+ * @param[in] cell Data to add
+ */
+ void addPropertyCell64(dtOffset_t parentNode, const char* propertyName,
+ const uint64_t cell);
+
+ /**
+ * Add a property to a node with a 32 bit array of "cells"
+ * (aka uint32_t data)
+ * @param[in] parentNode Offset to node to add property to
+ * @param[in] propertyName NULL terminated string of property name
+ * @param[in] cells Array of uint32_t data
+ * @param[in] numCells Number of cells
+ */
+ void addPropertyCells32(dtOffset_t parentNode, const char* propertyName,
+ uint32_t cells[], uint32_t numCells);
+
+ /**
+ * Add a property to a node with a 64 bit array of "cells"
+ * (aka uint64_t data)
+ * @param[in] parentNode Offset to node to add property to
+ * @param[in] propertyName NULL terminated string of property name
+ * @param[in] cells Array of uint64_t data
+ * @param[in] numCells Number of cells
+ */
+ void addPropertyCells64(dtOffset_t parentNode, const char* propertyName,
+ uint64_t cells[], uint32_t numCells);
+
+ /**
+ * Return the physical "blob" address to the start of the FDT
+ * @return uin64_t to the start of the FDT memory
+ */
+ uint64_t getBlobPhys();
+
+ /**
+ * Each devtree node has a "handle" number. This function returns the
+ * handle number for given node.
+ * @param[in] nodeOffset Offset to node
+ * @return uin32_t Handle number for node
+ */
+ uint32_t getPhandle(dtOffset_t nodeOffset);
+
+ /**
+ * Append bytes to a property
+ * @param[in] parentNode Offset to node to add property to
+ * @param[in] propertyName NULL terminated string of property name
+ * @param[in] propertyData Data to add
+ * @param[in] numBytes Number of data bytes
+ */
+ void appendPropertyBytes(dtOffset_t parentNode,
+ const char* propertyName,
+ const uint8_t* propertyData,
+ uint32_t numBytes);
+
+ /**
+ * Return the current size of the FDT (not max)
+ * @return uin32_t Size of the FDT
+ */
+ uint32_t getSize();
+
+
+ protected:
+ /*Constructor*/
+ devTree();
+
+ /*Destructor*/
+ ~devTree();
+
+ /**
+ * Get the internal struct section at node offset
+ * @param[in] offset Offset to node
+ * @return uin32_t* pointer to struct section
+ */
+ inline uint32_t* getStructSectionAtOffset(dtOffset_t offset);
+
+ /**
+ * Utility function to get the length fo the tag/name words for
+ * given node
+ * @param[in] nodeOffset Offset to node
+ * @return int Words consumed by tag/name in FDT
+ */
+ int getNodeTagAndNameWords(dtOffset_t nodeOffset);
+
+ /**
+ * Utility function to get the length fo the tag/name words for
+ * given node
+ * @param[in] nodeOffset Offset to node
+ * @return int Words consumed by tag/name in FDT
+ */
+ void insertStructSpace(uint32_t offset, int numNewWords);
+
+ /**
+ * Utility function to shift the string section
+ * @param[in] shiftSize Amount to shift
+ */
+ void shiftStringsSection(int shiftSize);
+
+ /**
+ * Get number of words for property
+ * @param[in] propertyOffset Offset of property
+ * @return int Words consumed by Property
+ */
+ int getPropertyWords(int propertyOffset);
+
+ /**
+ * Utility function to add String to string table
+ * @param[in] string NULL terminated string to add
+ * @return dtOffset_t Offset string was added at
+ */
+ dtOffset_t addString(const char *string);
+
+ /**
+ * Set the boot CPU PIR into FDT
+ * @param[in] pir PIR value for boot processor
+ */
+ void setBootCpu(uint32_t pir);
+
+ /**
+ * Utility function to locate string in string table
+ * @param[in] string NULL terminated string to find
+ * @param[out] stringOffset Offset if found
+ * @return bool True if found
+ */
+ bool locateStringOffset(const char* string, uint32_t& stringOffset);
+
+
+ private:
+
+ enum Constants {
+ DT_MAGIC =0xd00dfeed,
+ DT_CUR_VERSION =0x11,
+ DT_COMPAT_VERSION =0x10,
+
+ DT_BEGIN_NODE =0x1,
+ DT_END_NODE =0x2,
+ DT_PROP =0x3,
+ DT_NOP =0x4,
+ DT_END =0x9,
+ DT_INVALID_OFFSET =0xFFFFFFFF,
+
+ };
+
+
+ typedef struct dtHeader
+ {
+ uint32_t magicNumber;
+ uint32_t totalSize;
+ uint32_t offsetStruct;
+ uint32_t offsetStrings;
+ uint32_t offsetReservedMemMap;
+ uint32_t version;
+ uint32_t lastCompatVersion;
+ uint32_t bootCpuId;
+ uint32_t sizeStrings;
+ uint32_t sizeStruct;
+ }
+ dtHeader_t;
+
+ typedef struct dtReserveEntry
+ {
+ uint64_t address;
+ uint64_t size;
+ }
+ dtReserveEntry_t;
+
+
+
+ union
+ {
+ dtHeader_t* mHeader;
+ char* mSpace;
+ };
+ uint32_t mNextPhandle;
+ size_t mMaxSize;
+ uint64_t mPhysAddr;
+
+ // let my testcase poke around
+ friend class devTreeTest;
+
+ };
+
+
+
+ uint32_t* devTree::getStructSectionAtOffset(dtOffset_t offset)
+ {
+ return (uint32_t*) (mSpace + mHeader->offsetStruct + offset);
+ }
+}
+#endif /* _DEVTREE_H */
diff --git a/src/usr/devtree/makefile b/src/usr/devtree/makefile
new file mode 100644
index 000000000..8c727229a
--- /dev/null
+++ b/src/usr/devtree/makefile
@@ -0,0 +1,35 @@
+# IBM_PROLOG_BEGIN_TAG
+# This is an automatically generated prolog.
+#
+# $Source: src/usr/devtree/makefile $
+#
+# IBM CONFIDENTIAL
+#
+# COPYRIGHT International Business Machines Corp. 2012,2013
+#
+# p1
+#
+# Object Code Only (OCO) source materials
+# Licensed Internal Code Source Materials
+# IBM HostBoot Licensed Internal Code
+#
+# The source code for this program is not published or otherwise
+# divested of its trade secrets, irrespective of what has been
+# deposited with the U.S. Copyright Office.
+#
+# Origin: 30
+#
+# IBM_PROLOG_END_TAG
+
+#
+# The runtime module provides code to handle manipulating data
+# for the host. For example, verifying HDAT fields and writing
+# attribute data for HostServices.
+#
+
+ROOTPATH = ../../..
+MODULE = devtree
+
+OBJS = devtree.o bld_devtree.o
+
+include ${ROOTPATH}/config.mk
diff --git a/src/usr/hwpf/hwp/start_payload/start_payload.C b/src/usr/hwpf/hwp/start_payload/start_payload.C
index 1a8619307..3c06db171 100644
--- a/src/usr/hwpf/hwp/start_payload/start_payload.C
+++ b/src/usr/hwpf/hwp/start_payload/start_payload.C
@@ -65,6 +65,7 @@
#include "start_payload.H"
#include <runtime/runtime.H>
+#include <devtree/devtreeif.H>
// Uncomment these files as they become available:
// #include "host_start_payload/host_start_payload.H"
@@ -119,6 +120,7 @@ void* call_host_runtime_setup( void *io_pArgs )
do
{
+
// Need to load up the runtime module if it isn't already loaded
if ( !VFS::module_is_loaded( "libruntime.so" ) )
{
@@ -199,18 +201,32 @@ void* call_host_runtime_setup( void *io_pArgs )
}
break;
}
-
- // Write the HostServices attributes into mainstore
- l_err = RUNTIME::populate_attributes();
- if ( l_err )
+ else if( TARGETING::PAYLOAD_KIND_SAPPHIRE == payload_kind)
{
- TRACFCOMP( ISTEPS_TRACE::g_trac_isteps_trace,
- "Could not populate attributes" );
- // break from do loop if error occured
- break;
+ // Write the devtree out
+ l_err = DEVTREE::build_flatdevtree();
+ if ( l_err )
+ {
+ TRACFCOMP( ISTEPS_TRACE::g_trac_isteps_trace,
+ "Could not build dev tree" );
+ // break from do loop if error occured
+ break;
+ }
+ }
+ else
+ {
+ // Write the HostServices attributes into mainstore
+ l_err = RUNTIME::populate_attributes();
+ if ( l_err )
+ {
+ TRACFCOMP( ISTEPS_TRACE::g_trac_isteps_trace,
+ "Could not populate attributes" );
+ // break from do loop if error occured
+ break;
+ }
}
- // - Update HDAT with tpmd logs
+ // - Update HDAT/DEVTREE with tpmd logs
} while(0);
@@ -331,6 +347,7 @@ errlHndl_t callShutdown ( void )
errlHndl_t err = NULL;
uint64_t payloadBase = 0x0;
uint64_t payloadEntry = 0x0;
+ uint64_t payloadData = 0x0;
bool istepModeFlag = false;
uint64_t status = SHUTDOWN_STATUS_GOOD;
@@ -417,13 +434,22 @@ errlHndl_t callShutdown ( void )
break;
}
+ // Load payload data if in SAPPHIRE mode
+ TARGETING::ATTR_PAYLOAD_KIND_type payload_kind
+ = sys->getAttr<TARGETING::ATTR_PAYLOAD_KIND>();
+ if( TARGETING::PAYLOAD_KIND_SAPPHIRE == payload_kind )
+ {
+ payloadData = DEVTREE::get_flatdevtree_phys_addr();
+ }
+
// do the shutdown.
TRACFCOMP( ISTEPS_TRACE::g_trac_isteps_trace,
"callShutdown finished, shutdown = 0x%x.",
status );
INITSERVICE::doShutdown( status,
payloadBase,
- payloadEntry );
+ payloadEntry,
+ payloadData);
} while( 0 );
diff --git a/src/usr/initservice/baseinitsvc/initservice.C b/src/usr/initservice/baseinitsvc/initservice.C
index 4e8dd8aa9..e3ca0160b 100644
--- a/src/usr/initservice/baseinitsvc/initservice.C
+++ b/src/usr/initservice/baseinitsvc/initservice.C
@@ -617,11 +617,13 @@ void InitService::registerBlock(void* i_vaddr, uint64_t i_size,
void doShutdown ( uint64_t i_status,
uint64_t i_payload_base,
- uint64_t i_payload_entry )
+ uint64_t i_payload_entry,
+ uint64_t i_payload_data)
{
Singleton<InitService>::instance().doShutdown( i_status,
i_payload_base,
- i_payload_entry );
+ i_payload_entry,
+ i_payload_data);
while(1)
{
@@ -631,7 +633,8 @@ void doShutdown ( uint64_t i_status,
void InitService::doShutdown(uint64_t i_status,
uint64_t i_payload_base,
- uint64_t i_payload_entry)
+ uint64_t i_payload_entry,
+ uint64_t i_payload_data)
{
int l_rc = 0;
errlHndl_t l_err = NULL;
@@ -682,7 +685,7 @@ void InitService::doShutdown(uint64_t i_status,
l_rb_iter++;
}
- shutdown(i_status, i_payload_base, i_payload_entry);
+ shutdown(i_status, i_payload_base, i_payload_entry, i_payload_data);
}
bool InitService::registerShutdownEvent(msg_q_t i_msgQ,
diff --git a/src/usr/initservice/baseinitsvc/initservice.H b/src/usr/initservice/baseinitsvc/initservice.H
index 1457dc48d..795afae27 100644
--- a/src/usr/initservice/baseinitsvc/initservice.H
+++ b/src/usr/initservice/baseinitsvc/initservice.H
@@ -1,25 +1,25 @@
-// IBM_PROLOG_BEGIN_TAG
-// This is an automatically generated prolog.
-//
-// $Source: src/usr/initservice/baseinitsvc/initservice.H $
-//
-// IBM CONFIDENTIAL
-//
-// COPYRIGHT International Business Machines Corp. 2011
-//
-// p1
-//
-// Object Code Only (OCO) source materials
-// Licensed Internal Code Source Materials
-// IBM HostBoot Licensed Internal Code
-//
-// The source code for this program is not published or other-
-// wise divested of its trade secrets, irrespective of what has
-// been deposited with the U.S. Copyright Office.
-//
-// Origin: 30
-//
-// IBM_PROLOG_END
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/usr/initservice/baseinitsvc/initservice.H $ */
+/* */
+/* IBM CONFIDENTIAL */
+/* */
+/* COPYRIGHT International Business Machines Corp. 2011,2013 */
+/* */
+/* p1 */
+/* */
+/* Object Code Only (OCO) source materials */
+/* Licensed Internal Code Source Materials */
+/* IBM HostBoot Licensed Internal Code */
+/* */
+/* The source code for this program is not published or otherwise */
+/* divested of its trade secrets, irrespective of what has been */
+/* deposited with the U.S. Copyright Office. */
+/* */
+/* Origin: 30 */
+/* */
+/* IBM_PROLOG_END_TAG */
#ifndef __BASEINITSVC_INITSERVICE_H
#define __BASEINITSVC_INITSERVICE_H
@@ -207,6 +207,8 @@ public:
* payload.
* @param[in] i_payload_entry - The offset from base address of the
* payload entry-point.
+ * @param[in] i_payload_entry - HRMOR adjusted address of any payload data
+ * placed in r3
*
* @return Nothing
* @note This calls registered services to notify them of shutdown and it
@@ -214,7 +216,8 @@ public:
*/
void doShutdown ( uint64_t i_status,
uint64_t i_payload_base = 0,
- uint64_t i_payload_entry = 0 );
+ uint64_t i_payload_entry = 0,
+ uint64_t i_payload_data = 0);
protected:
diff --git a/src/usr/intr/intrrp.C b/src/usr/intr/intrrp.C
index 8838d22cf..11339dbc6 100644
--- a/src/usr/intr/intrrp.C
+++ b/src/usr/intr/intrrp.C
@@ -1619,6 +1619,7 @@ void IntrRp::cleanCheck()
}
}
+
//----------------------------------------------------------------------------
// External interfaces
//----------------------------------------------------------------------------
@@ -1831,3 +1832,20 @@ errlHndl_t INTR::enablePsiIntr(TARGETING::Target * i_target)
return err;
}
+uint64_t INTR::getIntpAddr(const TARGETING::Target * i_ex, uint8_t i_thread)
+{
+ const TARGETING::Target * l_proc = getParentChip(i_ex);
+ uint64_t l_intB =l_proc->getAttr<TARGETING::ATTR_INTP_BASE_ADDR>();
+
+ PIR_t pir(0);
+ pir.nodeId = l_proc->getAttr<TARGETING::ATTR_FABRIC_NODE_ID>();
+ pir.chipId = l_proc->getAttr<TARGETING::ATTR_FABRIC_CHIP_ID>();
+ pir.coreId = i_ex->getAttr<TARGETING::ATTR_CHIP_UNIT>();
+ pir.threadId = i_thread;
+
+ return (l_intB+ InterruptMsgHdlr::mmio_offset(
+ pir.word & (InterruptMsgHdlr::P8_PIR_THREADID_MSK |
+ InterruptMsgHdlr::P8_PIR_COREID_MSK)));
+}
+
+
diff --git a/src/usr/intr/intrrp.H b/src/usr/intr/intrrp.H
index c4301e7eb..a05bff542 100644
--- a/src/usr/intr/intrrp.H
+++ b/src/usr/intr/intrrp.H
@@ -44,38 +44,6 @@ namespace TARGETING
namespace INTR
{
/**
- * cpu PIR register
- */
- struct PIR_t
- {
- union
- {
- uint32_t word;
- struct
- {
- //P8:
- uint32_t reserved:19; //!< zeros
- uint32_t nodeId:3; //!< node (0-3)
- uint32_t chipId:3; //!< chip pos on node (0-5)
- uint32_t coreId:4; //!< Core number (1-6,9-14)?
- uint32_t threadId:3; //!< Thread number (0-7)
- } PACKED;
- };
- PIR_t(uint32_t i_word = 0) : word(i_word) {}
-
- PIR_t operator= (uint32_t i_word)
- {
- word = i_word;
- return word;
- }
-
- bool operator< (const PIR_t& r) const
- {
- return word < r.word;
- }
- };
-
- /**
* Make an XISR value
* @param[in] i_node The PIR node id (0-7)
* @param[in] i_chip The PIR chip id (0-7)
diff --git a/src/usr/makefile b/src/usr/makefile
index 1bad2ebe7..5855729f0 100644
--- a/src/usr/makefile
+++ b/src/usr/makefile
@@ -30,6 +30,6 @@ SUBDIRS = example.d trace.d cxxtest.d testcore.d errl.d devicefw.d \
scom.d xscom.d targeting.d initservice.d hwpf.d \
ecmddatabuffer.d pnor.d i2c.d vfs.d fsi.d hwas.d fsiscom.d \
intr.d pore.d util.d mbox.d diag.d vpd.d scan.d \
- runtime.d ibscom.d dump.d secureboot.d
+ runtime.d ibscom.d dump.d secureboot.d devtree.d
include ${ROOTPATH}/config.mk
diff --git a/src/usr/targeting/common/xmltohb/attribute_types.xml b/src/usr/targeting/common/xmltohb/attribute_types.xml
index 5ecc7ecf5..b8123c422 100644
--- a/src/usr/targeting/common/xmltohb/attribute_types.xml
+++ b/src/usr/targeting/common/xmltohb/attribute_types.xml
@@ -2030,9 +2030,13 @@
<value>2</value>
</enumerator>
<enumerator>
- <name>NONE</name>
+ <name>SAPPHIRE</name>
<value>3</value>
</enumerator>
+ <enumerator>
+ <name>NONE</name>
+ <value>4</value>
+ </enumerator>
<default>UNKNOWN</default>
</enumerationType>
OpenPOWER on IntegriCloud