barebox/arch/arm/lib/bootz.c
Sascha Hauer f30b191e36 of: make of_get_fixed_tree more universally usable
Currently the bootm code uses of_fix_tree to apply the fixups
to the devicetree given on the command line. This function assumes
that there is enough space for the fixups available. Also on ARM
we have to make sure the tree does not cross 1Mib boundaries.

This patch moves the space allocation and alignment ensurance
to of_get_fixed_tree and uses it in bootm. This is the first
step for making of_get_fixed_tree the single point of devicetree
handling in barebox.
of_get_fixed_tree now takes an argument of the input fdt. If it is
given, this one is used, otherwise an internal oftree is used which
will be created in subsequent patches.

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
2013-01-11 14:08:30 +01:00

140 lines
2.7 KiB
C

#include <common.h>
#include <command.h>
#include <fs.h>
#include <of.h>
#include <fcntl.h>
#include <errno.h>
#include <malloc.h>
#include <sizes.h>
#include <asm/byteorder.h>
#include <asm/armlinux.h>
#include <asm/system.h>
#include <asm-generic/memory_layout.h>
#include <memory.h>
struct zimage_header {
u32 unused[9];
u32 magic;
u32 start;
u32 end;
};
#define ZIMAGE_MAGIC 0x016F2818
static int do_bootz(int argc, char *argv[])
{
int fd, ret, swap = 0;
struct zimage_header __header, *header;
void *zimage;
void *oftree = NULL;
u32 end;
int usemap = 0;
struct memory_bank *bank = list_first_entry(&memory_banks, struct memory_bank, list);
struct resource *res = NULL;
if (argc != 2)
return COMMAND_ERROR_USAGE;
fd = open(argv[1], O_RDONLY);
if (fd < 0) {
perror("open");
return 1;
}
/*
* We can save the memcpy of the zImage if it already is in
* the first 128MB of SDRAM.
*/
zimage = memmap(fd, PROT_READ);
if (zimage && (unsigned long)zimage >= bank->start &&
(unsigned long)zimage < bank->start + SZ_128M) {
usemap = 1;
header = zimage;
}
if (!usemap) {
header = &__header;
ret = read(fd, header, sizeof(*header));
if (ret < sizeof(*header)) {
printf("could not read %s\n", argv[1]);
goto err_out;
}
}
switch (header->magic) {
#ifdef CONFIG_BOOT_ENDIANNESS_SWITCH
case swab32(ZIMAGE_MAGIC):
swap = 1;
/* fall through */
#endif
case ZIMAGE_MAGIC:
break;
default:
printf("invalid magic 0x%08x\n", header->magic);
goto err_out;
}
end = header->end;
if (swap)
end = swab32(end);
if (!usemap) {
if (bank->size <= SZ_128M) {
zimage = xmalloc(end);
} else {
zimage = (void *)bank->start + SZ_8M;
res = request_sdram_region("zimage",
bank->start + SZ_8M, end);
if (!res) {
printf("can't request region for kernel\n");
goto err_out1;
}
}
memcpy(zimage, header, sizeof(*header));
ret = read(fd, zimage + sizeof(*header), end - sizeof(*header));
if (ret < end - sizeof(*header)) {
printf("could not read %s\n", argv[1]);
goto err_out2;
}
}
if (swap) {
void *ptr;
for (ptr = zimage; ptr < zimage + end; ptr += 4)
*(u32 *)ptr = swab32(*(u32 *)ptr);
}
printf("loaded zImage from %s with size %d\n", argv[1], end);
#ifdef CONFIG_OFTREE
oftree = of_get_fixed_tree(NULL);
#endif
start_linux(zimage, swap, 0, 0, oftree);
return 0;
err_out2:
if (res)
release_sdram_region(res);
err_out1:
free(zimage);
err_out:
close(fd);
return 1;
}
static const __maybe_unused char cmd_bootz_help[] =
"Usage: bootz [FILE]\n"
"Boot a Linux zImage\n";
BAREBOX_CMD_START(bootz)
.cmd = do_bootz,
.usage = "start a zImage",
BAREBOX_CMD_HELP(cmd_bootz_help)
BAREBOX_CMD_END