Support long command lines as per 2.06 Linux boot protocol

This commit is contained in:
Vladimir 'phcoder' Serbinenko 2010-11-13 21:27:08 +01:00
parent bc5dd0b9ca
commit a06eb03ad0
3 changed files with 35 additions and 14 deletions

View file

@ -36,7 +36,6 @@
#include <grub/i386/floppy.h>
#define GRUB_LINUX_CL_OFFSET 0x9000
#define GRUB_LINUX_CL_END_OFFSET 0x90FF
static grub_dl_t my_mod;
@ -46,6 +45,7 @@ static struct grub_relocator *relocator = NULL;
static grub_addr_t grub_linux_real_target;
static char *grub_linux_real_chunk;
static grub_size_t grub_linux16_prot_size;
static grub_size_t maximal_cmdline_size;
static grub_err_t
grub_linux16_boot (void)
@ -126,15 +126,20 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
setup_sects = lh.setup_sects;
linux_mem_size = 0;
maximal_cmdline_size = 256;
if (lh.header == grub_cpu_to_le32 (GRUB_LINUX_MAGIC_SIGNATURE)
&& grub_le_to_cpu16 (lh.version) >= 0x0200)
{
grub_linux_is_bzimage = (lh.loadflags & GRUB_LINUX_FLAG_BIG_KERNEL);
lh.type_of_loader = GRUB_LINUX_BOOT_LOADER_TYPE;
if (grub_le_to_cpu16 (lh.version) >= 0x0206)
maximal_cmdline_size = grub_le_to_cpu32 (lh.cmdline_size) + 1;
/* Put the real mode part at as a high location as possible. */
grub_linux_real_target = grub_mmap_get_lower ()
- GRUB_LINUX_SETUP_MOVE_SIZE;
- (GRUB_LINUX_CL_OFFSET + maximal_cmdline_size);
/* But it must not exceed the traditional area. */
if (grub_linux_real_target > GRUB_LINUX_OLD_REAL_MODE_ADDR)
grub_linux_real_target = GRUB_LINUX_OLD_REAL_MODE_ADDR;
@ -151,7 +156,8 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
{
lh.cl_magic = grub_cpu_to_le16 (GRUB_LINUX_CL_MAGIC);
lh.cl_offset = grub_cpu_to_le16 (GRUB_LINUX_CL_OFFSET);
lh.setup_move_size = grub_cpu_to_le16 (GRUB_LINUX_SETUP_MOVE_SIZE);
lh.setup_move_size = grub_cpu_to_le16 (GRUB_LINUX_CL_OFFSET
+ maximal_cmdline_size);
}
}
else
@ -183,12 +189,13 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
goto fail;
}
if (grub_linux_real_target + GRUB_LINUX_SETUP_MOVE_SIZE
if (grub_linux_real_target + GRUB_LINUX_CL_OFFSET + maximal_cmdline_size
> grub_mmap_get_lower ())
{
grub_error (GRUB_ERR_OUT_OF_RANGE,
"too small lower memory (0x%x > 0x%x)",
grub_linux_real_target + GRUB_LINUX_SETUP_MOVE_SIZE,
grub_linux_real_target + GRUB_LINUX_CL_OFFSET
+ maximal_cmdline_size,
(int) grub_mmap_get_lower ());
goto fail;
}
@ -261,7 +268,8 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
grub_relocator_chunk_t ch;
err = grub_relocator_alloc_chunk_addr (relocator, &ch,
grub_linux_real_target,
GRUB_LINUX_SETUP_MOVE_SIZE);
GRUB_LINUX_CL_OFFSET
+ maximal_cmdline_size);
if (err)
return err;
grub_linux_real_chunk = get_virtual_current_address (ch);
@ -294,8 +302,9 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
/* Copy kernel parameters. */
for (i = 1;
i < argc
&& dest + grub_strlen (argv[i]) + 1 < (grub_linux_real_chunk
+ GRUB_LINUX_CL_END_OFFSET);
&& dest + grub_strlen (argv[i]) + 2 < (grub_linux_real_chunk
+ GRUB_LINUX_CL_OFFSET
+ maximal_cmdline_size);
i++)
{
*dest++ = ' ';