mirror of
https://github.com/xen-project/xen.git
synced 2026-10-28 02:01:24 +01:00
arm: load dom0 kernel from first boot module
Signed-off-by: Ian Campbell <ian.campbell@citrix.com> Acked-by: Tim Deegan <tim@xen.org> Committed-by: Ian Campbell <ian.campbell@citrix.com>
This commit is contained in:
1 parent
313140cbb1
commit
beddb3b6cc
2 files changed
+75
-27
No files matched your search
+64
-27
@@ -22,6 +22,7 @@
|
||||
#define ZIMAGE_MAGIC_OFFSET 0x24
|
||||
#define ZIMAGE_START_OFFSET 0x28
|
||||
#define ZIMAGE_END_OFFSET 0x2c
|
||||
#define ZIMAGE_HEADER_LEN 0x30
|
||||
|
||||
#define ZIMAGE_MAGIC 0x016f2818
|
||||
|
||||
@@ -65,40 +66,42 @@ void copy_from_paddr(void *dst, paddr_t paddr, unsigned long len, int attrindx)
|
||||
static void kernel_zimage_load(struct kernel_info *info)
|
||||
{
|
||||
paddr_t load_addr = info->zimage.load_addr;
|
||||
paddr_t paddr = info->zimage.kernel_addr;
|
||||
paddr_t attr = info->load_attr;
|
||||
paddr_t len = info->zimage.len;
|
||||
paddr_t flash = KERNEL_FLASH_ADDRESS;
|
||||
void *src = (void *)FIXMAP_ADDR(FIXMAP_MISC);
|
||||
unsigned long offs;
|
||||
|
||||
printk("Loading %"PRIpaddr" byte zImage from flash %"PRIpaddr" to %"PRIpaddr"-%"PRIpaddr": [",
|
||||
len, flash, load_addr, load_addr + len);
|
||||
for ( offs = 0; offs < len; offs += PAGE_SIZE )
|
||||
printk("Loading zImage from %"PRIpaddr" to %"PRIpaddr"-%"PRIpaddr"\n",
|
||||
paddr, load_addr, load_addr + len);
|
||||
for ( offs = 0; offs < len; )
|
||||
{
|
||||
paddr_t ma = gvirt_to_maddr(load_addr + offs);
|
||||
paddr_t s, l, ma = gvirt_to_maddr(load_addr + offs);
|
||||
void *dst = map_domain_page(ma>>PAGE_SHIFT);
|
||||
|
||||
if ( ( offs % (1<<20) ) == 0 )
|
||||
printk(".");
|
||||
s = offs & ~PAGE_MASK;
|
||||
l = min(PAGE_SIZE - s, len);
|
||||
|
||||
set_fixmap(FIXMAP_MISC, (flash+offs) >> PAGE_SHIFT, DEV_SHARED);
|
||||
memcpy(dst, src, PAGE_SIZE);
|
||||
clear_fixmap(FIXMAP_MISC);
|
||||
copy_from_paddr(dst + s, paddr + offs, l, attr);
|
||||
|
||||
unmap_domain_page(dst);
|
||||
offs += l;
|
||||
}
|
||||
printk("]\n");
|
||||
}
|
||||
|
||||
/**
|
||||
* Check the image is a zImage and return the load address and length
|
||||
*/
|
||||
static int kernel_try_zimage_prepare(struct kernel_info *info)
|
||||
static int kernel_try_zimage_prepare(struct kernel_info *info,
|
||||
paddr_t addr, paddr_t size)
|
||||
{
|
||||
uint32_t *zimage = (void *)FIXMAP_ADDR(FIXMAP_MISC);
|
||||
uint32_t zimage[ZIMAGE_HEADER_LEN/4];
|
||||
uint32_t start, end;
|
||||
struct minimal_dtb_header dtb_hdr;
|
||||
|
||||
set_fixmap(FIXMAP_MISC, KERNEL_FLASH_ADDRESS >> PAGE_SHIFT, DEV_SHARED);
|
||||
if ( size < ZIMAGE_HEADER_LEN )
|
||||
return -EINVAL;
|
||||
|
||||
copy_from_paddr(zimage, addr, sizeof(zimage), DEV_SHARED);
|
||||
|
||||
if (zimage[ZIMAGE_MAGIC_OFFSET/4] != ZIMAGE_MAGIC)
|
||||
return -EINVAL;
|
||||
@@ -106,16 +109,26 @@ static int kernel_try_zimage_prepare(struct kernel_info *info)
|
||||
start = zimage[ZIMAGE_START_OFFSET/4];
|
||||
end = zimage[ZIMAGE_END_OFFSET/4];
|
||||
|
||||
clear_fixmap(FIXMAP_MISC);
|
||||
if ( (end - start) > size )
|
||||
return -EINVAL;
|
||||
|
||||
/*
|
||||
* Check for an appended DTB.
|
||||
*/
|
||||
copy_from_paddr(&dtb_hdr, KERNEL_FLASH_ADDRESS + end - start, sizeof(dtb_hdr), DEV_SHARED);
|
||||
if (be32_to_cpu(dtb_hdr.magic) == DTB_MAGIC) {
|
||||
end += be32_to_cpu(dtb_hdr.total_size);
|
||||
if ( addr + end - start + sizeof(dtb_hdr) <= size )
|
||||
{
|
||||
copy_from_paddr(&dtb_hdr, addr + end - start,
|
||||
sizeof(dtb_hdr), DEV_SHARED);
|
||||
if (be32_to_cpu(dtb_hdr.magic) == DTB_MAGIC) {
|
||||
end += be32_to_cpu(dtb_hdr.total_size);
|
||||
|
||||
if ( end > addr + size )
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
info->zimage.kernel_addr = addr;
|
||||
|
||||
/*
|
||||
* If start is zero, the zImage is position independent -- load it
|
||||
* at 32k from start of RAM.
|
||||
@@ -142,25 +155,26 @@ static void kernel_elf_load(struct kernel_info *info)
|
||||
free_xenheap_pages(info->kernel_img, info->kernel_order);
|
||||
}
|
||||
|
||||
static int kernel_try_elf_prepare(struct kernel_info *info)
|
||||
static int kernel_try_elf_prepare(struct kernel_info *info,
|
||||
paddr_t addr, paddr_t size)
|
||||
{
|
||||
int rc;
|
||||
|
||||
info->kernel_order = get_order_from_bytes(KERNEL_FLASH_SIZE);
|
||||
info->kernel_order = get_order_from_bytes(size);
|
||||
info->kernel_img = alloc_xenheap_pages(info->kernel_order, 0);
|
||||
if ( info->kernel_img == NULL )
|
||||
panic("Cannot allocate temporary buffer for kernel.\n");
|
||||
|
||||
copy_from_paddr(info->kernel_img, KERNEL_FLASH_ADDRESS, KERNEL_FLASH_SIZE, DEV_SHARED);
|
||||
copy_from_paddr(info->kernel_img, addr, size, info->load_attr);
|
||||
|
||||
if ( (rc = elf_init(&info->elf.elf, info->kernel_img, KERNEL_FLASH_SIZE )) != 0 )
|
||||
return rc;
|
||||
if ( (rc = elf_init(&info->elf.elf, info->kernel_img, size )) != 0 )
|
||||
goto err;
|
||||
#ifdef VERBOSE
|
||||
elf_set_verbose(&info->elf.elf);
|
||||
#endif
|
||||
elf_parse_binary(&info->elf.elf);
|
||||
if ( (rc = elf_xen_parse(&info->elf.elf, &info->elf.parms)) != 0 )
|
||||
return rc;
|
||||
goto err;
|
||||
|
||||
/*
|
||||
* TODO: can the ELF header be used to find the physical address
|
||||
@@ -170,15 +184,38 @@ static int kernel_try_elf_prepare(struct kernel_info *info)
|
||||
info->load = kernel_elf_load;
|
||||
|
||||
return 0;
|
||||
err:
|
||||
free_xenheap_pages(info->kernel_img, info->kernel_order);
|
||||
return rc;
|
||||
}
|
||||
|
||||
int kernel_prepare(struct kernel_info *info)
|
||||
{
|
||||
int rc;
|
||||
|
||||
rc = kernel_try_zimage_prepare(info);
|
||||
paddr_t start, size;
|
||||
|
||||
if ( early_info.modules.nr_mods > 1 )
|
||||
panic("Cannot handle dom0 initrd yet\n");
|
||||
|
||||
if ( early_info.modules.nr_mods < 1 )
|
||||
{
|
||||
printk("No boot modules found, trying flash\n");
|
||||
start = KERNEL_FLASH_ADDRESS;
|
||||
size = KERNEL_FLASH_SIZE;
|
||||
info->load_attr = DEV_SHARED;
|
||||
}
|
||||
else
|
||||
{
|
||||
printk("Loading kernel from boot module 1\n");
|
||||
start = early_info.modules.module[1].start;
|
||||
size = early_info.modules.module[1].size;
|
||||
info->load_attr = BUFFERABLE;
|
||||
}
|
||||
|
||||
rc = kernel_try_zimage_prepare(info, start, size);
|
||||
if (rc < 0)
|
||||
rc = kernel_try_elf_prepare(info);
|
||||
rc = kernel_try_elf_prepare(info, start, size);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
@@ -22,6 +22,7 @@ struct kernel_info {
|
||||
|
||||
union {
|
||||
struct {
|
||||
paddr_t kernel_addr;
|
||||
paddr_t load_addr;
|
||||
paddr_t len;
|
||||
} zimage;
|
||||
@@ -33,9 +34,19 @@ struct kernel_info {
|
||||
};
|
||||
|
||||
void (*load)(struct kernel_info *info);
|
||||
int load_attr;
|
||||
};
|
||||
|
||||
int kernel_prepare(struct kernel_info *info);
|
||||
void kernel_load(struct kernel_info *info);
|
||||
|
||||
#endif /* #ifdef __ARCH_ARM_KERNEL_H__ */
|
||||
|
||||
/*
|
||||
* Local variables:
|
||||
* mode: C
|
||||
* c-set-style: "BSD"
|
||||
* c-basic-offset: 4
|
||||
* indent-tabs-mode: nil
|
||||
* End:
|
||||
*/
|
||||