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:
parent
141a288bb0
commit
ea4097134f
6 changed files with 222 additions and 85 deletions
20
ChangeLog
20
ChangeLog
|
@ -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>
|
||||
|
||||
* util/i386/pc/grub-install.in (datadir): New variable.
|
||||
|
|
2
THANKS
2
THANKS
|
@ -13,6 +13,8 @@ Hollis Blanchard <hollis@penguinppc.org>
|
|||
Marco Gerards <metgerards@student.han.nl>
|
||||
NIIBE Yutaka <gniibe@m17n.org>
|
||||
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>
|
||||
Tomas Ebenlendr <ebik@ucw.cz>
|
||||
Tsuneyoshi Yasuo <tuneyoshi@naic.co.jp>
|
||||
|
|
|
@ -83,17 +83,20 @@ grub_ls_list_disks (int longlist)
|
|||
grub_errno = GRUB_ERR_NONE;
|
||||
|
||||
grub_printf (", Filesystem type %s",
|
||||
fs ? fs->name : "Unknown");
|
||||
fs ? fs->name : "unknown");
|
||||
|
||||
(fs->label) (dev, &label);
|
||||
if (grub_errno == GRUB_ERR_NONE)
|
||||
if (fs && fs->label)
|
||||
{
|
||||
if (label && grub_strlen (label))
|
||||
grub_printf (", Label: %s", label);
|
||||
grub_free (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;
|
||||
}
|
||||
else
|
||||
grub_errno = GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
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)
|
||||
grub_errno = GRUB_ERR_NONE;
|
||||
|
||||
grub_printf ("(%s): Filesystem is %s.\n",
|
||||
grub_printf ("(%s): Filesystem is %s",
|
||||
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)
|
||||
{
|
||||
|
|
2
fs/fat.c
2
fs/fat.c
|
@ -629,7 +629,7 @@ grub_fat_dir (grub_device_t device, const char *path,
|
|||
struct grub_fat_data *data = 0;
|
||||
grub_disk_t disk = device->disk;
|
||||
grub_size_t len;
|
||||
char *dirname;
|
||||
char *dirname = 0;
|
||||
char *p;
|
||||
|
||||
#ifndef GRUB_UTIL
|
||||
|
|
|
@ -535,7 +535,7 @@ grub_print_partinfo (grub_device_t disk, char *partname)
|
|||
grub_printf ("\tPartition num:%s, Filesystem type %s",
|
||||
partname, fs ? fs->name : "Unknown");
|
||||
|
||||
if (fs)
|
||||
if (fs && fs->label)
|
||||
{
|
||||
(fs->label) (part, &label);
|
||||
if (grub_errno == GRUB_ERR_NONE)
|
||||
|
|
|
@ -81,6 +81,158 @@ grub_multiboot_unload (void)
|
|||
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
|
||||
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;
|
||||
grub_ssize_t len;
|
||||
int i;
|
||||
Elf32_Ehdr *ehdr;
|
||||
|
||||
grub_dl_ref (my_mod);
|
||||
|
||||
grub_loader_unset();
|
||||
grub_loader_unset ();
|
||||
|
||||
if (argc == 0)
|
||||
{
|
||||
|
@ -102,7 +253,7 @@ grub_rescue_cmd_multiboot (int argc, char *argv[])
|
|||
}
|
||||
|
||||
file = grub_file_open (argv[0]);
|
||||
if (!file)
|
||||
if (! file)
|
||||
{
|
||||
grub_error (GRUB_ERR_BAD_ARGUMENT, "Couldn't open file");
|
||||
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. */
|
||||
for (header = (struct grub_multiboot_header *) buffer;
|
||||
((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
|
||||
&& !(header->magic + header->flags + header->checksum))
|
||||
break;
|
||||
break;
|
||||
}
|
||||
|
||||
if (header == 0)
|
||||
|
@ -134,72 +285,16 @@ grub_rescue_cmd_multiboot (int argc, char *argv[])
|
|||
|
||||
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;
|
||||
}
|
||||
|
||||
ehdr = (Elf32_Ehdr *) buffer;
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
if (grub_multiboot_load_elf (file, buffer) != GRUB_ERR_NONE)
|
||||
goto fail;
|
||||
|
||||
mbi = grub_malloc (sizeof (struct grub_multiboot_info));
|
||||
if (!mbi)
|
||||
if (! mbi)
|
||||
goto fail;
|
||||
|
||||
mbi->flags = GRUB_MB_INFO_MEMORY;
|
||||
|
@ -212,7 +307,7 @@ grub_rescue_cmd_multiboot (int argc, char *argv[])
|
|||
len += grub_strlen (argv[i]) + 1;
|
||||
|
||||
cmdline = p = grub_malloc (len);
|
||||
if (!cmdline)
|
||||
if (! cmdline)
|
||||
goto fail;
|
||||
|
||||
for (i = 0; i < argc; i++)
|
||||
|
@ -267,12 +362,12 @@ grub_rescue_cmd_module (int argc, char *argv[])
|
|||
}
|
||||
|
||||
file = grub_file_open (argv[0]);
|
||||
if (!file)
|
||||
if (! file)
|
||||
goto fail;
|
||||
|
||||
size = grub_file_size (file);
|
||||
module = grub_memalign (GRUB_MB_MOD_ALIGN, size);
|
||||
if (!module)
|
||||
if (! module)
|
||||
goto fail;
|
||||
|
||||
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;
|
||||
|
||||
cmdline = p = grub_malloc (len);
|
||||
if (!cmdline)
|
||||
if (! cmdline)
|
||||
goto fail;
|
||||
|
||||
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)
|
||||
* sizeof (struct grub_mod_list));
|
||||
if (!modlist)
|
||||
if (! modlist)
|
||||
goto fail;
|
||||
mbi->mods_addr = (grub_uint32_t) modlist;
|
||||
modlist += mbi->mods_count;
|
||||
|
@ -316,7 +411,7 @@ grub_rescue_cmd_module (int argc, char *argv[])
|
|||
else
|
||||
{
|
||||
struct grub_mod_list *modlist = grub_malloc (sizeof (struct grub_mod_list));
|
||||
if (!modlist)
|
||||
if (! modlist)
|
||||
goto fail;
|
||||
modlist->mod_start = (grub_uint32_t) module;
|
||||
modlist->mod_end = (grub_uint32_t) module + size;
|
||||
|
|
Loading…
Reference in a new issue