Commit decd8ce0 authored by Mike Hibler's avatar Mike Hibler
Browse files

Avoid re-opening the kernel file just to re-read the ELF header.

Another gratuitous seek avoidance measure.
parent 13d46535
......@@ -17,6 +17,7 @@
*/
#include <grub/loader.h>
#include <grub/elfload.h>
#include <grub/i386/bsd.h>
#include <grub/i386/cpuid.h>
#include <grub/memory.h>
......@@ -25,7 +26,6 @@
#include <grub/err.h>
#include <grub/dl.h>
#include <grub/mm.h>
#include <grub/elfload.h>
#include <grub/env.h>
#include <grub/misc.h>
#include <grub/aout.h>
......@@ -1577,7 +1577,7 @@ grub_bsd_load_elf (grub_elf_t elf, const char *filename)
}
static grub_err_t
grub_bsd_load (int argc, char *argv[])
grub_bsd_load (int argc, char *argv[], grub_elf_t *elfp)
{
grub_file_t file;
grub_elf_t elf;
......@@ -1610,7 +1610,10 @@ grub_bsd_load (int argc, char *argv[])
{
is_elf_kernel = 1;
grub_bsd_load_elf (elf, argv[0]);
grub_elf_close (elf);
if (elfp)
*elfp = elf;
else
grub_elf_close (elf);
}
else
{
......@@ -1647,10 +1650,11 @@ grub_bsd_parse_flags (const struct grub_arg_list *state,
static grub_err_t
grub_cmd_freebsd (grub_extcmd_context_t ctxt, int argc, char *argv[])
{
grub_elf_t elf;
kernel_type = KERNEL_TYPE_FREEBSD;
bootflags = grub_bsd_parse_flags (ctxt->state, freebsd_flags);
if (grub_bsd_load (argc, argv) == GRUB_ERR_NONE)
if (grub_bsd_load (argc, argv, &elf) == GRUB_ERR_NONE)
{
grub_uint32_t unit, slice, part;
......@@ -1659,7 +1663,6 @@ grub_cmd_freebsd (grub_extcmd_context_t ctxt, int argc, char *argv[])
{
grub_err_t err;
grub_uint64_t data = 0;
grub_file_t file;
int len = is_64bit ? 8 : 4;
err = grub_freebsd_add_meta_module (argv[0], is_64bit
......@@ -1671,16 +1674,15 @@ grub_cmd_freebsd (grub_extcmd_context_t ctxt, int argc, char *argv[])
if (err)
return err;
file = grub_file_open (argv[0]);
if (! file)
return grub_errno;
if (is_64bit)
err = grub_freebsd_load_elf_meta64 (relocator, file, argv[0],
&kern_end);
err = grub_freebsd_load_elf_meta64 (relocator, elf->file,
&elf->ehdr.ehdr64,
argv[0], &kern_end);
else
err = grub_freebsd_load_elf_meta32 (relocator, file, argv[0],
&kern_end);
err = grub_freebsd_load_elf_meta32 (relocator, elf->file,
&elf->ehdr.ehdr32,
argv[0], &kern_end);
grub_elf_close(elf);
if (err)
return err;
......@@ -1808,7 +1810,7 @@ grub_cmd_openbsd (grub_extcmd_context_t ctxt, int argc, char *argv[])
bootflags &= ~OPENBSD_RB_SERCONS;
}
if (grub_bsd_load (argc, argv) == GRUB_ERR_NONE)
if (grub_bsd_load (argc, argv, NULL) == GRUB_ERR_NONE)
{
grub_loader_set (grub_openbsd_boot, grub_bsd_unload, 0);
openbsd_root = bootdev;
......@@ -1824,7 +1826,7 @@ grub_cmd_netbsd (grub_extcmd_context_t ctxt, int argc, char *argv[])
kernel_type = KERNEL_TYPE_NETBSD;
bootflags = grub_bsd_parse_flags (ctxt->state, netbsd_flags);
if (grub_bsd_load (argc, argv) == GRUB_ERR_NONE)
if (grub_bsd_load (argc, argv, NULL) == GRUB_ERR_NONE)
{
if (is_elf_kernel)
{
......
#include <grub/loader.h>
#include <grub/elfload.h>
#include <grub/i386/bsd.h>
#include <grub/mm.h>
#include <grub/elf.h>
#include <grub/misc.h>
#include <grub/i386/relocator.h>
#include <grub/i18n.h>
......@@ -24,19 +24,8 @@ load (grub_file_t file, const char *filename, void *where, grub_off_t off, grub_
}
static inline grub_err_t
read_headers (grub_file_t file, const char *filename, Elf_Ehdr *e, char **shdr)
valid_eheader (Elf_Ehdr *e)
{
if (grub_file_seek (file, 0) == (grub_off_t) -1)
return grub_errno;
if (grub_file_read (file, (char *) e, sizeof (*e)) != sizeof (*e))
{
if (grub_errno)
return grub_errno;
return grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"),
filename);
}
if (e->e_ident[EI_MAG0] != ELFMAG0
|| e->e_ident[EI_MAG1] != ELFMAG1
|| e->e_ident[EI_MAG2] != ELFMAG2
......@@ -47,11 +36,20 @@ read_headers (grub_file_t file, const char *filename, Elf_Ehdr *e, char **shdr)
if (e->e_ident[EI_CLASS] != SUFFIX (ELFCLASS))
return grub_error (GRUB_ERR_BAD_OS, N_("invalid arch-dependent ELF magic"));
return GRUB_ERR_NONE;
}
static inline grub_err_t
read_sheaders (grub_file_t file, const char *filename, Elf_Ehdr *e, char **shdr)
{
*shdr = grub_malloc (e->e_shnum * e->e_shentsize);
if (! *shdr)
return grub_errno;
grub_dprintf ("bsd", "Reading section headers from 0x%llx, size %d\n",
(unsigned long long)e->e_shoff,
(int)(e->e_shnum * e->e_shentsize));
if (grub_file_seek (file, e->e_shoff) == (grub_off_t) -1)
return grub_errno;
......@@ -67,6 +65,26 @@ read_headers (grub_file_t file, const char *filename, Elf_Ehdr *e, char **shdr)
return GRUB_ERR_NONE;
}
static inline grub_err_t
read_headers (grub_file_t file, const char *filename, Elf_Ehdr *e, char **shdr)
{
if (grub_file_seek (file, 0) == (grub_off_t) -1)
return grub_errno;
if (grub_file_read (file, (char *) e, sizeof (*e)) != sizeof (*e))
{
if (grub_errno)
return grub_errno;
return grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"),
filename);
}
if (!valid_eheader(e))
return grub_errno;
return read_sheaders(file, filename, e, shdr);
}
/* On i386 FreeBSD uses "elf module" approarch for 32-bit variant
and "elf obj module" for 64-bit variant. However it may differ on other
platforms. So I keep both versions. */
......@@ -271,7 +289,7 @@ out:
grub_free (shdr);
if (err)
return err;
return SUFFIX (grub_freebsd_load_elf_meta) (relocator, file, argv[0], kern_end);
return SUFFIX (grub_freebsd_load_elf_meta) (relocator, file, &e, argv[0], kern_end);
}
#endif
......@@ -279,11 +297,11 @@ out:
grub_err_t
SUFFIX (grub_freebsd_load_elf_meta) (struct grub_relocator *relocator,
grub_file_t file,
Elf_Ehdr *e,
const char *filename,
grub_addr_t *kern_end)
{
grub_err_t err;
Elf_Ehdr e;
Elf_Shdr *s;
char *shdr = 0;
unsigned symoff, stroff, symsize, strsize;
......@@ -296,23 +314,26 @@ SUFFIX (grub_freebsd_load_elf_meta) (struct grub_relocator *relocator,
unsigned i;
grub_size_t chunk_size;
err = read_headers (file, filename, &e, &shdr);
if (!valid_eheader(e))
return grub_errno;
err = read_sheaders (file, filename, e, &shdr);
if (err)
goto out;
err = grub_bsd_add_meta (FREEBSD_MODINFO_METADATA |
FREEBSD_MODINFOMD_ELFHDR, &e,
sizeof (e));
FREEBSD_MODINFOMD_ELFHDR, e,
sizeof (*e));
if (err)
goto out;
for (s = (Elf_Shdr *) shdr; s < (Elf_Shdr *) (shdr
+ e.e_shnum * e.e_shentsize);
s = (Elf_Shdr *) ((char *) s + e.e_shentsize))
+ e->e_shnum * e->e_shentsize);
s = (Elf_Shdr *) ((char *) s + e->e_shentsize))
if (s->sh_type == SHT_SYMTAB)
break;
if (s >= (Elf_Shdr *) ((char *) shdr
+ e.e_shnum * e.e_shentsize))
+ e->e_shnum * e->e_shentsize))
{
err = grub_error (GRUB_ERR_BAD_OS, N_("no symbol table"));
goto out;
......@@ -320,7 +341,7 @@ SUFFIX (grub_freebsd_load_elf_meta) (struct grub_relocator *relocator,
symoff = s->sh_offset;
symsize = s->sh_size;
symentsize = s->sh_entsize;
s = (Elf_Shdr *) (shdr + e.e_shentsize * s->sh_link);
s = (Elf_Shdr *) (shdr + e->e_shentsize * s->sh_link);
stroff = s->sh_offset;
strsize = s->sh_size;
......@@ -345,6 +366,10 @@ SUFFIX (grub_freebsd_load_elf_meta) (struct grub_relocator *relocator,
*((grub_freebsd_addr_t *) curload) = symsize;
curload += sizeof (grub_freebsd_addr_t);
grub_dprintf ("bsd", "Loading symbols at 0x%llx from 0x%llx, size %d\n",
(unsigned long long)symoff,
(unsigned long long)curload, (int)symsize);
if (grub_file_seek (file, symoff) == (grub_off_t) -1)
{
err = grub_errno;
......@@ -364,6 +389,11 @@ SUFFIX (grub_freebsd_load_elf_meta) (struct grub_relocator *relocator,
*((grub_freebsd_addr_t *) curload) = strsize;
curload += sizeof (grub_freebsd_addr_t);
grub_dprintf ("bsd", "Loading strings at 0x%llx from 0x%llx, size %d\n",
(unsigned long long)stroff,
(unsigned long long)curload, (int)strsize);
if (grub_file_seek (file, stroff) == (grub_off_t) -1)
{
err = grub_errno;
......
......@@ -81,10 +81,12 @@ grub_err_t grub_freebsd_load_elfmodule_obj64 (struct grub_relocator *relocator,
grub_addr_t *kern_end);
grub_err_t grub_freebsd_load_elf_meta32 (struct grub_relocator *relocator,
grub_file_t file,
Elf32_Ehdr *ehdr,
const char *filename,
grub_addr_t *kern_end);
grub_err_t grub_freebsd_load_elf_meta64 (struct grub_relocator *relocator,
grub_file_t file,
Elf64_Ehdr *ehdr,
const char *filename,
grub_addr_t *kern_end);
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment