2005-07-31 Yoshinori K. Okuji <okuji@enbug.org>

* loader/i386/pc/multiboot.c (grub_multiboot_is_elf32): New
	function.
	(grub_multiboot_load_elf32): Likewise.
	(grub_multiboot_is_elf64): Likewise.
	(grub_multiboot_load_elf64): Likewise.
	(grub_multiboot_load_elf): Likewise.
	(grub_rescue_cmd_multiboot): Call grub_multiboot_load_elf to load
	an ELF32 or ELF64 file.
	This is based on a patch from Ruslan Nikolaev <nruslan@mail.com>.

	From Serbinenko Vladimir <serbinenko.vova@list.ru>:
	* kern/disk.c (grub_print_partinfo): Check if FS->LABEL is not
	NULL before calling FS->LABEL.
	* fs/fat.c (grub_fat_dir): Initialize DIRNAME to NULL.
	* commands/ls.c (grub_ls_list_files): Show labels, if possible.
	(grub_ls_list_disks): Check if FS and FS->LABEL are not NULL
	before calling FS->LABEL.
This commit is contained in:
okuji 2005-07-31 16:12:29 +00:00
parent 141a288bb0
commit ea4097134f
6 changed files with 222 additions and 85 deletions

View file

@ -1,3 +1,23 @@
2005-07-31 Yoshinori K. Okuji <okuji@enbug.org>
* loader/i386/pc/multiboot.c (grub_multiboot_is_elf32): New
function.
(grub_multiboot_load_elf32): Likewise.
(grub_multiboot_is_elf64): Likewise.
(grub_multiboot_load_elf64): Likewise.
(grub_multiboot_load_elf): Likewise.
(grub_rescue_cmd_multiboot): Call grub_multiboot_load_elf to load
an ELF32 or ELF64 file.
This is based on a patch from Ruslan Nikolaev <nruslan@mail.com>.
From Serbinenko Vladimir <serbinenko.vova@list.ru>:
* kern/disk.c (grub_print_partinfo): Check if FS->LABEL is not
NULL before calling FS->LABEL.
* fs/fat.c (grub_fat_dir): Initialize DIRNAME to NULL.
* commands/ls.c (grub_ls_list_files): Show labels, if possible.
(grub_ls_list_disks): Check if FS and FS->LABEL are not NULL
before calling FS->LABEL.
2005-07-26 Yoshinori K. Okuji <okuji@enbug.org> 2005-07-26 Yoshinori K. Okuji <okuji@enbug.org>
* util/i386/pc/grub-install.in (datadir): New variable. * util/i386/pc/grub-install.in (datadir): New variable.

2
THANKS
View file

@ -13,6 +13,8 @@ Hollis Blanchard <hollis@penguinppc.org>
Marco Gerards <metgerards@student.han.nl> Marco Gerards <metgerards@student.han.nl>
NIIBE Yutaka <gniibe@m17n.org> NIIBE Yutaka <gniibe@m17n.org>
Robert Bihlmeyer <robbe@orcus.priv.at> Robert Bihlmeyer <robbe@orcus.priv.at>
Ruslan Nikolaev <nruslan@mail.com>
Serbinenko Vladimir <serbinenko.vova@list.ru>
Timothy Baldwin <T.E.Baldwin99@members.leeds.ac.uk> Timothy Baldwin <T.E.Baldwin99@members.leeds.ac.uk>
Tomas Ebenlendr <ebik@ucw.cz> Tomas Ebenlendr <ebik@ucw.cz>
Tsuneyoshi Yasuo <tuneyoshi@naic.co.jp> Tsuneyoshi Yasuo <tuneyoshi@naic.co.jp>

View file

@ -83,17 +83,20 @@ grub_ls_list_disks (int longlist)
grub_errno = GRUB_ERR_NONE; grub_errno = GRUB_ERR_NONE;
grub_printf (", Filesystem type %s", grub_printf (", Filesystem type %s",
fs ? fs->name : "Unknown"); fs ? fs->name : "unknown");
(fs->label) (dev, &label); if (fs && fs->label)
if (grub_errno == GRUB_ERR_NONE)
{ {
if (label && grub_strlen (label)) (fs->label) (dev, &label);
grub_printf (", Label: %s", label); if (grub_errno == GRUB_ERR_NONE)
grub_free (label); {
if (label && grub_strlen (label))
grub_printf (", Label: %s", label);
grub_free (label);
}
else
grub_errno = GRUB_ERR_NONE;
} }
else
grub_errno = GRUB_ERR_NONE;
} }
grub_putchar ('\n'); grub_putchar ('\n');
@ -221,8 +224,25 @@ grub_ls_list_files (char *dirname, int longlist, int all, int human)
if (grub_errno == GRUB_ERR_UNKNOWN_FS) if (grub_errno == GRUB_ERR_UNKNOWN_FS)
grub_errno = GRUB_ERR_NONE; grub_errno = GRUB_ERR_NONE;
grub_printf ("(%s): Filesystem is %s.\n", grub_printf ("(%s): Filesystem is %s",
device_name, fs ? fs->name : "unknown"); device_name, fs ? fs->name : "unknown");
if (fs && fs->label)
{
char *label;
(fs->label) (dev, &label);
if (grub_errno == GRUB_ERR_NONE)
{
if (label && grub_strlen (label))
grub_printf (", Label: %s", label);
grub_free (label);
}
else
grub_errno = GRUB_ERR_NONE;
}
grub_putchar ('\n');
} }
else if (fs) else if (fs)
{ {

View file

@ -629,7 +629,7 @@ grub_fat_dir (grub_device_t device, const char *path,
struct grub_fat_data *data = 0; struct grub_fat_data *data = 0;
grub_disk_t disk = device->disk; grub_disk_t disk = device->disk;
grub_size_t len; grub_size_t len;
char *dirname; char *dirname = 0;
char *p; char *p;
#ifndef GRUB_UTIL #ifndef GRUB_UTIL

View file

@ -535,7 +535,7 @@ grub_print_partinfo (grub_device_t disk, char *partname)
grub_printf ("\tPartition num:%s, Filesystem type %s", grub_printf ("\tPartition num:%s, Filesystem type %s",
partname, fs ? fs->name : "Unknown"); partname, fs ? fs->name : "Unknown");
if (fs) if (fs && fs->label)
{ {
(fs->label) (part, &label); (fs->label) (part, &label);
if (grub_errno == GRUB_ERR_NONE) if (grub_errno == GRUB_ERR_NONE)

View file

@ -81,6 +81,158 @@ grub_multiboot_unload (void)
return GRUB_ERR_NONE; return GRUB_ERR_NONE;
} }
/* Check if BUFFER contains ELF32. */
static int
grub_multiboot_is_elf32 (void *buffer)
{
Elf32_Ehdr *ehdr = (Elf32_Ehdr *) buffer;
return ehdr->e_ident[EI_CLASS] == ELFCLASS32;
}
static grub_err_t
grub_multiboot_load_elf32 (grub_file_t file, void *buffer)
{
Elf32_Ehdr *ehdr = (Elf32_Ehdr *) buffer;
Elf32_Phdr *phdr;
int i;
if (ehdr->e_ident[EI_CLASS] != ELFCLASS32)
return grub_error (GRUB_ERR_UNKNOWN_OS, "invalid ELF class");
if (grub_dl_check_header (ehdr, sizeof(Elf32_Ehdr)))
return grub_error (GRUB_ERR_UNKNOWN_OS, "no valid ELF header found");
if (ehdr->e_type != ET_EXEC)
return grub_error (GRUB_ERR_UNKNOWN_OS, "invalid ELF file type");
/* FIXME: Should we support program headers at strange locations? */
if (ehdr->e_phoff + ehdr->e_phnum * ehdr->e_phentsize > GRUB_MB_SEARCH)
return grub_error (GRUB_ERR_BAD_OS, "program header at a too high offset");
entry = ehdr->e_entry;
/* Load every loadable segment in memory. */
for (i = 0; i < ehdr->e_phnum; i++)
{
phdr = (Elf32_Phdr *) ((char *) buffer + ehdr->e_phoff
+ i * ehdr->e_phentsize);
if (phdr->p_type == PT_LOAD)
{
/* The segment should fit in the area reserved for the OS. */
if ((phdr->p_paddr < grub_os_area_addr)
|| (phdr->p_paddr + phdr->p_memsz
> grub_os_area_addr + grub_os_area_size))
return grub_error (GRUB_ERR_BAD_OS,
"segment doesn't fit in memory reserved for the OS");
if (grub_file_seek (file, phdr->p_offset) == -1)
return grub_error (GRUB_ERR_BAD_OS,
"invalid offset in program header");
if (grub_file_read (file, (void *) phdr->p_paddr, phdr->p_filesz)
!= (grub_ssize_t) phdr->p_filesz)
return grub_error (GRUB_ERR_BAD_OS,
"couldn't read segment from file");
if (phdr->p_filesz < phdr->p_memsz)
grub_memset ((char *) phdr->p_paddr + phdr->p_filesz, 0,
phdr->p_memsz - phdr->p_filesz);
}
}
return grub_errno;
}
/* Check if BUFFER contains ELF64. */
static int
grub_multiboot_is_elf64 (void *buffer)
{
Elf64_Ehdr *ehdr = (Elf64_Ehdr *) buffer;
return ehdr->e_ident[EI_CLASS] == ELFCLASS64;
}
static grub_err_t
grub_multiboot_load_elf64 (grub_file_t file, void *buffer)
{
Elf64_Ehdr *ehdr = (Elf64_Ehdr *) buffer;
Elf64_Phdr *phdr;
int i;
if (ehdr->e_ident[EI_CLASS] != ELFCLASS64)
return grub_error (GRUB_ERR_UNKNOWN_OS, "invalid ELF class");
if (ehdr->e_ident[EI_MAG0] != ELFMAG0
|| ehdr->e_ident[EI_MAG1] != ELFMAG1
|| ehdr->e_ident[EI_MAG2] != ELFMAG2
|| ehdr->e_ident[EI_MAG3] != ELFMAG3
|| ehdr->e_version != EV_CURRENT
|| ehdr->e_ident[EI_DATA] != ELFDATA2LSB
|| ehdr->e_machine != EM_X86_64)
return grub_error(GRUB_ERR_UNKNOWN_OS, "no valid ELF header found");
if (ehdr->e_type != ET_EXEC)
return grub_error (GRUB_ERR_UNKNOWN_OS, "invalid ELF file type");
/* FIXME: Should we support program headers at strange locations? */
if (ehdr->e_phoff + ehdr->e_phnum * ehdr->e_phentsize > GRUB_MB_SEARCH)
return grub_error (GRUB_ERR_BAD_OS, "program header at a too high offset");
/* We still in 32-bit mode */
if (ehdr->e_entry > 0xffffffff)
return grub_error (GRUB_ERR_BAD_OS, "invalid entry point for ELF64");
entry = ehdr->e_entry;
/* Load every loadable segment in memory. */
for (i = 0; i < ehdr->e_phnum; i++)
{
phdr = (Elf64_Phdr *) ((char *) buffer + ehdr->e_phoff
+ i * ehdr->e_phentsize);
if (phdr->p_type == PT_LOAD)
{
/* The segment should fit in the area reserved for the OS. */
if ((phdr->p_paddr < (grub_uint64_t) grub_os_area_addr)
|| (phdr->p_paddr + phdr->p_memsz
> ((grub_uint64_t) grub_os_area_addr
+ (grub_uint64_t) grub_os_area_size)))
return grub_error (GRUB_ERR_BAD_OS,
"segment doesn't fit in memory reserved for the OS");
if (grub_file_seek (file, phdr->p_offset) == -1)
return grub_error (GRUB_ERR_BAD_OS,
"invalid offset in program header");
if (grub_file_read (file, (void *) ((grub_uint32_t) phdr->p_paddr),
phdr->p_filesz)
!= (grub_ssize_t) phdr->p_filesz)
return grub_error (GRUB_ERR_BAD_OS,
"couldn't read segment from file");
if (phdr->p_filesz < phdr->p_memsz)
grub_memset (((char *) ((grub_uint32_t) phdr->p_paddr)
+ phdr->p_filesz),
0,
phdr->p_memsz - phdr->p_filesz);
}
}
return grub_errno;
}
/* Load ELF32 or ELF64. */
static grub_err_t
grub_multiboot_load_elf (grub_file_t file, void *buffer)
{
if (grub_multiboot_is_elf32 (buffer))
return grub_multiboot_load_elf32 (file, buffer);
else if (grub_multiboot_is_elf64 (buffer))
return grub_multiboot_load_elf64 (file, buffer);
return grub_error (GRUB_ERR_UNKNOWN_OS, "unknown ELF class");
}
void void
grub_rescue_cmd_multiboot (int argc, char *argv[]) grub_rescue_cmd_multiboot (int argc, char *argv[])
{ {
@ -89,11 +241,10 @@ grub_rescue_cmd_multiboot (int argc, char *argv[])
struct grub_multiboot_header *header; struct grub_multiboot_header *header;
grub_ssize_t len; grub_ssize_t len;
int i; int i;
Elf32_Ehdr *ehdr;
grub_dl_ref (my_mod); grub_dl_ref (my_mod);
grub_loader_unset(); grub_loader_unset ();
if (argc == 0) if (argc == 0)
{ {
@ -102,7 +253,7 @@ grub_rescue_cmd_multiboot (int argc, char *argv[])
} }
file = grub_file_open (argv[0]); file = grub_file_open (argv[0]);
if (!file) if (! file)
{ {
grub_error (GRUB_ERR_BAD_ARGUMENT, "Couldn't open file"); grub_error (GRUB_ERR_BAD_ARGUMENT, "Couldn't open file");
goto fail; goto fail;
@ -119,11 +270,11 @@ grub_rescue_cmd_multiboot (int argc, char *argv[])
be at least 12 bytes and aligned on a 4-byte boundary. */ be at least 12 bytes and aligned on a 4-byte boundary. */
for (header = (struct grub_multiboot_header *) buffer; for (header = (struct grub_multiboot_header *) buffer;
((char *) header <= buffer + len - 12) || (header = 0); ((char *) header <= buffer + len - 12) || (header = 0);
header = (struct grub_multiboot_header *) ((char *)header + 4)) header = (struct grub_multiboot_header *) ((char *) header + 4))
{ {
if (header->magic == GRUB_MB_MAGIC if (header->magic == GRUB_MB_MAGIC
&& !(header->magic + header->flags + header->checksum)) && !(header->magic + header->flags + header->checksum))
break; break;
} }
if (header == 0) if (header == 0)
@ -134,72 +285,16 @@ grub_rescue_cmd_multiboot (int argc, char *argv[])
if (header->flags & GRUB_MB_UNSUPPORTED) if (header->flags & GRUB_MB_UNSUPPORTED)
{ {
grub_error (GRUB_ERR_UNKNOWN_OS, "Unsupported flag: 0x%x", header->flags); grub_error (GRUB_ERR_UNKNOWN_OS,
"Unsupported flag: 0x%x", header->flags);
goto fail; goto fail;
} }
ehdr = (Elf32_Ehdr *) buffer; if (grub_multiboot_load_elf (file, buffer) != GRUB_ERR_NONE)
goto fail;
if (grub_dl_check_header (ehdr, sizeof(*ehdr)))
{
grub_error (GRUB_ERR_UNKNOWN_OS, "No valid ELF header found");
goto fail;
}
if (ehdr->e_type != ET_EXEC)
{
grub_error (GRUB_ERR_UNKNOWN_OS, "invalid ELF file type");
goto fail;
}
/* FIXME: Should we support program headers at strange locations? */
if (ehdr->e_phoff + ehdr->e_phnum * ehdr->e_phentsize > GRUB_MB_SEARCH)
{
grub_error (GRUB_ERR_UNKNOWN_OS, "Program header at a too high offset");
goto fail;
}
entry = ehdr->e_entry;
/* Load every loadable segment in memory. */
for (i = 0; i < ehdr->e_phnum; i++)
{
Elf32_Phdr *phdr;
phdr = (Elf32_Phdr *) (buffer + ehdr->e_phoff + i * ehdr->e_phentsize);
if (phdr->p_type == PT_LOAD)
{
/* The segment should fit in the area reserved for the OS. */
if ((phdr->p_paddr < grub_os_area_addr)
|| (phdr->p_paddr + phdr->p_memsz
> grub_os_area_addr + grub_os_area_size))
{
grub_error (GRUB_ERR_BAD_OS,
"Segment doesn't fit in memory reserved for the OS");
goto fail;
}
if (grub_file_seek (file, phdr->p_offset) == -1)
{
grub_error (GRUB_ERR_BAD_OS, "Invalid offset in program header");
goto fail;
}
if (grub_file_read (file, (void *) phdr->p_paddr, phdr->p_filesz)
!= (grub_ssize_t) phdr->p_filesz)
{
grub_error (GRUB_ERR_BAD_OS, "Couldn't read segment from file");
goto fail;
}
if (phdr->p_filesz < phdr->p_memsz)
grub_memset ((char *) phdr->p_paddr + phdr->p_filesz, 0,
phdr->p_memsz - phdr->p_filesz);
}
}
mbi = grub_malloc (sizeof (struct grub_multiboot_info)); mbi = grub_malloc (sizeof (struct grub_multiboot_info));
if (!mbi) if (! mbi)
goto fail; goto fail;
mbi->flags = GRUB_MB_INFO_MEMORY; mbi->flags = GRUB_MB_INFO_MEMORY;
@ -212,7 +307,7 @@ grub_rescue_cmd_multiboot (int argc, char *argv[])
len += grub_strlen (argv[i]) + 1; len += grub_strlen (argv[i]) + 1;
cmdline = p = grub_malloc (len); cmdline = p = grub_malloc (len);
if (!cmdline) if (! cmdline)
goto fail; goto fail;
for (i = 0; i < argc; i++) for (i = 0; i < argc; i++)
@ -267,12 +362,12 @@ grub_rescue_cmd_module (int argc, char *argv[])
} }
file = grub_file_open (argv[0]); file = grub_file_open (argv[0]);
if (!file) if (! file)
goto fail; goto fail;
size = grub_file_size (file); size = grub_file_size (file);
module = grub_memalign (GRUB_MB_MOD_ALIGN, size); module = grub_memalign (GRUB_MB_MOD_ALIGN, size);
if (!module) if (! module)
goto fail; goto fail;
if (grub_file_read (file, module, size) != size) if (grub_file_read (file, module, size) != size)
@ -285,7 +380,7 @@ grub_rescue_cmd_module (int argc, char *argv[])
len += grub_strlen (argv[i]) + 1; len += grub_strlen (argv[i]) + 1;
cmdline = p = grub_malloc (len); cmdline = p = grub_malloc (len);
if (!cmdline) if (! cmdline)
goto fail; goto fail;
for (i = 0; i < argc; i++) for (i = 0; i < argc; i++)
@ -303,7 +398,7 @@ grub_rescue_cmd_module (int argc, char *argv[])
modlist = grub_realloc (modlist, (mbi->mods_count + 1) modlist = grub_realloc (modlist, (mbi->mods_count + 1)
* sizeof (struct grub_mod_list)); * sizeof (struct grub_mod_list));
if (!modlist) if (! modlist)
goto fail; goto fail;
mbi->mods_addr = (grub_uint32_t) modlist; mbi->mods_addr = (grub_uint32_t) modlist;
modlist += mbi->mods_count; modlist += mbi->mods_count;
@ -316,7 +411,7 @@ grub_rescue_cmd_module (int argc, char *argv[])
else else
{ {
struct grub_mod_list *modlist = grub_malloc (sizeof (struct grub_mod_list)); struct grub_mod_list *modlist = grub_malloc (sizeof (struct grub_mod_list));
if (!modlist) if (! modlist)
goto fail; goto fail;
modlist->mod_start = (grub_uint32_t) module; modlist->mod_start = (grub_uint32_t) module;
modlist->mod_end = (grub_uint32_t) module + size; modlist->mod_end = (grub_uint32_t) module + size;