# HG changeset patch
# User Jerone Young <[EMAIL PROTECTED]>
# Date 1205296680 18000
# Branch merge
# Node ID 48651677b7d05254d6acf03551bfea05cef8aa47
# Parent  36d2646a3c3d42021425febf3d14f0500ebbaace
Create new load_uboot() & gunzip support to uboot loader in Qemu

This patch adds the ability for the load address to be caputred when loading a 
uImage or cuImage. It also adds a better return code as the size can be an 
usigned long. This is done by creating a new function prototype and calling it 
load_uboot_l . To keep compatibility with code already using the old load_uboot 
a wrapper function has been created so current callers will not break them.

Also added is gunzip support to allow for loading of uimages with a compressed 
kenrel imagexs.

Signed-off-by: Jerone Young <[EMAIL PROTECTED]>

diff --git a/qemu/loader.c b/qemu/loader.c
--- a/qemu/loader.c
+++ b/qemu/loader.c
@@ -26,6 +26,8 @@
 #include "sysemu.h"
 #include "uboot_image.h"
 
+#include <zlib.h>
+
 /* return the size or -1 if error */
 int get_image_size(const char *filename)
 {
@@ -263,14 +265,103 @@ static void bswap_uboot_header(uboot_ima
 }
 
 /* Load a U-Boot image.  */
-int load_uboot(const char *filename, target_ulong *ep, int *is_linux)
-{
-
+
+/* gunzip functionality is derived from gunzip function 
+ * in uboot source code 
+ */
+
+#define        ZALLOC_ALIGNMENT        16
+
+static void *zalloc(void *x, unsigned items, unsigned size)
+{
+       void *p;
+
+       size *= items;
+       size = (size + ZALLOC_ALIGNMENT - 1) & ~(ZALLOC_ALIGNMENT - 1);
+
+       p = malloc (size);
+
+       return (p);
+}
+
+static void zfree(void *x, void *addr, unsigned nb)
+{
+       free (addr);
+}
+
+
+#define HEAD_CRC       2
+#define EXTRA_FIELD    4
+#define ORIG_NAME      8
+#define COMMENT                0x10
+#define RESERVED       0xe0
+
+#define DEFLATED       8
+
+static int gunzip(void *dst, int dstlen, unsigned char *src, unsigned long 
*lenp)
+{
+       z_stream s;
+       int r, i, flags;
+
+       /* skip header */
+       i = 10;
+       flags = src[3];
+       if (src[2] != DEFLATED || (flags & RESERVED) != 0) {
+               puts ("Error: Bad gzipped data\n");
+               return -1;
+       }
+       if ((flags & EXTRA_FIELD) != 0)
+               i = 12 + src[10] + (src[11] << 8);
+       if ((flags & ORIG_NAME) != 0)
+               while (src[i++] != 0)
+                       ;
+       if ((flags & COMMENT) != 0)
+               while (src[i++] != 0)
+                       ;
+       if ((flags & HEAD_CRC) != 0)
+               i += 2;
+       if (i >= *lenp) {
+               puts ("Error: gunzip out of data in header\n");
+               return -1;
+       }
+
+       s.zalloc = zalloc;
+       s.zfree = zfree;
+
+       r = inflateInit2(&s, -MAX_WBITS);
+       if (r != Z_OK) {
+               printf ("Error: inflateInit2() returned %d\n", r);
+               return (-1);
+       }
+       s.next_in = src + i;
+       s.avail_in = *lenp - i;
+       s.next_out = dst;
+       s.avail_out = dstlen;
+       r = inflate(&s, Z_FINISH);
+       if (r != Z_OK && r != Z_STREAM_END) {
+               printf ("Error: inflate() returned %d\n", r);
+               return -1;
+       }
+       *lenp = s.next_out - (unsigned char *) dst;
+       inflateEnd(&s);
+
+       return 0;
+}
+
+
+#define MAX_KERNEL_SIZE 8*1024*1024  //8MB
+int load_uboot_l(const char *filename, target_ulong *ep,
+                  target_ulong *la, 
+                  target_ulong *loaded_image_size,
+                  int *is_linux)
+{
     int fd;
     int size;
+    int ret;
     uboot_image_header_t h;
     uboot_image_header_t *hdr = &h;
     uint8_t *data = NULL;
+    uint8_t *uncompressed_data = NULL;
 
     fd = open(filename, O_RDONLY | O_BINARY);
     if (fd < 0)
@@ -291,13 +382,14 @@ int load_uboot(const char *filename, tar
         goto fail;
     }
 
-    /* TODO: Implement compressed images.  */
-    if (hdr->ih_comp != IH_COMP_NONE) {
-        fprintf(stderr, "Unable to load compressed u-boot images\n");
+    /* TODO bzip2 support */
+    if (hdr->ih_comp == IH_COMP_BZIP2) {
+        fprintf(stderr, "Unable to load bzip2 compressed u-boot images\n");
         goto fail;
     }
 
     /* TODO: Check CPU type.  */
+
     if (is_linux) {
         if (hdr->ih_type == IH_TYPE_KERNEL && hdr->ih_os == IH_OS_LINUX)
             *is_linux = 1;
@@ -306,6 +398,8 @@ int load_uboot(const char *filename, tar
     }
 
     *ep = hdr->ih_ep;
+    *la = hdr->ih_load;
+
     data = qemu_malloc(hdr->ih_size);
     if (!data)
         goto fail;
@@ -315,9 +409,29 @@ int load_uboot(const char *filename, tar
         goto fail;
     }
 
-    cpu_physical_memory_write_rom(hdr->ih_load, data, hdr->ih_size);
-
-    return hdr->ih_size;
+    *loaded_image_size = hdr->ih_size;
+    
+    if (hdr->ih_comp == IH_COMP_GZIP) {
+       uncompressed_data = qemu_malloc(MAX_KERNEL_SIZE);
+       ret = gunzip(uncompressed_data, MAX_KERNEL_SIZE,
+                    (unsigned char *) data, 
+                    loaded_image_size);
+
+       if (ret < 0) {
+            fprintf(stderr, "Unable to decompress gziped image!\n");
+            goto fail;
+        }
+
+        qemu_free(data);
+        cpu_physical_memory_write_rom(hdr->ih_load, uncompressed_data,
+                                      *loaded_image_size);
+
+    }
+    else {
+        cpu_physical_memory_write_rom(hdr->ih_load, data, *loaded_image_size);
+    }
+
+    return 0;
 
 fail:
     if (data)
@@ -325,3 +439,18 @@ fail:
     close(fd);
     return -1;
 }
+
+
+int load_uboot(const char *filename, target_ulong *ep, int *is_linux)
+{
+    target_ulong la;
+    target_ulong size;
+    int ret;
+
+    ret = load_uboot_l(filename, ep, &la, &size, is_linux);
+
+    if (ret < 0)
+       return ret;
+    else
+       return (int)size;
+}
diff --git a/qemu/sysemu.h b/qemu/sysemu.h
--- a/qemu/sysemu.h
+++ b/qemu/sysemu.h
@@ -182,6 +182,9 @@ int load_elf(const char *filename, int64
              uint64_t *pentry, uint64_t *lowaddr, uint64_t *highaddr);
 int load_aout(const char *filename, uint8_t *addr);
 int load_uboot(const char *filename, target_ulong *ep, int *is_linux);
+int load_uboot_l(const char *filename, target_ulong *ep, 
+             target_ulong *la, target_ulong *loaded_image_size,
+             int *is_linux);
 #endif
 
 #ifdef HAS_AUDIO

-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2008.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
_______________________________________________
kvm-devel mailing list
kvm-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/kvm-devel

Reply via email to