NT4/private/ntos/boot/veneer/vrsup.c
2020-09-30 17:12:29 +02:00

370 lines
9.1 KiB
C

/*++
*
* Copyright (c) 1995 FirePower Systems, Inc.
* Copyright (c) 1994 FirmWorks, Mountain View CA USA. All rights reserved.
* Copyright (c) 1994 FirePower Systems, Inc.
*
* $RCSfile: vrsup.c $
* $Revision: 1.7 $
* $Date: 1996/02/17 00:42:16 $
* $Locker: $
*
Module Name:
vrsup.c
Abstract:
A given physical device may be represented by a variety
of objects. More importantly, the veneer must be able to
translate freely between these objects.
______________ ____________________
| 1275 | | ARC |
| | | |
| | | |
| Path | | ArcPath |
| \ | | / |
| \ | | / |
| \ | | / |
| \ | | / |
| \| |/ |
| \ / |
| |\ /| |
| | \ / | |
| | \ / | |
| | \ / | |
| | \ / | |
| | \ / | |
| | \ / | |
| Package---+-------Node | |
| | / \ | |
| | / \ | |
| | / \ | |
| | / \ | |
| | / \ | |
| | / \ | |
| |/ \| |
| / \ |
| /| |\ |
| / | | \ |
| / | | \ |
| Instance | | File Descriptor |
| | | |
|______________| |____________________|
1275 objects include the "Package," the "Instance,"
and the device specifier, here simply termed the "Path."
ARC objects include the ARC device specifier, here the
"ArcPath," and the File Descriptor which does not appear
in this module.
The CONFIGURATION_NODE object, a.k.a. the "Node," is the
central data object in the veneer, and is used to translate
from 1275 to ARC and vice versa.
This file contains the routines which do path traversal
and translation for both 1275 and ARC trees. The general
form of the publicly accessible functions is
P<yyy> <xxx>To<yyy>(P<xxx>);
where <xxx> and <yyy> are one of
Path
Package
Instance
Node
ArcPath
and P<xxx> and P<yyy> are types <xxx> and <yyy> if
<xxx> and <yyy> are scalar, and pointers-to-<xxx>/<yyy>
if not.
This sounds a lot more confusing than it is; see below.
Author:
Mike Tuciarone 9-May-1994
--*/
#include "veneer.h"
/*
* Given a configuration node, traverse the Veneer Configuration tree
* looking for a matching component name. Call this initially with
* Node = RootNode. Return the matching node (if any).
*/
STATIC PCONFIGURATION_NODE
DoArcPathToNode(
PCHAR Path,
PCONFIGURATION_NODE Node
)
{
PCONFIGURATION_NODE MatchedNode;
CHAR *name, *cp;
LONG TokenLen;
ULONG Key = 0;
if (Node == NULL) {
return (0);
}
if (cp = index(Path, '(')) {
TokenLen = cp - Path;
cp += 1;
Key = atoi(cp);
} else {
TokenLen = strlen(Path);
}
if (Node == RootNode) {
Node = RootNode->Child;
}
name = Node->ComponentName;
if (!strncmp(name, Path, TokenLen) && (Key == Node->Component.Key)) {
/*
* A match! Trim off the matching component.
*/
debug(VRDBG_CONF,
"ArcPathToNode: path '%s' matched node '%s' %x\n",
Path, Node->ComponentName, Node->OfPhandle);
cp = index(Path, ')');
if (cp == NULL) {
fatal("Malformed string: '%s'\n", Path);
}
cp += 1;
if (*cp == '\0') {
debug(VRDBG_CONF,
"String exhausted, returning %x\n", Node);
return(Node);
}
/*
* If this call returns non-NULL, then we had a match
* further down the tree. Otherwise this is the best
* we can do: return this node.
*/
MatchedNode = DoArcPathToNode(cp, Node->Child);
debug(VRDBG_CONF, "ArcPathToNode('%s') returning %x\n",
Path, MatchedNode ? MatchedNode->OfPhandle : 0);
return(MatchedNode ? MatchedNode : Node);
}
if (Node->Peer) {
return(DoArcPathToNode(Path, Node->Peer));
}
return (0);
}
/*
* External entry point:
*/
PCONFIGURATION_NODE
ArcPathToNode(PCHAR Path)
{
return (DoArcPathToNode(Path, RootNode));
}
/*
* Create the fully-qualified ARC path to describe the argument node.
*/
PCHAR
NodeToArcPath(PCONFIGURATION_NODE node)
{
CHAR *oldbuf, *newbuf;
LONG len;
// Add 3 to each length for the key.
len = 1;
newbuf = zalloc(len);
do {
oldbuf = newbuf;
len += strlen(node->ComponentName) + 3;
newbuf = zalloc(len);
strcpy(newbuf, node->ComponentName);
strcat(newbuf, "( )");
newbuf[strlen(newbuf) - 2] = (char) node->Component.Key + '0';
strcat(newbuf, oldbuf);
free(oldbuf);
} while ((node = node->Parent) && node != RootNode);
return (newbuf);
}
/*
* Search the tree rooted at Node for a node containing the phandle Ph.
* NOTE: Phandles are not unique! This routine does a depth-first
* search to find the *deepest* node matching the phandle.
*/
STATIC PCONFIGURATION_NODE
FindNodeUsingPhandle(PCONFIGURATION_NODE Node, phandle Ph)
{
PCONFIGURATION_NODE Found;
extern int level;
debug(VRDBG_CONF, "FindNodeUsingPhandle: Node %x (%s) phandle %x\n",
Node, Node ? Node->ComponentName : "NULL", Ph);
if (Node == NULL) {
return (NULL);
}
/*
* First check to see if this node matches *and* is a wildcard.
* If so, return immediately.
*/
if (Node->OfPhandle == Ph && Node->Wildcard) {
debug(VRDBG_CONF, "FindNodeUsingPhandle: return %x\n", Node);
return (Node);
}
/*
* Check descendants, since the terminal node may be a child of
* this one. See the comments in add_new_child() in vrtree.c.
*/
level++;
Found = FindNodeUsingPhandle(Node->Child, Ph);
level--;
if (Found) {
debug(VRDBG_CONF, "FindNodeUsingPhandle: return %x\n", Node);
return (Found);
}
if (Node->OfPhandle == Ph) {
debug(VRDBG_CONF, "FindNodeUsingPhandle: return %x\n", Node);
return (Node);
}
return (FindNodeUsingPhandle(Node->Peer, Ph));
}
PCONFIGURATION_NODE
PackageToNode(phandle ph)
{
return (FindNodeUsingPhandle(RootNode, ph));
}
PCONFIGURATION_NODE
PathToNode(PCHAR path)
{
PCONFIGURATION_NODE node, tmpnode;
phandle ph;
PCHAR cp;
ph = OFFinddevice(path);
node = FindNodeUsingPhandle(RootNode, ph);
if (node->Wildcard) {
// trim off final address
while ((cp = index(path, '@')) != NULL) {
path = cp + 1;
}
// XXX run decode-unit on it
// XXX search peers for match using wildcard criteria
if ((tmpnode = FindNodeUsingPhandle(node->Child, ph)) != NULL) {
return (tmpnode);
}
}
return (node);
}
PCONFIGURATION_NODE
InstanceToNode(ihandle ih)
{
char buf[1024];
OFInstanceToPath(ih, buf, 1024);
return (PathToNode(buf));
}
phandle
NodeToPackage(PCONFIGURATION_NODE node)
{
return (node->OfPhandle); // "It's a gift to be simple..."
}
PCHAR
NodeToPath(PCONFIGURATION_NODE node)
{
phandle ph = NodeToPackage(node);
int len;
char *bufp;
//
// Translate the device name into the device path for Open Firmware.
// Add 1 to the reported length to account for the null terminator.
// (See IEEE 1275-1994, Sec. 6.3.2.2.)
//
len = OFPackageToPath(ph, (char *)0, 0) + 1;
bufp = (char *) zalloc(len);
(VOID) OFPackageToPath(ph, bufp, len);
debug(VRDBG_CONF, "NodeToPath found '%s'\n", bufp);
if (node->Wildcard) {
char *newp;
while (node->Parent->Wildcard) {
node = node->Parent;
}
// XXX Generate AddrPath by running encode-unit
// XXX on wildcard criteria
len += strlen(node->WildcardAddrPath);
newp = (char *) zalloc(len);
strcpy(newp, bufp);
free(bufp);
bufp = newp;
debug(VRDBG_CONF, "NodeToPath adding '%s'\n",
node->WildcardAddrPath);
strcat(bufp, node->WildcardAddrPath);
}
debug(VRDBG_CONF, "NodeToPath returning '%s'\n", bufp);
return (bufp);
}
/*
* This routine is hopelessly naive. See VrOpen() for a version
* that's been around.
*/
ihandle
NodeToInstance(PCONFIGURATION_NODE node)
{
char *path = NodeToPath(node);
ihandle ih = OFOpen(path);
free(path);
return (ih);
}
STATIC phandle
DoFindNodeByType(char *type, phandle ph)
{
phandle res;
if (ph == 0) {
return(0);
}
if (strcmp(get_str_prop(ph, "device_type", NOALLOC), type) == 0) {
return(ph);
}
res = DoFindNodeByType(type, OFChild(ph));
if (res != 0) {
return(res);
}
return(DoFindNodeByType(type, OFPeer(ph)));
}
phandle
FindNodeByType(char *type)
{
return(DoFindNodeByType(type, OFPeer(0)));
}
ihandle
OpenPackage(phandle ph)
{
char buf[256];
(void) OFPackageToPath(ph, buf, 256);
return (OFOpen(buf));
}