mirror of https://github.com/xemu-project/xemu.git
uImage: implement gzip support (Hollis Blanchard)
Based on gzip uImage loading code from u-boot. Signed-off-by: Jerone Young <jyoung5@us.ibm.com> Signed-off-by: Hollis Blanchard <hollisb@us.ibm.com> Signed-off-by: Anthony Liguori <aliguori@us.ibm.com> git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@5762 c046a42c-6fe2-441c-8c8c-71466251a162
This commit is contained in:
parent
265ca29a71
commit
5a1235779e
140
loader.c
140
loader.c
|
@ -20,12 +20,37 @@
|
|||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
* Gunzip functionality in this file is derived from u-boot:
|
||||
*
|
||||
* (C) Copyright 2008 Semihalf
|
||||
*
|
||||
* (C) Copyright 2000-2005
|
||||
* Wolfgang Denk, DENX Software Engineering, wd@denx.de.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "qemu-common.h"
|
||||
#include "disas.h"
|
||||
#include "sysemu.h"
|
||||
#include "uboot_image.h"
|
||||
|
||||
#include <zlib.h>
|
||||
|
||||
/* return the size or -1 if error */
|
||||
int get_image_size(const char *filename)
|
||||
{
|
||||
|
@ -345,10 +370,94 @@ static void bswap_uboot_header(uboot_image_header_t *hdr)
|
|||
#endif
|
||||
}
|
||||
|
||||
|
||||
#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 = qemu_malloc(size);
|
||||
|
||||
return (p);
|
||||
}
|
||||
|
||||
static void zfree(void *x, void *addr, unsigned nb)
|
||||
{
|
||||
qemu_free(addr);
|
||||
}
|
||||
|
||||
|
||||
#define HEAD_CRC 2
|
||||
#define EXTRA_FIELD 4
|
||||
#define ORIG_NAME 8
|
||||
#define COMMENT 0x10
|
||||
#define RESERVED 0xe0
|
||||
|
||||
#define DEFLATED 8
|
||||
|
||||
/* This is the maximum in uboot, so if a uImage overflows this, it would
|
||||
* overflow on real hardware too. */
|
||||
#define UBOOT_MAX_GUNZIP_BYTES 0x800000
|
||||
|
||||
static ssize_t gunzip(void *dst, size_t dstlen, uint8_t *src,
|
||||
size_t srclen)
|
||||
{
|
||||
z_stream s;
|
||||
ssize_t dstbytes;
|
||||
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 >= srclen) {
|
||||
puts ("Error: gunzip out of data in header\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
s.zalloc = zalloc;
|
||||
s.zfree = (free_func)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 = srclen - 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;
|
||||
}
|
||||
dstbytes = s.next_out - (unsigned char *) dst;
|
||||
inflateEnd(&s);
|
||||
|
||||
return dstbytes;
|
||||
}
|
||||
|
||||
/* Load a U-Boot image. */
|
||||
int load_uboot(const char *filename, target_ulong *ep, int *is_linux)
|
||||
{
|
||||
|
||||
int fd;
|
||||
int size;
|
||||
uboot_image_header_t h;
|
||||
|
@ -375,9 +484,14 @@ int load_uboot(const char *filename, target_ulong *ep, int *is_linux)
|
|||
goto out;
|
||||
}
|
||||
|
||||
/* TODO: Implement compressed images. */
|
||||
if (hdr->ih_comp != IH_COMP_NONE) {
|
||||
fprintf(stderr, "Unable to load compressed u-boot images\n");
|
||||
switch (hdr->ih_comp) {
|
||||
case IH_COMP_NONE:
|
||||
case IH_COMP_GZIP:
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr,
|
||||
"Unable to load u-boot images with compression type %d\n",
|
||||
hdr->ih_comp);
|
||||
goto out;
|
||||
}
|
||||
|
||||
|
@ -399,6 +513,24 @@ int load_uboot(const char *filename, target_ulong *ep, int *is_linux)
|
|||
goto out;
|
||||
}
|
||||
|
||||
if (hdr->ih_comp == IH_COMP_GZIP) {
|
||||
uint8_t *compressed_data;
|
||||
size_t max_bytes;
|
||||
ssize_t bytes;
|
||||
|
||||
compressed_data = data;
|
||||
max_bytes = UBOOT_MAX_GUNZIP_BYTES;
|
||||
data = qemu_malloc(max_bytes);
|
||||
|
||||
bytes = gunzip(data, max_bytes, compressed_data, hdr->ih_size);
|
||||
qemu_free(compressed_data);
|
||||
if (bytes < 0) {
|
||||
fprintf(stderr, "Unable to decompress gzipped image!\n");
|
||||
goto out;
|
||||
}
|
||||
hdr->ih_size = bytes;
|
||||
}
|
||||
|
||||
cpu_physical_memory_write_rom(hdr->ih_load, data, hdr->ih_size);
|
||||
|
||||
ret = hdr->ih_size;
|
||||
|
|
Loading…
Reference in New Issue