[PATCH 6/7] Split Powerpc's uImage code

Sebastian Andrzej Siewior sebastian at breakpoint.cc
Wed Mar 31 04:24:17 EDT 2010


From: Sebastian Andrzej Siewior <bigeasy at linutronix.de>

The check and uncompress code could be split and recycled by other arch.

Signed-off-by: Sebastian Andrzej Siewior <bigeasy at linutronix.de>
---
 include/kexec-uImage.h            |   13 +++
 kexec/arch/ppc/Makefile           |    1 +
 kexec/arch/ppc/kexec-uImage-ppc.c |  201 ++---------------------------------
 kexec/kexec-uImage.c              |  213 +++++++++++++++++++++++++++++++++++++
 4 files changed, 236 insertions(+), 192 deletions(-)
 create mode 100644 include/kexec-uImage.h
 create mode 100644 kexec/kexec-uImage.c

diff --git a/include/kexec-uImage.h b/include/kexec-uImage.h
new file mode 100644
index 0000000..e8a4b69
--- /dev/null
+++ b/include/kexec-uImage.h
@@ -0,0 +1,13 @@
+#ifndef __KEXEC_UIMAGE_H__
+#define __KEXEC_UIMAGE_H__
+
+struct Image_info {
+	const char *buf;
+	off_t len;
+	unsigned int base;
+	unsigned int ep;
+};
+
+int uImage_probe(const char *buf, off_t len, unsigned int arch);
+int uImage_load(const char *buf, off_t len, struct Image_info *info);
+#endif
diff --git a/kexec/arch/ppc/Makefile b/kexec/arch/ppc/Makefile
index 698fd03..1c7441c 100644
--- a/kexec/arch/ppc/Makefile
+++ b/kexec/arch/ppc/Makefile
@@ -11,6 +11,7 @@ ppc_KEXEC_SRCS += kexec/arch/ppc/kexec-uImage-ppc.c
 ppc_KEXEC_SRCS += kexec/arch/ppc/ppc-setup-simple.S
 ppc_KEXEC_SRCS += kexec/arch/ppc/ppc-setup-dol.S
 ppc_KEXEC_SRCS += kexec/arch/ppc/fixup_dtb.c
+ppc_KEXEC_SRCS += kexec/kexec-uImage.c
 
 libfdt_SRCS = kexec/arch/ppc/libfdt-wrapper.c
 libfdt_SRCS += $(LIBFDT_SRCS:%=kexec/arch/ppc/libfdt/%)
diff --git a/kexec/arch/ppc/kexec-uImage-ppc.c b/kexec/arch/ppc/kexec-uImage-ppc.c
index 47e6c10..0a655a3 100644
--- a/kexec/arch/ppc/kexec-uImage-ppc.c
+++ b/kexec/arch/ppc/kexec-uImage-ppc.c
@@ -6,15 +6,13 @@
 #include <stdint.h>
 #include <string.h>
 #include <sys/types.h>
-#ifdef HAVE_LIBZ
-#include <zlib.h>
-#endif
 #include <image.h>
 #include <getopt.h>
 #include <arch/options.h>
 #include "../../kexec.h"
 #include "kexec-ppc.h"
 #include "fixup_dtb.h"
+#include <kexec-uImage.h>
 
 #define OPT_APPEND      (OPT_ARCH_MAX+0)
 #define OPT_DTB         (OPT_ARCH_MAX+1)
@@ -42,64 +40,7 @@ void uImage_ppc_usage(void)
 
 int uImage_ppc_probe(const char *buf, off_t len)
 {
-	struct image_header header;
-#ifdef HAVE_LIBZ
-	unsigned int crc;
-	unsigned int hcrc;
-#endif
-
-	if (len < sizeof(header))
-		return -1;
-
-	memcpy(&header, buf, sizeof(header));
-
-	if (cpu_to_be32(header.ih_magic) != IH_MAGIC)
-		return -1;
-#ifdef HAVE_LIBZ
-	hcrc = be32_to_cpu(header.ih_hcrc);
-	header.ih_hcrc = 0;
-	crc = crc32(0, (void *)&header, sizeof(header));
-	if (crc != hcrc) {
-		printf("Header checksum of the uImage does not match\n");
-		return -1;
-	}
-#endif
-
-	if (header.ih_type != IH_TYPE_KERNEL) {
-		printf("uImage type %d unsupported\n", header.ih_type);
-		return -1;
-	}
-
-	if (header.ih_os != IH_OS_LINUX) {
-		printf("uImage os %d unsupported\n", header.ih_os);
-		return -1;
-	}
-
-	if (header.ih_arch != IH_ARCH_PPC) {
-		printf("uImage arch %d unsupported\n", header.ih_arch);
-		return -1;
-	}
-
-	switch (header.ih_comp) {
-	case IH_COMP_NONE:
-#ifdef HAVE_LIBZ
-	case IH_COMP_GZIP:
-#endif
-		break;
-
-	default:
-		printf("uImage uses unsupported compression method\n");
-		return -1;
-	}
-#ifdef HAVE_LIBZ
-	crc = crc32(0, (void *)buf + sizeof(header), len - sizeof(header));
-	if (crc != be32_to_cpu(header.ih_dcrc)) {
-		printf("The data CRC does not match. Computed: %08x expected %08x\n",
-			crc, be32_to_cpu(header.ih_dcrc));
-		return -1;
-	}
-#endif
-	return 0;
+	return uImage_probe(buf, len, IH_ARCH_PPC);
 }
 
 static int ppc_load_bare_bits(int argc, char **argv, const char *buf,
@@ -209,140 +150,16 @@ static int ppc_load_bare_bits(int argc, char **argv, const char *buf,
 	return 0;
 }
 
-#ifdef HAVE_LIBZ
-/* gzip flag byte */
-#define ASCII_FLAG	0x01 /* bit 0 set: file probably ascii text */
-#define HEAD_CRC	0x02 /* bit 1 set: header CRC present */
-#define EXTRA_FIELD	0x04 /* bit 2 set: extra field present */
-#define ORIG_NAME	0x08 /* bit 3 set: original file name present */
-#define COMMENT		0x10 /* bit 4 set: file comment present */
-#define RESERVED	0xE0 /* bits 5..7: reserved */
-
-static int uImage_gz_load(int argc, char **argv, const char *buf, off_t len,
-		struct kexec_info *info, unsigned int load_addr,
-		unsigned int ep)
-{
-	int ret;
-	z_stream strm;
-	unsigned int skip;
-	unsigned int flags;
-	unsigned char *uncomp_buf;
-	unsigned int mem_alloc;
-
-	mem_alloc = 10 * 1024 * 1024;
-	uncomp_buf = malloc(mem_alloc);
-	if (!uncomp_buf)
-		return -1;
-
-	memset(&strm, 0, sizeof(strm));
-
-	/* Skip magic, method, time, flags, os code ... */
-	skip = 10;
-
-	/* check GZ magic */
-	if (buf[0] != 0x1f || buf[1] != 0x8b)
-		return -1;
-
-	flags = buf[3];
-	if (buf[2] != Z_DEFLATED || (flags & RESERVED) != 0) {
-		puts ("Error: Bad gzipped data\n");
-		return -1;
-	}
-
-	if (flags & EXTRA_FIELD) {
-		skip += 2;
-		skip += buf[10];
-		skip += buf[11] << 8;
-	}
-	if (flags & ORIG_NAME) {
-		while (buf[skip++])
-			;
-	}
-	if (flags & COMMENT) {
-		while (buf[skip++])
-			;
-	}
-	if (flags & HEAD_CRC)
-		skip += 2;
-
-	strm.avail_in = len - skip;
-	strm.next_in = (void *)buf + skip;
-
-	/* - activates parsing gz headers */
-	ret = inflateInit2(&strm, -MAX_WBITS);
-	if (ret != Z_OK)
-		return -1;
-
-	strm.next_out = uncomp_buf;
-	strm.avail_out = mem_alloc;
-
-	do {
-		ret = inflate(&strm, Z_FINISH);
-		if (ret == Z_STREAM_END)
-			break;
-
-		if (ret == Z_OK || ret == Z_BUF_ERROR) {
-			void *new_buf;
-			int inc_buf = 5 * 1024 * 1024;
-
-			mem_alloc += inc_buf;
-			new_buf = realloc(uncomp_buf, mem_alloc);
-			if (!new_buf) {
-				inflateEnd(&strm);
-				free(uncomp_buf);
-				return -1;
-			}
-
-			strm.next_out = uncomp_buf + mem_alloc - inc_buf;
-			strm.avail_out = inc_buf;
-			uncomp_buf = new_buf;
-		} else {
-			printf("Error during decompression %d\n", ret);
-			return -1;
-		}
-	} while (1);
-
-	inflateEnd(&strm);
-
-	ret = ppc_load_bare_bits(argc, argv, (char *)uncomp_buf,
-			mem_alloc - strm.avail_out, info,
-			load_addr, ep);
-
-	/* leak uncomp_buf since the buffer has to remain past this function */
-	return ret;
-}
-
-#else
-
-static int uImage_gz_load(int argc, char **argv, const char *buf, off_t len,
-		struct kexec_info *info, unsigned int load_addr,
-		unsigned int ep)
-{
-	return -1;
-}
-#endif
-
 int uImage_ppc_load(int argc, char **argv, const char *buf, off_t len,
 		struct kexec_info *info)
 {
-	const struct image_header *header = (const struct image_header *)buf;
-	const char *img_buf = buf + sizeof(struct image_header);
-	off_t img_len = len - sizeof(struct image_header);
-	unsigned int img_base = cpu_to_be32(header->ih_load);
-	unsigned int img_entry = cpu_to_be32(header->ih_ep);
-
-	switch (header->ih_comp) {
-	case IH_COMP_NONE:
-		return ppc_load_bare_bits(argc, argv, img_buf, img_len, info,
-				img_base, img_entry);
-		break;
+	struct Image_info img;
+	int ret;
 
-	case IH_COMP_GZIP:
-		return uImage_gz_load(argc, argv, img_buf, img_len, info,
-				img_base, img_entry);
-		break;
+	ret = uImage_load(buf, len, &img);
+	if (ret)
+		return ret;
 
-	default:
-		return -1;
-	}
+	return	ppc_load_bare_bits(argc, argv, img.buf, img.len, info,
+				img.base, img.ep);
 }
diff --git a/kexec/kexec-uImage.c b/kexec/kexec-uImage.c
new file mode 100644
index 0000000..4ce0f38
--- /dev/null
+++ b/kexec/kexec-uImage.c
@@ -0,0 +1,213 @@
+#define _GNU_SOURCE
+#include <stdlib.h>
+#include <stdint.h>
+#include <string.h>
+#include <sys/types.h>
+#include <image.h>
+#include <getopt.h>
+#include <arch/options.h>
+#include "kexec.h"
+#include <kexec-uImage.h>
+
+#ifdef HAVE_LIBZ
+#include <zlib.h>
+#endif
+/*
+ * Basic uImage loader. Not rocket science.
+ */
+
+int uImage_probe(const char *buf, off_t len, unsigned int arch)
+{
+	struct image_header header;
+#ifdef HAVE_LIBZ
+	unsigned int crc;
+	unsigned int hcrc;
+#endif
+
+	if ((uintmax_t)len < (uintmax_t)sizeof(header))
+		return -1;
+
+	memcpy(&header, buf, sizeof(header));
+	if (be32_to_cpu(header.ih_magic) != IH_MAGIC)
+		return -1;
+#ifdef HAVE_LIBZ
+	hcrc = be32_to_cpu(header.ih_hcrc);
+	header.ih_hcrc = 0;
+	crc = crc32(0, (void *)&header, sizeof(header));
+	if (crc != hcrc) {
+		printf("Header checksum of the uImage does not match\n");
+		return -1;
+	}
+#endif
+	if (header.ih_type != IH_TYPE_KERNEL) {
+		printf("uImage type %d unsupported\n", header.ih_type);
+		return -1;
+	}
+
+	if (header.ih_os != IH_OS_LINUX) {
+		printf("uImage os %d unsupported\n", header.ih_os);
+		return -1;
+	}
+
+	if (header.ih_arch != arch) {
+		printf("uImage arch %d unsupported\n", header.ih_arch);
+		return -1;
+	}
+
+	switch (header.ih_comp) {
+	case IH_COMP_NONE:
+#ifdef HAVE_LIBZ
+	case IH_COMP_GZIP:
+#endif
+		break;
+	default:
+		printf("uImage uses unsupported compression method\n");
+		return -1;
+	}
+
+	if (be32_to_cpu(header.ih_size) > len - sizeof(header)) {
+		printf("uImage header claims that image has %d bytes\n",
+				be32_to_cpu(header.ih_size));
+		printf("we read only %ld bytes.\n", len - sizeof(header));
+		return -1;
+	}
+#ifdef HAVE_LIBZ
+	crc = crc32(0, (void *)buf + sizeof(header), len - sizeof(header));
+	if (crc != be32_to_cpu(header.ih_dcrc)) {
+		printf("The data CRC does not match. Computed: %08x "
+				"expected %08x\n", crc,
+				be32_to_cpu(header.ih_dcrc));
+		return -1;
+	}
+#endif
+	return 0;
+}
+
+#ifdef HAVE_LIBZ
+/* gzip flag byte */
+#define ASCII_FLAG	0x01 /* bit 0 set: file probably ascii text */
+#define HEAD_CRC	0x02 /* bit 1 set: header CRC present */
+#define EXTRA_FIELD	0x04 /* bit 2 set: extra field present */
+#define ORIG_NAME	0x08 /* bit 3 set: original file name present */
+#define COMMENT		0x10 /* bit 4 set: file comment present */
+#define RESERVED	0xE0 /* bits 5..7: reserved */
+
+static int uImage_gz_load(const char *buf, off_t len,
+		struct Image_info *image)
+{
+	int ret;
+	z_stream strm;
+	unsigned int skip;
+	unsigned int flags;
+	unsigned char *uncomp_buf;
+	unsigned int mem_alloc;
+
+	mem_alloc = 10 * 1024 * 1024;
+	uncomp_buf = malloc(mem_alloc);
+	if (!uncomp_buf)
+		return -1;
+
+	memset(&strm, 0, sizeof(strm));
+
+	/* Skip magic, method, time, flags, os code ... */
+	skip = 10;
+
+	/* check GZ magic */
+	if (buf[0] != 0x1f || buf[1] != 0x8b)
+		return -1;
+
+	flags = buf[3];
+	if (buf[2] != Z_DEFLATED || (flags & RESERVED) != 0) {
+		puts ("Error: Bad gzipped data\n");
+		return -1;
+	}
+
+	if (flags & EXTRA_FIELD) {
+		skip += 2;
+		skip += buf[10];
+		skip += buf[11] << 8;
+	}
+	if (flags & ORIG_NAME) {
+		while (buf[skip++])
+			;
+	}
+	if (flags & COMMENT) {
+		while (buf[skip++])
+			;
+	}
+	if (flags & HEAD_CRC)
+		skip += 2;
+
+	strm.avail_in = len - skip;
+	strm.next_in = (void *)buf + skip;
+
+	/* - activates parsing gz headers */
+	ret = inflateInit2(&strm, -MAX_WBITS);
+	if (ret != Z_OK)
+		return -1;
+
+	strm.next_out = uncomp_buf;
+	strm.avail_out = mem_alloc;
+
+	do {
+		ret = inflate(&strm, Z_FINISH);
+		if (ret == Z_STREAM_END)
+			break;
+
+		if (ret == Z_OK || ret == Z_BUF_ERROR) {
+			void *new_buf;
+			int inc_buf = 5 * 1024 * 1024;
+
+			mem_alloc += inc_buf;
+			new_buf = realloc(uncomp_buf, mem_alloc);
+			if (!new_buf) {
+				inflateEnd(&strm);
+				free(uncomp_buf);
+				return -1;
+			}
+
+			strm.next_out = uncomp_buf + mem_alloc - inc_buf;
+			strm.avail_out = inc_buf;
+			uncomp_buf = new_buf;
+		} else {
+			printf("Error during decompression %d\n", ret);
+			return -1;
+		}
+	} while (1);
+
+	inflateEnd(&strm);
+	image->buf = (char *)uncomp_buf;
+	image->len = mem_alloc - strm.avail_out;
+	return 0;
+}
+#else
+static int uImage_gz_load(const char *UNUSED(buf), off_t UNUSED(len),
+		struct Image_info *UNUSED(image))
+{
+	return -1;
+}
+#endif
+
+int uImage_load(const char *buf, off_t len, struct Image_info *image)
+{
+	const struct image_header *header = (const struct image_header *)buf;
+	const char *img_buf = buf + sizeof(struct image_header);
+	off_t img_len = len - sizeof(struct image_header);
+
+	image->base = cpu_to_be32(header->ih_load);
+	image->ep = cpu_to_be32(header->ih_ep);
+	switch (header->ih_comp) {
+	case IH_COMP_NONE:
+		image->buf = img_buf;
+		image->len = len;
+		return 0;
+		break;
+
+	case IH_COMP_GZIP:
+		return uImage_gz_load(img_buf, img_len, image);
+		break;
+
+	default:
+		return -1;
+	}
+}
-- 
1.6.5.2




More information about the kexec mailing list