Author: arty
Date: Sun Nov 11 12:23:05 2007
New Revision: 30351
URL:
http://svn.reactos.org/svn/reactos?rev=30351&view=rev
Log:
Simple way to encode a device tree for early boot operations.
Added:
trunk/reactos/lib/ppcdevtree/
trunk/reactos/lib/ppcdevtree/devtree.c (with props)
trunk/reactos/lib/ppcdevtree/ppcdevtree.rbuild (with props)
Added: trunk/reactos/lib/ppcdevtree/devtree.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/lib/ppcdevtree/devtree.c?r…
==============================================================================
--- trunk/reactos/lib/ppcdevtree/devtree.c (added)
+++ trunk/reactos/lib/ppcdevtree/devtree.c Sun Nov 11 12:23:05 2007
@@ -1,0 +1,202 @@
+/*
+ * FreeLoader
+ * Copyright (C) 2007 arty
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/* A hardware describing device tree
+ * Upper layers will describe hardware they recognize in here. Hal will need
+ * this info to configure PICs, timers and such.
+ *
+ * When booting on openfirmware, we copy recognized devices from the device
+ * tree. Other host types will configure it in different ways.
+ *
+ * Structure is a flat buffer stacked with PPC_DEVICE_NODEs, built as a tree.
+ * Each node's child set is terminated by an empty (0) node.
+ * Nodes are followed directly by properties and child nodes, which are
+ * followed by their own child nodes, etc.
+ *
+ * A small management structure is used while the tree is being created, then
+ * ignored when the tree is sent to upper layers.
+ */
+
+#include <string.h>
+#include <ppcboot.h>
+
+#define DT_ROUND_UP(x,round) (((x) + (round - 1)) & ~(round - 1))
+
+PPPC_DEVICE_NODE PpcDevTreeGrow(PPPC_DEVICE_TREE tree, int newEntry)
+{
+ int newSize =
+ DT_ROUND_UP(tree->used_bytes + newEntry, tree->alloc_step);
+ PPPC_DEVICE_NODE newArea;
+ if (tree->alloc_size >= newSize) return tree->head;
+ newArea = tree->allocFn(newSize);
+ if (!newArea) return NULL;
+ memcpy(newArea, tree->head, tree->alloc_size);
+ tree->alloc_size = newSize;
+ if (tree->active)
+ tree->active =
+ (((char *)tree->active) - ((char *)tree->head)) + newArea;
+ if (tree->head) tree->freeFn(tree->head);
+ tree->head = newArea;
+ return tree->head;
+}
+
+PPC_DT_BOOLEAN PpcDevTreeInitialize
+(PPPC_DEVICE_TREE tree, int alloc_step, int align,
+ PPC_DEVICE_ALLOC allocFn, PPC_DEVICE_FREE freeFn)
+{
+ tree->alloc_size = 0;
+ tree->alloc_step = alloc_step;
+ tree->used_bytes = 0;
+ tree->align = align;
+ tree->allocFn = allocFn;
+ tree->freeFn = freeFn;
+ /* Initialize */
+ tree->active = tree->head = NULL;
+ /* Add a root node */
+ tree->head = PpcDevTreeGrow(tree, sizeof(PPC_DEVICE_NODE) + 1);
+ if (!tree->head) return PPC_DT_FALSE;
+ memset(tree->head, 0, sizeof(*tree->head) + 1);
+ strcpy(tree->head->name, "/");
+ tree->head->this_size = tree->head->total_size =
+ DT_ROUND_UP(sizeof(PPC_DEVICE_NODE)+1, tree->align);
+ tree->active = tree->head;
+ return tree->head != NULL;
+}
+
+PPPC_DEVICE_NODE PpcDevTreeGetRootNode(PPPC_DEVICE_TREE tree)
+{
+ return tree->head;
+}
+
+PPC_DT_BOOLEAN PpcDevTreeNodeIsChild
+(PPPC_DEVICE_NODE parent, PPPC_DEVICE_NODE child)
+{
+ char *this_entry = (char *)parent;
+ char *next_entry = ((char *)parent) + parent->total_size;
+ char *want_entry = (char *)child;
+ return want_entry > this_entry && want_entry < next_entry;
+}
+
+PPPC_DEVICE_NODE PpcDevTreeChildNode(PPPC_DEVICE_NODE parent)
+{
+ char *next_entry = ((char *)parent) + parent->this_size;
+ PPPC_DEVICE_NODE next = (PPPC_DEVICE_NODE)next_entry;
+ if (PpcDevTreeNodeIsChild(parent, next)) return next; else return NULL;
+}
+
+PPPC_DEVICE_NODE PpcDevTreeParentNode(PPPC_DEVICE_NODE child)
+{
+ char *parent = ((char *)child) - child->parent;
+ if (!child->parent) return NULL; else return (PPPC_DEVICE_NODE)parent;
+}
+
+PPPC_DEVICE_NODE PpcDevTreeSiblingNode(PPPC_DEVICE_NODE this_entry)
+{
+ char *next_entry = ((char *)this_entry) + this_entry->total_size;
+ PPPC_DEVICE_NODE next = (PPPC_DEVICE_NODE)next_entry;
+ if (PpcDevTreeNodeIsChild(PpcDevTreeParentNode(this_entry), next))
+ return next;
+ else
+ return NULL;
+}
+
+static
+PPPC_DEVICE_NODE PpcDevTreeAllocChild(PPPC_DEVICE_TREE tree, int size)
+{
+ PPPC_DEVICE_NODE newHead =
+ PpcDevTreeGrow(tree, DT_ROUND_UP(size, tree->align));
+ if (newHead == NULL) return NULL;
+ newHead = (PPPC_DEVICE_NODE)
+ (((char *)tree->active) + tree->active->total_size);
+ memset(newHead, 0, size);
+ return newHead;
+}
+
+PPC_DT_BOOLEAN PpcDevTreeAddProperty
+(PPPC_DEVICE_TREE tree, int type, char *propname, char *propval, int proplen)
+{
+ int propname_len = DT_ROUND_UP(strlen(propname) + 1, tree->align);
+ int entry_len = sizeof(PPC_DEVICE_NODE) + propname_len + proplen;
+ PPPC_DEVICE_NODE newprop = PpcDevTreeAllocChild(tree, entry_len);
+ if (!newprop) return PPC_DT_FALSE;
+ newprop->type = type;
+ newprop->parent = ((char *)newprop) - ((char *)tree->active);
+ newprop->this_size = entry_len;
+ newprop->value_offset = propname_len;
+ newprop->value_size = proplen;
+ strcpy(newprop->name, propname);
+ memcpy(newprop->name + newprop->value_offset, propval, proplen);
+ tree->active->total_size =
+ (((char *)newprop) + DT_ROUND_UP(newprop->this_size, tree->align)) -
+ ((char *)tree->active);
+ return PPC_DT_TRUE;
+}
+
+PPC_DT_BOOLEAN PpcDevTreeAddDevice
+(PPPC_DEVICE_TREE tree, int type, char *name)
+{
+ int entry_len = sizeof(PPC_DEVICE_NODE) + strlen(name);
+ PPPC_DEVICE_NODE newprop = PpcDevTreeAllocChild(tree, entry_len);
+ if (!newprop) return PPC_DT_FALSE;
+ newprop->type = type;
+ newprop->parent = ((char *)newprop) - ((char *)tree->active);
+ newprop->this_size = newprop->total_size =
+ DT_ROUND_UP(entry_len, tree->align);
+ strcpy(newprop->name, name);
+ tree->active->total_size =
+ (((char *)newprop) + DT_ROUND_UP(newprop->this_size, tree->align)) -
+ ((char *)tree->active);
+ tree->active = newprop;
+ return PPC_DT_TRUE;
+}
+
+PPC_DT_BOOLEAN PpcDevTreeCloseDevice(PPPC_DEVICE_TREE tree)
+{
+ PPPC_DEVICE_NODE parent = PpcDevTreeParentNode(tree->active);
+ if (!parent) return PPC_DT_FALSE;
+ parent->total_size = tree->active->total_size + tree->active->parent;
+ tree->active = parent;
+ return PPC_DT_TRUE;
+}
+
+PPPC_DEVICE_NODE PpcDevTreeFindDevice
+(PPPC_DEVICE_NODE root, int type, char *name)
+{
+ PPPC_DEVICE_NODE found = NULL;
+ if (name && !strcmp(root->name, name)) return root;
+ if (type && root->type == type) return root;
+ for (root = PpcDevTreeChildNode(root);
+ root && !(found = PpcDevTreeFindDevice(root, type, name));
+ root = PpcDevTreeSiblingNode(root));
+ return found;
+}
+
+char *PpcDevTreeFindProperty
+(PPPC_DEVICE_NODE root, int type, char *name, int *len)
+{
+ for (root = PpcDevTreeChildNode(root);
+ root &&
+ root->value_offset &&
+ (!strcmp(root->name, name) &&
+ (!type || root->type == type));
+ root = PpcDevTreeSiblingNode(root));
+ if (len)
+ *len = root->value_size;
+ return root->name + root->value_offset;
+}
Propchange: trunk/reactos/lib/ppcdevtree/devtree.c
------------------------------------------------------------------------------
svn:eol-style = native
Added: trunk/reactos/lib/ppcdevtree/ppcdevtree.rbuild
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/lib/ppcdevtree/ppcdevtree.…
==============================================================================
--- trunk/reactos/lib/ppcdevtree/ppcdevtree.rbuild (added)
+++ trunk/reactos/lib/ppcdevtree/ppcdevtree.rbuild Sun Nov 11 12:23:05 2007
@@ -1,0 +1,6 @@
+<?xml version="1.0"?>
+<!DOCTYPE module SYSTEM "../../tools/rbuild/project.dtd">
+<module name="ppcdevtree" type="staticlibrary">
+ <include base="ReactOS">include/reactos</include>
+ <file>devtree.c</file>
+</module>
Propchange: trunk/reactos/lib/ppcdevtree/ppcdevtree.rbuild
------------------------------------------------------------------------------
svn:eol-style = native