diff options
author | Dean Sanner <dsanner@us.ibm.com> | 2013-01-03 10:16:18 -0600 |
---|---|---|
committer | A. Patrick Williams III <iawillia@us.ibm.com> | 2013-08-09 13:43:19 -0500 |
commit | 97bd69daf028bec2f7d7f4fbd8feb49486fb4577 (patch) | |
tree | 3168aba491fb1cbdd181c40c3e3947410a47e28e /src/usr/devtree | |
parent | 7b0dcb2cc3a80cb09aa2af5d4cd2f2673c7146a6 (diff) | |
download | talos-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.C | 427 | ||||
-rw-r--r-- | src/usr/devtree/devtree.C | 711 | ||||
-rw-r--r-- | src/usr/devtree/devtree.H | 332 | ||||
-rw-r--r-- | src/usr/devtree/makefile | 35 |
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 |