symtab support for knetbsd
This commit is contained in:
parent
5fb5182f8a
commit
9766dafa74
3 changed files with 164 additions and 5 deletions
|
@ -210,6 +210,7 @@ struct grub_netbsd_bootinfo
|
||||||
#define NETBSD_BTINFO_BOOTPATH 0
|
#define NETBSD_BTINFO_BOOTPATH 0
|
||||||
#define NETBSD_BTINFO_ROOTDEVICE 1
|
#define NETBSD_BTINFO_ROOTDEVICE 1
|
||||||
#define NETBSD_BTINFO_CONSOLE 6
|
#define NETBSD_BTINFO_CONSOLE 6
|
||||||
|
#define NETBSD_BTINFO_SYMTAB 8
|
||||||
#define NETBSD_BTINFO_MEMMAP 9
|
#define NETBSD_BTINFO_MEMMAP 9
|
||||||
|
|
||||||
struct grub_netbsd_btinfo_common
|
struct grub_netbsd_btinfo_common
|
||||||
|
@ -222,7 +223,6 @@ struct grub_netbsd_btinfo_common
|
||||||
|
|
||||||
struct grub_netbsd_btinfo_bootdisk
|
struct grub_netbsd_btinfo_bootdisk
|
||||||
{
|
{
|
||||||
struct grub_netbsd_btinfo_common common;
|
|
||||||
int labelsector; /* label valid if != -1 */
|
int labelsector; /* label valid if != -1 */
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
|
@ -233,6 +233,14 @@ struct grub_netbsd_btinfo_bootdisk
|
||||||
int partition;
|
int partition;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct grub_netbsd_btinfo_symtab
|
||||||
|
{
|
||||||
|
grub_uint32_t nsyms;
|
||||||
|
grub_uint32_t ssyms;
|
||||||
|
grub_uint32_t esyms;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
struct grub_netbsd_btinfo_serial
|
struct grub_netbsd_btinfo_serial
|
||||||
{
|
{
|
||||||
char devname[16];
|
char devname[16];
|
||||||
|
@ -256,6 +264,13 @@ grub_err_t grub_freebsd_load_elf_meta64 (struct grub_relocator *relocator,
|
||||||
grub_file_t file,
|
grub_file_t file,
|
||||||
grub_addr_t *kern_end);
|
grub_addr_t *kern_end);
|
||||||
|
|
||||||
|
grub_err_t grub_netbsd_load_elf_meta32 (struct grub_relocator *relocator,
|
||||||
|
grub_file_t file,
|
||||||
|
grub_addr_t *kern_end);
|
||||||
|
grub_err_t grub_netbsd_load_elf_meta64 (struct grub_relocator *relocator,
|
||||||
|
grub_file_t file,
|
||||||
|
grub_addr_t *kern_end);
|
||||||
|
|
||||||
grub_err_t grub_bsd_add_meta (grub_uint32_t type,
|
grub_err_t grub_bsd_add_meta (grub_uint32_t type,
|
||||||
void *data, grub_uint32_t len);
|
void *data, grub_uint32_t len);
|
||||||
grub_err_t grub_freebsd_add_meta_module (char *filename, char *type,
|
grub_err_t grub_freebsd_add_meta_module (char *filename, char *type,
|
||||||
|
|
|
@ -1237,12 +1237,27 @@ grub_cmd_openbsd (grub_extcmd_t cmd, int argc, char *argv[])
|
||||||
static grub_err_t
|
static grub_err_t
|
||||||
grub_cmd_netbsd (grub_extcmd_t cmd, int argc, char *argv[])
|
grub_cmd_netbsd (grub_extcmd_t cmd, int argc, char *argv[])
|
||||||
{
|
{
|
||||||
|
grub_err_t err;
|
||||||
kernel_type = KERNEL_TYPE_NETBSD;
|
kernel_type = KERNEL_TYPE_NETBSD;
|
||||||
bootflags = grub_bsd_parse_flags (cmd->state, netbsd_flags);
|
bootflags = grub_bsd_parse_flags (cmd->state, netbsd_flags);
|
||||||
|
|
||||||
if (grub_bsd_load (argc, argv) == GRUB_ERR_NONE)
|
if (grub_bsd_load (argc, argv) == GRUB_ERR_NONE)
|
||||||
{
|
{
|
||||||
grub_loader_set (grub_netbsd_boot, grub_bsd_unload, 0);
|
if (is_elf_kernel)
|
||||||
|
{
|
||||||
|
grub_file_t file;
|
||||||
|
|
||||||
|
file = grub_gzfile_open (argv[0], 1);
|
||||||
|
if (! file)
|
||||||
|
return grub_errno;
|
||||||
|
|
||||||
|
if (is_64bit)
|
||||||
|
err = grub_netbsd_load_elf_meta64 (relocator, file, &kern_end);
|
||||||
|
else
|
||||||
|
err = grub_netbsd_load_elf_meta32 (relocator, file, &kern_end);
|
||||||
|
if (err)
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
char bootpath[GRUB_NETBSD_MAX_BOOTPATH_LEN];
|
char bootpath[GRUB_NETBSD_MAX_BOOTPATH_LEN];
|
||||||
|
@ -1307,6 +1322,8 @@ grub_cmd_netbsd (grub_extcmd_t cmd, int argc, char *argv[])
|
||||||
|
|
||||||
grub_bsd_add_meta (NETBSD_BTINFO_CONSOLE, &cons, sizeof (cons));
|
grub_bsd_add_meta (NETBSD_BTINFO_CONSOLE, &cons, sizeof (cons));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
grub_loader_set (grub_netbsd_boot, grub_bsd_unload, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
return grub_errno;
|
return grub_errno;
|
||||||
|
|
|
@ -254,7 +254,7 @@ SUFFIX (grub_freebsd_load_elfmodule) (struct grub_relocator *relocator,
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
grub_err_t
|
grub_err_t
|
||||||
SUFFIX (grub_freebsd_load_elf_meta) (struct grub_relocator *relocator,
|
SUFFIX (grub_freebsd_load_elf_meta) (struct grub_relocator *relocator,
|
||||||
grub_file_t file, grub_addr_t *kern_end)
|
grub_file_t file, grub_addr_t *kern_end)
|
||||||
{
|
{
|
||||||
grub_err_t err;
|
grub_err_t err;
|
||||||
|
@ -296,8 +296,9 @@ SUFFIX (grub_freebsd_load_elf_meta) (struct grub_relocator *relocator,
|
||||||
stroff = s->sh_offset;
|
stroff = s->sh_offset;
|
||||||
strsize = s->sh_size;
|
strsize = s->sh_size;
|
||||||
|
|
||||||
chunk_size = 2 * sizeof (grub_freebsd_addr_t)
|
chunk_size = ALIGN_UP (symsize + strsize, sizeof (grub_freebsd_addr_t))
|
||||||
+ ALIGN_UP (symsize + strsize, sizeof (grub_freebsd_addr_t));
|
+ 2 * sizeof (grub_freebsd_addr_t);
|
||||||
|
|
||||||
symtarget = ALIGN_UP (*kern_end, sizeof (grub_freebsd_addr_t));
|
symtarget = ALIGN_UP (*kern_end, sizeof (grub_freebsd_addr_t));
|
||||||
err = grub_relocator_alloc_chunk_addr (relocator, &sym_chunk,
|
err = grub_relocator_alloc_chunk_addr (relocator, &sym_chunk,
|
||||||
symtarget, chunk_size);
|
symtarget, chunk_size);
|
||||||
|
@ -310,6 +311,7 @@ SUFFIX (grub_freebsd_load_elf_meta) (struct grub_relocator *relocator,
|
||||||
curload = sym_chunk;
|
curload = sym_chunk;
|
||||||
*((grub_freebsd_addr_t *) curload) = symsize;
|
*((grub_freebsd_addr_t *) curload) = symsize;
|
||||||
curload += sizeof (grub_freebsd_addr_t);
|
curload += sizeof (grub_freebsd_addr_t);
|
||||||
|
|
||||||
if (grub_file_seek (file, symoff) == (grub_off_t) -1)
|
if (grub_file_seek (file, symoff) == (grub_off_t) -1)
|
||||||
return grub_errno;
|
return grub_errno;
|
||||||
sym = (Elf_Sym *) curload;
|
sym = (Elf_Sym *) curload;
|
||||||
|
@ -370,4 +372,129 @@ SUFFIX (grub_freebsd_load_elf_meta) (struct grub_relocator *relocator,
|
||||||
return GRUB_ERR_NONE;
|
return GRUB_ERR_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
grub_err_t
|
||||||
|
SUFFIX (grub_netbsd_load_elf_meta) (struct grub_relocator *relocator,
|
||||||
|
grub_file_t file, grub_addr_t *kern_end)
|
||||||
|
{
|
||||||
|
grub_err_t err;
|
||||||
|
Elf_Ehdr e;
|
||||||
|
Elf_Shdr *s, *symsh, *strsh;
|
||||||
|
char *shdr;
|
||||||
|
unsigned symsize, strsize;
|
||||||
|
Elf_Sym *sym;
|
||||||
|
void *sym_chunk;
|
||||||
|
grub_uint8_t *curload;
|
||||||
|
const char *str;
|
||||||
|
grub_size_t chunk_size;
|
||||||
|
Elf_Ehdr *e2;
|
||||||
|
struct grub_netbsd_btinfo_symtab symtab;
|
||||||
|
grub_addr_t symtarget;
|
||||||
|
|
||||||
|
err = read_headers (file, &e, &shdr);
|
||||||
|
if (err)
|
||||||
|
return err;
|
||||||
|
|
||||||
|
for (s = (Elf_Shdr *) shdr; s < (Elf_Shdr *) (shdr
|
||||||
|
+ 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))
|
||||||
|
return grub_error (GRUB_ERR_BAD_OS, "no symbol table");
|
||||||
|
symsize = s->sh_size;
|
||||||
|
symsh = s;
|
||||||
|
s = (Elf_Shdr *) (shdr + e.e_shentsize * s->sh_link);
|
||||||
|
strsize = s->sh_size;
|
||||||
|
strsh = s;
|
||||||
|
|
||||||
|
chunk_size = ALIGN_UP (symsize, sizeof (grub_freebsd_addr_t))
|
||||||
|
+ ALIGN_UP (strsize, sizeof (grub_freebsd_addr_t))
|
||||||
|
+ sizeof (e) + e.e_phnum * e.e_phentsize
|
||||||
|
+ e.e_shnum * e.e_shentsize;
|
||||||
|
|
||||||
|
symtarget = ALIGN_UP (*kern_end, sizeof (grub_freebsd_addr_t));
|
||||||
|
err = grub_relocator_alloc_chunk_addr (relocator, &sym_chunk,
|
||||||
|
symtarget, chunk_size);
|
||||||
|
if (err)
|
||||||
|
return err;
|
||||||
|
|
||||||
|
symtab.nsyms = chunk_size;
|
||||||
|
symtab.ssyms = symtarget;
|
||||||
|
symtab.esyms = symtarget + chunk_size;
|
||||||
|
|
||||||
|
curload = sym_chunk;
|
||||||
|
|
||||||
|
e2 = (Elf_Ehdr *) curload;
|
||||||
|
grub_memcpy (curload, &e, sizeof (e));
|
||||||
|
e2->e_phoff = sizeof (e);
|
||||||
|
e2->e_shoff = sizeof (e) + e.e_phnum * e.e_phentsize;
|
||||||
|
|
||||||
|
curload += sizeof (e);
|
||||||
|
if (grub_file_seek (file, e.e_phoff) == (grub_off_t) -1)
|
||||||
|
return grub_errno;
|
||||||
|
if (grub_file_read (file, curload, e.e_phnum * e.e_phentsize)
|
||||||
|
!= (grub_ssize_t) (e.e_phnum * e.e_phentsize))
|
||||||
|
{
|
||||||
|
if (! grub_errno)
|
||||||
|
return grub_error (GRUB_ERR_BAD_OS, "invalid ELF");
|
||||||
|
return grub_errno;
|
||||||
|
}
|
||||||
|
curload += e.e_phnum * e.e_phentsize;
|
||||||
|
|
||||||
|
for (s = (Elf_Shdr *) shdr; s < (Elf_Shdr *) (shdr
|
||||||
|
+ e.e_shnum * e.e_shentsize);
|
||||||
|
s = (Elf_Shdr *) ((char *) s + e.e_shentsize))
|
||||||
|
{
|
||||||
|
Elf_Shdr *s2;
|
||||||
|
s2 = (Elf_Shdr *) curload;
|
||||||
|
grub_memcpy (curload, s, e.e_shentsize);
|
||||||
|
if (s == symsh)
|
||||||
|
{
|
||||||
|
s2->sh_offset = sizeof (e) + e.e_phnum * e.e_phentsize
|
||||||
|
+ e.e_shnum * e.e_shentsize;
|
||||||
|
}
|
||||||
|
else if (s == strsh)
|
||||||
|
{
|
||||||
|
s2->sh_offset = ALIGN_UP (symsize, sizeof (grub_freebsd_addr_t))
|
||||||
|
+ sizeof (e) + e.e_phnum * e.e_phentsize
|
||||||
|
+ e.e_shnum * e.e_shentsize;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
s2->sh_offset = 0;
|
||||||
|
s2->sh_addr = s2->sh_offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (grub_file_seek (file, symsh->sh_offset) == (grub_off_t) -1)
|
||||||
|
return grub_errno;
|
||||||
|
sym = (Elf_Sym *) curload;
|
||||||
|
if (grub_file_read (file, curload, symsize) != (grub_ssize_t) symsize)
|
||||||
|
{
|
||||||
|
if (! grub_errno)
|
||||||
|
return grub_error (GRUB_ERR_BAD_OS, "invalid ELF");
|
||||||
|
return grub_errno;
|
||||||
|
}
|
||||||
|
curload += ALIGN_UP (symsize, sizeof (grub_freebsd_addr_t));
|
||||||
|
|
||||||
|
if (grub_file_seek (file, strsh->sh_offset) == (grub_off_t) -1)
|
||||||
|
return grub_errno;
|
||||||
|
str = (char *) curload;
|
||||||
|
if (grub_file_read (file, curload, strsize) != (grub_ssize_t) strsize)
|
||||||
|
{
|
||||||
|
if (! grub_errno)
|
||||||
|
return grub_error (GRUB_ERR_BAD_OS, "invalid ELF");
|
||||||
|
return grub_errno;
|
||||||
|
}
|
||||||
|
|
||||||
|
err = grub_bsd_add_meta (NETBSD_BTINFO_SYMTAB,
|
||||||
|
&symtab,
|
||||||
|
sizeof (symtab));
|
||||||
|
if (err)
|
||||||
|
return err;
|
||||||
|
|
||||||
|
*kern_end = ALIGN_PAGE (symtarget + chunk_size);
|
||||||
|
|
||||||
|
return GRUB_ERR_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue