/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2008,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+");
struct ia64_boot_param
{
struct
{
} console_info;
};
struct ia64_boot_payload
{
/* Payload command line */
};
typedef struct
{
void *fpswa;
static int loaded;
/* Kernel base and size. */
static void *kernel_mem;
/* Initrd base and size. */
static void *initrd_mem;
/* Can linux kernel be relocated ? */
static inline grub_size_t
{
}
static void
query_fpswa (void)
{
{ 0xc41b6531, 0x97b9, 0x11d3,
{0x9a, 0x29, 0x0, 0x90, 0x27, 0x3f, 0xc1, 0x4d} };
return;
size = sizeof(grub_efi_handle_t);
(void *)&fpswa_protocol,
if (status != GRUB_EFI_SUCCESS)
{
grub_printf("Could not locate FPSWA driver\n");
return;
}
(void *)&fpswa_protocol, (void *)&fpswa);
if (status != GRUB_EFI_SUCCESS)
{
grub_printf ("Fpswa protocol not able find the interface\n");
return;
}
}
/* Find the optimal number of pages for the memory map. Is it better to
static grub_efi_uintn_t
find_mmap_size (void)
{
if (mmap_size != 0)
return mmap_size;
while (1)
{
int ret;
if (! mmap)
return 0;
if (ret < 0)
grub_fatal ("cannot get memory map");
else if (ret > 0)
break;
}
/* Increase the size a bit for safety, because GRUB allocates more on
later, and EFI itself may allocate more. */
return page_align (mmap_size);
}
static void
free_pages (void)
{
if (kernel_mem)
{
kernel_mem = 0;
}
if (initrd_mem)
{
initrd_mem = 0;
}
if (boot_param)
{
/* Free payloads. */
while (payload != 0)
{
}
/* Free bootparam. */
boot_param = 0;
}
}
static void *
{
mmap_size = find_mmap_size ();
/* Read the memory map temporarily, to find free space. */
if (! mmap)
return 0;
grub_fatal ("cannot get memory map");
/* First, find free pages for the real mode code
and the memory map buffer. */
{
continue;
/* Align is a power of 2. */
continue;
if (aligned_start == nobase)
aligned_start += align;
continue;
if (! mem)
grub_fatal ("cannot allocate pages");
break;
}
if (! mem)
{
goto fail;
}
return mem;
fail:
free_pages ();
return 0;
}
static void
set_boot_param_console (void)
{
!= GRUB_EFI_SUCCESS)
return;
grub_dprintf("linux",
"Console info: cols=%lu rows=%lu x=%u y=%u\n",
}
static grub_err_t
grub_linux_boot (void)
{
/* FPSWA. */
query_fpswa ();
/* Initrd. */
/* MDT.
Must be done after grub_machine_fini because map_key is used by
exit_boot_services. */
mmap_size = find_mmap_size ();
if (! mmap_buf)
grub_fatal ("cannot allocate memory map");
&desc_size, &desc_version);
if (err)
return err;
/* See you next boot. */
/* Never reach here. */
return GRUB_ERR_NONE;
}
static grub_err_t
grub_linux_unload (void)
{
free_pages ();
loaded = 0;
return GRUB_ERR_NONE;
}
static grub_err_t
{
int i;
/* FIXME: Should we support program headers at strange locations? */
/* Compute low, high and align addresses. */
high_addr = 0;
align = 0;
{
+ i * ehdr->e_phentsize);
{
}
}
if (high_addr == 0)
if (relocate != RELOCATE_FORCE)
{
reloc_offset = 0;
}
/* Try to relocate. */
{
if (kernel_mem)
{
grub_printf (" Relocated at %p (offset=%016lx)\n",
entry += reloc_offset;
}
}
if (! kernel_mem)
return grub_error (GRUB_ERR_OUT_OF_MEMORY,
"cannot allocate memory for OS");
/* Load every loadable segment in memory. */
{
+ i * ehdr->e_phentsize);
{
grub_printf (" [paddr=%lx load=%lx memsz=%08lx "
"off=%lx flags=%x]\n",
return grub_error (GRUB_ERR_BAD_OS,
"invalid offset in program header");
{
if (!grub_errno)
filename);
return grub_errno;
}
/* Sync caches if necessary. */
}
}
loaded = 1;
return 0;
}
static grub_err_t
{
char *cmdline, *p;
int i;
if (argc == 0)
{
goto fail;
}
if (! file)
goto fail;
{
goto fail;
}
goto fail;
for (i = 0; i < argc; i++)
if (boot_param == 0)
{
"cannot allocate memory for bootparams");
goto fail;
}
/* Build cmdline. */
for (i = 0; i < argc; i++)
{
*p++ = ' ';
p = grub_stpcpy (p, argv[i]);
}
fail:
if (file)
if (grub_errno != GRUB_ERR_NONE)
{
}
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;
initrd_size = 0;
grub_printf ("Loading initrd: ");
for (i = 0; i < argc; i++)
{
if (! files[i])
goto fail;
nfiles++;
}
grub_printf ("\n");
if (! initrd_mem)
grub_fatal ("cannot allocate pages");
grub_printf (" [addr=0x%lx, size=0x%lx]\n",
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;
}
static grub_err_t
{
int i;
if (argc == 0)
{
goto fail;
}
if (!boot_param)
{
"You need to load the kernel first");
goto fail;
}
if (! file)
goto fail;
if (! base)
goto fail;
grub_printf ("Payload %s [addr=%lx + %lx]\n",
{
if (!grub_errno)
argv[0]);
goto fail;
}
len = sizeof (struct ia64_boot_payload);
for (i = 0; i < argc; i++)
if (len > 4096)
{
goto fail;
}
if (! payload)
goto fail;
p = (char *)(payload + 1);
if (last_payload)
else
{
}
/* Copy command line. */
for (i = 0; i < argc; i++)
{
p = grub_stpcpy (p, argv[i]);
*(p++) = ' ';
}
/* Remove the space after the last word. */
*(--p) = '\0';
fail:
if (file)
if (grub_errno != GRUB_ERR_NONE)
{
}
return grub_errno;
}
static grub_err_t
{
unsigned int i;
if (argc == 0)
{
return GRUB_ERR_NONE;
}
else if (argc == 1)
{
if (kernel_mem != NULL)
grub_printf ("Warning: kernel already loaded!\n");
{
relocate = i;
return GRUB_ERR_NONE;
}
}
else
{
}
}
static grub_err_t
{
if (argc != 0)
{
}
query_fpswa ();
grub_printf ("No FPSWA loaded\n");
else
return GRUB_ERR_NONE;
}
{
"FILE [ARGS...]", "Load Linux.");
"FILE", "Load initrd.");
"FILE [ARGS...]",
"Load an additional file.");
"[on|off|force]",
"Set relocate feature.");
"", "Display FPSWA version.");
}
{
}