]> git.sur5r.net Git - u-boot/blobdiff - cmd/elf.c
bootvx: x86: Make VxWorks EFI console driver happy
[u-boot] / cmd / elf.c
index 22d1918144d4861448c188da6e277007f76890b4..30c845833b6f6030545bb33a273f061867e0b3c1 100644 (file)
--- a/cmd/elf.c
+++ b/cmd/elf.c
 #include <net.h>
 #include <vxworks.h>
 #ifdef CONFIG_X86
+#include <vbe.h>
 #include <asm/e820.h>
 #include <linux/linkage.h>
 #endif
 
 /*
- * A very simple elf loader, assumes the image is valid, returns the
+ * A very simple ELF64 loader, assumes the image is valid, returns the
  * entry point address.
+ *
+ * Note if U-Boot is 32-bit, the loader assumes the to segment's
+ * physical address and size is within the lower 32-bit address space.
+ */
+static unsigned long load_elf64_image_phdr(unsigned long addr)
+{
+       Elf64_Ehdr *ehdr; /* Elf header structure pointer */
+       Elf64_Phdr *phdr; /* Program header structure pointer */
+       int i;
+
+       ehdr = (Elf64_Ehdr *)addr;
+       phdr = (Elf64_Phdr *)(addr + (ulong)ehdr->e_phoff);
+
+       /* Load each program header */
+       for (i = 0; i < ehdr->e_phnum; ++i) {
+               void *dst = (void *)(ulong)phdr->p_paddr;
+               void *src = (void *)addr + phdr->p_offset;
+
+               debug("Loading phdr %i to 0x%p (%lu bytes)\n",
+                     i, dst, (ulong)phdr->p_filesz);
+               if (phdr->p_filesz)
+                       memcpy(dst, src, phdr->p_filesz);
+               if (phdr->p_filesz != phdr->p_memsz)
+                       memset(dst + phdr->p_filesz, 0x00,
+                              phdr->p_memsz - phdr->p_filesz);
+               flush_cache((unsigned long)dst, phdr->p_filesz);
+               ++phdr;
+       }
+
+       return ehdr->e_entry;
+}
+
+/*
+ * A very simple ELF loader, assumes the image is valid, returns the
+ * entry point address.
+ *
+ * The loader firstly reads the EFI class to see if it's a 64-bit image.
+ * If yes, call the ELF64 loader. Otherwise continue with the ELF32 loader.
  */
 static unsigned long load_elf_image_phdr(unsigned long addr)
 {
@@ -35,12 +74,16 @@ static unsigned long load_elf_image_phdr(unsigned long addr)
        int i;
 
        ehdr = (Elf32_Ehdr *)addr;
+       if (ehdr->e_ident[EI_CLASS] == ELFCLASS64)
+               return load_elf64_image_phdr(addr);
+
        phdr = (Elf32_Phdr *)(addr + ehdr->e_phoff);
 
        /* Load each program header */
        for (i = 0; i < ehdr->e_phnum; ++i) {
                void *dst = (void *)(uintptr_t)phdr->p_paddr;
                void *src = (void *)addr + phdr->p_offset;
+
                debug("Loading phdr %i to 0x%p (%i bytes)\n",
                      i, dst, phdr->p_filesz);
                if (phdr->p_filesz)
@@ -210,8 +253,10 @@ int do_bootvx(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
        int ptr = 0;
 #ifdef CONFIG_X86
        ulong base;
-       struct e820info *info;
-       struct e820entry *data;
+       struct e820_info *info;
+       struct e820_entry *data;
+       struct efi_gop_info *gop;
+       struct vesa_mode_info *vesa = &mode_info.vesa;
 #endif
 
        /*
@@ -340,13 +385,13 @@ int do_bootvx(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
         * if we don't specify it in the environment, use a default one.
         */
        base = env_get_hex("vx_phys_mem_base", VXWORKS_PHYS_MEM_BASE);
-       data = (struct e820entry *)(base + E820_DATA_OFFSET);
-       info = (struct e820info *)(base + E820_INFO_OFFSET);
+       data = (struct e820_entry *)(base + E820_DATA_OFFSET);
+       info = (struct e820_info *)(base + E820_INFO_OFFSET);
 
-       memset(info, 0, sizeof(struct e820info));
+       memset(info, 0, sizeof(struct e820_info));
        info->sign = E820_SIGNATURE;
        info->entries = install_e820_map(E820MAX, data);
-       info->addr = (info->entries - 1) * sizeof(struct e820entry) +
+       info->addr = (info->entries - 1) * sizeof(struct e820_entry) +
                     E820_DATA_OFFSET;
 
        /*
@@ -355,6 +400,22 @@ int do_bootvx(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
         * available memory size for the kernel is insane.
         */
        *(u32 *)(base + BOOT_IMAGE_SIZE_OFFSET) = 0;
+
+       /*
+        * Prepare compatible framebuffer information block.
+        * The VESA mode has to be 32-bit RGBA.
+        */
+       if (vesa->x_resolution && vesa->y_resolution) {
+               gop = (struct efi_gop_info *)(base + EFI_GOP_INFO_OFFSET);
+               gop->magic = EFI_GOP_INFO_MAGIC;
+               gop->info.version = 0;
+               gop->info.width = vesa->x_resolution;
+               gop->info.height = vesa->y_resolution;
+               gop->info.pixel_format = EFI_GOT_RGBA8;
+               gop->info.pixels_per_scanline = vesa->bytes_per_scanline / 4;
+               gop->fb_base = vesa->phys_base_ptr;
+               gop->fb_size = vesa->bytes_per_scanline * vesa->y_resolution;
+       }
 #endif
 
        /*