[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-ppc] [PULL 076/130] elf-loader: add more return codes
From: |
Alexander Graf |
Subject: |
[Qemu-ppc] [PULL 076/130] elf-loader: add more return codes |
Date: |
Fri, 7 Mar 2014 00:33:23 +0100 |
From: Alexey Kardashevskiy <address@hidden>
The existing load_elf() just returns -1 if it fails to load ELF. However
it could be smarter than this and tell more about the failure such as
wrong endianness or incompatible platform.
This adds additional return codes for wrong architecture, wrong
endianness and if the image is not ELF at all.
This adds a load_elf_strerror() helper to convert return codes into
string messages.
This fixes handling of what load_elf() returns for s390x, other
callers just check the return value for <0 and this remains unchanged.
Signed-off-by: Alexey Kardashevskiy <address@hidden>
Signed-off-by: Alexander Graf <address@hidden>
---
hw/core/loader.c | 30 ++++++++++++++++++++++++------
hw/s390x/ipl.c | 4 ++--
include/hw/elf_ops.h | 19 ++++++++++++++-----
include/hw/loader.h | 6 ++++++
4 files changed, 46 insertions(+), 13 deletions(-)
diff --git a/hw/core/loader.c b/hw/core/loader.c
index e1c3f3a..b323c0c 100644
--- a/hw/core/loader.c
+++ b/hw/core/loader.c
@@ -284,12 +284,30 @@ static void *load_at(int fd, int offset, int size)
#define SZ 64
#include "hw/elf_ops.h"
+const char *load_elf_strerror(int error)
+{
+ switch (error) {
+ case 0:
+ return "No error";
+ case ELF_LOAD_FAILED:
+ return "Failed to load ELF";
+ case ELF_LOAD_NOT_ELF:
+ return "The image is not ELF";
+ case ELF_LOAD_WRONG_ARCH:
+ return "The image is from incompatible architecture";
+ case ELF_LOAD_WRONG_ENDIAN:
+ return "The image has incorrect endianness";
+ default:
+ return "Unknown error";
+ }
+}
+
/* return < 0 if error, otherwise the number of bytes loaded in memory */
int load_elf(const char *filename, uint64_t (*translate_fn)(void *, uint64_t),
void *translate_opaque, uint64_t *pentry, uint64_t *lowaddr,
uint64_t *highaddr, int big_endian, int elf_machine, int
clear_lsb)
{
- int fd, data_order, target_data_order, must_swab, ret;
+ int fd, data_order, target_data_order, must_swab, ret = ELF_LOAD_FAILED;
uint8_t e_ident[EI_NIDENT];
fd = open(filename, O_RDONLY | O_BINARY);
@@ -302,8 +320,10 @@ int load_elf(const char *filename, uint64_t
(*translate_fn)(void *, uint64_t),
if (e_ident[0] != ELFMAG0 ||
e_ident[1] != ELFMAG1 ||
e_ident[2] != ELFMAG2 ||
- e_ident[3] != ELFMAG3)
+ e_ident[3] != ELFMAG3) {
+ ret = ELF_LOAD_NOT_ELF;
goto fail;
+ }
#ifdef HOST_WORDS_BIGENDIAN
data_order = ELFDATA2MSB;
#else
@@ -317,6 +337,7 @@ int load_elf(const char *filename, uint64_t
(*translate_fn)(void *, uint64_t),
}
if (target_data_order != e_ident[EI_DATA]) {
+ ret = ELF_LOAD_WRONG_ENDIAN;
goto fail;
}
@@ -329,12 +350,9 @@ int load_elf(const char *filename, uint64_t
(*translate_fn)(void *, uint64_t),
pentry, lowaddr, highaddr, elf_machine, clear_lsb);
}
- close(fd);
- return ret;
-
fail:
close(fd);
- return -1;
+ return ret;
}
static void bswap_uboot_header(uboot_image_header_t *hdr)
diff --git a/hw/s390x/ipl.c b/hw/s390x/ipl.c
index 04fb1a8..32d38a0 100644
--- a/hw/s390x/ipl.c
+++ b/hw/s390x/ipl.c
@@ -98,10 +98,10 @@ static int s390_ipl_init(SysBusDevice *dev)
uint64_t pentry = KERN_IMAGE_START;
kernel_size = load_elf(ipl->kernel, NULL, NULL, &pentry, NULL,
NULL, 1, ELF_MACHINE, 0);
- if (kernel_size == -1) {
+ if (kernel_size < 0) {
kernel_size = load_image_targphys(ipl->kernel, 0, ram_size);
}
- if (kernel_size == -1) {
+ if (kernel_size < 0) {
fprintf(stderr, "could not load kernel '%s'\n", ipl->kernel);
return -1;
}
diff --git a/include/hw/elf_ops.h b/include/hw/elf_ops.h
index acc701e..c6b5129 100644
--- a/include/hw/elf_ops.h
+++ b/include/hw/elf_ops.h
@@ -201,6 +201,7 @@ static int glue(load_elf, SZ)(const char *name, int fd,
uint64_t addr, low = (uint64_t)-1, high = 0;
uint8_t *data = NULL;
char label[128];
+ int ret = ELF_LOAD_FAILED;
if (read(fd, &ehdr, sizeof(ehdr)) != sizeof(ehdr))
goto fail;
@@ -211,22 +212,30 @@ static int glue(load_elf, SZ)(const char *name, int fd,
switch (elf_machine) {
case EM_PPC64:
if (EM_PPC64 != ehdr.e_machine)
- if (EM_PPC != ehdr.e_machine)
+ if (EM_PPC != ehdr.e_machine) {
+ ret = ELF_LOAD_WRONG_ARCH;
goto fail;
+ }
break;
case EM_X86_64:
if (EM_X86_64 != ehdr.e_machine)
- if (EM_386 != ehdr.e_machine)
+ if (EM_386 != ehdr.e_machine) {
+ ret = ELF_LOAD_WRONG_ARCH;
goto fail;
+ }
break;
case EM_MICROBLAZE:
if (EM_MICROBLAZE != ehdr.e_machine)
- if (EM_MICROBLAZE_OLD != ehdr.e_machine)
+ if (EM_MICROBLAZE_OLD != ehdr.e_machine) {
+ ret = ELF_LOAD_WRONG_ARCH;
goto fail;
+ }
break;
default:
- if (elf_machine != ehdr.e_machine)
+ if (elf_machine != ehdr.e_machine) {
+ ret = ELF_LOAD_WRONG_ARCH;
goto fail;
+ }
}
if (pentry)
@@ -305,5 +314,5 @@ static int glue(load_elf, SZ)(const char *name, int fd,
fail:
g_free(data);
g_free(phdr);
- return -1;
+ return ret;
}
diff --git a/include/hw/loader.h b/include/hw/loader.h
index 91b0122..aaf08c3 100644
--- a/include/hw/loader.h
+++ b/include/hw/loader.h
@@ -15,6 +15,12 @@ int get_image_size(const char *filename);
int load_image(const char *filename, uint8_t *addr); /* deprecated */
int load_image_targphys(const char *filename, hwaddr,
uint64_t max_sz);
+
+#define ELF_LOAD_FAILED -1
+#define ELF_LOAD_NOT_ELF -2
+#define ELF_LOAD_WRONG_ARCH -3
+#define ELF_LOAD_WRONG_ENDIAN -4
+const char *load_elf_strerror(int error);
int load_elf(const char *filename, uint64_t (*translate_fn)(void *, uint64_t),
void *translate_opaque, uint64_t *pentry, uint64_t *lowaddr,
uint64_t *highaddr, int big_endian, int elf_machine,
--
1.8.1.4
- [Qemu-ppc] [PULL 065/130] target-ppc: Add Flag for Power ISA V2.06 Floating Point Test Instructions, (continued)
- [Qemu-ppc] [PULL 065/130] target-ppc: Add Flag for Power ISA V2.06 Floating Point Test Instructions, Alexander Graf, 2014/03/06
- [Qemu-ppc] [PULL 062/130] target-ppc: Add ISA2.06 Float to Integer Instructions, Alexander Graf, 2014/03/06
- [Qemu-ppc] [PULL 074/130] spapr: support only ELF kernel images, Alexander Graf, 2014/03/06
- [Qemu-ppc] [PULL 066/130] target-ppc: Add ISA 2.06 ftdiv Instruction, Alexander Graf, 2014/03/06
- [Qemu-ppc] [PULL 063/130] target-ppc: Add ISA 2.06 fcfid[u][s] Instructions, Alexander Graf, 2014/03/06
- [Qemu-ppc] [PULL 072/130] PPC: KVM: suppress warnings about not supported SPRs, Alexander Graf, 2014/03/06
- [Qemu-ppc] [PULL 059/130] target-ppc: Add ISA2.06 lbarx, lharx Instructions, Alexander Graf, 2014/03/06
- [Qemu-ppc] [PULL 064/130] target-ppc: Fix and enable fri[mnpz], Alexander Graf, 2014/03/06
- [Qemu-ppc] [PULL 077/130] spapr: print more detailed error message on failed load_elf(), Alexander Graf, 2014/03/06
- [Qemu-ppc] [PULL 080/130] target-ppc: add extended opcodes for dcbt/dcbtst, Alexander Graf, 2014/03/06
- [Qemu-ppc] [PULL 076/130] elf-loader: add more return codes,
Alexander Graf <=
- [Qemu-ppc] [PULL 075/130] moxie: fix load_elf() usage, Alexander Graf, 2014/03/06
- [Qemu-ppc] [PULL 078/130] target-ppc: Update external_htab even when HTAB is managed by kernel, Alexander Graf, 2014/03/06
- [Qemu-ppc] [PULL 082/130] target-ppc: Add Flag for bctar, Alexander Graf, 2014/03/06
- [Qemu-ppc] [PULL 083/130] target-ppc: Add Target Address SPR (TAR) to Power8, Alexander Graf, 2014/03/06
- [Qemu-ppc] [PULL 081/130] target-ppc: Fix xxpermdi When T==A or T==B, Alexander Graf, 2014/03/06
- [Qemu-ppc] [PULL 084/130] target-ppc: Add bctar Instruction, Alexander Graf, 2014/03/06
- [Qemu-ppc] [PULL 086/130] target-ppc: Add is_user_mode Utility Routine, Alexander Graf, 2014/03/06
- [Qemu-ppc] [PULL 079/130] qdev: Keep global allocation counter per bus, Alexander Graf, 2014/03/06
- [Qemu-ppc] [PULL 085/130] target-ppc: Add Flag for ISA 2.07 Load/Store Quadword Instructions, Alexander Graf, 2014/03/06
- [Qemu-ppc] [PULL 087/130] target-ppc: Load Quadword, Alexander Graf, 2014/03/06