mirror of
https://git.savannah.gnu.org/git/grub.git
synced 2026-10-22 07:12:39 +00:00
* stage2/char_io.c [!GRUB_UTIL] (memcpy): New function. It is defined as an alias of grub_memmove. This is copied from GRUB 2. * stage2/disk_io.c (print_completions): Simplified conditionals to make it easier to edit the file with Emacs. Added support for (cd). (set_device): Likewise. * stage2/common.c (init_bios_info): Check if BOOT_DRIVE is a CDROM drive. If it is true, set CDROM_DRIVE to BOOT_DRIVE. (cdrom_drive): New variable. From Leonid Lisovskiy <lly@pisem.net>: * stage2/start_eltorito.S: New file. * stage2/stage2.c (run_menu): Use GRUB_INVALID_DRIVE instead of 0xFF. * stage2/shared.h (STAGE2_ID_ISO9660_STAGE1_5): New macro. [FSYS_ISO9660] (STAGE2_ID): Set to STAGE2_ID_ISO9660_STAGE1_5. (struct geometry): Added a new member ``sector_size''. (BIOSDISK_FLAG_CDROM): New macro. (cdrom_drive): Declared. * stage2/fsys_iso9660.c: New file. * stage2/iso9660.h: Likewise. * stage2/filesys.h (FSYS_ISO9660_NUM): New macro. [FSYS_ISO9660] (iso9660_mount): Declared. [FSYS_ISO9660] (iso9660_read): Likewise. [FSYS_ISO9660] (iso9660_dir): Likewise. (NUM_FSYS): Added FSYS_ISO9660_NUM. * stage2/disk_io.c (fsys_table) [FSYS_ISO9660]: Added iso9660. (current_drive): Use GRUB_INVALID_DRIVE. (log2): New function. (rawread): Use BUF_GEOM.SECTOR_SIZE instead of SECTOR_SIZE. Change the type of BUFADDR from int to char *. Use a virtual track to make sure that one track fits in the buffer. (sane_partition): Allow CURRENT_DRIVE to be CDROM_DRIVE, because a bios drive for a CD-ROM is often assigned to greater than 0x88. (set_device): Use GRUB_INVALID_DRIVE instead of 0xFF. (setup_part): Likewise. * stage2/cmdline.c (init_cmdline): Use GRUB_INVALID_DRIVE. * stage2/builtins.c (install_func): Use GRUB_INVALID_DRIVE. (setup_func): Added iso9660_stage1_5. * stage2/bios.c (biosdisk): Don't fall back to the CHS mode if the drive is a CDROM. (get_cdinfo): New function. (get_diskinfo): Call get_cdinfo if the drive is greater than or equal to 0x88 or the drive supports LBA. Set the sector size to SECTOR_SIZE if it is not a CD-ROM. * stage2/asm.S (biosdisk_int13_extensions): Take a word argument AX instead of a byte argument AH. (get_diskinfo_int13_extensions): Removed. * stage2/Makefile.am (noinst_HEADERS): Added iso9660.h. (libgrub_a_SOURCES): Added fsys_iso9660.c. (libgrub_a_CFLAGS): Added -DFSYS_ISO9660=1. (pkgdata_DATA): Added iso9660_stage1_5 and stage2_eltorito. (noinst_PROGRAMS): Added iso9660_stage1_5.exec and start_eltorito.exec. (noinst_DATA): Added start_eltorito. (pre_stage2_exec_SOURCES): Added fsys_iso9660.c. (START_ELTORITO_LINK): New variable. (start_eltorito_exec_SOURCES): Likewise. (start_eltorito_exec_CCASFLAGS): Likewise. (start_eltorito_exec_LDFLAGS): Likewise. (start_eltorito_exec-start.$(OBJEXT)): New dependency. (stage2_eltorito): New target. (iso9660_stage1_5_exec_SOURCES): New variable. (iso9660_stage1_5_exec_CFLAGS): Likewise. (iso9660_stage1_5_exec_CCASFLAGS): Likewise. (iso9660_stage1_5_exec_LDFLAGS): Likewise. * stage1/stage1.h (GRUB_INVALID_DRIVE): New macro. * stage1/stage1.S (boot_drive): Use the macro GRUB_INVALID_DRIVE. (real_start): Likewise. * lib/device.c (get_drive_geometry): Set GEOM->SECTOR_SIZE to SECTOR_SIZE by default. * configure.ac (--disable-iso9660): New option.
258 lines
6.3 KiB
C
258 lines
6.3 KiB
C
/* cmdline.c - the device-independent GRUB text command line */
|
|
/*
|
|
* GRUB -- GRand Unified Bootloader
|
|
* Copyright (C) 1999,2000,2001,2002,2004 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
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program 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 this program; if not, write to the Free Software
|
|
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
*/
|
|
|
|
#include <shared.h>
|
|
|
|
#ifdef SUPPORT_DISKLESS
|
|
# define GRUB 1
|
|
# include <etherboot.h>
|
|
#endif
|
|
|
|
grub_jmp_buf restart_cmdline_env;
|
|
|
|
/* Find the next word from CMDLINE and return the pointer. If
|
|
AFTER_EQUAL is non-zero, assume that the character `=' is treated as
|
|
a space. Caution: this assumption is for backward compatibility. */
|
|
char *
|
|
skip_to (int after_equal, char *cmdline)
|
|
{
|
|
/* Skip until we hit whitespace, or maybe an equal sign. */
|
|
while (*cmdline && *cmdline != ' ' && *cmdline != '\t' &&
|
|
! (after_equal && *cmdline == '='))
|
|
cmdline ++;
|
|
|
|
/* Skip whitespace, and maybe equal signs. */
|
|
while (*cmdline == ' ' || *cmdline == '\t' ||
|
|
(after_equal && *cmdline == '='))
|
|
cmdline ++;
|
|
|
|
return cmdline;
|
|
}
|
|
|
|
/* Print a helpful message for the command-line interface. */
|
|
void
|
|
print_cmdline_message (int forever)
|
|
{
|
|
printf (" [ Minimal BASH-like line editing is supported. For the first word, TAB\n"
|
|
" lists possible command completions. Anywhere else TAB lists the possible\n"
|
|
" completions of a device/filename.%s ]\n",
|
|
(forever ? "" : " ESC at any time exits."));
|
|
}
|
|
|
|
/* Find the builtin whose command name is COMMAND and return the
|
|
pointer. If not found, return 0. */
|
|
struct builtin *
|
|
find_command (char *command)
|
|
{
|
|
char *ptr;
|
|
char c;
|
|
struct builtin **builtin;
|
|
|
|
/* Find the first space and terminate the command name. */
|
|
ptr = command;
|
|
while (*ptr && *ptr != ' ' && *ptr != '\t' && *ptr != '=')
|
|
ptr ++;
|
|
|
|
c = *ptr;
|
|
*ptr = 0;
|
|
|
|
/* Seek out the builtin whose command name is COMMAND. */
|
|
for (builtin = builtin_table; *builtin != 0; builtin++)
|
|
{
|
|
int ret = grub_strcmp (command, (*builtin)->name);
|
|
|
|
if (ret == 0)
|
|
{
|
|
/* Find the builtin for COMMAND. */
|
|
*ptr = c;
|
|
return *builtin;
|
|
}
|
|
else if (ret < 0)
|
|
break;
|
|
}
|
|
|
|
/* Cannot find COMMAND. */
|
|
errnum = ERR_UNRECOGNIZED;
|
|
*ptr = c;
|
|
return 0;
|
|
}
|
|
|
|
/* Initialize the data for the command-line. */
|
|
static void
|
|
init_cmdline (void)
|
|
{
|
|
/* Initialization. */
|
|
saved_drive = boot_drive;
|
|
saved_partition = install_partition;
|
|
current_drive = GRUB_INVALID_DRIVE;
|
|
errnum = 0;
|
|
count_lines = -1;
|
|
|
|
/* Restore memory probe state. */
|
|
mbi.mem_upper = saved_mem_upper;
|
|
if (mbi.mmap_length)
|
|
mbi.flags |= MB_INFO_MEM_MAP;
|
|
|
|
/* Initialize the data for the builtin commands. */
|
|
init_builtins ();
|
|
}
|
|
|
|
/* Enter the command-line interface. HEAP is used for the command-line
|
|
buffer. Return only if FOREVER is nonzero and get_cmdline returns
|
|
nonzero (ESC is pushed). */
|
|
void
|
|
enter_cmdline (char *heap, int forever)
|
|
{
|
|
/* Initialize the data and print a message. */
|
|
init_cmdline ();
|
|
grub_setjmp (restart_cmdline_env);
|
|
init_page ();
|
|
#ifdef SUPPORT_DISKLESS
|
|
print_network_configuration ();
|
|
grub_putchar ('\n');
|
|
#endif
|
|
print_cmdline_message (forever);
|
|
|
|
while (1)
|
|
{
|
|
struct builtin *builtin;
|
|
char *arg;
|
|
|
|
*heap = 0;
|
|
print_error ();
|
|
errnum = ERR_NONE;
|
|
|
|
/* Get the command-line with the minimal BASH-like interface. */
|
|
if (get_cmdline (PACKAGE "> ", heap, 2048, 0, 1))
|
|
return;
|
|
|
|
/* If there was no command, grab a new one. */
|
|
if (! heap[0])
|
|
continue;
|
|
|
|
/* Find a builtin. */
|
|
builtin = find_command (heap);
|
|
if (! builtin)
|
|
continue;
|
|
|
|
/* If BUILTIN cannot be run in the command-line, skip it. */
|
|
if (! (builtin->flags & BUILTIN_CMDLINE))
|
|
{
|
|
errnum = ERR_UNRECOGNIZED;
|
|
continue;
|
|
}
|
|
|
|
/* Invalidate the cache, because the user may exchange removable
|
|
disks. */
|
|
buf_drive = -1;
|
|
|
|
/* Start to count lines, only if the internal pager is in use. */
|
|
if (use_pager)
|
|
count_lines = 0;
|
|
|
|
/* Run BUILTIN->FUNC. */
|
|
arg = skip_to (1, heap);
|
|
(builtin->func) (arg, BUILTIN_CMDLINE);
|
|
|
|
/* Finish the line count. */
|
|
count_lines = -1;
|
|
}
|
|
}
|
|
|
|
/* Run an entry from the script SCRIPT. HEAP is used for the
|
|
command-line buffer. If an error occurs, return non-zero, otherwise
|
|
return zero. */
|
|
int
|
|
run_script (char *script, char *heap)
|
|
{
|
|
char *old_entry;
|
|
char *cur_entry = script;
|
|
|
|
/* Initialize the data. */
|
|
init_cmdline ();
|
|
|
|
while (1)
|
|
{
|
|
struct builtin *builtin;
|
|
char *arg;
|
|
|
|
print_error ();
|
|
|
|
if (errnum)
|
|
{
|
|
errnum = ERR_NONE;
|
|
|
|
/* If a fallback entry is defined, don't prompt a user's
|
|
intervention. */
|
|
if (fallback_entry < 0)
|
|
{
|
|
grub_printf ("\nPress any key to continue...");
|
|
(void) getkey ();
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
/* Copy the first string in CUR_ENTRY to HEAP. */
|
|
old_entry = cur_entry;
|
|
while (*cur_entry++)
|
|
;
|
|
|
|
grub_memmove (heap, old_entry, (int) cur_entry - (int) old_entry);
|
|
if (! *heap)
|
|
{
|
|
/* If there is no more command in SCRIPT... */
|
|
|
|
/* If any kernel is not loaded, just exit successfully. */
|
|
if (kernel_type == KERNEL_TYPE_NONE)
|
|
return 0;
|
|
|
|
/* Otherwise, the command boot is run implicitly. */
|
|
grub_memmove (heap, "boot", 5);
|
|
}
|
|
|
|
/* Find a builtin. */
|
|
builtin = find_command (heap);
|
|
if (! builtin)
|
|
{
|
|
grub_printf ("%s\n", old_entry);
|
|
continue;
|
|
}
|
|
|
|
if (! (builtin->flags & BUILTIN_NO_ECHO))
|
|
grub_printf ("%s\n", old_entry);
|
|
|
|
/* If BUILTIN cannot be run in the command-line, skip it. */
|
|
if (! (builtin->flags & BUILTIN_CMDLINE))
|
|
{
|
|
errnum = ERR_UNRECOGNIZED;
|
|
continue;
|
|
}
|
|
|
|
/* Invalidate the cache, because the user may exchange removable
|
|
disks. */
|
|
buf_drive = -1;
|
|
|
|
/* Run BUILTIN->FUNC. */
|
|
arg = skip_to (1, heap);
|
|
(builtin->func) (arg, BUILTIN_SCRIPT);
|
|
}
|
|
}
|