167 lines
3.7 KiB
C
167 lines
3.7 KiB
C
/*
|
|
* Copyright (c) 2006-2023, RT-Thread Development Team
|
|
*
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*/
|
|
#include "libfdt.h"
|
|
#include "dtb_node.h"
|
|
|
|
static off_t dtb_node_find_and_add_subnode(void *fdt, char* name)
|
|
{
|
|
off_t chosen_offset = 0;
|
|
|
|
chosen_offset = fdt_subnode_offset(fdt, 0, name);
|
|
|
|
if (chosen_offset == -FDT_ERR_NOTFOUND)
|
|
{
|
|
chosen_offset = fdt_add_subnode(fdt, 0, name);
|
|
}
|
|
|
|
return chosen_offset;
|
|
}
|
|
|
|
size_t dtb_node_set_linux_cmdline(void *fdt, char *cmdline)
|
|
{
|
|
off_t chosen_offset;
|
|
size_t cmdline_size;
|
|
|
|
if (cmdline == NULL || fdt == NULL)
|
|
{
|
|
goto end;
|
|
}
|
|
|
|
chosen_offset = dtb_node_find_and_add_subnode(fdt, "chosen");
|
|
cmdline_size = strlen(cmdline);
|
|
|
|
/* install bootargs */
|
|
if (chosen_offset >= 0 || chosen_offset == -FDT_ERR_EXISTS)
|
|
{
|
|
if (fdt_setprop(fdt, chosen_offset, "bootargs", cmdline, cmdline_size) < 0)
|
|
{
|
|
fdt_open_into(fdt, fdt, fdt_totalsize(fdt) + FDT_DTB_PAD_SIZE);
|
|
fdt_setprop(fdt, chosen_offset, "bootargs", cmdline, cmdline_size);
|
|
}
|
|
}
|
|
|
|
end:
|
|
return fdt_totalsize(fdt);
|
|
}
|
|
|
|
size_t dtb_node_set_linux_initrd(void *fdt, uint64_t initrd_addr, size_t initrd_size)
|
|
{
|
|
uint64_t addr, size_ptr;
|
|
off_t chosen_offset;
|
|
int i;
|
|
|
|
if (fdt == NULL)
|
|
{
|
|
goto end;
|
|
}
|
|
|
|
chosen_offset = dtb_node_find_and_add_subnode(fdt, "chosen");
|
|
|
|
/* update the entry */
|
|
for (i = fdt_num_mem_rsv(fdt) - 1; i >= 0; --i)
|
|
{
|
|
fdt_get_mem_rsv(fdt, i, &addr, &size_ptr);
|
|
if (addr == initrd_addr)
|
|
{
|
|
fdt_del_mem_rsv(fdt, i);
|
|
break;
|
|
}
|
|
}
|
|
|
|
/* add the memory */
|
|
if (fdt_add_mem_rsv(fdt, initrd_addr, initrd_size) < 0)
|
|
{
|
|
/* move the memory */
|
|
fdt_open_into(fdt, fdt, fdt_totalsize(fdt) + FDT_DTB_PAD_SIZE);
|
|
if (fdt_add_mem_rsv(fdt, initrd_addr, initrd_size) < 0)
|
|
{
|
|
goto end;
|
|
}
|
|
}
|
|
|
|
/* install initrd */
|
|
if (chosen_offset >= 0 || chosen_offset == -FDT_ERR_EXISTS)
|
|
{
|
|
chosen_offset = fdt_path_offset(fdt, "/chosen");
|
|
|
|
if (IN_64BITS_MODE)
|
|
{
|
|
fdt_setprop_u64(fdt, chosen_offset, "linux,initrd-start", initrd_addr);
|
|
fdt_setprop_u64(fdt, chosen_offset, "linux,initrd-end", initrd_addr + initrd_size);
|
|
}
|
|
else
|
|
{
|
|
fdt_setprop_u32(fdt, chosen_offset, "linux,initrd-start", initrd_addr);
|
|
fdt_setprop_u32(fdt, chosen_offset, "linux,initrd-end", initrd_addr + initrd_size);
|
|
}
|
|
}
|
|
|
|
end:
|
|
return fdt_totalsize(fdt);
|
|
}
|
|
|
|
size_t dtb_node_set_dtb_property(void *fdt, char *pathname, char *property_name, uint32_t *cells, size_t cells_size)
|
|
{
|
|
int node_off;
|
|
|
|
if (fdt == NULL)
|
|
{
|
|
goto end;
|
|
}
|
|
|
|
node_off = fdt_path_offset(fdt, pathname);
|
|
|
|
if (node_off >= 0 && cells_size != 0)
|
|
{
|
|
fdt_setprop(fdt, node_off, property_name, cells, cells_size);
|
|
}
|
|
|
|
end:
|
|
return fdt_totalsize(fdt);
|
|
}
|
|
|
|
size_t dtb_node_add_dtb_memreserve(void *fdt, uint64_t address, uint64_t size)
|
|
{
|
|
if (fdt == NULL)
|
|
{
|
|
goto end;
|
|
}
|
|
|
|
fdt_add_mem_rsv(fdt, address, size);
|
|
|
|
end:
|
|
return fdt_totalsize(fdt);
|
|
}
|
|
|
|
size_t dtb_node_del_dtb_memreserve(void *fdt, uint64_t address)
|
|
{
|
|
int i;
|
|
int num_mem_rsvmap;
|
|
uint32_t off_mem_rsvmap;
|
|
struct fdt_reserve_entry *rsvmap;
|
|
|
|
if (fdt == NULL)
|
|
{
|
|
goto end;
|
|
}
|
|
|
|
num_mem_rsvmap = fdt_num_mem_rsv(fdt);
|
|
off_mem_rsvmap = fdt_off_mem_rsvmap(fdt);
|
|
rsvmap = (struct fdt_reserve_entry *)((char *)fdt + off_mem_rsvmap);
|
|
|
|
for (i = 0; i < num_mem_rsvmap; ++i)
|
|
{
|
|
if (address == fdt64_to_cpu(rsvmap[i].address))
|
|
{
|
|
fdt_del_mem_rsv(fdt, i);
|
|
break;
|
|
}
|
|
}
|
|
|
|
end:
|
|
return fdt_totalsize(fdt);
|
|
}
|