From patchwork Tue Jan 27 17:59:24 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Nathan Whitehorn X-Patchwork-Id: 433592 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.ozlabs.org (lists.ozlabs.org [IPv6:2401:3900:2:1::3]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id E99BB140276 for ; Wed, 28 Jan 2015 04:59:37 +1100 (AEDT) Received: from ozlabs.org (ozlabs.org [103.22.144.67]) by lists.ozlabs.org (Postfix) with ESMTP id D78281A0627 for ; Wed, 28 Jan 2015 04:59:37 +1100 (AEDT) X-Original-To: skiboot@lists.ozlabs.org Delivered-To: skiboot@lists.ozlabs.org Received: from d.mail.sonic.net (d.mail.sonic.net [64.142.111.50]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by lists.ozlabs.org (Postfix) with ESMTPS id EE4961A051F for ; Wed, 28 Jan 2015 04:59:34 +1100 (AEDT) Received: from comporellon.tachypleus.net (polaris.tachypleus.net [75.101.50.44]) (authenticated bits=0) by d.mail.sonic.net (8.15.1/8.14.9) with ESMTPSA id t0RHxO3X011891 (version=TLSv1.2 cipher=DHE-RSA-AES256-SHA bits=256 verify=NOT); Tue, 27 Jan 2015 09:59:25 -0800 Message-ID: <54C7D1FC.6090902@freebsd.org> Date: Tue, 27 Jan 2015 09:59:24 -0800 From: Nathan Whitehorn User-Agent: Mozilla/5.0 (X11; FreeBSD amd64; rv:31.0) Gecko/20100101 Thunderbird/31.4.0 MIME-Version: 1.0 To: Benjamin Herrenschmidt References: <54BFD7A5.5080603@freebsd.org> <1421946125.4949.72.camel@kernel.crashing.org> In-Reply-To: <1421946125.4949.72.camel@kernel.crashing.org> X-Sonic-CAuth: UmFuZG9tSVa4UiEa9SnXDGpoE4J67ocoGUbBnBTp0bE+wFMbHzsxa28ZkHLqXy2HPrFOABNaJOwrLLtCTdKPnN9x6QIaBiVaHzxXvphG6FE= X-Sonic-ID: C;RkZUOk6m5BG6MZCx7jkJAQ== M;YnfjOk6m5BG6MZCx7jkJAQ== X-Spam-Flag: No X-Sonic-Spam-Details: 0.0/5.0 by cerberusd Cc: skiboot list Subject: Re: [Skiboot] [PATCH] Load ELF64 binaries correctly X-BeenThere: skiboot@lists.ozlabs.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: Mailing list for skiboot development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: skiboot-bounces+incoming=patchwork.ozlabs.org@lists.ozlabs.org Sender: "Skiboot" On 01/22/15 09:02, Benjamin Herrenschmidt wrote: > On Wed, 2015-01-21 at 08:45 -0800, Nathan Whitehorn wrote: >> The attached patch fixes the big-endian ELF64 loader in skiboot to >> handle the fact that the ELF entry point is specified to point to a >> function descriptor describing the entry point rather than the entry >> point itself. (I haven't set it up to load the TOC base pointer though) >> This is required to load the FreeBSD kernel as a skiboot payload. The >> patch does not touch the little-endian loader since I'm not sure if the >> ELFv2 spec still has function descriptors or not. > An additional problem is that the Linux 64-bit BE kernel vmlinux doesn't > have a correct function descriptor as an entry point :-( So that patch > breaks loading a raw BE vmlinux... We probably need a quirk to recognize > such an image, possibly via the fact that the value that would be in the > function descriptor cannot possibly be a valid entry point as part of > the image. Here's a second version of the patch that can load both Linux and FreeBSD. It iterates through the ELF section table and, if the entry point points to an executable section, treats the entry point as the first instruction to run. Otherwise, it treats it as a function descriptor. -Nathan > > As for LE, there are no descriptors. > > Cheers, > Ben. > >> -Nathan >> _______________________________________________ >> Skiboot mailing list >> Skiboot@lists.ozlabs.org >> https://lists.ozlabs.org/listinfo/skiboot > diff --git a/core/init.c b/core/init.c index 2c7e30c..e75b5a3 100644 --- a/core/init.c +++ b/core/init.c @@ -111,6 +111,7 @@ static bool try_load_elf64(struct elf_hdr *header) struct elf64_hdr *kh = (struct elf64_hdr *)header; uint64_t load_base = (uint64_t)kh; struct elf64_phdr *ph; + struct elf64_shdr *sh; unsigned int i; /* Check it's a ppc64 LE ELF */ @@ -152,6 +153,27 @@ static bool try_load_elf64(struct elf_hdr *header) prerror("INIT: Failed to find kernel entry !\n"); return false; } + + /* For the normal big-endian ELF ABI, the kernel entry points + * to a function descriptor in the data section. Linux instead + * has it point directly to code. Test whether it is pointing + * into an executable section or not to figure this out. Default + * to assuming it obeys the ABI. + */ + sh = (struct elf64_shdr *)(load_base + kh->e_shoff); + for (i = 0; i < kh->e_shnum; i++, sh++) { + if (sh->sh_addr > kh->e_entry || + (sh->sh_addr + sh->sh_size) <= kh->e_entry) + continue; + + break; + } + + if (i == kh->e_shnum || !(sh->sh_flags & ELF_SFLAGS_X)) { + kernel_entry = *(uint64_t *)(kernel_entry + load_base); + kernel_entry = kernel_entry - ph->p_vaddr + ph->p_offset; + } + kernel_entry += load_base; kernel_32bit = false;