From 30ec0405c4429fdfe92a0a745a2e3a63cbf45e9a Mon Sep 17 00:00:00 2001 From: okuji Date: Mon, 25 Mar 2002 21:43:55 +0000 Subject: [PATCH] 2002-03-26 Yoshinori K. Okuji * stage2/boot.c (linux_mem_size): New variable. (load_image): Check a mem= option and set LINUX_MEM_SIZE to the specified memory size, if any. Otherwise, to zero. When an overflow is detected, use LINUX_INITRD_MAX_ADDRESS instead. (load_initrd): If LINUX_MEM_SIZE is non-zero, use it instead of the actual memory size. * stage2/char_io.c (safe_parse_maxint): Use ERR_NUMBER_OVERFLOW instead of ERR_NUMBER_PARSING, when an overflow occurs. * stage2/common.c [!STAGE1_5] (err_list): Added ERR_NUMBER_OVERFLOW. * stage2/shared.h (ERR_NUMBER_OVERFLOW): New constant. --- ChangeLog | 14 +++++++++++ NEWS | 5 ++++ stage2/boot.c | 65 +++++++++++++++++++++++++++++++++++++++++++++--- stage2/char_io.c | 2 +- stage2/common.c | 3 ++- stage2/shared.h | 1 + 6 files changed, 85 insertions(+), 5 deletions(-) diff --git a/ChangeLog b/ChangeLog index 101370144..8b97ea497 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,17 @@ +2002-03-26 Yoshinori K. Okuji + + * stage2/boot.c (linux_mem_size): New variable. + (load_image): Check a mem= option and set LINUX_MEM_SIZE to the + specified memory size, if any. Otherwise, to zero. When an + overflow is detected, use LINUX_INITRD_MAX_ADDRESS instead. + (load_initrd): If LINUX_MEM_SIZE is non-zero, use it instead of + the actual memory size. + * stage2/char_io.c (safe_parse_maxint): Use ERR_NUMBER_OVERFLOW + instead of ERR_NUMBER_PARSING, when an overflow occurs. + * stage2/common.c [!STAGE1_5] (err_list): Added + ERR_NUMBER_OVERFLOW. + * stage2/shared.h (ERR_NUMBER_OVERFLOW): New constant. + 2002-03-24 Yoshinori K. Okuji * stage2/stage2.c (run_menu): Call cls outside the loop to run diff --git a/NEWS b/NEWS index 7b10123c3..68105444f 100644 --- a/NEWS +++ b/NEWS @@ -17,6 +17,11 @@ New in 0.92: * The command "terminal" accepts a new option, "--lines=LINES". You can set the maximum number of lines arbitrarily with this option. If you don't specify it, the maximum number will be 24. +* The mem= option for Linux is recognized and used to limit the maximum + address of initrd. +* A fallback entry is executed immediately after a default entry, + without prompting a user's intervention, as the manual has ever been + saying. New in 0.91 - 2002-01-21: * Support for Linux DAC960 is added. diff --git a/stage2/boot.c b/stage2/boot.c index 157018798..cc23a052e 100644 --- a/stage2/boot.c +++ b/stage2/boot.c @@ -1,7 +1,7 @@ /* boot.c - load and bootstrap a kernel */ /* * GRUB -- GRand Unified Bootloader - * Copyright (C) 1999, 2000, 2001 Free Software Foundation, Inc. + * Copyright (C) 1999,2000,2001,2002 Free Software Foundation, Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -28,7 +28,7 @@ static int cur_addr; entry_func entry_addr; static struct mod_list mll[99]; - +static int linux_mem_size; /* * The next two functions, 'load_image' and 'load_module', are the building @@ -298,6 +298,60 @@ load_image (char *kernel, char *arg, kernel_t suggested_type, lh->vid_mode = vid_mode; } } + + /* Check the mem= option to limit memory used for initrd. */ + { + char *mem; + + mem = grub_strstr (arg, "mem="); + if (mem) + { + char *value = mem + 4; + + safe_parse_maxint (&value, &linux_mem_size); + switch (errnum) + { + case ERR_NUMBER_OVERFLOW: + /* If an overflow occurs, use the maximum address for + initrd instead. This is good, because MAXINT is + greater than LINUX_INITRD_MAX_ADDRESS. */ + linux_mem_size = LINUX_INITRD_MAX_ADDRESS; + errnum = ERR_NONE; + break; + + case ERR_NONE: + { + int shift = 0; + + switch (grub_tolower (*value)) + { + case 'g': + shift += 10; + case 'm': + shift += 10; + case 'k': + shift += 10; + default: + break; + } + + /* Check an overflow. */ + if (linux_mem_size > (MAXINT >> shift)) + linux_mem_size = LINUX_INITRD_MAX_ADDRESS; + else + linux_mem_size <<= shift; + } + break; + + default: + linux_mem_size = 0; + errnum = ERR_NONE; + break; + } + } + else + linux_mem_size = 0; + } memmove ((char *) LINUX_SETUP, buffer, data_len + SECTOR_SIZE); @@ -720,7 +774,12 @@ load_initrd (char *initrd) goto fail; } - moveto = ((mbi.mem_upper + 0x400) * 0x400 - len) & 0xfffff000; + if (linux_mem_size) + moveto = linux_mem_size; + else + moveto = (mbi.mem_upper + 0x400) << 10; + + moveto = (moveto - len) & 0xfffff000; if (moveto + len >= LINUX_INITRD_MAX_ADDRESS) moveto = (LINUX_INITRD_MAX_ADDRESS - len) & 0xfffff000; diff --git a/stage2/char_io.c b/stage2/char_io.c index 8a5a2ceb7..d82ed5be7 100644 --- a/stage2/char_io.c +++ b/stage2/char_io.c @@ -948,7 +948,7 @@ safe_parse_maxint (char **str_ptr, int *myint_ptr) found = 1; if (myint > ((MAXINT - digit) / mult)) { - errnum = ERR_NUMBER_PARSING; + errnum = ERR_NUMBER_OVERFLOW; return 0; } myint = (myint * mult) + digit; diff --git a/stage2/common.c b/stage2/common.c index 3e63c171f..e9cfeb535 100644 --- a/stage2/common.c +++ b/stage2/common.c @@ -1,7 +1,7 @@ /* common.c - miscellaneous shared variables and routines */ /* * GRUB -- GRand Unified Bootloader - * Copyright (C) 1999, 2000, 2001 Free Software Foundation, Inc. + * Copyright (C) 1999,2000,2001,2002 Free Software Foundation, Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -77,6 +77,7 @@ char *err_list[] = [ERR_NO_DISK] = "Selected disk does not exist", [ERR_NO_DISK_SPACE] = "No spare sectors on the disk", [ERR_NO_PART] = "No such partition", + [ERR_NUMBER_OVERFLOW] = "Overflow while parsing number", [ERR_NUMBER_PARSING] = "Error while parsing number", [ERR_OUTSIDE_PART] = "Attempt to access block outside partition", [ERR_PRIVILEGED] = "Must be authenticated", diff --git a/stage2/shared.h b/stage2/shared.h index 87688e5aa..b540852c9 100644 --- a/stage2/shared.h +++ b/stage2/shared.h @@ -548,6 +548,7 @@ typedef enum ERR_PRIVILEGED, ERR_NEED_SERIAL, ERR_NO_DISK_SPACE, + ERR_NUMBER_OVERFLOW, MAX_ERR_NUM } grub_error_t;