[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