Commit 1c7b3754f68382941a1921e578ead25d97d116fb

Authored by pbrook
1 parent 35f1de31

Simple u-boot image loading support.


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2472 c046a42c-6fe2-441c-8c8c-71466251a162
hw/arm_boot.c
... ... @@ -71,7 +71,9 @@ void arm_load_kernel(CPUState *env, int ram_size, const char *kernel_filename,
71 71 int kernel_size;
72 72 int initrd_size;
73 73 int n;
74   - uint64_t entry;
  74 + int is_linux = 0;
  75 + uint64_t elf_entry;
  76 + target_ulong entry;
75 77  
76 78 /* Load the kernel. */
77 79 if (!kernel_filename) {
... ... @@ -79,19 +81,27 @@ void arm_load_kernel(CPUState *env, int ram_size, const char *kernel_filename,
79 81 exit(1);
80 82 }
81 83  
82   - kernel_size = load_elf(kernel_filename, 0, &entry);
83   - if (kernel_size >= 0) {
84   - /* An ELF image. Jump to the entry point. */
  84 + /* Assume that raw images are linux kernels, and ELF images are not. */
  85 + kernel_size = load_elf(kernel_filename, 0, &elf_entry);
  86 + entry = elf_entry;
  87 + if (kernel_size < 0) {
  88 + kernel_size = load_uboot(kernel_filename, &entry, &is_linux);
  89 + }
  90 + if (kernel_size < 0) {
  91 + kernel_size = load_image(kernel_filename,
  92 + phys_ram_base + KERNEL_LOAD_ADDR);
  93 + entry = KERNEL_LOAD_ADDR;
  94 + is_linux = 1;
  95 + }
  96 + if (kernel_size < 0) {
  97 + fprintf(stderr, "qemu: could not load kernel '%s'\n", kernel_filename);
  98 + exit(1);
  99 + }
  100 + if (!is_linux) {
  101 + /* Jump to the entry point. */
85 102 env->regs[15] = entry & 0xfffffffe;
86 103 env->thumb = entry & 1;
87 104 } else {
88   - /* Raw binary image. Assume it is a Linux zImage. */
89   - kernel_size = load_image(kernel_filename,
90   - phys_ram_base + KERNEL_LOAD_ADDR);
91   - if (kernel_size < 0) {
92   - fprintf(stderr, "qemu: could not load kernel '%s'\n", kernel_filename);
93   - exit(1);
94   - }
95 105 if (initrd_filename) {
96 106 initrd_size = load_image(initrd_filename,
97 107 phys_ram_base + INITRD_LOAD_ADDR);
... ... @@ -106,7 +116,7 @@ void arm_load_kernel(CPUState *env, int ram_size, const char *kernel_filename,
106 116 bootloader[1] |= board_id & 0xff;
107 117 bootloader[2] |= (board_id >> 8) & 0xff;
108 118 bootloader[5] = KERNEL_ARGS_ADDR;
109   - bootloader[6] = KERNEL_LOAD_ADDR;
  119 + bootloader[6] = entry;
110 120 for (n = 0; n < sizeof(bootloader) / 4; n++)
111 121 stl_raw(phys_ram_base + (n * 4), bootloader[n]);
112 122 set_kernel_args(ram_size, initrd_size, kernel_cmdline);
... ...
loader.c
... ... @@ -23,6 +23,7 @@
23 23 */
24 24 #include "vl.h"
25 25 #include "disas.h"
  26 +#include "uboot_image.h"
26 27  
27 28 /* return the size or -1 if error */
28 29 int get_image_size(const char *filename)
... ... @@ -241,3 +242,80 @@ int load_elf(const char *filename, int64_t virt_to_phys_addend,
241 242 close(fd);
242 243 return -1;
243 244 }
  245 +
  246 +static void bswap_uboot_header(uboot_image_header_t *hdr)
  247 +{
  248 +#ifndef WORDS_BIGENDIAN
  249 + bswap32s(&hdr->ih_magic);
  250 + bswap32s(&hdr->ih_hcrc);
  251 + bswap32s(&hdr->ih_time);
  252 + bswap32s(&hdr->ih_size);
  253 + bswap32s(&hdr->ih_load);
  254 + bswap32s(&hdr->ih_ep);
  255 + bswap32s(&hdr->ih_dcrc);
  256 +#endif
  257 +}
  258 +
  259 +/* Load a U-Boot image. */
  260 +int load_uboot(const char *filename, target_ulong *ep, int *is_linux)
  261 +{
  262 +
  263 + int fd;
  264 + int size;
  265 + uboot_image_header_t h;
  266 + uboot_image_header_t *hdr = &h;
  267 + uint8_t *data = NULL;
  268 +
  269 + fd = open(filename, O_RDONLY | O_BINARY);
  270 + if (fd < 0)
  271 + return -1;
  272 +
  273 + size = read(fd, hdr, sizeof(uboot_image_header_t));
  274 + if (size < 0)
  275 + goto fail;
  276 +
  277 + bswap_uboot_header(hdr);
  278 +
  279 + if (hdr->ih_magic != IH_MAGIC)
  280 + goto fail;
  281 +
  282 + /* TODO: Implement Multi-File images. */
  283 + if (hdr->ih_type == IH_TYPE_MULTI) {
  284 + fprintf(stderr, "Unable to load multi-file u-boot images\n");
  285 + goto fail;
  286 + }
  287 +
  288 + /* TODO: Implement compressed images. */
  289 + if (hdr->ih_comp != IH_COMP_NONE) {
  290 + fprintf(stderr, "Unable to load compressed u-boot images\n");
  291 + goto fail;
  292 + }
  293 +
  294 + /* TODO: Check CPU type. */
  295 + if (is_linux) {
  296 + if (hdr->ih_type == IH_TYPE_KERNEL && hdr->ih_os == IH_OS_LINUX)
  297 + *is_linux = 1;
  298 + else
  299 + *is_linux = 0;
  300 + }
  301 +
  302 + *ep = hdr->ih_ep;
  303 + data = qemu_malloc(hdr->ih_size);
  304 + if (!data)
  305 + goto fail;
  306 +
  307 + if (read(fd, data, hdr->ih_size) != hdr->ih_size) {
  308 + fprintf(stderr, "Error reading file\n");
  309 + goto fail;
  310 + }
  311 +
  312 + cpu_physical_memory_write_rom(hdr->ih_load, data, hdr->ih_size);
  313 +
  314 + return hdr->ih_size;
  315 +
  316 +fail:
  317 + if (data)
  318 + qemu_free(data);
  319 + close(fd);
  320 + return -1;
  321 +}
... ...
uboot_image.h 0 โ†’ 100644
  1 +/*
  2 + * (C) Copyright 2000-2005
  3 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
  4 + *
  5 + * See file CREDITS for list of people who contributed to this
  6 + * project.
  7 + *
  8 + * This program is free software; you can redistribute it and/or
  9 + * modify it under the terms of the GNU General Public License as
  10 + * published by the Free Software Foundation; either version 2 of
  11 + * the License, or (at your option) any later version.
  12 + *
  13 + * This program is distributed in the hope that it will be useful,
  14 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16 + * GNU General Public License for more details.
  17 + *
  18 + * You should have received a copy of the GNU General Public License
  19 + * along with this program; if not, write to the Free Software
  20 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
  21 + * MA 02111-1307 USA
  22 + *
  23 + ********************************************************************
  24 + * NOTE: This header file defines an interface to U-Boot. Including
  25 + * this (unmodified) header file in another file is considered normal
  26 + * use of U-Boot, and does *not* fall under the heading of "derived
  27 + * work".
  28 + ********************************************************************
  29 + */
  30 +
  31 +#ifndef __UBOOT_IMAGE_H__
  32 +#define __UBOOT_IMAGE_H__
  33 +
  34 +/*
  35 + * Operating System Codes
  36 + */
  37 +#define IH_OS_INVALID 0 /* Invalid OS */
  38 +#define IH_OS_OPENBSD 1 /* OpenBSD */
  39 +#define IH_OS_NETBSD 2 /* NetBSD */
  40 +#define IH_OS_FREEBSD 3 /* FreeBSD */
  41 +#define IH_OS_4_4BSD 4 /* 4.4BSD */
  42 +#define IH_OS_LINUX 5 /* Linux */
  43 +#define IH_OS_SVR4 6 /* SVR4 */
  44 +#define IH_OS_ESIX 7 /* Esix */
  45 +#define IH_OS_SOLARIS 8 /* Solaris */
  46 +#define IH_OS_IRIX 9 /* Irix */
  47 +#define IH_OS_SCO 10 /* SCO */
  48 +#define IH_OS_DELL 11 /* Dell */
  49 +#define IH_OS_NCR 12 /* NCR */
  50 +#define IH_OS_LYNXOS 13 /* LynxOS */
  51 +#define IH_OS_VXWORKS 14 /* VxWorks */
  52 +#define IH_OS_PSOS 15 /* pSOS */
  53 +#define IH_OS_QNX 16 /* QNX */
  54 +#define IH_OS_U_BOOT 17 /* Firmware */
  55 +#define IH_OS_RTEMS 18 /* RTEMS */
  56 +#define IH_OS_ARTOS 19 /* ARTOS */
  57 +#define IH_OS_UNITY 20 /* Unity OS */
  58 +
  59 +/*
  60 + * CPU Architecture Codes (supported by Linux)
  61 + */
  62 +#define IH_CPU_INVALID 0 /* Invalid CPU */
  63 +#define IH_CPU_ALPHA 1 /* Alpha */
  64 +#define IH_CPU_ARM 2 /* ARM */
  65 +#define IH_CPU_I386 3 /* Intel x86 */
  66 +#define IH_CPU_IA64 4 /* IA64 */
  67 +#define IH_CPU_MIPS 5 /* MIPS */
  68 +#define IH_CPU_MIPS64 6 /* MIPS 64 Bit */
  69 +#define IH_CPU_PPC 7 /* PowerPC */
  70 +#define IH_CPU_S390 8 /* IBM S390 */
  71 +#define IH_CPU_SH 9 /* SuperH */
  72 +#define IH_CPU_SPARC 10 /* Sparc */
  73 +#define IH_CPU_SPARC64 11 /* Sparc 64 Bit */
  74 +#define IH_CPU_M68K 12 /* M68K */
  75 +#define IH_CPU_NIOS 13 /* Nios-32 */
  76 +#define IH_CPU_MICROBLAZE 14 /* MicroBlaze */
  77 +#define IH_CPU_NIOS2 15 /* Nios-II */
  78 +#define IH_CPU_BLACKFIN 16 /* Blackfin */
  79 +#define IH_CPU_AVR32 17 /* AVR32 */
  80 +
  81 +/*
  82 + * Image Types
  83 + *
  84 + * "Standalone Programs" are directly runnable in the environment
  85 + * provided by U-Boot; it is expected that (if they behave
  86 + * well) you can continue to work in U-Boot after return from
  87 + * the Standalone Program.
  88 + * "OS Kernel Images" are usually images of some Embedded OS which
  89 + * will take over control completely. Usually these programs
  90 + * will install their own set of exception handlers, device
  91 + * drivers, set up the MMU, etc. - this means, that you cannot
  92 + * expect to re-enter U-Boot except by resetting the CPU.
  93 + * "RAMDisk Images" are more or less just data blocks, and their
  94 + * parameters (address, size) are passed to an OS kernel that is
  95 + * being started.
  96 + * "Multi-File Images" contain several images, typically an OS
  97 + * (Linux) kernel image and one or more data images like
  98 + * RAMDisks. This construct is useful for instance when you want
  99 + * to boot over the network using BOOTP etc., where the boot
  100 + * server provides just a single image file, but you want to get
  101 + * for instance an OS kernel and a RAMDisk image.
  102 + *
  103 + * "Multi-File Images" start with a list of image sizes, each
  104 + * image size (in bytes) specified by an "uint32_t" in network
  105 + * byte order. This list is terminated by an "(uint32_t)0".
  106 + * Immediately after the terminating 0 follow the images, one by
  107 + * one, all aligned on "uint32_t" boundaries (size rounded up to
  108 + * a multiple of 4 bytes - except for the last file).
  109 + *
  110 + * "Firmware Images" are binary images containing firmware (like
  111 + * U-Boot or FPGA images) which usually will be programmed to
  112 + * flash memory.
  113 + *
  114 + * "Script files" are command sequences that will be executed by
  115 + * U-Boot's command interpreter; this feature is especially
  116 + * useful when you configure U-Boot to use a real shell (hush)
  117 + * as command interpreter (=> Shell Scripts).
  118 + */
  119 +
  120 +#define IH_TYPE_INVALID 0 /* Invalid Image */
  121 +#define IH_TYPE_STANDALONE 1 /* Standalone Program */
  122 +#define IH_TYPE_KERNEL 2 /* OS Kernel Image */
  123 +#define IH_TYPE_RAMDISK 3 /* RAMDisk Image */
  124 +#define IH_TYPE_MULTI 4 /* Multi-File Image */
  125 +#define IH_TYPE_FIRMWARE 5 /* Firmware Image */
  126 +#define IH_TYPE_SCRIPT 6 /* Script file */
  127 +#define IH_TYPE_FILESYSTEM 7 /* Filesystem Image (any type) */
  128 +#define IH_TYPE_FLATDT 8 /* Binary Flat Device Tree Blob */
  129 +
  130 +/*
  131 + * Compression Types
  132 + */
  133 +#define IH_COMP_NONE 0 /* No Compression Used */
  134 +#define IH_COMP_GZIP 1 /* gzip Compression Used */
  135 +#define IH_COMP_BZIP2 2 /* bzip2 Compression Used */
  136 +
  137 +#define IH_MAGIC 0x27051956 /* Image Magic Number */
  138 +#define IH_NMLEN 32 /* Image Name Length */
  139 +
  140 +/*
  141 + * all data in network byte order (aka natural aka bigendian)
  142 + */
  143 +
  144 +typedef struct uboot_image_header {
  145 + uint32_t ih_magic; /* Image Header Magic Number */
  146 + uint32_t ih_hcrc; /* Image Header CRC Checksum */
  147 + uint32_t ih_time; /* Image Creation Timestamp */
  148 + uint32_t ih_size; /* Image Data Size */
  149 + uint32_t ih_load; /* Data Load Address */
  150 + uint32_t ih_ep; /* Entry Point Address */
  151 + uint32_t ih_dcrc; /* Image Data CRC Checksum */
  152 + uint8_t ih_os; /* Operating System */
  153 + uint8_t ih_arch; /* CPU architecture */
  154 + uint8_t ih_type; /* Image Type */
  155 + uint8_t ih_comp; /* Compression Type */
  156 + uint8_t ih_name[IH_NMLEN]; /* Image Name */
  157 +} uboot_image_header_t;
  158 +
  159 +
  160 +#endif /* __IMAGE_H__ */
... ...
... ... @@ -1155,6 +1155,7 @@ int get_image_size(const char *filename);
1155 1155 int load_image(const char *filename, uint8_t *addr);
1156 1156 int load_elf(const char *filename, int64_t virt_to_phys_addend, uint64_t *pentry);
1157 1157 int load_aout(const char *filename, uint8_t *addr);
  1158 +int load_uboot(const char *filename, target_ulong *ep, int *is_linux);
1158 1159  
1159 1160 /* slavio_timer.c */
1160 1161 void slavio_timer_init(uint32_t addr, int irq, int mode, unsigned int cpu);
... ...