123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197 |
- /*
- * Copyright (c) 2006-2022, RT-Thread Development Team
- *
- * SPDX-License-Identifier: Apache-2.0
- *
- * Change Logs:
- * Date Author Notes
- * 2022-10-19 GuEe-GUI first version
- */
- #include <drivers/ofw_raw.h>
- int fdt_add_subnode_possible(void *fdt, int parentoffset, const char *name)
- {
- int nodeoffset;
- if ((nodeoffset = fdt_add_subnode(fdt, parentoffset, name)) < 0)
- {
- fdt_open_into(fdt, fdt, fdt_totalsize(fdt) + FDT_PADDING_SIZE);
- nodeoffset = fdt_add_subnode(fdt, parentoffset, name);
- }
- return nodeoffset;
- }
- int fdt_add_mem_rsv_possible(void *fdt, size_t addr, size_t size)
- {
- int err = 0;
- if (fdt_add_mem_rsv(fdt, addr, size) < 0)
- {
- fdt_open_into(fdt, fdt, fdt_totalsize(fdt) + FDT_PADDING_SIZE);
- err = fdt_add_mem_rsv(fdt, addr, size);
- }
- return err;
- }
- int fdt_setprop_uxx(void *fdt, int nodeoffset, const char *name, uint64_t val, bool is_u64)
- {
- int err;
- if (is_u64)
- {
- err = fdt_setprop_u64(fdt, nodeoffset, name, val);
- }
- else
- {
- err = fdt_setprop_u32(fdt, nodeoffset, name, (uint32_t)val);
- }
- return err;
- }
- #define FDT_RAW_GET_VAL_FLAG(std_type, s, sz) \
- int fdt_getprop_##std_type##sz(void *fdt, int nodeoffset, \
- const char *name, s##int##sz##_t *out_value, int *lenp) \
- { \
- int err = -FDT_ERR_NOTFOUND; \
- if (fdt && nodeoffset >= 0 && name && out_value) \
- { \
- const fdt##sz##_t *ptr; \
- if ((ptr = fdt_getprop(fdt, nodeoffset, name, lenp))) \
- { \
- *out_value = fdt##sz##_to_cpu(*ptr); \
- err = 0; \
- } \
- } \
- return err; \
- }
- #define FDT_RAW_GET_VAL(size) \
- FDT_RAW_GET_VAL_FLAG(u, u, size) \
- FDT_RAW_GET_VAL_FLAG(s, , size)
- FDT_RAW_GET_VAL(64)
- FDT_RAW_GET_VAL(32)
- FDT_RAW_GET_VAL(16)
- FDT_RAW_GET_VAL(8)
- #undef FDT_RAW_GET_VAL
- #undef FDT_RAW_GET_VAL_FLAG
- int fdt_io_addr_cells(void *fdt, int nodeoffset)
- {
- int cells = -1;
- int parentoffset = fdt_parent_offset(fdt, nodeoffset);
- for (; parentoffset >= 0 ; parentoffset = fdt_parent_offset(fdt, parentoffset))
- {
- const fdt32_t *cells_tmp = fdt_getprop(fdt, parentoffset, "#address-cells", NULL);
- if (cells_tmp)
- {
- cells = fdt32_to_cpu(*cells_tmp);
- }
- }
- if (cells < 0)
- {
- cells = fdt_address_cells(fdt, nodeoffset);
- }
- return cells;
- }
- int fdt_io_size_cells(void *fdt, int nodeoffset)
- {
- int cells = -1;
- int parentoffset = fdt_parent_offset(fdt, nodeoffset);
- for (; parentoffset >= 0 ; parentoffset = fdt_parent_offset(fdt, parentoffset))
- {
- const fdt32_t *cells_tmp = fdt_getprop(fdt, parentoffset, "#size-cells", NULL);
- if (cells_tmp)
- {
- cells = fdt32_to_cpu(*cells_tmp);
- }
- }
- if (cells < 0)
- {
- cells = fdt_size_cells(fdt, nodeoffset);
- }
- return cells;
- }
- int fdt_install_initrd(void *fdt, char *os_name, size_t initrd_addr, size_t initrd_size)
- {
- int err = -FDT_ERR_NOTFOUND;
- int chosen_offset = -1, root_off = fdt_path_offset(fdt, "/");
- if (root_off >= 0)
- {
- chosen_offset = fdt_subnode_offset(fdt, root_off, "chosen");
- if (chosen_offset == -FDT_ERR_NOTFOUND)
- {
- chosen_offset = fdt_add_subnode_possible(fdt, root_off, "chosen");
- }
- }
- if (chosen_offset >= 0)
- {
- uint64_t addr, size;
- err = 0;
- /* Update the entry */
- for (int i = fdt_num_mem_rsv(fdt) - 1; i >= 0; --i)
- {
- fdt_get_mem_rsv(fdt, i, &addr, &size);
- 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_PADDING_SIZE);
- if (fdt_add_mem_rsv(fdt, initrd_addr, initrd_size) < 0)
- {
- err = -FDT_ERR_NOSPACE;
- }
- }
- if (!err)
- {
- size_t name_len;
- char initrd_name[64];
- bool is_u64 = (fdt_io_addr_cells(fdt, root_off) == 2);
- if (!os_name)
- {
- os_name = "rt-thread";
- }
- name_len = strlen(initrd_name);
- strncpy(&initrd_name[name_len], ",initrd-start", sizeof(initrd_name) - name_len);
- fdt_setprop_uxx(fdt, chosen_offset, initrd_name, initrd_addr, is_u64);
- strncpy(&initrd_name[name_len], ",initrd-end", sizeof(initrd_name) - name_len);
- fdt_setprop_uxx(fdt, chosen_offset, initrd_name, initrd_addr + initrd_size, is_u64);
- }
- }
- return err;
- }
|