/* Copyright 2013-2014 IBM Corp. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or * implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include #include #include #include #include #include #include #include #include "spira.h" #include "hdata.h" static void merge_property(const struct dt_node *src_root, struct dt_node *dst_root, const char *name) { const struct dt_property *src; struct dt_property *dst; /* Nothing to merge if old one doesn't exist. */ src = dt_find_property(src_root, name); if (!src) return; /* Just create a new one if there's none in dst. */ dst = __dt_find_property(dst_root, name); if (!dst) { dt_add_property(dst_root, name, src->prop, src->len); return; } /* Append src to dst. */ dt_resize_property(&dst, dst->len + src->len); memcpy(dst->prop + dst->len, src->prop, src->len); dst->len += src->len; } static void hservice_parse_dt_tree(const struct dt_node *src) { const struct dt_property *sprop; /* Copy/merge reserved names & ranges properties. */ list_for_each(&src->properties, sprop, list) { if (streq(sprop->name, "reserved-names") || streq(sprop->name, "reserved-ranges") || streq(sprop->name, "ibm,enabled-idle-states")) merge_property(src, dt_root, sprop->name); } } /* Get host services information from hdat. */ bool hservices_from_hdat(const void *fdt, size_t size) { int err; struct dt_node *hservices; prlog(PR_DEBUG, "HBRT: Found mini-DT at 0x%p size: 0x%08lx\n", fdt, size); /* For diagnostic purposes, we copy the whole blob over */ dt_add_property(dt_root, "ibm,hbrt-mini-fdt", fdt, size); /* Parse & extract relevant properties */ err = fdt_check_header(fdt); if (err) { prerror("HBRT: fdt blob %p hdr error %d\n", fdt, err); return false; } hservices = dt_new_root("ibm,hostservices"); err = dt_expand_node(hservices, fdt, 0); if (err < 0) { prerror("HBRT: fdt blob %p parse error %d\n", fdt, err); return false; } hservice_parse_dt_tree(hservices); dt_free(hservices); return true; }