Skip to content

Commit

Permalink
elf-loader: Allow late loading of elf
Browse files Browse the repository at this point in the history
The current QEMU ROM infrastructure rejects late loading of ROMs.
And ELFs are currently loaded as ROM, this prevents delayed loading
of ELFs. So when loading ELF, allow the user to specify if ELF should
be loaded as ROM or not.

If an ELF is not loaded as ROM, then they are not restored on a
guest reboot/reset and so its upto the user to handle the reloading.

Signed-off-by: Farhan Ali <alifm@linux.vnet.ibm.com>
Reviewed-by: Christian Borntraeger <borntraeger@de.ibm.com>
Cc: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Cornelia Huck <cornelia.huck@de.ibm.com>
  • Loading branch information
Farhan Ali authored and cohuck committed Feb 28, 2017
1 parent 6181478 commit 34f1b23
Show file tree
Hide file tree
Showing 3 changed files with 36 additions and 7 deletions.
17 changes: 15 additions & 2 deletions hw/core/loader.c
Expand Up @@ -434,6 +434,19 @@ int load_elf_as(const char *filename,
void *translate_opaque, uint64_t *pentry, uint64_t *lowaddr,
uint64_t *highaddr, int big_endian, int elf_machine,
int clear_lsb, int data_swab, AddressSpace *as)
{
return load_elf_ram(filename, translate_fn, translate_opaque,
pentry, lowaddr, highaddr, big_endian, elf_machine,
clear_lsb, data_swab, as, true);
}

/* return < 0 if error, otherwise the number of bytes loaded in memory */
int load_elf_ram(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 data_swab, AddressSpace *as,
bool load_rom)
{
int fd, data_order, target_data_order, must_swab, ret = ELF_LOAD_FAILED;
uint8_t e_ident[EI_NIDENT];
Expand Down Expand Up @@ -473,11 +486,11 @@ int load_elf_as(const char *filename,
if (e_ident[EI_CLASS] == ELFCLASS64) {
ret = load_elf64(filename, fd, translate_fn, translate_opaque, must_swab,
pentry, lowaddr, highaddr, elf_machine, clear_lsb,
data_swab, as);
data_swab, as, load_rom);
} else {
ret = load_elf32(filename, fd, translate_fn, translate_opaque, must_swab,
pentry, lowaddr, highaddr, elf_machine, clear_lsb,
data_swab, as);
data_swab, as, load_rom);
}

fail:
Expand Down
13 changes: 9 additions & 4 deletions include/hw/elf_ops.h
Expand Up @@ -264,7 +264,7 @@ static int glue(load_elf, SZ)(const char *name, int fd,
int must_swab, uint64_t *pentry,
uint64_t *lowaddr, uint64_t *highaddr,
int elf_machine, int clear_lsb, int data_swab,
AddressSpace *as)
AddressSpace *as, bool load_rom)
{
struct elfhdr ehdr;
struct elf_phdr *phdr = NULL, *ph;
Expand Down Expand Up @@ -403,10 +403,15 @@ static int glue(load_elf, SZ)(const char *name, int fd,
*pentry = ehdr.e_entry - ph->p_vaddr + ph->p_paddr;
}

snprintf(label, sizeof(label), "phdr #%d: %s", i, name);
if (load_rom) {
snprintf(label, sizeof(label), "phdr #%d: %s", i, name);

/* rom_add_elf_program() seize the ownership of 'data' */
rom_add_elf_program(label, data, file_size, mem_size, addr, as);
/* rom_add_elf_program() seize the ownership of 'data' */
rom_add_elf_program(label, data, file_size, mem_size, addr, as);
} else {
cpu_physical_memory_write(addr, data, file_size);
g_free(data);
}

total_size += mem_size;
if (addr < low)
Expand Down
13 changes: 12 additions & 1 deletion include/hw/loader.h
Expand Up @@ -65,7 +65,7 @@ int load_image_gzipped(const char *filename, hwaddr addr, uint64_t max_sz);
#define ELF_LOAD_WRONG_ENDIAN -4
const char *load_elf_strerror(int error);

/** load_elf_as:
/** load_elf_ram:
* @filename: Path of ELF file
* @translate_fn: optional function to translate load addresses
* @translate_opaque: opaque data passed to @translate_fn
Expand All @@ -81,6 +81,7 @@ const char *load_elf_strerror(int error);
* words and 3 for within doublewords.
* @as: The AddressSpace to load the ELF to. The value of address_space_memory
* is used if nothing is supplied here.
* @load_rom : Load ELF binary as ROM
*
* Load an ELF file's contents to the emulated system's address space.
* Clients may optionally specify a callback to perform address
Expand All @@ -93,6 +94,16 @@ const char *load_elf_strerror(int error);
* If @elf_machine is EM_NONE then the machine type will be read from the
* ELF header and no checks will be carried out against the machine type.
*/
int load_elf_ram(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 data_swab, AddressSpace *as,
bool load_rom);

/** load_elf_as:
* Same as load_elf_ram(), but always loads the elf as ROM
*/
int load_elf_as(const char *filename,
uint64_t (*translate_fn)(void *, uint64_t),
void *translate_opaque, uint64_t *pentry, uint64_t *lowaddr,
Expand Down

0 comments on commit 34f1b23

Please sign in to comment.