From: Laurent Dufour <ldufour@linux.vnet.ibm.com>
To: "Cédric Le Goater" <clg@fr.ibm.com>, kexec@lists.infradead.org
Cc: horms@verge.net.au
Subject: Re: [PATCH 3/7] ppc64: detect zImage files and load the uncompressed vmlinux
Date: Mon, 12 May 2014 11:56:15 +0200 [thread overview]
Message-ID: <53709ABF.8060707@linux.vnet.ibm.com> (raw)
In-Reply-To: <1397830120-13323-4-git-send-email-clg@fr.ibm.com>
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
next prev parent reply other threads:[~2014-05-12 9:56 UTC|newest]
Thread overview: 10+ messages / expand[flat|nested] mbox.gz Atom feed top
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 [this message]
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
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=53709ABF.8060707@linux.vnet.ibm.com \
--to=ldufour@linux.vnet.ibm.com \
--cc=clg@fr.ibm.com \
--cc=horms@verge.net.au \
--cc=kexec@lists.infradead.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
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.