98 lines
2.5 KiB
C
98 lines
2.5 KiB
C
/* 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 <stdint.h>
|
|
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
|
|
#include <libfdt/libfdt.h>
|
|
#include <skiboot.h>
|
|
#include <device.h>
|
|
#include <compiler.h>
|
|
#include <hostservices.h>
|
|
|
|
#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;
|
|
}
|
|
|