/* linux.c - boot Linux */
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2003,2004,2005,2007,2009,2010 Free Software Foundation, Inc.
*
* 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/>.
*/
GRUB_MOD_LICENSE ("GPLv3+");
/* For frequencies. */
#ifdef GRUB_MACHINE_MIPS_LOONGSON
{
[GRUB_ARCH_MACHINE_YEELOONG] = "machtype=lemote-yeeloong-2f-8.9inches",
[GRUB_ARCH_MACHINE_FULOONG2F] = "machtype=lemote-fuloong-2f-box",
[GRUB_ARCH_MACHINE_FULOONG2E] = "machtype=lemote-fuloong-2e-unknown"
};
#endif
static int loaded;
#ifdef GRUB_MACHINE_MIPS_QEMU_MIPS
static char *params;
#else
static int linux_argc;
#ifdef GRUB_MACHINE_MIPS_LOONGSON
#endif
#endif
static int initrd_loaded = 0;
static grub_err_t
grub_linux_boot (void)
{
/* Boot the kernel. */
#ifdef GRUB_MACHINE_MIPS_QEMU_MIPS
{
char *str;
((16 << 20) - 264),
if (err)
return err;
*memsize = grub_mmap_get_lower ();
*magic = 0x12345678;
}
#endif
#ifndef GRUB_MACHINE_MIPS_QEMU_MIPS
#ifdef GRUB_MACHINE_MIPS_LOONGSON
#else
#endif
#endif
return GRUB_ERR_NONE;
}
static grub_err_t
grub_linux_unload (void)
{
#ifdef GRUB_MACHINE_MIPS_QEMU_MIPS
params = 0;
#endif
loaded = 0;
return GRUB_ERR_NONE;
}
static grub_err_t
{
int extraoff;
/* Linux's entry point incorrectly contains a virtual address. */
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 += extra_size;
relocator = grub_relocator_new ();
if (!relocator)
return grub_errno;
{
target_addr & 0x1fffffff,
if (err)
return err;
}
/* Now load the segments into the area we claimed. */
{
{
*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. */
return 0;
}
}
static grub_err_t
{
int extraoff;
/* Linux's entry point incorrectly contains a virtual address. */
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 += extra_size;
relocator = grub_relocator_new ();
if (!relocator)
return grub_errno;
{
target_addr & 0x1fffffff,
if (err)
return err;
}
/* Now load the segments into the area we claimed. */
{
{
*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. */
return 0;
}
}
static grub_err_t
{
int size;
#ifndef GRUB_MACHINE_MIPS_QEMU_MIPS
int i;
char *linux_args;
#endif
#ifdef GRUB_MACHINE_MIPS_LOONGSON
char *linux_envs;
#endif
if (argc == 0)
if (! elf)
return grub_errno;
{
return grub_error (GRUB_ERR_UNKNOWN_OS,
"this ELF file is not of the right type\n");
}
/* Release the previously used memory. */
loaded = 0;
#ifdef GRUB_MACHINE_MIPS_QEMU_MIPS
size = 0;
#else
/* For arguments. */
linux_argc = argc;
#ifdef GRUB_MACHINE_MIPS_LOONGSON
linux_argc++;
#endif
/* Main arguments. */
/* Initrd address and size. */
/* NULL terminator. */
size += sizeof (grub_uint32_t);
/* First argument is always "a0". */
/* Normal arguments. */
for (i = 1; i < argc; i++)
#ifdef GRUB_MACHINE_MIPS_LOONGSON
#endif
/* rd arguments. */
/* For the environment. */
size += sizeof (grub_uint32_t);
#endif
if (grub_elf_is_elf32 (elf))
else
if (grub_elf_is_elf64 (elf))
else
if (err)
return err;
#ifdef GRUB_MACHINE_MIPS_QEMU_MIPS
/* Create kernel command line. */
if (! params)
{
return grub_errno;
}
size);
#else
linux_argv = extra;
linux_args = extra;
+ target_addr;
linux_argv++;
#ifdef GRUB_MACHINE_MIPS_LOONGSON
{
unsigned mtype = grub_arch_machine;
mtype = 0;
/* In Loongson platform, it is the responsibility of the bootloader/firmware
to supply the OS kernel with machine type information. */
sizeof (loongson_machtypes[mtype]));
+ target_addr;
linux_argv++;
}
#endif
for (i = 1; i < argc; i++)
{
+ target_addr;
linux_argv++;
}
/* Reserve space for rd arguments. */
*linux_argv = 0;
linux_argv++;
*linux_argv = 0;
linux_argv++;
*linux_argv = 0;
extra = linux_args;
#ifdef GRUB_MACHINE_MIPS_LOONGSON
linux_envp = extra;
"memsize=%lld",
(unsigned long long) grub_mmap_get_lower () >> 20);
+ target_addr;
"highmemsize=%lld",
(unsigned long long) grub_mmap_get_upper () >> 20);
+ target_addr;
"busclock=%d", grub_arch_busclock);
+ target_addr;
"cpuclock=%d", grub_arch_cpuclock);
+ target_addr;
linux_envp[4] = 0;
#endif
#endif
initrd_loaded = 0;
loaded = 1;
return GRUB_ERR_NONE;
}
static grub_err_t
{
void *initrd_src;
int i;
int nfiles = 0;
if (argc == 0)
if (!loaded)
if (initrd_loaded)
if (!files)
goto fail;
for (i = 0; i < argc; i++)
{
if (! files[i])
goto fail;
nfiles++;
}
{
(target_addr & 0x1fffffff)
+ linux_size + 0x10000,
(0x10000000 - size),
size, 0x10000,
if (err)
goto fail;
}
ptr = initrd_src;
for (i = 0; i < nfiles; i++)
{
{
if (!grub_errno)
argv[i]);
goto fail;
}
}
#ifdef GRUB_MACHINE_MIPS_QEMU_MIPS
{
char *tmp;
initrd_dest, size);
if (!tmp)
goto fail;
}
#else
sizeof ("rd_start=0xXXXXXXXXXXXXXXXX"), "rd_start=0x%llx",
(unsigned long long) initrd_dest);
linux_argc++;
sizeof ("rd_size=0xXXXXXXXXXXXXXXXXX"), "rd_size=0x%llx",
(unsigned long long) size);
linux_argc++;
#endif
initrd_loaded = 1;
fail:
for (i = 0; i < nfiles; i++)
grub_file_close (files[i]);
return grub_errno;
}
{
0, N_("Load Linux."));
0, N_("Load initrd."));
}
{
}