From 4366e1db16a3ec7bf24171e5c7619c8ea038e43b Mon Sep 17 00:00:00 2001 From: Liam Merwick Date: Tue, 15 Jan 2019 12:18:03 +0000 Subject: elf: Add optional function ptr to load_elf() to parse ELF notes This patch adds an optional function pointer, 'elf_note_fn', to load_elf() which causes load_elf() to additionally parse any ELF program headers of type PT_NOTE and check to see if the ELF Note is of the type specified by the 'translate_opaque' arg. If a matching ELF Note is found then the specfied function pointer is called to process the ELF note. Passing a NULL function pointer results in ELF Notes being skipped. The first consumer of this functionality is the PVHboot support which needs to read the XEN_ELFNOTE_PHYS32_ENTRY ELF Note while loading the uncompressed kernel binary in order to discover the boot entry address for the x86/HVM direct boot ABI. Signed-off-by: Liam Merwick Signed-off-by: Paolo Bonzini --- hw/core/loader.c | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) (limited to 'hw/core/loader.c') diff --git a/hw/core/loader.c b/hw/core/loader.c index c4f62fe427..3a000d576b 100644 --- a/hw/core/loader.c +++ b/hw/core/loader.c @@ -396,37 +396,42 @@ fail: } /* 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), +int load_elf(const char *filename, + uint64_t (*elf_note_fn)(void *, void *, bool), + 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) { - return load_elf_as(filename, translate_fn, translate_opaque, pentry, - lowaddr, highaddr, big_endian, elf_machine, clear_lsb, - data_swab, NULL); + return load_elf_as(filename, elf_note_fn, translate_fn, translate_opaque, + pentry, lowaddr, highaddr, big_endian, elf_machine, + clear_lsb, data_swab, NULL); } /* return < 0 if error, otherwise the number of bytes loaded in memory */ int load_elf_as(const char *filename, + uint64_t (*elf_note_fn)(void *, void *, bool), 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) { - return load_elf_ram(filename, translate_fn, translate_opaque, + return load_elf_ram(filename, elf_note_fn, 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 (*elf_note_fn)(void *, void *, bool), 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) { - return load_elf_ram_sym(filename, translate_fn, translate_opaque, + return load_elf_ram_sym(filename, elf_note_fn, + translate_fn, translate_opaque, pentry, lowaddr, highaddr, big_endian, elf_machine, clear_lsb, data_swab, as, load_rom, NULL); @@ -434,6 +439,7 @@ int load_elf_ram(const char *filename, /* return < 0 if error, otherwise the number of bytes loaded in memory */ int load_elf_ram_sym(const char *filename, + uint64_t (*elf_note_fn)(void *, void *, bool), uint64_t (*translate_fn)(void *, uint64_t), void *translate_opaque, uint64_t *pentry, uint64_t *lowaddr, uint64_t *highaddr, int big_endian, @@ -476,11 +482,13 @@ int load_elf_ram_sym(const char *filename, lseek(fd, 0, SEEK_SET); if (e_ident[EI_CLASS] == ELFCLASS64) { - ret = load_elf64(filename, fd, translate_fn, translate_opaque, must_swab, + ret = load_elf64(filename, fd, elf_note_fn, + translate_fn, translate_opaque, must_swab, pentry, lowaddr, highaddr, elf_machine, clear_lsb, data_swab, as, load_rom, sym_cb); } else { - ret = load_elf32(filename, fd, translate_fn, translate_opaque, must_swab, + ret = load_elf32(filename, fd, elf_note_fn, + translate_fn, translate_opaque, must_swab, pentry, lowaddr, highaddr, elf_machine, clear_lsb, data_swab, as, load_rom, sym_cb); } -- cgit 1.4.1 From 1f40547f5ce0c135faa7d14f066b97002fd8c204 Mon Sep 17 00:00:00 2001 From: Li Zhijian Date: Thu, 17 Jan 2019 20:49:02 +0800 Subject: hw/core/loader.c: Read as long as possible in load_image_size() Don't expect read(2) can always read as many as it's told. CC: Richard Henderson CC: Stefano Garzarella Signed-off-by: Li Zhijian Reviewed-by: Richard Henderson Reviewed-by: Stefano Garzarella Signed-off-by: Paolo Bonzini --- hw/core/loader.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) (limited to 'hw/core/loader.c') diff --git a/hw/core/loader.c b/hw/core/loader.c index 3a000d576b..fe5cb24122 100644 --- a/hw/core/loader.c +++ b/hw/core/loader.c @@ -77,21 +77,20 @@ int64_t get_image_size(const char *filename) ssize_t load_image_size(const char *filename, void *addr, size_t size) { int fd; - ssize_t actsize; + ssize_t actsize, l = 0; fd = open(filename, O_RDONLY | O_BINARY); if (fd < 0) { return -1; } - actsize = read(fd, addr, size); - if (actsize < 0) { - close(fd); - return -1; + while ((actsize = read(fd, addr + l, size - l)) > 0) { + l += actsize; } + close(fd); - return actsize; + return actsize < 0 ? -1 : l; } /* read()-like version */ -- cgit 1.4.1