From patchwork Sat Dec 7 23:26:58 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Aaro Koskinen X-Patchwork-Id: 298735 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming@ozlabs.org Delivered-To: patchwork-incoming@ozlabs.org Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 934D92C00E3 for ; Sun, 8 Dec 2013 10:27:36 +1100 (EST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1754340Ab3LGX1d (ORCPT ); Sat, 7 Dec 2013 18:27:33 -0500 Received: from filtteri5.pp.htv.fi ([213.243.153.188]:55852 "EHLO filtteri5.pp.htv.fi" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1758780Ab3LGX12 (ORCPT ); Sat, 7 Dec 2013 18:27:28 -0500 Received: from localhost (localhost [127.0.0.1]) by filtteri5.pp.htv.fi (Postfix) with ESMTP id BF31F5A741E; Sun, 8 Dec 2013 01:27:25 +0200 (EET) X-Virus-Scanned: Debian amavisd-new at pp.htv.fi Received: from smtp4.welho.com ([213.243.153.38]) by localhost (filtteri5.pp.htv.fi [213.243.153.188]) (amavisd-new, port 10024) with ESMTP id d8sjqI2zp+2s; Sun, 8 Dec 2013 01:27:20 +0200 (EET) Received: from blackmetal.bb.dnainternet.fi (91-145-91-118.bb.dnainternet.fi [91.145.91.118]) by smtp4.welho.com (Postfix) with ESMTP id 1CD4E5BC01E; Sun, 8 Dec 2013 01:27:21 +0200 (EET) From: Aaro Koskinen To: sparclinux@vger.kernel.org Cc: Aaro Koskinen Subject: [PATCH 09/10] tilo: support ELF binaries Date: Sun, 8 Dec 2013 01:26:58 +0200 Message-Id: <1386458819-6590-10-git-send-email-aaro.koskinen@iki.fi> X-Mailer: git-send-email 1.8.4.4 In-Reply-To: <1386458819-6590-1-git-send-email-aaro.koskinen@iki.fi> References: <1386458819-6590-1-git-send-email-aaro.koskinen@iki.fi> Sender: sparclinux-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: sparclinux@vger.kernel.org Support booting ELF and normal a.out binaries, also retain compatiblity with the "raw" a.out prepared by tilo.sh. Signed-off-by: Aaro Koskinen --- tilo/tilo.c | 105 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 105 insertions(+) diff --git a/tilo/tilo.c b/tilo/tilo.c index dc626efc7b02..d2fcd97b525f 100644 --- a/tilo/tilo.c +++ b/tilo/tilo.c @@ -18,6 +18,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ +#include #include #include #ifndef NULL @@ -170,6 +171,108 @@ extern struct ImageInfo image_table[4]; /* Sun4 kernel, Sun4c/d/m kernel, Sun4u #define HDRS_TAG (('H'<<24) | ('d'<<16) | ('r'<<8) | 'S') +void parse_executable(char *base, int image_len) +{ + union { + char *b; + struct aout_hdr *a; + Elf32_Ehdr *e; + Elf64_Ehdr *f; + } hp; + unsigned off = 0; + int len = 0; + + /* + * Check if the image is an executable file, either an a.out or an elf + * binary. + */ + + hp.b = base; + if (hp.a->magic == 0x01030107) { + off = sizeof (struct aout_hdr); + if (image_len > hp.a->ltext + hp.a->ldata) + len = hp.a->ltext + hp.a->ldata; + else + len = image_len; + } else if (hp.e->e_ident[EI_MAG0] == ELFMAG0 && + hp.e->e_ident[EI_MAG1] == ELFMAG1 && + hp.e->e_ident[EI_MAG2] == ELFMAG2 && + hp.e->e_ident[EI_MAG3] == ELFMAG3) { + if (hp.e->e_ident[EI_DATA] != ELFDATA2MSB) { + printf("Image is not a MSB ELF.\n"); + prom_halt(); + } + if (hp.e->e_ident[EI_CLASS] == ELFCLASS32) { + Elf32_Phdr *p; + int i; + unsigned long n; + Elf32_Phdr *q; + + p = (Elf32_Phdr *) (hp.b + hp.e->e_phoff); + if (p->p_type != PT_LOAD) { + printf("Cannot find a loadable segment in your ELF image.\n"); + prom_halt(); + } + + q = p + 1; + for (i = 1; i < hp.e->e_phnum; i++, q++) { + if (q->p_type != PT_LOAD) + break; + n = q->p_offset - p->p_offset; + if (q->p_vaddr - p->p_vaddr == n && + q->p_paddr - p->p_paddr == n && + p->p_memsz == p->p_filesz && + p->p_memsz <= n) { + p->p_filesz = n + q->p_filesz; + p->p_memsz = n + q->p_memsz; + } else { + printf("Multiple loadable segments in your ELF image.\n"); + prom_halt(); + } + } + off = p->p_offset + hp.e->e_entry - p->p_vaddr; + len = p->p_filesz; + if (len > image_len) + len = image_len; + } else if (hp.e->e_ident[EI_CLASS] == ELFCLASS64) { + Elf64_Phdr *p; + unsigned long long n; + int i; + Elf64_Phdr *q; + + p = (Elf64_Phdr *) (hp.b + hp.f->e_phoff); + if (p->p_type != PT_LOAD) { + printf("Cannot find a loadable segment in your ELF image.\n"); + prom_halt(); + } + q = p + 1; + for (i = 1; i < hp.f->e_phnum; i++, q++) { + if (q->p_type != PT_LOAD) + break; + n = q->p_offset - p->p_offset; + if (q->p_vaddr - p->p_vaddr == n && + q->p_paddr - p->p_paddr == n && + p->p_memsz == p->p_filesz && + p->p_memsz <= n) { + p->p_filesz = n + q->p_filesz; + p->p_memsz = n + q->p_memsz; + } else { + printf("Multiple loadable segments in your ELF image.\n"); + prom_halt(); + } + } + off = p->p_offset + hp.f->e_entry - p->p_vaddr; + len = p->p_filesz; + if (len > image_len) + len = image_len; + } + } else { + /* Assume "raw" a.out format prepared by tilo.sh. */ + return; + } + memmove(base, base + off, len); +} + char *my_main (struct linux_romvec *promvec, void *cifh, void *cifs) { char *orig_code,*moved_code,*moved_ramdisk,*moved_kernel,*kernel_base; @@ -231,6 +334,8 @@ char *kernel_end, *kernel_limit; prom_halt(); } + parse_executable(kernel_base, kernel_end - kernel_base); + switch (kernel_number) { case SUN4U_KERNEL: