#include <l4/types.h>
#include <piggybacker/string.h>
#include <piggybacker/ieee1275.h>
#include <piggybacker/1275tree.h>
#include <piggybacker/io.h>
#define NAME_BUFSIZ 256
device_t *device_find( device_t *list, const char *name )
{
while( list->handle )
{
if( !strcmp_of(list->name, name) )
return list;
list = device_next( list );
}
return (device_t *)0;
}
device_t *device_find_handle( device_t *list, L4_Word32_t handle )
{
while( list->handle )
{
if( list->handle == handle )
return list;
list = device_next( list );
}
return (device_t *)0;
}
item_t *item_find( device_t *dev, const char *name )
{
L4_Word_t i;
item_t *item_name, *item_data;
i = 0;
item_name = item_first( dev );
item_data = item_next( item_name );
while( i < dev->prop_count )
{
if( !strcmp(item_name->data, name) )
return item_data;
item_name = item_next( item_data );
item_data = item_next( item_name );
i++;
}
return (item_t *)0;
}
static void spill_node( device_t *dev, prom_handle_t node )
{
item_t *item, *prev_item, *prop;
int r;
L4_Word_t start_offset;
dev->prop_count = 0;
dev->prop_size = 0;
item = item_first( dev );
start_offset = (L4_Word_t)item;
prev_item = item;
*prev_item->data = '\0';
r = prom_next_prop( node, prev_item->data, item->data );
while( r > 0 )
{
dev->prop_count++;
prev_item = item;
item->len = strlen( item->data ) + 1;
prop = item_next( item );
prop->len = prom_get_prop_len( node, item->data );
if( prop->len < 0 )
prop->len = 0;
else
{
prom_get_prop( node, item->data, prop->data, prop->len );
if( (prop->len == 4) &&
!strcmp_of(dev->name, "/chosen") )
{
L4_Word32_t *handle = (L4_Word32_t *)&prop->data;
*handle = (L4_Word_t)prom_instance_to_package( (void*)(L4_Word_t)*handle );
}
}
item = item_next( prop );
r = prom_next_prop( node, prev_item->data, item->data );
}
dev->prop_size = (L4_Word_t)item - start_offset;
}
static void shift_str( char *name, int shift_point )
{
do {
name[shift_point] = name[shift_point+1];
shift_point++;
} while( name[shift_point] );
}
L4_Word_t build_device_tree( char *spill )
{
prom_handle_t next, node;
int len;
device_t *dev;
node = prom_nav_tree( ROOT_PROM_HANDLE, "peer" );
dev = device_first( spill );
while( node != INVALID_PROM_HANDLE ) {
len = prom_package_to_path( node, dev->name, NAME_BUFSIZ );
if( len > 0 ) {
dev->len = len + 1;
dev->handle = (L4_Word_t)node;
if( (int)strlen(dev->name) != len )
shift_str( dev->name, strlen(dev->name) );
spill_node( dev, node );
dev = device_next( dev );
}
next = prom_nav_tree( node, "child" );
if( next != INVALID_PROM_HANDLE ) {
node = next;
continue;
}
next = prom_nav_tree( node, "peer" );
if( next != INVALID_PROM_HANDLE ) {
node = next;
continue;
}
while( 1 ) {
node = prom_nav_tree( node, "parent" );
if( node == INVALID_PROM_HANDLE )
break;
next = prom_nav_tree( node, "peer" );
if( next != INVALID_PROM_HANDLE ) {
node = next;
break;
}
}
}
dev->handle = dev->len = 0;
dev->prop_count = dev->prop_size = 0;
return (L4_Word_t)dev - (L4_Word_t)spill;
}