summaryrefslogtreecommitdiffstats
path: root/sys/boot/common
diff options
context:
space:
mode:
authorpeter <peter@FreeBSD.org>1998-10-16 03:04:15 +0000
committerpeter <peter@FreeBSD.org>1998-10-16 03:04:15 +0000
commita8354e7057ecc1506a7ee2d57e04b8e3b63bc8e0 (patch)
treead069f71dd229b63d256bd22730d0c8884501fd1 /sys/boot/common
parentd7cc2cb36c77a91d19922907e0bbb6941b4821a2 (diff)
downloadFreeBSD-src-a8354e7057ecc1506a7ee2d57e04b8e3b63bc8e0.zip
FreeBSD-src-a8354e7057ecc1506a7ee2d57e04b8e3b63bc8e0.tar.gz
"fix" the gzipped kernel load problem by having the loader check that it
can seek back to the first PT_LOAD and doing a close/reopen if it cannot. This is because the first PT_LOAD section includes the ELF headers. This fixes gzipped kernels on the i386, it should solve mike's problem for the Alpha.
Diffstat (limited to 'sys/boot/common')
-rw-r--r--sys/boot/common/load_elf.c55
1 files changed, 33 insertions, 22 deletions
diff --git a/sys/boot/common/load_elf.c b/sys/boot/common/load_elf.c
index e29996b..b2b38c7 100644
--- a/sys/boot/common/load_elf.c
+++ b/sys/boot/common/load_elf.c
@@ -24,7 +24,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: load_elf.c,v 1.6 1998/10/14 00:41:17 peter Exp $
+ * $Id: load_elf.c,v 1.7 1998/10/15 21:56:47 dfr Exp $
*/
#include <sys/param.h>
@@ -40,7 +40,7 @@
#include "bootstrap.h"
-static int elf_loadimage(struct loaded_module *mp, int fd, vm_offset_t loadaddr, Elf_Ehdr *ehdr, int kernel);
+static int elf_loadimage(struct loaded_module *mp, int fd, vm_offset_t loadaddr, Elf_Ehdr *ehdr, Elf_Phdr *phdr, int kernel);
char *elf_kerneltype = "elf kernel";
char *elf_moduletype = "elf module";
@@ -55,12 +55,14 @@ elf_loadmodule(char *filename, vm_offset_t dest, struct loaded_module **result)
{
struct loaded_module *mp, *kmp;
Elf_Ehdr ehdr;
+ Elf_Phdr *phdr;
int fd;
int err, kernel;
u_int pad;
char *s;
mp = NULL;
+ phdr = NULL;
/*
* Open the image, read and validate the ELF header
@@ -162,7 +164,31 @@ elf_loadmodule(char *filename, vm_offset_t dest, struct loaded_module **result)
printf("%s ", filename);
#endif
- mp->m_size = elf_loadimage(mp, fd, dest, &ehdr, kernel);
+ phdr = malloc(ehdr.e_phnum * sizeof(*phdr));
+ if (phdr == NULL) {
+ err = ENOMEM;
+ goto out;
+ }
+
+ if (lseek(fd, ehdr.e_phoff, SEEK_SET) == -1) {
+ printf("elf_loadexec: lseek for phdr failed\n");
+ goto ioerr;
+ }
+ if (read(fd, phdr, ehdr.e_phnum * sizeof(*phdr)) !=
+ ehdr.e_phnum * sizeof(*phdr)) {
+ printf("elf_loadmodule: cannot read program header\n");
+ goto ioerr;
+ }
+ if (lseek(fd, 0, SEEK_SET) == -1) {
+ close(fd);
+ if ((fd = open(filename, O_RDONLY)) == -1) {
+ printf("elf_loadmodule: cannot reset file position\n");
+ mod_discard(mp);
+ return errno;
+ }
+ }
+
+ mp->m_size = elf_loadimage(mp, fd, dest, &ehdr, phdr, kernel);
if (mp->m_size == 0 || mp->m_addr == 0)
goto ioerr;
@@ -179,6 +205,8 @@ elf_loadmodule(char *filename, vm_offset_t dest, struct loaded_module **result)
oerr:
mod_discard(mp);
out:
+ if (phdr)
+ free(phdr);
close(fd);
return(err);
}
@@ -189,10 +217,9 @@ elf_loadmodule(char *filename, vm_offset_t dest, struct loaded_module **result)
*/
static int
elf_loadimage(struct loaded_module *mp, int fd, vm_offset_t off,
- Elf_Ehdr *ehdr, int kernel)
+ Elf_Ehdr *ehdr, Elf_Phdr *phdr, int kernel)
{
int i, j;
- Elf_Phdr *phdr;
Elf_Shdr *shdr;
int ret;
vm_offset_t firstaddr;
@@ -225,20 +252,6 @@ elf_loadimage(struct loaded_module *mp, int fd, vm_offset_t off,
#endif
}
- phdr = malloc(ehdr->e_phnum * sizeof(*phdr));
- if (phdr == NULL)
- goto out;
-
- if (lseek(fd, ehdr->e_phoff, SEEK_SET) == -1) {
- printf("elf_loadexec: lseek for phdr failed\n");
- goto out;
- }
- if (read(fd, phdr, ehdr->e_phnum * sizeof(*phdr)) !=
- ehdr->e_phnum * sizeof(*phdr)) {
- printf("elf_loadexec: cannot read program header\n");
- goto out;
- }
-
for (i = 0; i < ehdr->e_phnum; i++) {
/* We want to load PT_LOAD segments only.. */
if (phdr[i].p_type != PT_LOAD)
@@ -379,7 +392,7 @@ elf_loadimage(struct loaded_module *mp, int fd, vm_offset_t off,
#else
if (i == symstrindex)
printf("+");
- printf("0x%lx+0x%lx", sizeof(size), size);
+ printf("0x%lx+0x%lx", (long)sizeof(size), size);
#endif
if (lseek(fd, shdr[i].sh_offset, SEEK_SET) == -1) {
@@ -503,7 +516,5 @@ out:
free(dp);
if (shdr)
free(shdr);
- if (phdr)
- free(phdr);
return ret;
}
OpenPOWER on IntegriCloud