mirror of
https://gitlab.rtems.org/rtems/rtos/rtems.git
synced 2026-10-06 10:59:48 +08:00
cpukit/rtems-fdt: test and fix index search by offset
The rtems_fdt_subnode_offset and rtems_fdt_get_name try to binary search the entries index by the DTB offset, but the index is sorted by alphabetically by the name, so the search is broken. Replace these searches by directly calling the libfdt functions. Since the DTB offset is known, the performance hit for invoking the libfdt should not be too much. Closes #5606.
This commit is contained in:
committed by
Kinsey Moore
parent
19c75efc9e
commit
fd3d811a9c
@@ -289,38 +289,6 @@ static int rtems_fdt_index_find_by_name(
|
||||
return -FDT_ERR_NOTFOUND;
|
||||
}
|
||||
|
||||
/**
|
||||
* For a given FDT offset, find the corresponding path name.
|
||||
*/
|
||||
static const char *rtems_fdt_index_find_name_by_offset(
|
||||
rtems_fdt_index *index,
|
||||
int offset
|
||||
)
|
||||
{
|
||||
int min = 0;
|
||||
int max = index->num_entries;
|
||||
|
||||
/*
|
||||
* Binary search for the offset.
|
||||
*/
|
||||
while ( min < max ) {
|
||||
int middle = ( min + max ) / 2;
|
||||
if ( offset < index->entries[ middle ].offset ) {
|
||||
/* Look lower than here. */
|
||||
max = middle;
|
||||
} else if ( offset > index->entries[ middle ].offset ) {
|
||||
/* Look higher than here. */
|
||||
min = middle + 1;
|
||||
} else {
|
||||
/* Found it. */
|
||||
return index->entries[ middle ].name;
|
||||
}
|
||||
}
|
||||
|
||||
/* Didn't find it. */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void rtems_fdt_init_handle( rtems_fdt_handle *handle )
|
||||
{
|
||||
if ( handle ) {
|
||||
@@ -662,20 +630,11 @@ int rtems_fdt_subnode_offset(
|
||||
const char *name
|
||||
)
|
||||
{
|
||||
char full_name[ 256 ];
|
||||
const char *path;
|
||||
|
||||
if ( !handle->blob ) {
|
||||
return -RTEMS_FDT_ERR_INVALID_HANDLE;
|
||||
}
|
||||
|
||||
path = rtems_fdt_index_find_name_by_offset(
|
||||
&handle->blob->index,
|
||||
parentoffset
|
||||
);
|
||||
snprintf( full_name, sizeof( full_name ), "%s/%s", path, name );
|
||||
|
||||
return rtems_fdt_index_find_by_name( &handle->blob->index, full_name );
|
||||
return fdt_subnode_offset( handle->blob->blob, parentoffset, name );
|
||||
}
|
||||
|
||||
int rtems_fdt_path_offset( rtems_fdt_handle *handle, const char *path )
|
||||
@@ -693,15 +652,7 @@ const char *rtems_fdt_get_name(
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const char *name = rtems_fdt_index_find_name_by_offset(
|
||||
&handle->blob->index,
|
||||
nodeoffset
|
||||
);
|
||||
if ( name && length ) {
|
||||
*length = strlen( name );
|
||||
}
|
||||
|
||||
return name;
|
||||
return fdt_get_name( handle->blob->blob, nodeoffset, length );
|
||||
}
|
||||
|
||||
int rtems_fdt_first_prop_offset( rtems_fdt_handle *handle, int nodeoffset )
|
||||
|
||||
@@ -71,6 +71,13 @@ void test_getprop(
|
||||
int plen
|
||||
);
|
||||
|
||||
void test_subnode(
|
||||
rtems_fdt_handle *handle,
|
||||
int offset,
|
||||
const char *sname,
|
||||
int slen
|
||||
);
|
||||
|
||||
const char rtems_test_name[] = "FDT 01";
|
||||
|
||||
/* triplets of identical uncompressed/compressed dtbs */
|
||||
@@ -166,6 +173,38 @@ void test_getprop(
|
||||
rtems_test_assert( strncmp( namep, pname, name_len ) == 0 );
|
||||
}
|
||||
|
||||
void test_subnode(
|
||||
rtems_fdt_handle *handle,
|
||||
int offset,
|
||||
const char *sname,
|
||||
int slen
|
||||
)
|
||||
{
|
||||
int idx1, idx2;
|
||||
const char *name;
|
||||
int len = 0;
|
||||
int parent_offset;
|
||||
|
||||
name = rtems_fdt_get_name( handle, offset, &len );
|
||||
rtems_test_assert( strncmp( name, sname, slen ) == 0 );
|
||||
|
||||
parent_offset = rtems_fdt_parent_offset( handle, offset );
|
||||
rtems_test_assert( parent_offset >= 0 );
|
||||
|
||||
idx1 = rtems_fdt_subnode_offset( handle, parent_offset, sname );
|
||||
rtems_test_assert( idx1 >= 0 );
|
||||
rtems_test_assert( idx1 != parent_offset );
|
||||
|
||||
idx2 = rtems_fdt_subnode_offset_namelen(
|
||||
handle,
|
||||
parent_offset,
|
||||
sname,
|
||||
slen
|
||||
);
|
||||
rtems_test_assert( idx2 >= 0 );
|
||||
rtems_test_assert( idx1 == idx2 );
|
||||
}
|
||||
|
||||
rtems_task Init( rtems_task_argument ignored )
|
||||
{
|
||||
(void) ignored;
|
||||
@@ -173,6 +212,8 @@ rtems_task Init( rtems_task_argument ignored )
|
||||
int rc;
|
||||
size_t i;
|
||||
uint32_t val;
|
||||
int idx;
|
||||
const char *name = "interrupt-controller@c000000";
|
||||
rtems_fdt_handle handles[ NUM_DTB ];
|
||||
|
||||
TEST_BEGIN();
|
||||
@@ -233,6 +274,21 @@ rtems_task Init( rtems_task_argument ignored )
|
||||
val = cpu_to_fdt32( 0x2 );
|
||||
test_getprop( &handles[ 0 ], "clocks", &val, sizeof( val ) );
|
||||
|
||||
idx = rtems_fdt_node_offset_by_compatible(
|
||||
&handles[ 6 ],
|
||||
-1,
|
||||
"riscv,plic0"
|
||||
);
|
||||
rtems_test_assert( idx >= 0 );
|
||||
test_subnode( &handles[ 6 ], idx, name, strlen( name ) );
|
||||
/* try again with length truncated to the unit address */
|
||||
test_subnode(
|
||||
&handles[ 6 ],
|
||||
idx,
|
||||
name,
|
||||
(const char *) memchr( name, '@', strlen( name ) ) - name
|
||||
);
|
||||
|
||||
for ( i = 0; i < NUM_DTB; i++ ) {
|
||||
rc = rtems_fdt_unload( &handles[ i ] );
|
||||
rtems_test_assert( rc == 0 );
|
||||
|
||||
Reference in New Issue
Block a user