All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/7] ppc64: little endian zImage support
@ 2014-04-18 14:08 Cédric Le Goater
  2014-04-18 14:08 ` [PATCH 1/7] kexec: add a elf_rel_find_section service Cédric Le Goater
                   ` (6 more replies)
  0 siblings, 7 replies; 10+ messages in thread
From: Cédric Le Goater @ 2014-04-18 14:08 UTC (permalink / raw)
  To: kexec; +Cc: horms, Cédric Le Goater

Hi,

A zImage is ppc64 elf executable file containing an elf section 
".kernel:vmlinux.strip" in which a vmlinux file is compressed. 

The support for such files is simply added by detecting the 
".kernel:vmlinux.strip" section when a ppc64 executable is loaded. 
If found, the embedded vmlinux file is uncompressed and loaded 
in lieu of the original zImage file.

Patch 1 adds a simple helper routine to look for a section. Patch 2
adds a proposal to bypass the check on the interp program header 
which is needed for zImage files on little endian. Patch 3 adds the 
core funtionnality and the final patches are ppc64 compile cleanups 
which poluted output.

Also available here :

     https://github.com/legoater/kexec-tools zimage

Comments are welcome ! 

Thanks
C.

Cédric Le Goater (7):
  kexec: add a elf_rel_find_section service
  kexec: bypass check on interp program header for ppc64le zImage
  ppc64: detect zImage files and load the uncompressed vmlinux
  ppc64, cleanup: cmdline_len variables are unused
  ppc64, cleanup: remove dead code in kexec-zImage-ppc64
  ppc64, cleanup: fix implicit declaration compile warnings
  ppc64, cleanup: fix unused variable compile warning

 kexec/arch/arm/kexec-elf-rel-arm.c       |    5 +
 kexec/arch/cris/kexec-elf-rel-cris.c     |    5 +
 kexec/arch/i386/kexec-elf-rel-x86.c      |    5 +
 kexec/arch/ia64/kexec-elf-rel-ia64.c     |    5 +
 kexec/arch/m68k/kexec-elf-rel-m68k.c     |    5 +
 kexec/arch/mips/kexec-elf-rel-mips.c     |    5 +
 kexec/arch/ppc/kexec-elf-rel-ppc.c       |    5 +
 kexec/arch/ppc64/crashdump-ppc64.c       |    3 +-
 kexec/arch/ppc64/kexec-elf-ppc64.c       |   23 +++-
 kexec/arch/ppc64/kexec-elf-rel-ppc64.c   |   35 +++--
 kexec/arch/ppc64/kexec-ppc64.c           |    1 +
 kexec/arch/ppc64/kexec-ppc64.h           |    2 +
 kexec/arch/ppc64/kexec-zImage-ppc64.c    |  214 ++++++++++++++----------------
 kexec/arch/s390/kexec-elf-rel-s390.c     |    5 +
 kexec/arch/sh/kexec-elf-rel-sh.c         |    5 +
 kexec/arch/x86_64/kexec-elf-rel-x86_64.c |    5 +
 kexec/kexec-elf-exec.c                   |    4 +
 kexec/kexec-elf-rel.c                    |   17 +++
 kexec/kexec-elf.h                        |    3 +
 19 files changed, 208 insertions(+), 144 deletions(-)

-- 
1.7.10.4


_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec

^ permalink raw reply	[flat|nested] 10+ messages in thread

* [PATCH 1/7] kexec: add a elf_rel_find_section service
  2014-04-18 14:08 [PATCH 0/7] ppc64: little endian zImage support Cédric Le Goater
@ 2014-04-18 14:08 ` Cédric Le Goater
  2014-04-18 14:08 ` [PATCH 2/7] kexec: bypass check on interp program header for ppc64le zImage Cédric Le Goater
                   ` (5 subsequent siblings)
  6 siblings, 0 replies; 10+ messages in thread
From: Cédric Le Goater @ 2014-04-18 14:08 UTC (permalink / raw)
  To: kexec; +Cc: horms, Cédric Le Goater

It can be directly used to find the .toc section on ppc64 and it
will be used to look for the section containing the compressed
vmlinux in a ppc64 zImage.

Signed-off-by: Cédric Le Goater <clg@fr.ibm.com>
---
 kexec/arch/ppc64/kexec-elf-rel-ppc64.c |   19 +------------------
 kexec/kexec-elf-rel.c                  |   17 +++++++++++++++++
 kexec/kexec-elf.h                      |    2 ++
 3 files changed, 20 insertions(+), 18 deletions(-)

diff --git a/kexec/arch/ppc64/kexec-elf-rel-ppc64.c b/kexec/arch/ppc64/kexec-elf-rel-ppc64.c
index 9b191d0025a4..708f507a50a6 100644
--- a/kexec/arch/ppc64/kexec-elf-rel-ppc64.c
+++ b/kexec/arch/ppc64/kexec-elf-rel-ppc64.c
@@ -17,23 +17,6 @@ int machine_verify_elf_rel(struct mem_ehdr *ehdr)
 	return 1;
 }
 
-static struct mem_shdr *toc_section(const struct mem_ehdr *ehdr)
-{
-	struct mem_shdr *shdr, *shdr_end;
-	unsigned char *strtab;
-
-	strtab = (unsigned char *)ehdr->e_shdr[ehdr->e_shstrndx].sh_data;
-	shdr_end = &ehdr->e_shdr[ehdr->e_shnum];
-	for (shdr = ehdr->e_shdr; shdr != shdr_end; shdr++) {
-		if (shdr->sh_size &&
-			strcmp((char *)&strtab[shdr->sh_name], ".toc") == 0) {
-			return shdr;
-		}
-	}
-
-	return NULL;
-}
-
 /* r2 is the TOC pointer: it actually points 0x8000 into the TOC (this
    gives the value maximum span in an instruction which uses a signed
    offset) */
@@ -41,7 +24,7 @@ unsigned long my_r2(const struct mem_ehdr *ehdr)
 {
 	struct mem_shdr *shdr;
 
-	shdr = toc_section(ehdr);
+	shdr = elf_rel_find_section(ehdr, ".toc");
 	if (!shdr) {
 		die("TOC reloc without a toc section?");
 	}
diff --git a/kexec/kexec-elf-rel.c b/kexec/kexec-elf-rel.c
index c625f30381bc..322ac123cbd6 100644
--- a/kexec/kexec-elf-rel.c
+++ b/kexec/kexec-elf-rel.c
@@ -435,6 +435,23 @@ void elf_rel_build_load(struct kexec_info *info, struct mem_ehdr *ehdr,
 	}
 }
 
+struct mem_shdr *elf_rel_find_section(const struct mem_ehdr *ehdr,
+				      const char *name)
+{
+	struct mem_shdr *shdr, *shdr_end;
+	unsigned char *strtab;
+
+	strtab = (unsigned char *)ehdr->e_shdr[ehdr->e_shstrndx].sh_data;
+	shdr_end = &ehdr->e_shdr[ehdr->e_shnum];
+	for (shdr = ehdr->e_shdr; shdr != shdr_end; shdr++) {
+		if (shdr->sh_size &&
+		    strcmp((char *)&strtab[shdr->sh_name], name) == 0) {
+			return shdr;
+		}
+	}
+	return NULL;
+}
+
 int elf_rel_find_symbol(struct mem_ehdr *ehdr,
 	const char *name, struct mem_sym *ret_sym)
 {
diff --git a/kexec/kexec-elf.h b/kexec/kexec-elf.h
index d0e9dc0b1e02..19b5769d1838 100644
--- a/kexec/kexec-elf.h
+++ b/kexec/kexec-elf.h
@@ -109,6 +109,8 @@ extern void elf_rel_build_load(struct kexec_info *info, struct mem_ehdr *ehdr,
 	const char *buf, off_t len, unsigned long min, unsigned long max, 
 	int end, uint32_t flags);
 
+extern struct mem_shdr *elf_rel_find_section(const struct mem_ehdr *ehdr,
+					     const char *name);
 extern int elf_rel_find_symbol(struct mem_ehdr *ehdr,
 	const char *name, struct mem_sym *ret_sym);
 extern unsigned long elf_rel_get_addr(struct mem_ehdr *ehdr, const char *name);
-- 
1.7.10.4


_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec

^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH 2/7] kexec: bypass check on interp program header for ppc64le zImage
  2014-04-18 14:08 [PATCH 0/7] ppc64: little endian zImage support Cédric Le Goater
  2014-04-18 14:08 ` [PATCH 1/7] kexec: add a elf_rel_find_section service Cédric Le Goater
@ 2014-04-18 14:08 ` Cédric Le Goater
  2014-04-18 14:08 ` [PATCH 3/7] ppc64: detect zImage files and load the uncompressed vmlinux Cédric Le Goater
                   ` (4 subsequent siblings)
  6 siblings, 0 replies; 10+ messages in thread
From: Cédric Le Goater @ 2014-04-18 14:08 UTC (permalink / raw)
  To: kexec; +Cc: horms, Cédric Le Goater

When the elf information is built from the executable, kexec checks
for an interp elf program header and fails if it exists. The following
patch adds a new service machine_check_elf_phdr_interp() which lets
platforms eventually bypass this check.

This is needed for the zImage boot wrapper on PPC 64bit little endian.
The executable is linked as position independent and has a interp elf
program header.

An alternative to this patch would be to remove the whole test on the
interp elf program header as kexec seems to be ignoring the information
after all.

Signed-off-by: Cédric Le Goater <clg@fr.ibm.com>
---
 kexec/arch/arm/kexec-elf-rel-arm.c       |    5 +++++
 kexec/arch/cris/kexec-elf-rel-cris.c     |    5 +++++
 kexec/arch/i386/kexec-elf-rel-x86.c      |    5 +++++
 kexec/arch/ia64/kexec-elf-rel-ia64.c     |    5 +++++
 kexec/arch/m68k/kexec-elf-rel-m68k.c     |    5 +++++
 kexec/arch/mips/kexec-elf-rel-mips.c     |    5 +++++
 kexec/arch/ppc/kexec-elf-rel-ppc.c       |    5 +++++
 kexec/arch/ppc64/kexec-elf-rel-ppc64.c   |   16 ++++++++++++++++
 kexec/arch/s390/kexec-elf-rel-s390.c     |    5 +++++
 kexec/arch/sh/kexec-elf-rel-sh.c         |    5 +++++
 kexec/arch/x86_64/kexec-elf-rel-x86_64.c |    5 +++++
 kexec/kexec-elf-exec.c                   |    4 ++++
 kexec/kexec-elf.h                        |    1 +
 13 files changed, 71 insertions(+)

diff --git a/kexec/arch/arm/kexec-elf-rel-arm.c b/kexec/arch/arm/kexec-elf-rel-arm.c
index 214f0ccc2a33..6fbe8c485447 100644
--- a/kexec/arch/arm/kexec-elf-rel-arm.c
+++ b/kexec/arch/arm/kexec-elf-rel-arm.c
@@ -3,6 +3,11 @@
 #include "../../kexec.h"
 #include "../../kexec-elf.h"
 
+int machine_check_elf_phdr_interp(const struct mem_ehdr *ehdr)
+{
+	return 1;
+}
+
 int machine_verify_elf_rel(struct mem_ehdr *ehdr)
 {
 	if (ehdr->ei_data != ELFDATA2MSB) {
diff --git a/kexec/arch/cris/kexec-elf-rel-cris.c b/kexec/arch/cris/kexec-elf-rel-cris.c
index c4427cc144be..b0add16444ad 100644
--- a/kexec/arch/cris/kexec-elf-rel-cris.c
+++ b/kexec/arch/cris/kexec-elf-rel-cris.c
@@ -15,6 +15,11 @@
 #include "../../kexec.h"
 #include "../../kexec-elf.h"
 
+int machine_check_elf_phdr_interp(const struct mem_ehdr *ehdr)
+{
+	return 1;
+}
+
 int machine_verify_elf_rel(struct mem_ehdr *ehdr)
 {
 	if (ehdr->ei_data != ELFDATA2MSB) {
diff --git a/kexec/arch/i386/kexec-elf-rel-x86.c b/kexec/arch/i386/kexec-elf-rel-x86.c
index fdc3d52feeb2..c7d783e70ecc 100644
--- a/kexec/arch/i386/kexec-elf-rel-x86.c
+++ b/kexec/arch/i386/kexec-elf-rel-x86.c
@@ -3,6 +3,11 @@
 #include "../../kexec.h"
 #include "../../kexec-elf.h"
 
+int machine_check_elf_phdr_interp(const struct mem_ehdr *ehdr)
+{
+	return 1;
+}
+
 int machine_verify_elf_rel(struct mem_ehdr *ehdr)
 {
 	if (ehdr->ei_data != ELFDATA2LSB) {
diff --git a/kexec/arch/ia64/kexec-elf-rel-ia64.c b/kexec/arch/ia64/kexec-elf-rel-ia64.c
index cfb106169643..a2aec0d03e3f 100644
--- a/kexec/arch/ia64/kexec-elf-rel-ia64.c
+++ b/kexec/arch/ia64/kexec-elf-rel-ia64.c
@@ -32,6 +32,11 @@
 
 #define MAX_LTOFF       ((uint64_t) (1 << 22))
 
+int machine_check_elf_phdr_interp(const struct mem_ehdr *ehdr)
+{
+	return 1;
+}
+
 int machine_verify_elf_rel(struct mem_ehdr *ehdr)
 {
 	if (ehdr->ei_data != ELFDATA2LSB) {
diff --git a/kexec/arch/m68k/kexec-elf-rel-m68k.c b/kexec/arch/m68k/kexec-elf-rel-m68k.c
index fa12a1670149..bc9fd1aa9899 100644
--- a/kexec/arch/m68k/kexec-elf-rel-m68k.c
+++ b/kexec/arch/m68k/kexec-elf-rel-m68k.c
@@ -12,6 +12,11 @@
 #include "../../kexec.h"
 #include "../../kexec-elf.h"
 
+int machine_check_elf_phdr_interp(const struct mem_ehdr *ehdr)
+{
+	return 1;
+}
+
 int machine_verify_elf_rel(struct mem_ehdr *ehdr)
 {
 	if (ehdr->ei_data != ELFDATA2MSB)
diff --git a/kexec/arch/mips/kexec-elf-rel-mips.c b/kexec/arch/mips/kexec-elf-rel-mips.c
index 6f436393a87a..8789e3366aa1 100644
--- a/kexec/arch/mips/kexec-elf-rel-mips.c
+++ b/kexec/arch/mips/kexec-elf-rel-mips.c
@@ -15,6 +15,11 @@
 #include "../../kexec.h"
 #include "../../kexec-elf.h"
 
+int machine_check_elf_phdr_interp(const struct mem_ehdr *ehdr)
+{
+	return 1;
+}
+
 int machine_verify_elf_rel(struct mem_ehdr *ehdr)
 {
 	if (ehdr->ei_data != ELFDATA2MSB) {
diff --git a/kexec/arch/ppc/kexec-elf-rel-ppc.c b/kexec/arch/ppc/kexec-elf-rel-ppc.c
index 90a66f420409..a8ab54e0c0c6 100644
--- a/kexec/arch/ppc/kexec-elf-rel-ppc.c
+++ b/kexec/arch/ppc/kexec-elf-rel-ppc.c
@@ -3,6 +3,11 @@
 #include "../../kexec.h"
 #include "../../kexec-elf.h"
 
+int machine_check_elf_phdr_interp(const struct mem_ehdr *ehdr)
+{
+	return 1;
+}
+
 int machine_verify_elf_rel(struct mem_ehdr *ehdr)
 {
 	if (ehdr->ei_data != ELFDATA2MSB) {
diff --git a/kexec/arch/ppc64/kexec-elf-rel-ppc64.c b/kexec/arch/ppc64/kexec-elf-rel-ppc64.c
index 708f507a50a6..300f15149542 100644
--- a/kexec/arch/ppc64/kexec-elf-rel-ppc64.c
+++ b/kexec/arch/ppc64/kexec-elf-rel-ppc64.c
@@ -5,6 +5,22 @@
 #include "../../kexec-elf.h"
 #include "kexec-ppc64.h"
 
+/* The zImage boot wrapper on 64bit little endian is linked as a
+ * position independant executable and has a interp program
+ * header. We don't want to check for it.
+ */
+int machine_check_elf_phdr_interp(const struct mem_ehdr *ehdr)
+{
+	if (ehdr->ei_data == ELFDATA2MSB)
+		return 1;
+
+	/* sections are loaded in build_elf_info */
+	if (elf_rel_find_section(ehdr, ".kernel:vmlinux.strip"))
+		return 0;
+
+	return 1;
+}
+
 int machine_verify_elf_rel(struct mem_ehdr *ehdr)
 {
 	if (ehdr->ei_class != ELFCLASS64) {
diff --git a/kexec/arch/s390/kexec-elf-rel-s390.c b/kexec/arch/s390/kexec-elf-rel-s390.c
index 80bcd1bb92ef..df2d15af88cd 100644
--- a/kexec/arch/s390/kexec-elf-rel-s390.c
+++ b/kexec/arch/s390/kexec-elf-rel-s390.c
@@ -12,6 +12,11 @@
 #include "../../kexec.h"
 #include "../../kexec-elf.h"
 
+int machine_check_elf_phdr_interp(const struct mem_ehdr *ehdr)
+{
+	return 1;
+}
+
 int machine_verify_elf_rel(struct mem_ehdr *ehdr)
 {
 	if (ehdr->ei_data != ELFDATA2MSB)
diff --git a/kexec/arch/sh/kexec-elf-rel-sh.c b/kexec/arch/sh/kexec-elf-rel-sh.c
index 0bfc45ec0d6d..5db74ea91213 100644
--- a/kexec/arch/sh/kexec-elf-rel-sh.c
+++ b/kexec/arch/sh/kexec-elf-rel-sh.c
@@ -15,6 +15,11 @@
 #include "../../kexec.h"
 #include "../../kexec-elf.h"
 
+int machine_check_elf_phdr_interp(const struct mem_ehdr *ehdr)
+{
+	return 1;
+}
+
 int machine_verify_elf_rel(struct mem_ehdr *ehdr)
 {
 	/* Intentionally don't bother with endianness validation, it's
diff --git a/kexec/arch/x86_64/kexec-elf-rel-x86_64.c b/kexec/arch/x86_64/kexec-elf-rel-x86_64.c
index c795037cdb0f..6ddc28198882 100644
--- a/kexec/arch/x86_64/kexec-elf-rel-x86_64.c
+++ b/kexec/arch/x86_64/kexec-elf-rel-x86_64.c
@@ -3,6 +3,11 @@
 #include "../../kexec.h"
 #include "../../kexec-elf.h"
 
+int machine_check_elf_phdr_interp(const struct mem_ehdr *ehdr)
+{
+	return 1;
+}
+
 int machine_verify_elf_rel(struct mem_ehdr *ehdr)
 {
 	if (ehdr->ei_data != ELFDATA2LSB) {
diff --git a/kexec/kexec-elf-exec.c b/kexec/kexec-elf-exec.c
index cb62d04849e5..adc794d32481 100644
--- a/kexec/kexec-elf-exec.c
+++ b/kexec/kexec-elf-exec.c
@@ -33,6 +33,10 @@ int build_elf_exec_info(const char *buf, off_t len, struct mem_ehdr *ehdr,
 		fprintf(stderr, "No ELF program header\n");
 		return -1; 
 	}
+
+	if (!machine_check_elf_phdr_interp(ehdr))
+		return 0;
+
 	end_phdr = &ehdr->e_phdr[ehdr->e_phnum];
 	for(phdr = ehdr->e_phdr; phdr != end_phdr; phdr++) {
 		/* Kexec does not support loading interpreters.
diff --git a/kexec/kexec-elf.h b/kexec/kexec-elf.h
index 19b5769d1838..739639418429 100644
--- a/kexec/kexec-elf.h
+++ b/kexec/kexec-elf.h
@@ -133,5 +133,6 @@ unsigned long elf_max_addr(const struct mem_ehdr *ehdr);
 extern int machine_verify_elf_rel(struct mem_ehdr *ehdr);
 extern void machine_apply_elf_rel(struct mem_ehdr *ehdr, unsigned long r_type, 
 	void *location, unsigned long address, unsigned long value);
+extern int machine_check_elf_phdr_interp(const struct mem_ehdr *ehdr);
 #endif /* KEXEC_ELF_H */
 
-- 
1.7.10.4


_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec

^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH 3/7] ppc64: detect zImage files and load the uncompressed vmlinux
  2014-04-18 14:08 [PATCH 0/7] ppc64: little endian zImage support Cédric Le Goater
  2014-04-18 14:08 ` [PATCH 1/7] kexec: add a elf_rel_find_section service Cédric Le Goater
  2014-04-18 14:08 ` [PATCH 2/7] kexec: bypass check on interp program header for ppc64le zImage Cédric Le Goater
@ 2014-04-18 14:08 ` Cédric Le Goater
  2014-05-12  9:56   ` Laurent Dufour
  2014-04-18 14:08 ` [PATCH 4/7] ppc64, cleanup: cmdline_len variables are unused Cédric Le Goater
                   ` (3 subsequent siblings)
  6 siblings, 1 reply; 10+ messages in thread
From: Cédric Le Goater @ 2014-04-18 14:08 UTC (permalink / raw)
  To: kexec; +Cc: horms, Cédric Le Goater

The zImage* executable files on ppc64 use a special section called
".kernel:vmlinux.strip" which contains a compressed vmlinux executable
file.

This patch adds a service to detect and unzip such a section in a
malloc'ed buffer. The buffer is then used in elf_ppc64_load() to
load the new vmlinux.

Signed-off-by: Cédric Le Goater <clg@fr.ibm.com>
---
 kexec/arch/ppc64/kexec-elf-ppc64.c    |   15 ++++
 kexec/arch/ppc64/kexec-ppc64.h        |    2 +
 kexec/arch/ppc64/kexec-zImage-ppc64.c |  123 +++++++++++++++++++++++++++++++++
 3 files changed, 140 insertions(+)

diff --git a/kexec/arch/ppc64/kexec-elf-ppc64.c b/kexec/arch/ppc64/kexec-elf-ppc64.c
index ce1036762582..069d8ba6e690 100644
--- a/kexec/arch/ppc64/kexec-elf-ppc64.c
+++ b/kexec/arch/ppc64/kexec-elf-ppc64.c
@@ -116,6 +116,8 @@ int elf_ppc64_load(int argc, char **argv, const char *buf, off_t len,
 	uint64_t toc_addr;
 	uint32_t my_run_at_load;
 	unsigned int slave_code[256/sizeof (unsigned int)], master_entry;
+	void *vmlinux_addr;
+	int vmlinux_size;
 
 	/* See options.h -- add any more there, too. */
 	static const struct option options[] = {
@@ -184,6 +186,7 @@ int elf_ppc64_load(int argc, char **argv, const char *buf, off_t len,
 		modified_cmdline_len = strlen(modified_cmdline);
 	}
 
+retry:
 	/* Parse the Elf file */
 	result = build_elf_exec_info(buf, len, &ehdr, 0);
 	if (result < 0) {
@@ -191,6 +194,18 @@ int elf_ppc64_load(int argc, char **argv, const char *buf, off_t len,
 		return result;
 	}
 
+	/* If this is a zimage boot wrapper, rebuild the elf info on
+	 * the new vmlinux which has been unzipped and go on with the
+	 * kernel load.
+	 */
+	if (!zImage_ppc64_unzip(&ehdr, &vmlinux_addr, &vmlinux_size)) {
+		free_elf_info(&ehdr);
+		free((void *) buf);
+		buf = vmlinux_addr;
+		len = vmlinux_size;
+		goto retry;
+	}
+
 	/* Load the Elf data. Physical load addresses in elf64 header do not
 	 * show up correctly. Use user supplied address for now to patch the
 	 * elf header
diff --git a/kexec/arch/ppc64/kexec-ppc64.h b/kexec/arch/ppc64/kexec-ppc64.h
index 9a0aecff7b33..e546d4737bfa 100644
--- a/kexec/arch/ppc64/kexec-ppc64.h
+++ b/kexec/arch/ppc64/kexec-ppc64.h
@@ -37,4 +37,6 @@ typedef struct mem_rgns {
 
 extern mem_rgns_t usablemem_rgns;
 
+int zImage_ppc64_unzip(struct mem_ehdr *ehdr, void **buf, int *len);
+
 #endif /* KEXEC_PPC64_H */
diff --git a/kexec/arch/ppc64/kexec-zImage-ppc64.c b/kexec/arch/ppc64/kexec-zImage-ppc64.c
index d084ee587be5..67d751f19d7d 100644
--- a/kexec/arch/ppc64/kexec-zImage-ppc64.c
+++ b/kexec/arch/ppc64/kexec-zImage-ppc64.c
@@ -30,6 +30,9 @@
 #include <getopt.h>
 #include <linux/elf.h>
 #include "../../kexec.h"
+#include "kexec-ppc64.h"
+
+#include <zlib.h>
 
 #define MAX_HEADERS 32
 
@@ -175,3 +178,123 @@ void zImage_ppc64_usage(void)
 {
 	fprintf(stderr, "zImage support is still broken\n");
 }
+
+#define HEAD_CRC	2
+#define EXTRA_FIELD	4
+#define ORIG_NAME	8
+#define COMMENT		0x10
+#define RESERVED	0xe0
+
+static int get_header_len(const char *header)
+{
+	int len = 10;
+	int flags = header[3];
+
+	/* check for gzip header */
+	if ((header[0] != 0x1f) || (header[1] != 0x8b) ||
+	    (header[2] != Z_DEFLATED) || (flags & RESERVED) != 0) {
+		fprintf(stderr, "bad gzip header\n");
+		return -1;
+	}
+
+	if ((flags & EXTRA_FIELD) != 0)
+		len = 12 + header[10] + (header[11] << 8);
+
+	if ((flags & ORIG_NAME) != 0)
+		while (header[len++] != 0)
+				;
+	if ((flags & COMMENT) != 0)
+		while (header[len++] != 0)
+			;
+	if ((flags & HEAD_CRC) != 0)
+		len += 2;
+
+	return len;
+}
+
+static int gunzip(void *src, int srclen, void *dst, int dstlen)
+{
+	z_stream strm;
+	int hdrlen;
+	int len;
+	int ret;
+
+	strm.zalloc = Z_NULL;
+	strm.zfree = Z_NULL;
+	strm.opaque = Z_NULL;
+	strm.avail_in = 0;
+	strm.next_in = Z_NULL;
+
+	hdrlen = get_header_len(src);
+	if (hdrlen == -1)
+		return -1;
+
+	if (hdrlen >= srclen) {
+		fprintf(stderr, "gzip header too large : %d\n", hdrlen);
+		return -1;
+	}
+
+	ret = inflateInit2(&strm, -MAX_WBITS);
+	if (ret != Z_OK) {
+		fprintf(stderr, "inflateInit2 failed : %d\n", ret);
+		return -1;
+	}
+
+	/* skip gzip header */
+	strm.total_in = hdrlen;
+	strm.next_in = src + hdrlen;
+	strm.avail_in = srclen - hdrlen;
+
+	strm.next_out = dst;
+	strm.avail_out = dstlen;
+
+	ret = inflate(&strm, Z_FULL_FLUSH);
+	if (ret != Z_OK && ret != Z_STREAM_END) {
+		fprintf(stderr, "inflate failed: %d %s\n", ret, strm.msg);
+		return -1;
+	}
+
+	len = strm.next_out - (unsigned char *) dst;
+
+	inflateEnd(&strm);
+
+	return len;
+}
+
+int zImage_ppc64_unzip(struct mem_ehdr *ehdr, void **buf, int *len)
+{
+	struct mem_shdr *shdr;
+	void *vmlinuz_addr;
+	unsigned long vmlinuz_size;
+	unsigned int *vmlinux_sizep;
+
+	void *vmlinux_addr;
+	int vmlinux_size;
+
+	shdr = elf_rel_find_section(ehdr, ".kernel:vmlinux.strip");
+	if (!shdr)
+		return -1;
+
+	vmlinuz_addr = (void *) shdr->sh_data;
+	vmlinuz_size = shdr->sh_size;
+
+	 /* The size of the uncompressed file is stored in the last 4
+	  * bytes. The vmlinux size should be less than 4G ... */
+	vmlinux_sizep = (vmlinuz_addr + vmlinuz_size) - 4;
+
+	fprintf(stderr, "Found vmlinuz at %p, unzipping %d bytes\n",
+		vmlinuz_addr, *vmlinux_sizep);
+	vmlinux_addr = xmalloc(*vmlinux_sizep);
+
+	vmlinux_size = gunzip(vmlinuz_addr, vmlinuz_size,
+			      vmlinux_addr, *vmlinux_sizep);
+	if (vmlinux_size != *vmlinux_sizep) {
+		fprintf(stderr, "gunzip failed : only got %d of %d bytes.\n",
+				vmlinux_size, *vmlinux_sizep);
+		return -1;
+	}
+
+	*buf = vmlinux_addr;
+	*len = vmlinux_size;
+	return 0;
+}
-- 
1.7.10.4


_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec

^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH 4/7] ppc64, cleanup: cmdline_len variables are unused
  2014-04-18 14:08 [PATCH 0/7] ppc64: little endian zImage support Cédric Le Goater
                   ` (2 preceding siblings ...)
  2014-04-18 14:08 ` [PATCH 3/7] ppc64: detect zImage files and load the uncompressed vmlinux Cédric Le Goater
@ 2014-04-18 14:08 ` Cédric Le Goater
  2014-04-18 14:08 ` [PATCH 5/7] ppc64, cleanup: remove dead code in kexec-zImage-ppc64 Cédric Le Goater
                   ` (2 subsequent siblings)
  6 siblings, 0 replies; 10+ messages in thread
From: Cédric Le Goater @ 2014-04-18 14:08 UTC (permalink / raw)
  To: kexec; +Cc: horms, Cédric Le Goater

../kexec/arch/ppc64/kexec-elf-ppc64.c:100:19: warning: variable ‘modified_cmdline_len’ set but not used [-Wunused-but-set-variable]
  int cmdline_len, modified_cmdline_len;
                   ^
../kexec/arch/ppc64/kexec-elf-ppc64.c:100:6: warning: variable ‘cmdline_len’ set but not used [-Wunused-but-set-variable]
  int cmdline_len, modified_cmdline_len;

Signed-off-by: Cédric Le Goater <clg@fr.ibm.com>
---
 kexec/arch/ppc64/kexec-elf-ppc64.c |    8 +-------
 1 file changed, 1 insertion(+), 7 deletions(-)

diff --git a/kexec/arch/ppc64/kexec-elf-ppc64.c b/kexec/arch/ppc64/kexec-elf-ppc64.c
index 069d8ba6e690..7be35199c7e0 100644
--- a/kexec/arch/ppc64/kexec-elf-ppc64.c
+++ b/kexec/arch/ppc64/kexec-elf-ppc64.c
@@ -97,7 +97,6 @@ int elf_ppc64_load(int argc, char **argv, const char *buf, off_t len,
 	struct mem_ehdr ehdr;
 	char *cmdline, *modified_cmdline = NULL;
 	const char *devicetreeblob;
-	int cmdline_len, modified_cmdline_len;
 	uint64_t max_addr, hole_addr;
 	char *seg_buf = NULL;
 	off_t seg_size = 0;
@@ -164,10 +163,7 @@ int elf_ppc64_load(int argc, char **argv, const char *buf, off_t len,
 		}
 	}
 
-	cmdline_len = 0;
-	if (cmdline)
-		cmdline_len = strlen(cmdline) + 1;
-	else
+	if (!cmdline)
 		fprintf(stdout, "Warning: append= option is not passed. Using the first kernel root partition\n");
 
 	if (ramdisk && reuse_initrd)
@@ -183,7 +179,6 @@ int elf_ppc64_load(int argc, char **argv, const char *buf, off_t len,
 			strncpy(modified_cmdline, cmdline, COMMAND_LINE_SIZE);
 			modified_cmdline[COMMAND_LINE_SIZE - 1] = '\0';
 		}
-		modified_cmdline_len = strlen(modified_cmdline);
 	}
 
 retry:
@@ -234,7 +229,6 @@ retry:
 			return -1;
 		/* Use new command line. */
 		cmdline = modified_cmdline;
-		cmdline_len = strlen(modified_cmdline) + 1;
 	}
 
 	/* Add v2wrap to the current image */
-- 
1.7.10.4


_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec

^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH 5/7] ppc64, cleanup: remove dead code in kexec-zImage-ppc64
  2014-04-18 14:08 [PATCH 0/7] ppc64: little endian zImage support Cédric Le Goater
                   ` (3 preceding siblings ...)
  2014-04-18 14:08 ` [PATCH 4/7] ppc64, cleanup: cmdline_len variables are unused Cédric Le Goater
@ 2014-04-18 14:08 ` Cédric Le Goater
  2014-04-18 14:08 ` [PATCH 6/7] ppc64, cleanup: fix implicit declaration compile warnings Cédric Le Goater
  2014-04-18 14:08 ` [PATCH 7/7] ppc64, cleanup: fix unused variable compile warning Cédric Le Goater
  6 siblings, 0 replies; 10+ messages in thread
From: Cédric Le Goater @ 2014-04-18 14:08 UTC (permalink / raw)
  To: kexec; +Cc: horms, Cédric Le Goater

This code was never used.

Signed-off-by: Cédric Le Goater <clg@fr.ibm.com>
---
 kexec/arch/ppc64/kexec-zImage-ppc64.c |  145 ---------------------------------
 1 file changed, 145 deletions(-)

diff --git a/kexec/arch/ppc64/kexec-zImage-ppc64.c b/kexec/arch/ppc64/kexec-zImage-ppc64.c
index 67d751f19d7d..3a26bca0de8b 100644
--- a/kexec/arch/ppc64/kexec-zImage-ppc64.c
+++ b/kexec/arch/ppc64/kexec-zImage-ppc64.c
@@ -34,151 +34,6 @@
 
 #include <zlib.h>
 
-#define MAX_HEADERS 32
-
-int zImage_ppc64_probe(FILE *file)
-{
-	Elf32_Ehdr elf;
-	int valid;
-
-	if (fseek(file, 0, SEEK_SET) < 0) {
-		fprintf(stderr, "seek error: %s\n",
-			strerror(errno));
-		return -1;
-	}
-	if (fread(&elf, sizeof(Elf32_Ehdr), 1, file) != 1) {
-		fprintf(stderr, "read error: %s\n",
-			strerror(errno));
-		return -1;
-	}
-
-	if (elf.e_machine == EM_PPC64) {
-		fprintf(stderr, "Elf64 not supported\n");
-		return -1;
-	}
-
-	valid = (elf.e_ident[EI_MAG0]  == ELFMAG0        &&
-		elf.e_ident[EI_MAG1]  == ELFMAG1        &&
-		elf.e_ident[EI_MAG2]  == ELFMAG2        &&
-		elf.e_ident[EI_MAG3]  == ELFMAG3        &&
-		elf.e_ident[EI_CLASS] == ELFCLASS32  &&
-		elf.e_ident[EI_DATA]  == ELFDATA2MSB &&
-		elf.e_type            == ET_EXEC        &&
-		elf.e_machine         == EM_PPC);
-
-	return valid ? 0 : -1;
-}
-
-int zImage_ppc64_load(FILE *file, int UNUSED(argc), char **UNUSED(argv),
-		      void **ret_entry, struct kexec_segment **ret_segments,
-		      int *ret_nr_segments)
-{
-	Elf32_Ehdr elf;
-	Elf32_Phdr *p, *ph;
-	struct kexec_segment *segment;
-	int i;
-	unsigned long memsize, filesize, offset, load_loc = 0;
-
-	/* Parse command line arguments */
-
-	/* Read in the Elf32 header */
-        if (fseek(file, 0, SEEK_SET) < 0) {
-		perror("seek error:");
-		return -1;
-	}
-        if (fread(&elf, sizeof(Elf32_Ehdr), 1, file) != 1) {
-		perror("read error: ");
-		return -1;
-	}
-	if (elf.e_phnum > MAX_HEADERS) {
-		fprintf(stderr,
-			"Only kernels with %i program headers are supported\n",
-			MAX_HEADERS);
-		return -1;
-	}
-
-	/* Read the section header */
-	ph = (Elf32_Phdr *)malloc(sizeof(Elf32_Phdr) * elf.e_phnum);
-	if (ph == 0) {
-		perror("malloc failed: ");
-		return -1;
-	}
-	if (fseek(file, elf.e_phoff, SEEK_SET) < 0) {
-		perror("seek failed: ");
-		return -1;
-	}
-	if (fread(ph, sizeof(Elf32_Phdr) * elf.e_phnum, 1, file) != 1) {
-		perror("read error: ");
-		return -1;
-	}
-
-	*ret_segments = malloc(elf.e_phnum * sizeof(struct kexec_segment));
-	if (*ret_segments == 0) {
-		fprintf(stderr, "malloc failed: %s\n",
-			strerror(errno));
-		return -1;
-	}
-	segment = ret_segments[0];
-
-	/* Scan through the program header */
-	memsize = filesize = offset = 0;
-	p = ph;
-	for (i = 0; i < elf.e_phnum; ++i, ++p) {
-		if (p->p_type != PT_LOAD || p->p_offset == 0)
-			continue;
-		if (memsize == 0) {
-			offset = p->p_offset;
-			memsize = p->p_memsz;
-			filesize = p->p_filesz;
-			load_loc = p->p_vaddr;
-		} else {
-			memsize = p->p_offset + p->p_memsz - offset;
-			filesize = p->p_offset + p->p_filesz - offset;
-		}
-	}
-	if (memsize == 0) {
-		fprintf(stderr, "Can't find a loadable segment.\n");
-		return -1;
-	}
-
-	/* Load program segments */
-	p = ph;
-	segment->buf = malloc(filesize);
-	if (segment->buf == 0) {
-		perror("malloc failed: ");
-		return -1;
-	}
-	for (i = 0; i < elf.e_phnum; ++i, ++p) {
-		unsigned long mem_offset;
-		if (p->p_type != PT_LOAD || p->p_offset == 0)
-			continue;
-
-		/* skip to the actual image */
-		if (fseek(file, p->p_offset, SEEK_SET) < 0) {
-			perror("seek error: ");
-			return -1;
-		}
-		mem_offset = p->p_vaddr - load_loc;
-		if (fread((void *)segment->buf+mem_offset, p->p_filesz, 1,
-				file) != 1) {
-			perror("read error: ");
-			return -1;
-		}
-	}
-	segment->mem = (void *) load_loc;
-	segment->memsz = memsize;
-	segment->bufsz = filesize;
-	*ret_entry = (void *)(uintptr_t)elf.e_entry;
-	*ret_nr_segments = i - 1;
-	free(ph);
-	return 0;
-}
-
-void zImage_ppc64_usage(void)
-{
-	fprintf(stderr, "zImage support is still broken\n");
-}
-
 #define HEAD_CRC	2
 #define EXTRA_FIELD	4
 #define ORIG_NAME	8
-- 
1.7.10.4


_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec

^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH 6/7] ppc64, cleanup: fix implicit declaration compile warnings
  2014-04-18 14:08 [PATCH 0/7] ppc64: little endian zImage support Cédric Le Goater
                   ` (4 preceding siblings ...)
  2014-04-18 14:08 ` [PATCH 5/7] ppc64, cleanup: remove dead code in kexec-zImage-ppc64 Cédric Le Goater
@ 2014-04-18 14:08 ` Cédric Le Goater
  2014-04-18 14:08 ` [PATCH 7/7] ppc64, cleanup: fix unused variable compile warning Cédric Le Goater
  6 siblings, 0 replies; 10+ messages in thread
From: Cédric Le Goater @ 2014-04-18 14:08 UTC (permalink / raw)
  To: kexec; +Cc: horms, Cédric Le Goater

../kexec/arch/ppc64/kexec-ppc64.c: In function ‘get_devtree_details’:
../kexec/arch/ppc64/kexec-ppc64.c:414:5: warning: implicit declaration of function ‘reserve’ [-Wimplicit-function-declaration]
     reserve(KDUMP_BACKUP_LIMIT, crash_base-KDUMP_BACKUP_LIMIT);
     ^
../kexec/arch/ppc64/crashdump-ppc64.c: In function ‘load_crashdump_segments’:
../kexec/arch/ppc64/crashdump-ppc64.c:391:2: warning: implicit declaration of function ‘reserve’ [-Wimplicit-function-declaration]
  reserve(info->backup_start, sz);
  ^

Signed-off-by: Cédric Le Goater <clg@fr.ibm.com>
---
 kexec/arch/ppc64/crashdump-ppc64.c |    1 +
 kexec/arch/ppc64/kexec-ppc64.c     |    1 +
 2 files changed, 2 insertions(+)

diff --git a/kexec/arch/ppc64/crashdump-ppc64.c b/kexec/arch/ppc64/crashdump-ppc64.c
index c0d575d87be0..71a09dbff17f 100644
--- a/kexec/arch/ppc64/crashdump-ppc64.c
+++ b/kexec/arch/ppc64/crashdump-ppc64.c
@@ -34,6 +34,7 @@
 #include "../../crashdump.h"
 #include "kexec-ppc64.h"
 #include "crashdump-ppc64.h"
+#include "../../fs2dt.h"
 
 static struct crash_elf_info elf_info64 =
 {
diff --git a/kexec/arch/ppc64/kexec-ppc64.c b/kexec/arch/ppc64/kexec-ppc64.c
index 49b291d1e986..f64b833b665b 100644
--- a/kexec/arch/ppc64/kexec-ppc64.c
+++ b/kexec/arch/ppc64/kexec-ppc64.c
@@ -33,6 +33,7 @@
 #include "kexec-ppc64.h"
 #include "crashdump-ppc64.h"
 #include <arch/options.h>
+#include "../../fs2dt.h"
 
 static struct memory_range *exclude_range = NULL;
 static struct memory_range *memory_range = NULL;
-- 
1.7.10.4


_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec

^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH 7/7] ppc64, cleanup: fix unused variable compile warning
  2014-04-18 14:08 [PATCH 0/7] ppc64: little endian zImage support Cédric Le Goater
                   ` (5 preceding siblings ...)
  2014-04-18 14:08 ` [PATCH 6/7] ppc64, cleanup: fix implicit declaration compile warnings Cédric Le Goater
@ 2014-04-18 14:08 ` Cédric Le Goater
  6 siblings, 0 replies; 10+ messages in thread
From: Cédric Le Goater @ 2014-04-18 14:08 UTC (permalink / raw)
  To: kexec; +Cc: horms, Cédric Le Goater

../kexec/arch/ppc64/crashdump-ppc64.c: In function ‘get_crash_memory_ranges’:
../kexec/arch/ppc64/crashdump-ppc64.c:186:6: warning: unused variable ‘i’ [-Wunused-variable]
  int i, n, crash_rng_len = 0;

Signed-off-by: Cédric Le Goater <clg@fr.ibm.com>
---
 kexec/arch/ppc64/crashdump-ppc64.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/kexec/arch/ppc64/crashdump-ppc64.c b/kexec/arch/ppc64/crashdump-ppc64.c
index 71a09dbff17f..a3b56697c8db 100644
--- a/kexec/arch/ppc64/crashdump-ppc64.c
+++ b/kexec/arch/ppc64/crashdump-ppc64.c
@@ -184,7 +184,7 @@ static int get_crash_memory_ranges(struct memory_range **range, int *ranges)
 	DIR *dir, *dmem;
 	FILE *file;
 	struct dirent *dentry, *mentry;
-	int i, n, crash_rng_len = 0;
+	int n, crash_rng_len = 0;
 	unsigned long long start, end;
 	int page_size;
 
-- 
1.7.10.4


_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec

^ permalink raw reply related	[flat|nested] 10+ messages in thread

* Re: [PATCH 3/7] ppc64: detect zImage files and load the uncompressed vmlinux
  2014-04-18 14:08 ` [PATCH 3/7] ppc64: detect zImage files and load the uncompressed vmlinux Cédric Le Goater
@ 2014-05-12  9:56   ` Laurent Dufour
  2014-05-12 15:58     ` Cedric Le Goater
  0 siblings, 1 reply; 10+ messages in thread
From: Laurent Dufour @ 2014-05-12  9:56 UTC (permalink / raw)
  To: Cédric Le Goater, kexec; +Cc: horms

On 18/04/2014 16:08, Cédric Le Goater wrote:
> The zImage* executable files on ppc64 use a special section called
> ".kernel:vmlinux.strip" which contains a compressed vmlinux executable
> file.
> 
> This patch adds a service to detect and unzip such a section in a
> malloc'ed buffer. The buffer is then used in elf_ppc64_load() to
> load the new vmlinux.
> 
> Signed-off-by: Cédric Le Goater <clg@fr.ibm.com>
> ---
>  kexec/arch/ppc64/kexec-elf-ppc64.c    |   15 ++++
>  kexec/arch/ppc64/kexec-ppc64.h        |    2 +
>  kexec/arch/ppc64/kexec-zImage-ppc64.c |  123 +++++++++++++++++++++++++++++++++
>  3 files changed, 140 insertions(+)
> 
> diff --git a/kexec/arch/ppc64/kexec-elf-ppc64.c b/kexec/arch/ppc64/kexec-elf-ppc64.c
> index ce1036762582..069d8ba6e690 100644
> --- a/kexec/arch/ppc64/kexec-elf-ppc64.c
> +++ b/kexec/arch/ppc64/kexec-elf-ppc64.c
> @@ -116,6 +116,8 @@ int elf_ppc64_load(int argc, char **argv, const char *buf, off_t len,
>  	uint64_t toc_addr;
>  	uint32_t my_run_at_load;
>  	unsigned int slave_code[256/sizeof (unsigned int)], master_entry;
> +	void *vmlinux_addr;
> +	int vmlinux_size;
>  
>  	/* See options.h -- add any more there, too. */
>  	static const struct option options[] = {
> @@ -184,6 +186,7 @@ int elf_ppc64_load(int argc, char **argv, const char *buf, off_t len,
>  		modified_cmdline_len = strlen(modified_cmdline);
>  	}
>  
> +retry:
>  	/* Parse the Elf file */
>  	result = build_elf_exec_info(buf, len, &ehdr, 0);
>  	if (result < 0) {
> @@ -191,6 +194,18 @@ int elf_ppc64_load(int argc, char **argv, const char *buf, off_t len,
>  		return result;
>  	}
>  
> +	/* If this is a zimage boot wrapper, rebuild the elf info on
> +	 * the new vmlinux which has been unzipped and go on with the
> +	 * kernel load.
> +	 */
> +	if (!zImage_ppc64_unzip(&ehdr, &vmlinux_addr, &vmlinux_size)) {
> +		free_elf_info(&ehdr);
> +		free((void *) buf);
> +		buf = vmlinux_addr;
> +		len = vmlinux_size;
> +		goto retry;
> +	}
> +
>  	/* Load the Elf data. Physical load addresses in elf64 header do not
>  	 * show up correctly. Use user supplied address for now to patch the
>  	 * elf header
> diff --git a/kexec/arch/ppc64/kexec-ppc64.h b/kexec/arch/ppc64/kexec-ppc64.h
> index 9a0aecff7b33..e546d4737bfa 100644
> --- a/kexec/arch/ppc64/kexec-ppc64.h
> +++ b/kexec/arch/ppc64/kexec-ppc64.h
> @@ -37,4 +37,6 @@ typedef struct mem_rgns {
>  
>  extern mem_rgns_t usablemem_rgns;
>  
> +int zImage_ppc64_unzip(struct mem_ehdr *ehdr, void **buf, int *len);
> +
>  #endif /* KEXEC_PPC64_H */
> diff --git a/kexec/arch/ppc64/kexec-zImage-ppc64.c b/kexec/arch/ppc64/kexec-zImage-ppc64.c
> index d084ee587be5..67d751f19d7d 100644
> --- a/kexec/arch/ppc64/kexec-zImage-ppc64.c
> +++ b/kexec/arch/ppc64/kexec-zImage-ppc64.c
> @@ -30,6 +30,9 @@
>  #include <getopt.h>
>  #include <linux/elf.h>
>  #include "../../kexec.h"
> +#include "kexec-ppc64.h"
> +
> +#include <zlib.h>
>  
>  #define MAX_HEADERS 32
>  
> @@ -175,3 +178,123 @@ void zImage_ppc64_usage(void)
>  {
>  	fprintf(stderr, "zImage support is still broken\n");
>  }
> +
> +#define HEAD_CRC	2
> +#define EXTRA_FIELD	4
> +#define ORIG_NAME	8
> +#define COMMENT		0x10
> +#define RESERVED	0xe0
> +
> +static int get_header_len(const char *header)
> +{
> +	int len = 10;
> +	int flags = header[3];
> +
> +	/* check for gzip header */
> +	if ((header[0] != 0x1f) || (header[1] != 0x8b) ||
> +	    (header[2] != Z_DEFLATED) || (flags & RESERVED) != 0) {
> +		fprintf(stderr, "bad gzip header\n");
> +		return -1;
> +	}
> +
> +	if ((flags & EXTRA_FIELD) != 0)
> +		len = 12 + header[10] + (header[11] << 8);
> +
> +	if ((flags & ORIG_NAME) != 0)
> +		while (header[len++] != 0)
> +				;
> +	if ((flags & COMMENT) != 0)
> +		while (header[len++] != 0)
> +			;
> +	if ((flags & HEAD_CRC) != 0)
> +		len += 2;
> +
> +	return len;
> +}
> +
> +static int gunzip(void *src, int srclen, void *dst, int dstlen)
> +{
> +	z_stream strm;
> +	int hdrlen;
> +	int len;
> +	int ret;
> +
> +	strm.zalloc = Z_NULL;
> +	strm.zfree = Z_NULL;
> +	strm.opaque = Z_NULL;
> +	strm.avail_in = 0;
> +	strm.next_in = Z_NULL;
> +
> +	hdrlen = get_header_len(src);
> +	if (hdrlen == -1)
> +		return -1;
> +
> +	if (hdrlen >= srclen) {
> +		fprintf(stderr, "gzip header too large : %d\n", hdrlen);
> +		return -1;
> +	}
> +
> +	ret = inflateInit2(&strm, -MAX_WBITS);
> +	if (ret != Z_OK) {
> +		fprintf(stderr, "inflateInit2 failed : %d\n", ret);
> +		return -1;
> +	}
> +
> +	/* skip gzip header */
> +	strm.total_in = hdrlen;
> +	strm.next_in = src + hdrlen;
> +	strm.avail_in = srclen - hdrlen;
> +
> +	strm.next_out = dst;
> +	strm.avail_out = dstlen;
> +
> +	ret = inflate(&strm, Z_FULL_FLUSH);
> +	if (ret != Z_OK && ret != Z_STREAM_END) {
> +		fprintf(stderr, "inflate failed: %d %s\n", ret, strm.msg);
> +		return -1;
> +	}
> +
> +	len = strm.next_out - (unsigned char *) dst;
> +
> +	inflateEnd(&strm);
> +
> +	return len;
> +}
> +
> +int zImage_ppc64_unzip(struct mem_ehdr *ehdr, void **buf, int *len)
> +{
> +	struct mem_shdr *shdr;
> +	void *vmlinuz_addr;
> +	unsigned long vmlinuz_size;
> +	unsigned int *vmlinux_sizep;
> +
> +	void *vmlinux_addr;
> +	int vmlinux_size;
> +
> +	shdr = elf_rel_find_section(ehdr, ".kernel:vmlinux.strip");
> +	if (!shdr)
> +		return -1;
> +
> +	vmlinuz_addr = (void *) shdr->sh_data;
> +	vmlinuz_size = shdr->sh_size;
> +
> +	 /* The size of the uncompressed file is stored in the last 4
> +	  * bytes. The vmlinux size should be less than 4G ... */
> +	vmlinux_sizep = (vmlinuz_addr + vmlinuz_size) - 4;
> +
> +	fprintf(stderr, "Found vmlinuz at %p, unzipping %d bytes\n",
> +		vmlinuz_addr, *vmlinux_sizep);

Hi Cédric,

I'd rather use dbgprintf instead of directly call fprintf here.

Laurent.

> +	vmlinux_addr = xmalloc(*vmlinux_sizep);
> +
> +	vmlinux_size = gunzip(vmlinuz_addr, vmlinuz_size,
> +			      vmlinux_addr, *vmlinux_sizep);
> +	if (vmlinux_size != *vmlinux_sizep) {
> +		fprintf(stderr, "gunzip failed : only got %d of %d bytes.\n",
> +				vmlinux_size, *vmlinux_sizep);
> +		return -1;
> +	}
> +
> +	*buf = vmlinux_addr;
> +	*len = vmlinux_size;
> +	return 0;
> +}
> 


_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH 3/7] ppc64: detect zImage files and load the uncompressed vmlinux
  2014-05-12  9:56   ` Laurent Dufour
@ 2014-05-12 15:58     ` Cedric Le Goater
  0 siblings, 0 replies; 10+ messages in thread
From: Cedric Le Goater @ 2014-05-12 15:58 UTC (permalink / raw)
  To: Laurent Dufour, kexec; +Cc: horms

Hi Laurent,

[ ... ]

>> +int zImage_ppc64_unzip(struct mem_ehdr *ehdr, void **buf, int *len)
>> +{
>> +	struct mem_shdr *shdr;
>> +	void *vmlinuz_addr;
>> +	unsigned long vmlinuz_size;
>> +	unsigned int *vmlinux_sizep;
>> +
>> +	void *vmlinux_addr;
>> +	int vmlinux_size;
>> +
>> +	shdr = elf_rel_find_section(ehdr, ".kernel:vmlinux.strip");
>> +	if (!shdr)
>> +		return -1;
>> +
>> +	vmlinuz_addr = (void *) shdr->sh_data;
>> +	vmlinuz_size = shdr->sh_size;
>> +
>> +	 /* The size of the uncompressed file is stored in the last 4
>> +	  * bytes. The vmlinux size should be less than 4G ... */
>> +	vmlinux_sizep = (vmlinuz_addr + vmlinuz_size) - 4;
>> +
>> +	fprintf(stderr, "Found vmlinuz at %p, unzipping %d bytes\n",
>> +		vmlinuz_addr, *vmlinux_sizep);
> 
> Hi Cédric,
> 
> I'd rather use dbgprintf instead of directly call fprintf here.

Sure. Thanks for the review. I have a new version of this patch which 
also fixes the way the uncompressed size is read, as it is stored as 
a little endian uint.

Simon, do you want a resend of the patchset or a fix on top of it ? 

Cheers, 

C.


_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec

^ permalink raw reply	[flat|nested] 10+ messages in thread

end of thread, other threads:[~2014-05-12 15:58 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2014-04-18 14:08 [PATCH 0/7] ppc64: little endian zImage support Cédric Le Goater
2014-04-18 14:08 ` [PATCH 1/7] kexec: add a elf_rel_find_section service Cédric Le Goater
2014-04-18 14:08 ` [PATCH 2/7] kexec: bypass check on interp program header for ppc64le zImage Cédric Le Goater
2014-04-18 14:08 ` [PATCH 3/7] ppc64: detect zImage files and load the uncompressed vmlinux Cédric Le Goater
2014-05-12  9:56   ` Laurent Dufour
2014-05-12 15:58     ` Cedric Le Goater
2014-04-18 14:08 ` [PATCH 4/7] ppc64, cleanup: cmdline_len variables are unused Cédric Le Goater
2014-04-18 14:08 ` [PATCH 5/7] ppc64, cleanup: remove dead code in kexec-zImage-ppc64 Cédric Le Goater
2014-04-18 14:08 ` [PATCH 6/7] ppc64, cleanup: fix implicit declaration compile warnings Cédric Le Goater
2014-04-18 14:08 ` [PATCH 7/7] ppc64, cleanup: fix unused variable compile warning Cédric Le Goater

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.