333 lines
8.0 KiB
C
333 lines
8.0 KiB
C
|
/*
|
|||
|
* libfdt - Flat Device Tree manipulation
|
|||
|
* Copyright (C) 2006 David Gibson, IBM Corporation.
|
|||
|
* SPDX-License-Identifier: GPL-2.0+ BSD-2-Clause
|
|||
|
*/
|
|||
|
#include <common.h>
|
|||
|
#include "libfdt.h"
|
|||
|
#include "fdt_support.h"
|
|||
|
#include "fdt_acc.h"
|
|||
|
#include "common.h"
|
|||
|
//<2F><><EFBFBD>ض<EFBFBD>Ӧ<EFBFBD><D3A6>name<6D><65>head node<64><65>ƫ<EFBFBD><C6AB><EFBFBD><EFBFBD>
|
|||
|
//<2F><>0<EFBFBD><30>ʾ<EFBFBD>ҵ<EFBFBD><D2B5><EFBFBD>0ֵ<30><D6B5>ʾ<EFBFBD>Ҳ<EFBFBD><D2B2><EFBFBD>
|
|||
|
DECLARE_GLOBAL_DATA_PTR;
|
|||
|
|
|||
|
int fdtfast_search_head(char *head_base, char *dtb_base, char *head_buff, char *name)
|
|||
|
{
|
|||
|
struct head_node *head = NULL, *next_head;
|
|||
|
char *tmp_name = name, *next_end_char;
|
|||
|
uint full_string_sum = 0, full_string_len = 0;
|
|||
|
uint at_flag = 0;
|
|||
|
int i;
|
|||
|
|
|||
|
//ȡ<><C8A1><EFBFBD>ڵ<D7BD>
|
|||
|
head = (struct head_node *)head_buff;
|
|||
|
|
|||
|
//<2F><><EFBFBD><EFBFBD>name<6D><65>/
|
|||
|
while(*tmp_name == '/')
|
|||
|
tmp_name ++;
|
|||
|
//<2F>ҵ<EFBFBD><D2B5><EFBFBD>һ<EFBFBD><D2BB>/<2F><><EFBFBD><EFBFBD><EFBFBD>߿<EFBFBD><DFBF>ַ<EFBFBD>
|
|||
|
next_end_char = tmp_name;
|
|||
|
while(1) {
|
|||
|
if (*next_end_char == '/')
|
|||
|
break;
|
|||
|
if (*next_end_char == '\0')
|
|||
|
break;
|
|||
|
if (*next_end_char == '@')
|
|||
|
at_flag = 1;
|
|||
|
|
|||
|
full_string_sum += *next_end_char;
|
|||
|
full_string_len ++;
|
|||
|
|
|||
|
next_end_char ++;
|
|||
|
}
|
|||
|
//printf("%s %d\n", __FILE__, __LINE__);
|
|||
|
//printf("string_sum=%d\n", full_string_sum);
|
|||
|
for(i=0;i<head->head_count;i++) {
|
|||
|
|
|||
|
next_head = (struct head_node *)(head->head_offset + head_base) + i;
|
|||
|
|
|||
|
//printf("next_head->name_offset=0x%x\n", next_head->name_offset);
|
|||
|
//<2F>Ƚ<EFBFBD><C8BD>ڴ<EFBFBD><DAB4><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
//printf("offset=0x%x\n", (uint)((unsigned long)next_head - (unsigned long)head_base));
|
|||
|
//printf("i=%d\n", i);
|
|||
|
if (!memcmp(tmp_name, next_head->name_offset + dtb_base, full_string_len)) {
|
|||
|
//<2F><><EFBFBD><EFBFBD><EFBFBD>ַ<EFBFBD><D6B7><EFBFBD><EFBFBD><EFBFBD>ͬ<EFBFBD><CDAC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڵ<EFBFBD><DAB5>Dz<EFBFBD><C7B2><EFBFBD><EFBFBD>ظ<EFBFBD><D8B8><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
if ((next_head->repeate_count) && (at_flag))
|
|||
|
continue; //<2F>ڵ<EFBFBD><DAB5><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ظ<EFBFBD><D8B8><EFBFBD><EFBFBD>֣<EFBFBD><D6A3><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
//<2F>ڵ<EFBFBD>û<EFBFBD><C3BB><EFBFBD>ظ<EFBFBD><D8B8><EFBFBD><EFBFBD>֣<EFBFBD><D6A3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
if (*next_end_char != '\0')
|
|||
|
return fdtfast_search_head(head_base, dtb_base, (char *)next_head, next_end_char);
|
|||
|
else
|
|||
|
return (int)((unsigned long)next_head - (unsigned long)head_base);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
return 0;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
struct fdt_property *fdtfast_search_prop(char *dtbfast_buffer, char *fdt_buffer, uint32_t offset, char *name)
|
|||
|
{
|
|||
|
struct fdt_header *fdt = (struct fdt_header *)fdt_buffer;
|
|||
|
struct prop_node *node;
|
|||
|
struct head_node *head;
|
|||
|
|
|||
|
char *tmp_name = name;
|
|||
|
uint32_t string_sum = 0, i;
|
|||
|
char *fdt_string_base, *fdt_string_off;
|
|||
|
|
|||
|
head = (struct head_node *)(dtbfast_buffer + offset + sizeof(struct dtbfast_header));
|
|||
|
while(*tmp_name)
|
|||
|
string_sum += *tmp_name++;
|
|||
|
|
|||
|
fdt_string_base = fdt_buffer + cpu_to_be32(fdt->off_dt_strings);
|
|||
|
for(i=0;i<head->data_count;i++) {
|
|||
|
node = (struct prop_node *)(dtbfast_buffer + head->data_offset + sizeof(struct dtbfast_header)) + i;
|
|||
|
if (string_sum == node->name_sum) {
|
|||
|
fdt_string_off = fdt_string_base + node->name_offset;
|
|||
|
if (!strcmp(name, fdt_string_off)) {
|
|||
|
return (struct fdt_property *)(fdt_buffer + cpu_to_be32(fdt->off_dt_struct) + node->offset);
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
return NULL;
|
|||
|
}
|
|||
|
|
|||
|
int fdtfast_path_offset(const void *fdt, const char *path)
|
|||
|
{
|
|||
|
char *dtbfast_buffer = gd->fdtfast_blob;
|
|||
|
char *dtb_buffer = (char *)fdt;
|
|||
|
uint32_t base_header_size = sizeof(struct dtbfast_header);
|
|||
|
struct fdt_header *fdt_head;
|
|||
|
uint32_t offset;
|
|||
|
|
|||
|
fdt_head = (struct fdt_header *)dtb_buffer;
|
|||
|
if (path == NULL)
|
|||
|
return 0;
|
|||
|
|
|||
|
// printf("path=%s\n", path);
|
|||
|
//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>"/"<22><>ʼ<EFBFBD><CABC><EFBFBD><EFBFBD>ʾ<EFBFBD><CABE><EFBFBD><EFBFBD>һ<EFBFBD><D2BB>aliase<73><65><EFBFBD><EFBFBD>Ҫ<EFBFBD><D2AA>aliase<73>ڵ<EFBFBD><DAB5><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
if (path[0] != '/') {
|
|||
|
struct fdt_property *prop_node;
|
|||
|
|
|||
|
offset = fdtfast_search_head(dtbfast_buffer + base_header_size,
|
|||
|
dtb_buffer + cpu_to_be32(fdt_head->off_dt_struct),
|
|||
|
dtbfast_buffer + base_header_size, "/aliases");
|
|||
|
//printf("%s %d\n", __FILE__, __LINE__);
|
|||
|
if (offset == 0) {
|
|||
|
printf("dtbfast path offset err: cant find aliases\n");
|
|||
|
|
|||
|
return 0;
|
|||
|
}
|
|||
|
|
|||
|
prop_node = fdtfast_search_prop(dtbfast_buffer, dtb_buffer, offset, (char *)path);
|
|||
|
//printf("%s %d\n", __FILE__, __LINE__);
|
|||
|
return fdtfast_search_head(dtbfast_buffer + base_header_size,
|
|||
|
dtb_buffer + cpu_to_be32(fdt_head->off_dt_struct),
|
|||
|
dtbfast_buffer + base_header_size,
|
|||
|
prop_node->data);
|
|||
|
}
|
|||
|
else
|
|||
|
return fdtfast_search_head(dtbfast_buffer + base_header_size, dtb_buffer +
|
|||
|
cpu_to_be32(fdt_head->off_dt_struct),
|
|||
|
dtbfast_buffer + base_header_size, (char *)path);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
int fdtfast_setprop_string(const void *fdt, uint32_t offset, const char *name, const void *val)
|
|||
|
{
|
|||
|
struct fdt_property *prop_node;
|
|||
|
char *dtbfast_buffer = gd->fdtfast_blob;
|
|||
|
char *data, *src;
|
|||
|
int i=0;
|
|||
|
|
|||
|
//printf("%s %d\n", __FILE__, __LINE__);
|
|||
|
prop_node = fdtfast_search_prop(dtbfast_buffer, (char *)fdt, offset, (char *)name);
|
|||
|
if (prop_node == NULL) {
|
|||
|
printf("can not find the string named %s\n", name);
|
|||
|
|
|||
|
return -1;
|
|||
|
}
|
|||
|
|
|||
|
if (cpu_to_be32(prop_node->len) < 4) {
|
|||
|
printf("the name len is too short\n");
|
|||
|
|
|||
|
return -1;
|
|||
|
}
|
|||
|
data = (char *)prop_node->data;
|
|||
|
src = (char *)val;
|
|||
|
|
|||
|
while(src[i]) {
|
|||
|
data[i] = src[i];
|
|||
|
i ++;
|
|||
|
}
|
|||
|
while(i < cpu_to_be32(prop_node->len))
|
|||
|
data[i++] = '\0';
|
|||
|
|
|||
|
|
|||
|
return 0;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
int fdtfast_set_node_status(void *fdt, int nodeoffset, enum fdt_status status, unsigned int error_code)
|
|||
|
{
|
|||
|
//char buf[16];
|
|||
|
int ret = 0;
|
|||
|
|
|||
|
if (nodeoffset < 0)
|
|||
|
return nodeoffset;
|
|||
|
//printf("%s %d\n", __FILE__, __LINE__);
|
|||
|
switch (status) {
|
|||
|
case FDT_STATUS_OKAY:
|
|||
|
ret = fdtfast_setprop_string(fdt, nodeoffset, "status", "okay");
|
|||
|
break;
|
|||
|
case FDT_STATUS_DISABLED:
|
|||
|
ret = fdtfast_setprop_string(fdt, nodeoffset, "status", "bad");
|
|||
|
break;
|
|||
|
case FDT_STATUS_FAIL:
|
|||
|
ret = fdtfast_setprop_string(fdt, nodeoffset, "status", "fail");
|
|||
|
break;
|
|||
|
//case FDT_STATUS_FAIL_ERROR_CODE:
|
|||
|
// sprintf(buf, "fail-%d", error_code);
|
|||
|
// ret = fdtfast_setprop_string(fdt, nodeoffset, "status", buf);
|
|||
|
// break;
|
|||
|
default:
|
|||
|
printf("Invalid fdt status: %x\n", status);
|
|||
|
ret = -1;
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
return ret;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
int fdtfast_setprop_u32(void *fdt, int nodeoffset, const char *name,
|
|||
|
uint32_t val)
|
|||
|
{
|
|||
|
struct fdt_property *prop_node;
|
|||
|
char *dtbfast_buffer = gd->fdtfast_blob;
|
|||
|
uint32_t *data;
|
|||
|
|
|||
|
prop_node = fdtfast_search_prop(dtbfast_buffer, (char *)fdt, nodeoffset, (char *)name);
|
|||
|
if (prop_node == NULL) {
|
|||
|
printf("can not find the string named %s\n", name);
|
|||
|
|
|||
|
return -1;
|
|||
|
}
|
|||
|
|
|||
|
if (cpu_to_be32(prop_node->len) != 4) {
|
|||
|
printf("the name len is invalid\n");
|
|||
|
|
|||
|
return -1;
|
|||
|
}
|
|||
|
data = (uint32_t *)prop_node->data;
|
|||
|
*data = val;
|
|||
|
|
|||
|
return 0;
|
|||
|
}
|
|||
|
|
|||
|
int fdtfast_getprop_u32(const void *fdt, int nodeoffset,
|
|||
|
const char *name, uint32_t *val)
|
|||
|
{
|
|||
|
struct fdt_property *prop_node;
|
|||
|
char *dtbfast_buffer = gd->fdtfast_blob;
|
|||
|
int len, j;
|
|||
|
uint32_t *p;
|
|||
|
|
|||
|
if (val == NULL) {
|
|||
|
printf("the input buff is empty\n");
|
|||
|
|
|||
|
return -1;
|
|||
|
}
|
|||
|
|
|||
|
prop_node = fdtfast_search_prop(dtbfast_buffer, (char *)fdt, nodeoffset, (char *)name);
|
|||
|
if (prop_node == NULL) {
|
|||
|
printf("can not find the string named %s\n", name);
|
|||
|
|
|||
|
return -1;
|
|||
|
}
|
|||
|
|
|||
|
len = cpu_to_be32(prop_node->len);
|
|||
|
if (len & 3) {
|
|||
|
printf("the name len %d is invalid\n", len);
|
|||
|
|
|||
|
return -1;
|
|||
|
}
|
|||
|
|
|||
|
for (j = 0, p = (uint32_t *)prop_node->data; j < len/4; j++)
|
|||
|
{
|
|||
|
*val = fdt32_to_cpu(p[j]);
|
|||
|
val++;
|
|||
|
}
|
|||
|
|
|||
|
return len/4;
|
|||
|
}
|
|||
|
|
|||
|
int fdtfast_getprop_string(const void *fdt, int nodeoffset,
|
|||
|
const char *name, char **val)
|
|||
|
{
|
|||
|
struct fdt_property *prop_node;
|
|||
|
char *dtbfast_buffer = gd->fdtfast_blob;
|
|||
|
int len;
|
|||
|
|
|||
|
if (val == NULL) {
|
|||
|
printf("the input buff is empty\n");
|
|||
|
|
|||
|
return -1;
|
|||
|
}
|
|||
|
|
|||
|
prop_node = fdtfast_search_prop(dtbfast_buffer, (char *)fdt, nodeoffset, (char *)name);
|
|||
|
if (prop_node == NULL) {
|
|||
|
printf("can not find the string named %s\n", name);
|
|||
|
|
|||
|
return -1;
|
|||
|
}
|
|||
|
len = cpu_to_be32(prop_node->len);
|
|||
|
|
|||
|
*val = prop_node->data;
|
|||
|
|
|||
|
return len;
|
|||
|
}
|
|||
|
|
|||
|
int fdtfast_getprop_gpio(const void *fdt, int nodeoffset,
|
|||
|
const char* prop_name, user_gpio_set_t* gpio_list)
|
|||
|
{
|
|||
|
int ret ;
|
|||
|
u32 data[10];
|
|||
|
|
|||
|
memset(data, 0, sizeof(data));
|
|||
|
ret = fdtfast_getprop_u32(fdt, nodeoffset, prop_name, data);
|
|||
|
if (ret < 0) {
|
|||
|
printf("can not find gpio\n");
|
|||
|
|
|||
|
return -1;
|
|||
|
}
|
|||
|
|
|||
|
strcpy(gpio_list->gpio_name, prop_name);
|
|||
|
|
|||
|
gpio_list->port = data[1] + 1; //0: PA
|
|||
|
gpio_list->port_num = data[2];
|
|||
|
gpio_list->mul_sel = data[3];
|
|||
|
gpio_list->pull = data[4];
|
|||
|
gpio_list->drv_level = data[5];
|
|||
|
gpio_list->data = data[6];
|
|||
|
|
|||
|
debug("name = %s, port = %x,portnum=%x,mul_sel=%x,pull=%x drive= %x, data=%x\n",
|
|||
|
gpio_list->gpio_name,
|
|||
|
gpio_list->port,
|
|||
|
gpio_list->port_num,
|
|||
|
gpio_list->mul_sel,
|
|||
|
gpio_list->pull,
|
|||
|
gpio_list->drv_level,
|
|||
|
gpio_list->data);
|
|||
|
|
|||
|
return 0;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|