mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-12-23 02:54:32 +08:00
c10c178a92
If the vmlinux binary in memory is larger than 4 MiB than it collides with the initial boot code which is linked at 4 MiB in case of cuBoot. If the the uncompressed image size (on disk size) is less than 4 MiB then it would fit. The difference between those two sizes is the bss section. In cuBoot we have the dtb embedded right after the data section so it is very likely that the reset of the bss section (in kernel's start up code) will overwrite the dtb blob. Therefore we reallocate the dtb. Something similar is allready done to the initrd. Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de> Acked-by: David Gibson <david@gibson.dropbear.id.au> Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
194 lines
4.9 KiB
C
194 lines
4.9 KiB
C
/*
|
|
* This file does the necessary interface mapping between the bootwrapper
|
|
* device tree operations and the interface provided by shared source
|
|
* files flatdevicetree.[ch].
|
|
*
|
|
* Copyright 2007 David Gibson, IBM Corporation.
|
|
*
|
|
* This library is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU General Public License as
|
|
* published by the Free Software Foundation; either version 2 of the
|
|
* License, or (at your option) any later version.
|
|
*
|
|
* This library is distributed in the hope that it will be useful, but
|
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this library; if not, write to the Free Software
|
|
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
|
|
* 02110-1301 USA
|
|
*/
|
|
|
|
#include <stddef.h>
|
|
#include <stdio.h>
|
|
#include <page.h>
|
|
#include <libfdt.h>
|
|
#include "ops.h"
|
|
|
|
#define DEBUG 0
|
|
#define BAD_ERROR(err) (((err) < 0) \
|
|
&& ((err) != -FDT_ERR_NOTFOUND) \
|
|
&& ((err) != -FDT_ERR_EXISTS))
|
|
|
|
#define check_err(err) \
|
|
({ \
|
|
if (BAD_ERROR(err) || ((err < 0) && DEBUG)) \
|
|
printf("%s():%d %s\n\r", __func__, __LINE__, \
|
|
fdt_strerror(err)); \
|
|
if (BAD_ERROR(err)) \
|
|
exit(); \
|
|
(err < 0) ? -1 : 0; \
|
|
})
|
|
|
|
#define offset_devp(off) \
|
|
({ \
|
|
int _offset = (off); \
|
|
check_err(_offset) ? NULL : (void *)(_offset+1); \
|
|
})
|
|
|
|
#define devp_offset_find(devp) (((int)(devp))-1)
|
|
#define devp_offset(devp) (devp ? ((int)(devp))-1 : 0)
|
|
|
|
static void *fdt;
|
|
static void *buf; /* = NULL */
|
|
|
|
#define EXPAND_GRANULARITY 1024
|
|
|
|
static void expand_buf(int minexpand)
|
|
{
|
|
int size = fdt_totalsize(fdt);
|
|
int rc;
|
|
|
|
size = _ALIGN(size + minexpand, EXPAND_GRANULARITY);
|
|
buf = platform_ops.realloc(buf, size);
|
|
if (!buf)
|
|
fatal("Couldn't find %d bytes to expand device tree\n\r", size);
|
|
rc = fdt_open_into(fdt, buf, size);
|
|
if (rc != 0)
|
|
fatal("Couldn't expand fdt into new buffer: %s\n\r",
|
|
fdt_strerror(rc));
|
|
|
|
fdt = buf;
|
|
}
|
|
|
|
static void *fdt_wrapper_finddevice(const char *path)
|
|
{
|
|
return offset_devp(fdt_path_offset(fdt, path));
|
|
}
|
|
|
|
static int fdt_wrapper_getprop(const void *devp, const char *name,
|
|
void *buf, const int buflen)
|
|
{
|
|
const void *p;
|
|
int len;
|
|
|
|
p = fdt_getprop(fdt, devp_offset(devp), name, &len);
|
|
if (!p)
|
|
return check_err(len);
|
|
memcpy(buf, p, min(len, buflen));
|
|
return len;
|
|
}
|
|
|
|
static int fdt_wrapper_setprop(const void *devp, const char *name,
|
|
const void *buf, const int len)
|
|
{
|
|
int rc;
|
|
|
|
rc = fdt_setprop(fdt, devp_offset(devp), name, buf, len);
|
|
if (rc == -FDT_ERR_NOSPACE) {
|
|
expand_buf(len + 16);
|
|
rc = fdt_setprop(fdt, devp_offset(devp), name, buf, len);
|
|
}
|
|
|
|
return check_err(rc);
|
|
}
|
|
|
|
static void *fdt_wrapper_get_parent(const void *devp)
|
|
{
|
|
return offset_devp(fdt_parent_offset(fdt, devp_offset(devp)));
|
|
}
|
|
|
|
static void *fdt_wrapper_create_node(const void *devp, const char *name)
|
|
{
|
|
int offset;
|
|
|
|
offset = fdt_add_subnode(fdt, devp_offset(devp), name);
|
|
if (offset == -FDT_ERR_NOSPACE) {
|
|
expand_buf(strlen(name) + 16);
|
|
offset = fdt_add_subnode(fdt, devp_offset(devp), name);
|
|
}
|
|
|
|
return offset_devp(offset);
|
|
}
|
|
|
|
static void *fdt_wrapper_find_node_by_prop_value(const void *prev,
|
|
const char *name,
|
|
const char *val,
|
|
int len)
|
|
{
|
|
int offset = fdt_node_offset_by_prop_value(fdt, devp_offset_find(prev),
|
|
name, val, len);
|
|
return offset_devp(offset);
|
|
}
|
|
|
|
static void *fdt_wrapper_find_node_by_compatible(const void *prev,
|
|
const char *val)
|
|
{
|
|
int offset = fdt_node_offset_by_compatible(fdt, devp_offset_find(prev),
|
|
val);
|
|
return offset_devp(offset);
|
|
}
|
|
|
|
static char *fdt_wrapper_get_path(const void *devp, char *buf, int len)
|
|
{
|
|
int rc;
|
|
|
|
rc = fdt_get_path(fdt, devp_offset(devp), buf, len);
|
|
if (check_err(rc))
|
|
return NULL;
|
|
return buf;
|
|
}
|
|
|
|
static unsigned long fdt_wrapper_finalize(void)
|
|
{
|
|
int rc;
|
|
|
|
rc = fdt_pack(fdt);
|
|
if (rc != 0)
|
|
fatal("Couldn't pack flat tree: %s\n\r",
|
|
fdt_strerror(rc));
|
|
return (unsigned long)fdt;
|
|
}
|
|
|
|
void fdt_init(void *blob)
|
|
{
|
|
int err;
|
|
int bufsize;
|
|
|
|
dt_ops.finddevice = fdt_wrapper_finddevice;
|
|
dt_ops.getprop = fdt_wrapper_getprop;
|
|
dt_ops.setprop = fdt_wrapper_setprop;
|
|
dt_ops.get_parent = fdt_wrapper_get_parent;
|
|
dt_ops.create_node = fdt_wrapper_create_node;
|
|
dt_ops.find_node_by_prop_value = fdt_wrapper_find_node_by_prop_value;
|
|
dt_ops.find_node_by_compatible = fdt_wrapper_find_node_by_compatible;
|
|
dt_ops.get_path = fdt_wrapper_get_path;
|
|
dt_ops.finalize = fdt_wrapper_finalize;
|
|
|
|
/* Make sure the dt blob is the right version and so forth */
|
|
fdt = blob;
|
|
bufsize = fdt_totalsize(fdt) + 4;
|
|
buf = malloc(bufsize);
|
|
if(!buf)
|
|
fatal("malloc failed. can't relocate the device tree\n\r");
|
|
|
|
err = fdt_open_into(fdt, buf, bufsize);
|
|
|
|
if (err != 0)
|
|
fatal("fdt_init(): %s\n\r", fdt_strerror(err));
|
|
|
|
fdt = buf;
|
|
}
|