summaryrefslogtreecommitdiffstats
path: root/src/usr/devtree
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/usr/devtree
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/usr/devtree')
-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
4 files changed, 1505 insertions, 0 deletions
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
OpenPOWER on IntegriCloud