merge bootcheck and mainline into newreloc

This commit is contained in:
Vladimir 'phcoder' Serbinenko 2010-01-20 11:48:36 +01:00
commit 3c83bc50db
165 changed files with 4132 additions and 665 deletions

View file

@ -33,7 +33,7 @@
#include <grub/command.h>
#include <grub/extcmd.h>
#include <grub/i18n.h>
#include <grub/i386/pc/serial.h>
#include <grub/serial.h>
#include <grub/video.h>
#ifdef GRUB_MACHINE_PCBIOS
@ -849,11 +849,9 @@ grub_netbsd_setup_video (void)
if (modevar && *modevar != 0)
{
char *tmp;
tmp = grub_malloc (grub_strlen (modevar)
+ sizeof (";" NETBSD_DEFAULT_VIDEO_MODE));
tmp = grub_xasprintf ("%s;" NETBSD_DEFAULT_VIDEO_MODE, modevar);
if (! tmp)
return grub_errno;
grub_sprintf (tmp, "%s;" NETBSD_DEFAULT_VIDEO_MODE, modevar);
err = grub_video_set_mode (tmp, 0, 0);
grub_free (tmp);
}
@ -1634,14 +1632,20 @@ grub_cmd_freebsd_loadenv (grub_command_t cmd __attribute__ ((unused)),
if (*curr)
{
char name[grub_strlen (curr) + sizeof("kFreeBSD.")];
char *name;
if (*p == '"')
p++;
grub_sprintf (name, "kFreeBSD.%s", curr);
if (grub_env_set (name, p))
name = grub_xasprintf ("kFreeBSD.%s", curr);
if (!name)
goto fail;
if (grub_env_set (name, p))
{
grub_free (name);
goto fail;
}
grub_free (name);
}
}

View file

@ -612,11 +612,9 @@ grub_linux_boot (void)
May change in future if we have modes without framebuffer. */
if (modevar && *modevar != 0)
{
tmp = grub_malloc (grub_strlen (modevar)
+ sizeof (";" DEFAULT_VIDEO_MODE));
tmp = grub_xasprintf ("%s;" DEFAULT_VIDEO_MODE, modevar);
if (! tmp)
return grub_errno;
grub_sprintf (tmp, "%s;" DEFAULT_VIDEO_MODE, modevar);
err = grub_video_set_mode (tmp, 0, 0);
grub_free (tmp);
}
@ -941,19 +939,18 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
break;
}
buf = grub_malloc (sizeof ("WWWWxHHHHxDD;WWWWxHHHH"));
if (! buf)
goto fail;
linux_mode
= &linux_vesafb_modes[vid_mode - GRUB_LINUX_VID_MODE_VESA_START];
grub_sprintf (buf, "%ux%ux%u,%ux%u",
linux_vesafb_res[linux_mode->res_index].width,
linux_vesafb_res[linux_mode->res_index].height,
linux_mode->depth,
linux_vesafb_res[linux_mode->res_index].width,
linux_vesafb_res[linux_mode->res_index].height);
buf = grub_xasprintf ("%ux%ux%u,%ux%u",
linux_vesafb_res[linux_mode->res_index].width,
linux_vesafb_res[linux_mode->res_index].height,
linux_mode->depth,
linux_vesafb_res[linux_mode->res_index].width,
linux_vesafb_res[linux_mode->res_index].height);
if (! buf)
goto fail;
grub_printf ("%s is deprecated. "
"Use set gfxpayload=%s before "
"linux command instead.\n",

View file

@ -231,17 +231,20 @@ grub_multiboot (int argc, char *argv[])
case 0:
{
char buf[sizeof ("XXXXXXXXXXxXXXXXXXXXXxXXXXXXXXXX,XXXXXXXXXXxXXXXXXXXXX,auto")];
char *buf;
if (header->depth && header->width && header->height)
grub_sprintf (buf, "%dx%dx%d,%dx%d,auto", header->width,
header->height, header->depth, header->width,
header->height);
buf = grub_xasprintf ("%dx%dx%d,%dx%d,auto", header->width,
header->height, header->depth, header->width,
header->height);
else if (header->width && header->height)
grub_sprintf (buf, "%dx%d,auto", header->width, header->height);
buf = grub_xasprintf ("%dx%d,auto", header->width, header->height);
else
grub_sprintf (buf, "auto");
buf = grub_strdup ("auto");
if (!buf)
goto fail;
grub_env_set ("gfxpayload", buf);
grub_free (buf);
break;
}
}

View file

@ -114,6 +114,18 @@ grub_fill_multiboot_mmap (struct multiboot_mmap_entry *first_entry)
case GRUB_MACHINE_MEMORY_AVAILABLE:
mmap_entry->type = MULTIBOOT_MEMORY_AVAILABLE;
break;
#ifdef GRUB_MACHINE_MEMORY_ACPI_RECLAIMABLE
case GRUB_MACHINE_MEMORY_ACPI_RECLAIMABLE:
mmap_entry->type = MULTIBOOT_MEMORY_ACPI_RECLAIMABLE;
break;
#endif
#ifdef GRUB_MACHINE_MEMORY_NVS
case GRUB_MACHINE_MEMORY_NVS:
mmap_entry->type = MULTIBOOT_MEMORY_NVS;
break;
#endif
default:
mmap_entry->type = MULTIBOOT_MEMORY_RESERVED;
@ -142,11 +154,9 @@ set_video_mode (void)
else
{
char *tmp;
tmp = grub_malloc (grub_strlen (modevar)
+ sizeof (DEFAULT_VIDEO_MODE) + 1);
tmp = grub_xasprintf ("%s;" DEFAULT_VIDEO_MODE, modevar);
if (! tmp)
return grub_errno;
grub_sprintf (tmp, "%s;" DEFAULT_VIDEO_MODE, modevar);
err = grub_video_set_mode (tmp, 0, 0);
grub_free (tmp);
}

View file

@ -753,11 +753,13 @@ grub_cpu_xnu_fill_devicetree (void)
#endif
/* The name of key for new table. */
grub_sprintf (guidbuf, "%08x-%04x-%04x-%02x%02x-",
guid.data1, guid.data2, guid.data3, guid.data4[0],
guid.data4[1]);
grub_snprintf (guidbuf, sizeof (guidbuf), "%08x-%04x-%04x-%02x%02x-",
guid.data1, guid.data2, guid.data3, guid.data4[0],
guid.data4[1]);
for (j = 2; j < 8; j++)
grub_sprintf (guidbuf + grub_strlen (guidbuf), "%02x", guid.data4[j]);
grub_snprintf (guidbuf + grub_strlen (guidbuf),
sizeof (guidbuf) - grub_strlen (guidbuf),
"%02x", guid.data4[j]);
/* For some reason GUID has to be in uppercase. */
for (j = 0; guidbuf[j] ; j++)
if (guidbuf[j] >= 'a' && guidbuf[j] <= 'f')
@ -858,12 +860,10 @@ grub_xnu_set_video (struct grub_xnu_boot_params *params)
32 << GRUB_VIDEO_MODE_TYPE_DEPTH_POS);
else
{
tmp = grub_malloc (grub_strlen (modevar)
+ sizeof (DEFAULT_VIDEO_MODE) + 1);
tmp = grub_xasprintf ("%s;" DEFAULT_VIDEO_MODE, modevar);
if (! tmp)
return grub_error (GRUB_ERR_OUT_OF_MEMORY,
"couldn't allocate temporary storag");
grub_sprintf (tmp, "%s;" DEFAULT_VIDEO_MODE, modevar);
err = grub_video_set_mode (tmp,
GRUB_VIDEO_MODE_TYPE_PURE_TEXT
| GRUB_VIDEO_MODE_TYPE_DEPTH_MASK,

398
loader/mips/linux.c Normal file
View file

@ -0,0 +1,398 @@
/* linux.c - boot Linux */
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2003,2004,2005,2007,2009,2010 Free Software Foundation, Inc.
*
* GRUB is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GRUB is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
*/
#include <grub/elf.h>
#include <grub/elfload.h>
#include <grub/loader.h>
#include <grub/dl.h>
#include <grub/mm.h>
#include <grub/misc.h>
#include <grub/machine/loader.h>
#include <grub/command.h>
#include <grub/mips/relocator.h>
#include <grub/machine/memory.h>
#include <grub/i18n.h>
/* For frequencies. */
#include <grub/pci.h>
#include <grub/machine/time.h>
#define ELF32_LOADMASK (0x00000000UL)
#define ELF64_LOADMASK (0x0000000000000000ULL)
static grub_dl_t my_mod;
static int loaded;
static grub_size_t linux_size;
static grub_uint8_t *playground;
static grub_addr_t target_addr, entry_addr;
static int linux_argc;
static grub_off_t argv_off, envp_off;
static grub_off_t rd_addr_arg_off, rd_size_arg_off;
static int initrd_loaded = 0;
static grub_err_t
grub_linux_boot (void)
{
struct grub_relocator32_state state;
/* Boot the kernel. */
state.gpr[1] = entry_addr;
state.gpr[4] = linux_argc;
state.gpr[5] = target_addr + argv_off;
state.gpr[6] = target_addr + envp_off;
state.jumpreg = 1;
grub_relocator32_boot (playground, target_addr, state);
return GRUB_ERR_NONE;
}
static grub_err_t
grub_linux_release_mem (void)
{
grub_relocator32_free (playground);
return GRUB_ERR_NONE;
}
static grub_err_t
grub_linux_unload (void)
{
grub_err_t err;
err = grub_linux_release_mem ();
grub_dl_unref (my_mod);
loaded = 0;
return err;
}
static grub_err_t
grub_linux_load32 (grub_elf_t elf, void **extra_mem, grub_size_t extra_size)
{
Elf32_Addr base;
int extraoff;
/* Linux's entry point incorrectly contains a virtual address. */
entry_addr = elf->ehdr.ehdr32.e_entry & ~ELF32_LOADMASK;
linux_size = grub_elf32_size (elf, &base);
if (linux_size == 0)
return grub_errno;
target_addr = base;
/* Pad it; the kernel scribbles over memory beyond its load address. */
linux_size += 0x100000;
linux_size = ALIGN_UP (base + linux_size, 4) - base;
extraoff = linux_size;
linux_size += extra_size;
playground = grub_relocator32_alloc (linux_size);
if (!playground)
return grub_errno;
*extra_mem = playground + extraoff;
/* Now load the segments into the area we claimed. */
auto grub_err_t offset_phdr (Elf32_Phdr *phdr, grub_addr_t *addr, int *do_load);
grub_err_t offset_phdr (Elf32_Phdr *phdr, grub_addr_t *addr, int *do_load)
{
if (phdr->p_type != PT_LOAD)
{
*do_load = 0;
return 0;
}
*do_load = 1;
/* Linux's program headers incorrectly contain virtual addresses.
* Translate those to physical, and offset to the area we claimed. */
*addr = (grub_addr_t) (phdr->p_paddr - base + playground);
return 0;
}
return grub_elf32_load (elf, offset_phdr, 0, 0);
}
static grub_err_t
grub_linux_load64 (grub_elf_t elf, void **extra_mem, grub_size_t extra_size)
{
Elf64_Addr base;
int extraoff;
/* Linux's entry point incorrectly contains a virtual address. */
entry_addr = elf->ehdr.ehdr64.e_entry & ~ELF64_LOADMASK;
linux_size = grub_elf64_size (elf, &base);
if (linux_size == 0)
return grub_errno;
target_addr = base;
/* Pad it; the kernel scribbles over memory beyond its load address. */
linux_size += 0x100000;
linux_size = ALIGN_UP (base + linux_size, 4) - base;
extraoff = linux_size;
linux_size += extra_size;
playground = grub_relocator32_alloc (linux_size);
if (!playground)
return grub_errno;
*extra_mem = playground + extraoff;
/* Now load the segments into the area we claimed. */
auto grub_err_t offset_phdr (Elf64_Phdr *phdr, grub_addr_t *addr, int *do_load);
grub_err_t offset_phdr (Elf64_Phdr *phdr, grub_addr_t *addr, int *do_load)
{
if (phdr->p_type != PT_LOAD)
{
*do_load = 0;
return 0;
}
*do_load = 1;
/* Linux's program headers incorrectly contain virtual addresses.
* Translate those to physical, and offset to the area we claimed. */
*addr = (grub_addr_t) (phdr->p_paddr - base + playground);
return 0;
}
return grub_elf64_load (elf, offset_phdr, 0, 0);
}
static grub_err_t
grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
int argc, char *argv[])
{
grub_elf_t elf = 0;
int i;
int size;
void *extra = NULL;
grub_uint32_t *linux_argv, *linux_envp;
char *linux_args, *linux_envs;
grub_err_t err;
if (argc == 0)
return grub_error (GRUB_ERR_BAD_ARGUMENT, "no kernel specified");
elf = grub_elf_open (argv[0]);
if (! elf)
return grub_errno;
if (elf->ehdr.ehdr32.e_type != ET_EXEC)
{
grub_elf_close (elf);
return grub_error (GRUB_ERR_UNKNOWN_OS,
"This ELF file is not of the right type\n");
}
/* Release the previously used memory. */
grub_loader_unset ();
loaded = 0;
/* For arguments. */
linux_argc = argc;
/* Main arguments. */
size = (linux_argc) * sizeof (grub_uint32_t);
/* Initrd address and size. */
size += 2 * sizeof (grub_uint32_t);
/* NULL terminator. */
size += sizeof (grub_uint32_t);
/* First argument is always "a0". */
size += ALIGN_UP (sizeof ("a0"), 4);
/* Normal arguments. */
for (i = 1; i < argc; i++)
size += ALIGN_UP (grub_strlen (argv[i]) + 1, 4);
/* rd arguments. */
size += ALIGN_UP (sizeof ("rd_start=0xXXXXXXXXXXXXXXXX"), 4);
size += ALIGN_UP (sizeof ("rd_size=0xXXXXXXXXXXXXXXXX"), 4);
/* For the environment. */
size += sizeof (grub_uint32_t);
size += 4 * sizeof (grub_uint32_t);
size += ALIGN_UP (sizeof ("memsize=XXXXXXXXXXXXXXXXXXXX"), 4)
+ ALIGN_UP (sizeof ("highmemsize=XXXXXXXXXXXXXXXXXXXX"), 4)
+ ALIGN_UP (sizeof ("busclock=XXXXXXXXXX"), 4)
+ ALIGN_UP (sizeof ("cpuclock=XXXXXXXXXX"), 4);
if (grub_elf_is_elf32 (elf))
err = grub_linux_load32 (elf, &extra, size);
else
if (grub_elf_is_elf64 (elf))
err = grub_linux_load64 (elf, &extra, size);
else
err = grub_error (GRUB_ERR_BAD_FILE_TYPE, "Unknown ELF class");
grub_elf_close (elf);
if (err)
return err;
linux_argv = extra;
argv_off = (grub_uint8_t *) linux_argv - (grub_uint8_t *) playground;
extra = linux_argv + (linux_argc + 1 + 2);
linux_args = extra;
grub_memcpy (linux_args, "a0", sizeof ("a0"));
*linux_argv = (grub_uint8_t *) linux_args - (grub_uint8_t *) playground
+ target_addr;
linux_argv++;
linux_args += ALIGN_UP (sizeof ("a0"), 4);
for (i = 1; i < argc; i++)
{
grub_memcpy (linux_args, argv[i], grub_strlen (argv[i]) + 1);
*linux_argv = (grub_uint8_t *) linux_args - (grub_uint8_t *) playground
+ target_addr;
linux_argv++;
linux_args += ALIGN_UP (grub_strlen (argv[i]) + 1, 4);
}
/* Reserve space for rd arguments. */
rd_addr_arg_off = (grub_uint8_t *) linux_args - (grub_uint8_t *) playground;
linux_args += ALIGN_UP (sizeof ("rd_start=0xXXXXXXXXXXXXXXXX"), 4);
*linux_argv = 0;
linux_argv++;
rd_size_arg_off = (grub_uint8_t *) linux_args - (grub_uint8_t *) playground;
linux_args += ALIGN_UP (sizeof ("rd_size=0xXXXXXXXXXXXXXXXX"), 4);
*linux_argv = 0;
linux_argv++;
*linux_argv = 0;
extra = linux_args;
linux_envp = extra;
envp_off = (grub_uint8_t *) linux_envp - (grub_uint8_t *) playground;
linux_envs = (char *) (linux_envp + 5);
grub_snprintf (linux_envs, sizeof ("memsize=XXXXXXXXXXXXXXXXXXXX"),
"memsize=%lld",
(unsigned long long) grub_mmap_get_lower () >> 20);
linux_envp[0] = (grub_uint8_t *) linux_envs - (grub_uint8_t *) playground
+ target_addr;
linux_envs += ALIGN_UP (grub_strlen (linux_envs) + 1, 4);
grub_snprintf (linux_envs, sizeof ("highmemsize=XXXXXXXXXXXXXXXXXXXX"),
"highmemsize=%lld",
(unsigned long long) grub_mmap_get_upper () >> 20);
linux_envp[1] = (grub_uint8_t *) linux_envs - (grub_uint8_t *) playground
+ target_addr;
linux_envs += ALIGN_UP (grub_strlen (linux_envs) + 1, 4);
grub_snprintf (linux_envs, sizeof ("busclock=XXXXXXXXXX"),
"busclock=%d", grub_arch_busclock);
linux_envp[2] = (grub_uint8_t *) linux_envs - (grub_uint8_t *) playground
+ target_addr;
linux_envs += ALIGN_UP (grub_strlen (linux_envs) + 1, 4);
grub_snprintf (linux_envs, sizeof ("cpuclock=XXXXXXXXXX"),
"cpuclock=%d", grub_arch_cpuclock);
linux_envp[3] = (grub_uint8_t *) linux_envs - (grub_uint8_t *) playground
+ target_addr;
linux_envs += ALIGN_UP (grub_strlen (linux_envs) + 1, 4);
linux_envp[4] = 0;
grub_loader_set (grub_linux_boot, grub_linux_unload, 1);
initrd_loaded = 0;
loaded = 1;
grub_dl_ref (my_mod);
return GRUB_ERR_NONE;
}
static grub_err_t
grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)),
int argc, char *argv[])
{
grub_file_t file = 0;
grub_ssize_t size;
grub_size_t overhead;
if (argc == 0)
return grub_error (GRUB_ERR_BAD_ARGUMENT, "No initrd specified");
if (!loaded)
return grub_error (GRUB_ERR_BAD_ARGUMENT, "You need to load Linux first.");
if (initrd_loaded)
return grub_error (GRUB_ERR_BAD_ARGUMENT, "Only one initrd can be loaded.");
file = grub_file_open (argv[0]);
if (! file)
return grub_errno;
size = grub_file_size (file);
overhead = ALIGN_UP (target_addr + linux_size + 0x10000, 0x10000)
- (target_addr + linux_size);
playground = grub_relocator32_realloc (playground,
linux_size + overhead + size);
if (!playground)
{
grub_file_close (file);
return grub_errno;
}
if (grub_file_read (file, playground + linux_size + overhead, size) != size)
{
grub_error (GRUB_ERR_FILE_READ_ERROR, "Couldn't read file");
grub_file_close (file);
return grub_errno;
}
grub_snprintf ((char *) playground + rd_addr_arg_off,
sizeof ("rd_start=0xXXXXXXXXXXXXXXXX"), "rd_start=0x%llx",
(unsigned long long) target_addr + linux_size + overhead);
((grub_uint32_t *) (playground + argv_off))[linux_argc]
= target_addr + rd_addr_arg_off;
linux_argc++;
grub_snprintf ((char *) playground + rd_size_arg_off,
sizeof ("rd_size=0xXXXXXXXXXXXXXXXXX"), "rd_size=0x%llx",
(unsigned long long) size);
((grub_uint32_t *) (playground + argv_off))[linux_argc]
= target_addr + rd_size_arg_off;
linux_argc++;
initrd_loaded = 1;
grub_file_close (file);
return GRUB_ERR_NONE;
}
static grub_command_t cmd_linux, cmd_initrd;
GRUB_MOD_INIT(linux)
{
cmd_linux = grub_register_command ("linux", grub_cmd_linux,
0, N_("Load Linux."));
cmd_initrd = grub_register_command ("initrd", grub_cmd_initrd,
0, N_("Load initrd."));
my_mod = mod;
}
GRUB_MOD_FINI(linux)
{
grub_unregister_command (cmd_linux);
grub_unregister_command (cmd_initrd);
}

View file

@ -111,7 +111,7 @@ grub_linux_load32 (grub_elf_t elf)
if (entry == 0)
entry = 0x01400000;
linux_size = grub_elf32_size (elf);
linux_size = grub_elf32_size (elf, 0);
if (linux_size == 0)
return grub_errno;
/* Pad it; the kernel scribbles over memory beyond its load address. */
@ -161,7 +161,7 @@ grub_linux_load64 (grub_elf_t elf)
if (entry == 0)
entry = 0x01400000;
linux_size = grub_elf64_size (elf);
linux_size = grub_elf64_size (elf, 0);
if (linux_size == 0)
return grub_errno;
/* Pad it; the kernel scribbles over memory beyond its load address. */

View file

@ -247,7 +247,7 @@ grub_linux_load64 (grub_elf_t elf)
linux_entry = elf->ehdr.ehdr64.e_entry;
linux_addr = 0x40004000;
off = 0x4000;
linux_size = grub_elf64_size (elf);
linux_size = grub_elf64_size (elf, 0);
if (linux_size == 0)
return grub_errno;

View file

@ -561,10 +561,9 @@ grub_xnu_register_memory (char *prefix, int *suffix,
return grub_error (GRUB_ERR_OUT_OF_MEMORY, "can't register memory");
if (suffix)
{
driverkey->name = grub_malloc (grub_strlen (prefix) + 10);
driverkey->name = grub_xasprintf ("%s%d", prefix, (*suffix)++);
if (!driverkey->name)
return grub_error (GRUB_ERR_OUT_OF_MEMORY, "can't register memory");
grub_sprintf (driverkey->name, "%s%d", prefix, (*suffix)++);
}
else
driverkey->name = grub_strdup (prefix);