/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2006,2007,2008,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/>.
*/
#include <grub/video_fb.h>
GRUB_MOD_LICENSE ("GPLv3+");
#ifdef GRUB_MACHINE_PCBIOS
#endif
#ifdef GRUB_MACHINE_EFI
#define HAS_VGA_TEXT 0
#define ACCEPTS_PURE_TEXT 0
#elif defined (GRUB_MACHINE_IEEE1275)
#define HAS_VGA_TEXT 0
#else
#endif
static int loaded;
static void *real_mode_mem;
static void *prot_mode_mem;
static void *initrd_mem;
static void *efi_mmap_buf;
#ifdef GRUB_MACHINE_EFI
#else
#endif
/* FIXME */
#if 0
struct idt_descriptor
{
void *base;
} __attribute__ ((packed));
static struct idt_descriptor idt_desc =
{
0,
0
};
#endif
/* Find the optimal number of pages for the memory map. */
static grub_size_t
find_mmap_size (void)
{
{
count++;
return 0;
}
/* Increase the size a bit for safety, because GRUB allocates more on
later. */
return grub_page_align (mmap_size);
}
static void
free_pages (void)
{
}
/* Allocate pages for the real mode code and the protected mode code
for linux as well as a memory map buffer. */
static grub_err_t
{
/* Make sure that each size is aligned to a page boundary. */
mmap_size = find_mmap_size ();
#ifdef GRUB_MACHINE_EFI
if (efi_mmap_size == 0)
return grub_errno;
#endif
/* Calculate the number of pages; Combine the real mode code with
the memory map buffer for simplicity. */
/* Initialize the memory pointers with NULL for convenience. */
free_pages ();
relocator = grub_relocator_new ();
if (!relocator)
{
err = grub_errno;
goto fail;
}
/* FIXME: Should request low memory from the heap when this feature is
implemented. */
{
/* We must put real mode code in the traditional space. */
if (type == GRUB_MEMORY_AVAILABLE
&& addr <= 0x90000)
{
if (addr < 0x10000)
{
addr = 0x10000;
}
return 0;
return 1;
}
return 0;
}
if (! real_mode_target)
{
goto fail;
}
{
+ efi_mmap_size));
if (err)
goto fail;
}
{
if (err)
goto fail;
}
"prot_mode_mem = %lx, prot_mode_pages = %x\n",
(unsigned long) real_mode_mem, (unsigned) real_mode_pages,
(unsigned long) prot_mode_mem, (unsigned) prot_mode_pages);
return GRUB_ERR_NONE;
fail:
free_pages ();
return err;
}
static grub_err_t
{
int n = *e820_num;
if (n >= GRUB_E820_MAX_ENTRY)
{
return grub_error (GRUB_ERR_OUT_OF_RANGE,
"Too many e820 memory map entries");
}
else
{
(*e820_num)++;
}
return GRUB_ERR_NONE;
}
static grub_err_t
{
void *framebuffer;
if (driver_id == GRUB_VIDEO_DRIVER_NONE)
return 1;
if (err)
{
return 1;
}
else
{
switch (driver_id)
{
case GRUB_VIDEO_DRIVER_VBE:
break;
break;
/* FIXME: check if better id is available. */
case GRUB_VIDEO_DRIVER_SM712:
case GRUB_VIDEO_DRIVER_VGA:
case GRUB_VIDEO_DRIVER_CIRRUS:
case GRUB_VIDEO_DRIVER_BOCHS:
/* Make gcc happy. */
case GRUB_VIDEO_DRIVER_SDL:
case GRUB_VIDEO_DRIVER_NONE:
break;
}
}
#ifdef GRUB_MACHINE_PCBIOS
/* VESA packed modes may come with zeroed mask sizes, which need
to be set here according to DAC Palette width. If we don't,
this results in Linux displaying a black screen. */
{
int status;
if (status == GRUB_VBE_STATUS_OK &&
if (status != GRUB_VBE_STATUS_OK)
/* 6 is default after mode reset. */
width = 6;
params->reserved_mask_size = 0;
}
#endif
return GRUB_ERR_NONE;
}
static grub_err_t
grub_linux_boot (void)
{
int e820_num;
const char *modevar;
char *tmp;
#ifdef GRUB_MACHINE_IEEE1275
{
const char *bootpath;
if (bootpath)
"bootpath", bootpath,
&len);
}
#endif
(unsigned) params->code32_start);
{
switch (type)
{
case GRUB_MEMORY_AVAILABLE:
break;
case GRUB_MEMORY_ACPI:
break;
case GRUB_MEMORY_NVS:
break;
case GRUB_MEMORY_BADRAM:
break;
default:
}
return 1;
return 0;
}
e820_num = 0;
if (grub_mmap_iterate (hook))
return grub_errno;
/* Now all graphical modes are acceptable.
May change in future if we have modes without framebuffer. */
{
if (! tmp)
return grub_errno;
#else
#endif
}
else
{
#else
#endif
}
if (err)
{
grub_print_error ();
}
if (grub_linux_setup_video (params))
{
#else
params->video_mode = 0;
params->video_width = 0;
params->video_height = 0;
#endif
}
/* Initialize these last, because terminal position could be affected by printfs above. */
#ifndef GRUB_MACHINE_IEEE1275
#endif
{
int found = 0;
{
found = 1;
break;
}
if (!found)
{
params->video_cursor_x = 0;
params->video_cursor_y = 0;
}
}
#ifdef GRUB_MACHINE_IEEE1275
{
}
#endif
#ifdef GRUB_MACHINE_EFI
{
if (err)
return err;
/* Note that no boot services are available from here. */
/* Pass EFI parameters. */
{
#ifdef __x86_64__
#endif
}
{
}
}
#endif
/* FIXME. */
/* asm volatile ("lidt %0" : : "m" (idt_desc)); */
}
static grub_err_t
grub_linux_unload (void)
{
loaded = 0;
return GRUB_ERR_NONE;
}
static grub_err_t
{
int i;
if (argc == 0)
{
goto fail;
}
if (! file)
goto fail;
{
if (!grub_errno)
argv[0]);
goto fail;
}
{
goto fail;
}
{
goto fail;
}
{
#ifdef GRUB_MACHINE_PCBIOS
" (try with `linux16')"
#endif
);
goto fail;
}
/* FIXME: 2.03 is not always good enough (Linux 2.4 can be 2.03 and
still not support 32-bit boot. */
{
#ifdef GRUB_MACHINE_PCBIOS
" (try with `linux16')"
#endif
);
goto fail;
}
else
maximal_cmdline_size = 256;
if (maximal_cmdline_size < 128)
maximal_cmdline_size = 128;
/* If SETUP_SECTS is not set, set it to the default (4). */
if (! setup_sects)
if (allocate_pages (prot_size))
goto fail;
{
if (!grub_errno)
argv[0]);
goto fail;
}
/* These two are used (instead of cmd_line_ptr) by older versions of Linux,
and otherwise ignored. */
params->ramdisk_image = 0;
params->ramdisk_size = 0;
/* These are not needed to be precise, because Linux uses these values
only to raise an error when the decompression code cannot find good
space. */
/* Ignored by Linux. */
params->video_page = 0;
/* Only used when `video_mode == 0x7', otherwise ignored. */
params->video_ega_bx = 0;
#ifdef GRUB_MACHINE_EFI
{
#ifdef __x86_64__
#endif
}
{
}
#endif
/* The other parameters are filled when booting. */
/* Look for memory size and video mode specified on the command line. */
linux_mem_size = 0;
for (i = 1; i < argc; i++)
#ifdef GRUB_MACHINE_PCBIOS
{
/* Video mode selection support. */
char *buf;
grub_dl_load ("vbe");
{
/* We usually would never do this in a loader, but "vga=ask" means user
requested interaction, so it can't hurt to request keyboard input. */
goto fail;
}
else
switch (vid_mode)
{
case 0:
"Use set gfxpayload=text before "
"linux command instead.\n"),
argv[i]);
break;
case 1:
/* FIXME: support 80x50 text. */
"Use set gfxpayload=text before "
"linux command instead.\n"),
argv[i]);
break;
default:
/* Ignore invalid values. */
if (vid_mode < GRUB_VESA_MODE_TABLE_START ||
{
"Use set gfxpayload=WIDTHxHEIGHT[xDEPTH] "
"before linux command instead.\n"),
break;
}
if (! buf)
goto fail;
"Use set gfxpayload=%s before "
"linux command instead.\n"),
if (err)
goto fail;
}
}
else
#endif /* GRUB_MACHINE_PCBIOS */
{
if (grub_errno)
{
linux_mem_size = 0;
}
else
{
int shift = 0;
switch (grub_tolower (val[0]))
{
case 'g':
shift += 10;
case 'm':
shift += 10;
case 'k':
shift += 10;
default:
break;
}
/* Check an overflow. */
linux_mem_size = 0;
else
}
}
{
}
/* Create kernel command line. */
sizeof (LINUX_IMAGE));
(char *)real_mode_mem + GRUB_LINUX_CL_OFFSET
+ sizeof (LINUX_IMAGE) - 1,
- (sizeof (LINUX_IMAGE) - 1));
argv[0]);
if (grub_errno == GRUB_ERR_NONE)
{
0 /* set noreturn=0 in order to avoid grub_console_fini() */);
loaded = 1;
}
fail:
if (file)
if (grub_errno != GRUB_ERR_NONE)
{
loaded = 0;
}
return grub_errno;
}
static grub_err_t
{
int i;
int nfiles = 0;
if (argc == 0)
{
goto fail;
}
if (! loaded)
{
goto fail;
}
if (!files)
goto fail;
for (i = 0; i < argc; i++)
{
if (! files[i])
goto fail;
nfiles++;
}
/* Get the highest address available for the initrd. */
{
/* XXX in reality, Linux specifies a bogus value, so
it is necessary to make sure that ADDR_MAX does not exceed
0x3fffffff. */
}
else
/* Linux 2.3.xx has a bug in the memory range check, so avoid
the last page.
Linux 2.2.xx has a bug in the memory range check, which is
worse than that of Linux 2.3.xx, so avoid the last 64kb. */
addr_max -= 0x10000;
/* Usually, the compression ratio is about 50%. */
+ grub_page_align (size);
/* Put the initrd as high as possible, 4KiB aligned. */
{
goto fail;
}
{
if (err)
return err;
}
ptr = initrd_mem;
for (i = 0; i < nfiles; i++)
{
{
if (!grub_errno)
argv[i]);
goto fail;
}
}
fail:
for (i = 0; i < nfiles; i++)
grub_file_close (files[i]);
return grub_errno;
}
{
0, N_("Load Linux."));
0, N_("Load initrd."));
}
{
}