On Mon, Aug 17, 2020 at 3:49 AM Chris Johns <chr...@rtems.org> wrote:
> On 16/8/20 11:19 pm, Niteesh G. S. wrote: > > > > On Sun, Aug 16, 2020 at 2:25 PM Chris Johns <chr...@rtems.org > > <mailto:chr...@rtems.org>> wrote: > > > > On 16/8/20 4:49 am, G S Niteesh Babu wrote: > > > --- > > > > > + > > > +#ifdef HAVE_CONFIG_H > > > +#include "config.h" > > > +#endif > > > + > > > +#include <bsp/fdt.h> > > > +#include <sys/param.h> > > > +#include <ofw/ofw.h> > > > +#include <libfdt.h> > > > +#include <assert.h> > > > +#include <rtems/sysinit.h> > > > + > > > +const void *fdtp = NULL; > > > + > > > +static phandle_t rtems_fdt_offset_to_phandle( int offset ) > > > +{ > > > + if (offset < 0) { > > > + return 0; > > > + } > > > + > > > + return (phandle_t)offset + fdt_off_dt_struct(fdtp); > > > +} > > > + > > > +static int rtems_fdt_phandle_to_offset( phandle_t handle ) > > > +{ > > > + int off; > > > + int fdt_off; > > > + > > > + off = (int) handle; > > > + fdt_off = fdt_off_dt_struct(fdtp); > > > + > > > + if (off < fdt_off) { > > > + return -1; > > > + > > > + } > > > + > > > + return off - fdt_off; > > > +} > > > + > > > +static void rtems_ofw_init( void ) { > > > + int rv; > > > + const void *fdt; > > > + > > > + fdt = bsp_fdt_get(); > > > + > > > + rv = fdt_check_header(fdt); > > > + > > > + /* > > > + * Is assert a good option to handle error? > > > + * AFIAK there is no other way to recover from invalid FDT. > > > + * On providing an invalid FDT most driver's will fail/crash > anyway. > > > + */ > > > > If you want to fail with an error I suggest a documented internal > error. I > > however would prefer we fail in degraded manner but I understand > this may not be > > possible. > > > > > > During the initial discussion, we discussed adding a new error code in > case of an > > invalid FDT, something like BSP_INVALID_FDT. I had also sent a patch but > then we > > decided not to add one(for some reason that I don't remember). Instead, > use > > RTEMS_NOT_CONFIGURED. This has also been used in my previous OFW patch. > > I am sorry I missed the discussion or I would have commented. Currently > the FDT > support in RTEMS is hostile. If you build a u-boot image and forget to add > FDT > support added you get a low level crash dump and that is unfriendly. I > woud like > to this changed. > So should we add a proper fatal code in case of invalid FDT or FDT is not provided? ARM, POWERPC and RISCV are the only architectures in RTEMS that use FDT. Can we add an FDT check inside start.S before bsp_fdt_copy? and fail properly in case of an invalid FDT. Or is it a better idea to add the check inside bsp_fdt_copy but bsp_fdt_copy is optional in architectures like ARM, RISCV it is compile time guarded with BSP_START_COPY_FDT_FROM_UBOOT > So should we add a new error code like BSP_INVALID_FDT and fatal exit or > just > > use RTEMS_NOT_CONIGURED like the previous patch? > > Not configured is fine with me. > > Chris > > > > > > > + assert(rv == 0); > > > > I would prefer we did not make this code dependent on -DNDEBUG. > > > > Chris > > > > > + > > > + fdtp = fdt; > > > +} > > > + > > > +RTEMS_SYSINIT_ITEM( > > > + rtems_ofw_init, > > > + RTEMS_SYSINIT_BSP_PRE_DRIVERS, > > > + RTEMS_SYSINIT_ORDER_FIRST > > > +); > > > + > > > +phandle_t rtems_ofw_peer( phandle_t node ) > > > +{ > > > + int offset; > > > + > > > + if (node == 0) { > > > + int root = fdt_path_offset(fdtp, "/"); > > > + return rtems_fdt_offset_to_phandle(root); > > > + } > > > + > > > + offset = rtems_fdt_phandle_to_offset(node); > > > + if (offset < 0) { > > > + return 0; > > > + } > > > + > > > + offset = fdt_next_subnode(fdtp, offset); > > > + return rtems_fdt_offset_to_phandle(offset); > > > +} > > > + > > > +phandle_t rtems_ofw_child( phandle_t node ) > > > +{ > > > + int offset; > > > + > > > + offset = rtems_fdt_phandle_to_offset(node); > > > + > > > + if (offset < 0) { > > > + return 0; > > > + } > > > + > > > + offset = fdt_first_subnode(fdtp, offset); > > > + return rtems_fdt_offset_to_phandle(offset); > > > +} > > > + > > > +phandle_t rtems_ofw_parent( phandle_t node ) > > > +{ > > > + int offset; > > > + > > > + offset = rtems_fdt_phandle_to_offset(node); > > > + > > > + if (offset < 0) { > > > + return 0; > > > + } > > > + > > > + offset = fdt_parent_offset(fdtp, offset); > > > + return rtems_fdt_offset_to_phandle(offset); > > > +} > > > + > > > +size_t rtems_ofw_get_prop_len( > > > + phandle_t node, > > > + const char *propname > > > +) > > > +{ > > > + int offset; > > > + int len; > > > + const void *prop; > > > + > > > + offset = rtems_fdt_phandle_to_offset(node); > > > + > > > + if (offset < 0) { > > > + return -1; > > > + } > > > + > > > + prop = fdt_getprop(fdtp, offset, propname, &len); > > > + > > > + if (prop == NULL && strcmp(propname, "name") == 0) { > > > + fdt_get_name(fdtp, offset, &len); > > > + return len + 1; > > > + } > > > + > > > + if (prop == NULL && strcmp(propname, "/chosen") == 0) { > > > + if (strcmp(propname, "fdtbootcpu") == 0) > > > + return sizeof(pcell_t); > > > + if (strcmp(propname, "fdtmemreserv") == 0) > > > + return 2 * sizeof(uint64_t) * fdt_num_mem_rsv(fdtp); > > > + } > > > + > > > + if (prop == NULL) { > > > + return -1; > > > + } > > > + > > > + return len; > > > +} > > > + > > > +size_t rtems_ofw_get_prop( > > > + phandle_t node, > > > + const char *propname, > > > + void *buf, > > > + size_t bufsize > > > +) > > > +{ > > > + int offset; > > > + int len; > > > + const void *prop; > > > + > > > + offset = rtems_fdt_phandle_to_offset(node); > > > + > > > + if (offset < 0) { > > > + return -1; > > > + } > > > + > > > + prop = fdt_getprop(fdtp, offset, propname, &len); > > > + > > > + if (prop == NULL && strcmp(propname, "name") == 0) { > > > + fdt_get_name(fdtp, offset, &len); > > > + return len + 1; > > > + } > > > + > > > + if (prop == NULL && strcmp(propname, "/chosen") == 0) { > > > + if (strcmp(propname, "fdtbootcpu") == 0) > > > + return sizeof(pcell_t); > > > + if (strcmp(propname, "fdtmemreserv") == 0) > > > + return 2 * sizeof(uint64_t) * fdt_num_mem_rsv(fdtp); > > > + } > > > + > > > + if (prop == NULL) { > > > + return -1; > > > + } > > > + > > > + bcopy(prop, buf, MIN(len, bufsize)); > > > + > > > + return len; > > > +} > > > + > > > +size_t rtems_ofw_get_enc_prop( > > > + phandle_t node, > > > + const char *prop, > > > + pcell_t *buf, > > > + size_t len > > > +) > > > +{ > > > + size_t rv; > > > + > > > + assert(len % 4 == 0); > > > + rv = rtems_ofw_get_prop(node, prop, buf, len); > > > + > > > + if (rv < 0) { > > > + return rv; > > > + } > > > + > > > + for (int i = 0; i < (len / 4); i++) { > > > + buf[i] = fdt32_to_cpu(buf[i]); > > > + } > > > + > > > + return rv; > > > +} > > > + > > > +int rtems_ofw_has_prop( > > > + phandle_t node, > > > + const char *propname > > > +) > > > +{ > > > + size_t rv; > > > + > > > + rv = rtems_ofw_get_prop_len(node, propname); > > > + return rv >= 0 ? 1 : 0; > > > +} > > > + > > > +size_t rtems_ofw_search_prop( > > > + phandle_t node, > > > + const char *propname, > > > + void *buf, > > > + size_t len > > > +) > > > +{ > > > + size_t rv; > > > + > > > + for (; node != 0; node = rtems_ofw_parent(node)) { > > > + if ((rv = rtems_ofw_get_prop(node, propname, buf, len) != > -1)) { > > > + return rv; > > > + } > > > + } > > > + > > > + return -1; > > > +} > > > + > > > +size_t rtems_ofw_search_enc_prop( > > > + phandle_t node, > > > + const char *propname, > > > + pcell_t *buf, > > > + size_t len > > > +) > > > +{ > > > + size_t rv; > > > + > > > + for (; node != 0; node = rtems_ofw_parent(node)) { > > > + if ((rv = rtems_ofw_get_enc_prop(node, propname, buf, len) != > -1)) { > > > + return rv; > > > + } > > > + } > > > + > > > + return -1; > > > +} > > > + > > > +size_t rtems_ofw_get_prop_alloc( > > > + phandle_t node, > > > + const char *propname, > > > + void **buf > > > +) > > > +{ > > > + size_t len; > > > + > > > + if ((len = rtems_ofw_get_prop_len(node, propname)) == -1) { > > > + return -1; > > > + } > > > + > > > + *buf = NULL; > > > + > > > + if (len > 0) { > > > + *buf = malloc(len); > > > + > > > + if (rtems_ofw_get_prop(node, propname, *buf, len) == -1) { > > > + rtems_ofw_free(buf); > > > + *buf = NULL; > > > + return -1; > > > + } > > > + } > > > + > > > + return len; > > > +} > > > + > > > +size_t rtems_ofw_get_prop_alloc_multi( > > > + phandle_t node, > > > + const char *propname, > > > + int elsz, > > > + void **buf > > > +) > > > +{ > > > + size_t len; > > > + > > > + if ((len = rtems_ofw_get_prop_len(node, propname)) == -1 || > > > + (len % elsz != 0)) { > > > + return -1; > > > + } > > > + > > > + *buf = NULL; > > > + > > > + if (len > 0) { > > > + *buf = malloc(len); > > > + > > > + if (rtems_ofw_get_prop(node, propname, *buf, len) == -1) { > > > + rtems_ofw_free(buf); > > > + *buf = NULL; > > > + return -1; > > > + } > > > + } > > > + > > > + return (len / elsz); > > > +} > > > + > > > +size_t rtems_ofw_get_enc_prop_alloc( > > > + phandle_t node, > > > + const char *propname, > > > + void **buf > > > +) > > > +{ > > > + size_t len; > > > + > > > + if ((len = rtems_ofw_get_prop_len(node, propname)) == -1) { > > > + return -1; > > > + } > > > + > > > + *buf = NULL; > > > + > > > + if (len > 0) { > > > + *buf = malloc(len); > > > + > > > + if (rtems_ofw_get_enc_prop(node, propname, *buf, len) == -1) { > > > + rtems_ofw_free(buf); > > > + *buf = NULL; > > > + return -1; > > > + } > > > + } > > > + > > > + return len; > > > +} > > > + > > > +size_t rtems_ofw_get_enc_prop_alloc_multi( > > > + phandle_t node, > > > + const char *propname, > > > + int elsz, > > > + void **buf > > > +) > > > +{ > > > + size_t len; > > > + > > > + if ((len = rtems_ofw_get_prop_len(node, propname)) == -1 || > > > + (len % elsz != 0)) { > > > + return -1; > > > + } > > > + > > > + *buf = NULL; > > > + > > > + if (len > 0) { > > > + *buf = malloc(len); > > > + > > > + if (rtems_ofw_get_enc_prop(node, propname, *buf, len) == -1) { > > > + rtems_ofw_free(buf); > > > + *buf = NULL; > > > + return -1; > > > + } > > > + } > > > + > > > + return (len / elsz); > > > +} > > > + > > > +void rtems_ofw_free( void *buf ) > > > +{ > > > + free(buf); > > > +} > > > + > > > +int rtems_ofw_next_prop( > > > + phandle_t node, > > > + const char *previous, > > > + char *buf, > > > + size_t len > > > +) > > > +{ > > > + const void *name; > > > + const void *prop; > > > + int offset; > > > + > > > + offset = rtems_fdt_phandle_to_offset(node); > > > + > > > + if (offset < 0) { > > > + return -1; > > > + } > > > + > > > + if (previous == NULL) { > > > + offset = fdt_first_property_offset(fdtp, offset); > > > + } else { > > > + fdt_for_each_property_offset(offset, fdtp, offset) { > > > + prop = fdt_getprop_by_offset(fdtp, offset, (const char > **)&name, NULL); > > > + if (prop == NULL) > > > + return -1; > > > + > > > + if (strcmp(previous, name) != 0) > > > + continue; > > > + > > > + offset = fdt_next_property_offset(fdtp, offset); > > > + break; > > > + } > > > + } > > > + > > > + if (offset < 0) > > > + return 0; > > > + > > > + prop = fdt_getprop_by_offset(fdtp, offset, (const char > **)&name, &offset); > > > + if (prop == NULL) > > > + return -1; > > > + > > > + strncpy(buf, name, len); > > > + > > > + return 1; > > > +} > > > + > > > +int rtems_ofw_set_prop( > > > + phandle_t node, > > > + const char *name, > > > + const void *buf, > > > + size_t len > > > +) > > > +{ > > > + int offset; > > > + > > > + offset = rtems_fdt_phandle_to_offset(node); > > > + > > > + if (offset < 0) > > > + return -1; > > > + > > > + if (fdt_setprop_inplace(fdtp, offset, name, buf, len) != 0) > > > + return (fdt_setprop(fdtp, offset, name, buf, len)); > > > + > > > + return 0; > > > +} > > > + > > > +phandle_t rtems_ofw_find_device( const char *path ) > > > +{ > > > + int offset; > > > + > > > + offset = fdt_path_offset(fdtp, path); > > > + if (offset < 0) > > > + return -1; > > > + > > > + return rtems_fdt_offset_to_phandle(offset); > > > +} > > > + > > > +static phandle_t rtems_ofw_get_effective_phandle( > > > + phandle_t node, > > > + phandle_t xref > > > +) > > > +{ > > > + phandle_t child; > > > + phandle_t ref; > > > + > > > + for (child = rtems_ofw_child(node); child != 0; child = > > rtems_ofw_peer(node)) { > > > + ref = rtems_ofw_get_effective_phandle(child, xref); > > > + if (ref != -1) > > > + return ref; > > > + > > > + if (rtems_ofw_get_enc_prop(child, "phandle", &ref, > sizeof(ref)) == -1 && > > > + rtems_ofw_get_enc_prop(child, "ibm,phandle", &ref, > sizeof(ref)) > > == -1 && > > > + rtems_ofw_get_enc_prop(child, "linux,phandle", &ref, > sizeof(ref)) > > == -1 > > > + ) { > > > + continue; > > > + } > > > + > > > + if (ref == xref) > > > + return child; > > > + } > > > + > > > + return -1; > > > +} > > > + > > > +phandle_t rtems_ofw_node_from_xref( phandle_t xref ) > > > +{ > > > + phandle_t node; > > > + > > > + if ((node = rtems_ofw_get_effective_phandle(rtems_ofw_peer(0), > xref)) > > == -1) > > > + return xref; > > > + > > > + return node; > > > +} > > > + > > > +phandle_t rtems_ofw_xref_from_node( phandle_t node ) > > > +{ > > > + phandle_t ref; > > > + > > > + if (rtems_ofw_get_enc_prop(node, "phandle", &ref, > sizeof(ref)) == -1 && > > > + rtems_ofw_get_enc_prop(node, "ibm,phandle", &ref, > sizeof(ref)) == > > -1 && > > > + rtems_ofw_get_enc_prop(node, "linux,phandle", &ref, > sizeof(ref)) > > == -1) > > > + { > > > + return node; > > > + } > > > + > > > + return ref; > > > +} > > > + > > > +phandle_t rtems_ofw_instance_to_package( ihandle_t instance ) > > > +{ > > > + return rtems_ofw_node_from_xref(instance); > > > +} > > > + > > > +size_t rtems_ofw_package_to_path( > > > + phandle_t node, > > > + char *buf, > > > + size_t len > > > +) > > > +{ > > > + int offset; > > > + int rv; > > > + > > > + offset = rtems_fdt_phandle_to_offset(node); > > > + > > > + rv = fdt_get_path(fdtp, offset, buf, len); > > > + if (rv != 0) > > > + return -1; > > > + > > > + return rv; > > > +} > > > + > > > +size_t rtems_ofw_instance_to_path( > > > + ihandle_t instance, > > > + char *buf, > > > + size_t len > > > +) > > > +{ > > > + int offset; > > > + int rv; > > > + > > > + offset = rtems_ofw_instance_to_package(instance); > > > + offset = rtems_fdt_phandle_to_offset(offset); > > > + > > > + rv = fdt_get_path(fdtp, offset, buf, len); > > > + if (rv != 0) > > > + return -1; > > > + > > > + return rv; > > > +} > > > + > > > +int rtems_ofw_get_reg( > > > + phandle_t node, > > > + rtems_ofw_memory_area *buf, > > > + size_t size > > > +) > > > +{ > > > + int len; > > > + int offset; > > > + int nranges; > > > + int nregs; > > > + phandle_t parent; > > > + rtems_ofw_ranges range; > > > + const rtems_ofw_ranges *ptr; > > > + > > > + len = rtems_ofw_get_enc_prop(node, "reg", (pcell_t *)buf, size); > > > + if (len <= 0) { > > > + return len; > > > + } > > > + > > > + nregs = MIN(len, size) / sizeof(rtems_ofw_memory_area); > > > + > > > + for (parent = rtems_ofw_parent(node); parent > 0; > > > + parent = rtems_ofw_parent(parent)) { > > > + > > > + offset = rtems_fdt_phandle_to_offset(parent); > > > + ptr = fdt_getprop(fdtp, offset, "ranges", &len); > > > + > > > + if (len < 0) { > > > + break; > > > + } > > > + > > > + nranges = len / sizeof(rtems_ofw_ranges); > > > + > > > + offset = 0; > > > + for (int i=0; i < nregs; i++) { > > > + for (int j=0; j < nranges; j++) { > > > + > > > + range.parent_bus = fdt32_to_cpu(ptr[j].parent_bus); > > > + range.child_bus = fdt32_to_cpu(ptr[j].child_bus); > > > + range.size = fdt32_to_cpu(ptr[j].size); > > > + > > > + if (buf[i].start >= range.child_bus && > > > + buf[i].start < range.child_bus + range.size) { > > > + offset = range.parent_bus - range.child_bus; > > > + break; > > > + } > > > + > > > + } > > > + buf[i].start += offset; > > > + } > > > + } > > > + > > > + return nregs; > > > +} > > > + > > > +int rtems_ofw_get_interrupts( > > > + phandle_t node, > > > + void *buf, > > > + size_t size > > > +) > > > +{ > > > + int rv; > > > + > > > + rv = rtems_ofw_get_enc_prop(node, "interrupts", buf, size); > > > + return rv; > > > +} > > > + > > > +bool rtems_ofw_node_status( phandle_t node ) > > > +{ > > > + int len; > > > + const char buf[10]; > > > + > > > + len = rtems_ofw_get_prop(node, "status", &buf[0], sizeof(buf)); > > > + if ((len == -1) || > > > + (strncmp(buf, "okay", MIN(5, len)) == 0) || > > > + (strncmp(buf, "ok", MIN(3, len)) == 0)) { > > > + return true; > > > + } > > > + > > > + return false; > > > +} > > > diff --git a/spec/build/bsps/obj.yml b/spec/build/bsps/obj.yml > > > index 8809238057..141ba25f5e 100644 > > > --- a/spec/build/bsps/obj.yml > > > +++ b/spec/build/bsps/obj.yml > > > @@ -24,6 +24,9 @@ install: > > > - bsps/include/bsp/u-boot.h > > > - bsps/include/bsp/uart-output-char.h > > > - bsps/include/bsp/utility.h > > > +- destination: ${BSP_INCLUDEDIR}/ofw > > > + source: > > > + - bsps/include/ofw/ofw.h > > > - destination: ${BSP_INCLUDEDIR}/libchip > > > source: > > > - bsps/include/libchip/am29lv160.h > > > @@ -104,4 +107,5 @@ source: > > > - bsps/shared/dev/serial/z85c30_reg.c > > > - bsps/shared/start/bootcard.c > > > - bsps/shared/rtems-version.c > > > +- bsps/shared/ofw/ofw.c > > > type: build > > > > > >
_______________________________________________ devel mailing list devel@rtems.org http://lists.rtems.org/mailman/listinfo/devel