17c478bd9Sstevel@tonic-gate /* builtins.c - the GRUB builtin commands */
27c478bd9Sstevel@tonic-gate /*
37c478bd9Sstevel@tonic-gate * GRUB -- GRand Unified Bootloader
47c478bd9Sstevel@tonic-gate * Copyright (C) 1999,2000,2001,2002,2003,2004 Free Software Foundation, Inc.
5*1a065e93SAndrew Stormont * Copyright 2021 RackTop Systems, Inc.
67c478bd9Sstevel@tonic-gate *
77c478bd9Sstevel@tonic-gate * This program is free software; you can redistribute it and/or modify
87c478bd9Sstevel@tonic-gate * it under the terms of the GNU General Public License as published by
97c478bd9Sstevel@tonic-gate * the Free Software Foundation; either version 2 of the License, or
107c478bd9Sstevel@tonic-gate * (at your option) any later version.
117c478bd9Sstevel@tonic-gate *
127c478bd9Sstevel@tonic-gate * This program is distributed in the hope that it will be useful,
137c478bd9Sstevel@tonic-gate * but WITHOUT ANY WARRANTY; without even the implied warranty of
147c478bd9Sstevel@tonic-gate * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
157c478bd9Sstevel@tonic-gate * GNU General Public License for more details.
167c478bd9Sstevel@tonic-gate *
177c478bd9Sstevel@tonic-gate * You should have received a copy of the GNU General Public License
187c478bd9Sstevel@tonic-gate * along with this program; if not, write to the Free Software
197c478bd9Sstevel@tonic-gate * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
207c478bd9Sstevel@tonic-gate */
21342440ecSPrasad Singamsetty
227c478bd9Sstevel@tonic-gate /* Include stdio.h before shared.h, because we can't define
237c478bd9Sstevel@tonic-gate WITHOUT_LIBC_STUBS here. */
247c478bd9Sstevel@tonic-gate #ifdef GRUB_UTIL
257c478bd9Sstevel@tonic-gate # include <stdio.h>
267c478bd9Sstevel@tonic-gate #endif
277c478bd9Sstevel@tonic-gate
287c478bd9Sstevel@tonic-gate #include <shared.h>
297c478bd9Sstevel@tonic-gate #include <filesys.h>
307c478bd9Sstevel@tonic-gate #include <term.h>
317c478bd9Sstevel@tonic-gate
327c478bd9Sstevel@tonic-gate #ifdef SUPPORT_NETBOOT
337c478bd9Sstevel@tonic-gate # include <grub.h>
347c478bd9Sstevel@tonic-gate #endif
357c478bd9Sstevel@tonic-gate
367c478bd9Sstevel@tonic-gate #ifdef SUPPORT_SERIAL
377c478bd9Sstevel@tonic-gate # include <serial.h>
387c478bd9Sstevel@tonic-gate # include <terminfo.h>
397c478bd9Sstevel@tonic-gate #endif
407c478bd9Sstevel@tonic-gate
417c478bd9Sstevel@tonic-gate #ifdef GRUB_UTIL
427c478bd9Sstevel@tonic-gate # include <device.h>
437c478bd9Sstevel@tonic-gate #else /* ! GRUB_UTIL */
447c478bd9Sstevel@tonic-gate # include <apic.h>
457c478bd9Sstevel@tonic-gate # include <smp-imps.h>
467c478bd9Sstevel@tonic-gate #endif /* ! GRUB_UTIL */
477c478bd9Sstevel@tonic-gate
487c478bd9Sstevel@tonic-gate #ifdef USE_MD5_PASSWORDS
497c478bd9Sstevel@tonic-gate # include <md5.h>
507c478bd9Sstevel@tonic-gate #endif
517c478bd9Sstevel@tonic-gate
52ae115bc7Smrj #include <cpu.h>
53a5602e1bSKeith M Wesolowski #include <expand.h>
54ae115bc7Smrj
557c478bd9Sstevel@tonic-gate /* The type of kernel loaded. */
567c478bd9Sstevel@tonic-gate kernel_t kernel_type;
577c478bd9Sstevel@tonic-gate /* The boot device. */
587c478bd9Sstevel@tonic-gate static int bootdev;
597c478bd9Sstevel@tonic-gate /* True when the debug mode is turned on, and false
607c478bd9Sstevel@tonic-gate when it is turned off. */
617c478bd9Sstevel@tonic-gate int debug = 0;
627c478bd9Sstevel@tonic-gate /* The default entry. */
637c478bd9Sstevel@tonic-gate int default_entry = 0;
647c478bd9Sstevel@tonic-gate /* The fallback entry. */
657c478bd9Sstevel@tonic-gate int fallback_entryno;
667c478bd9Sstevel@tonic-gate int fallback_entries[MAX_FALLBACK_ENTRIES];
677c478bd9Sstevel@tonic-gate /* The number of current entry. */
687c478bd9Sstevel@tonic-gate int current_entryno;
697c478bd9Sstevel@tonic-gate /* The address for Multiboot command-line buffer. */
707c478bd9Sstevel@tonic-gate static char *mb_cmdline;
717c478bd9Sstevel@tonic-gate /* The password. */
727c478bd9Sstevel@tonic-gate char *password;
737c478bd9Sstevel@tonic-gate /* The password type. */
747c478bd9Sstevel@tonic-gate password_t password_type;
757c478bd9Sstevel@tonic-gate /* The flag for indicating that the user is authoritative. */
767c478bd9Sstevel@tonic-gate int auth = 0;
777c478bd9Sstevel@tonic-gate /* The timeout. */
787c478bd9Sstevel@tonic-gate int grub_timeout = -1;
797c478bd9Sstevel@tonic-gate /* Whether to show the menu or not. */
807c478bd9Sstevel@tonic-gate int show_menu = 1;
817c478bd9Sstevel@tonic-gate /* The BIOS drive map. */
827c478bd9Sstevel@tonic-gate static unsigned short bios_drive_map[DRIVE_MAP_SIZE + 1];
837c478bd9Sstevel@tonic-gate
847c478bd9Sstevel@tonic-gate /* Prototypes for allowing straightfoward calling of builtins functions
857c478bd9Sstevel@tonic-gate inside other functions. */
867c478bd9Sstevel@tonic-gate static int configfile_func (char *arg, int flags);
877c478bd9Sstevel@tonic-gate #ifdef SUPPORT_NETBOOT
887c478bd9Sstevel@tonic-gate static void solaris_config_file (void);
897c478bd9Sstevel@tonic-gate #endif
907c478bd9Sstevel@tonic-gate
91a5602e1bSKeith M Wesolowski unsigned int min_mem64 = 0;
92342440ecSPrasad Singamsetty
937c478bd9Sstevel@tonic-gate #if defined(__sun) && !defined(GRUB_UTIL)
947c478bd9Sstevel@tonic-gate extern void __enable_execute_stack (void *);
957c478bd9Sstevel@tonic-gate void
__enable_execute_stack(void * addr)967c478bd9Sstevel@tonic-gate __enable_execute_stack (void *addr)
977c478bd9Sstevel@tonic-gate {
987c478bd9Sstevel@tonic-gate }
997c478bd9Sstevel@tonic-gate #endif /* __sun && !GRUB_UTIL */
1007c478bd9Sstevel@tonic-gate
1017c478bd9Sstevel@tonic-gate /* Initialize the data for builtins. */
1027c478bd9Sstevel@tonic-gate void
init_builtins(void)1037c478bd9Sstevel@tonic-gate init_builtins (void)
1047c478bd9Sstevel@tonic-gate {
1057c478bd9Sstevel@tonic-gate kernel_type = KERNEL_TYPE_NONE;
1067c478bd9Sstevel@tonic-gate /* BSD and chainloading evil hacks! */
1077c478bd9Sstevel@tonic-gate bootdev = set_bootdev (0);
1087c478bd9Sstevel@tonic-gate mb_cmdline = (char *) MB_CMDLINE_BUF;
1097c478bd9Sstevel@tonic-gate }
1107c478bd9Sstevel@tonic-gate
1117c478bd9Sstevel@tonic-gate /* Initialize the data for the configuration file. */
1127c478bd9Sstevel@tonic-gate void
init_config(void)1137c478bd9Sstevel@tonic-gate init_config (void)
1147c478bd9Sstevel@tonic-gate {
1157c478bd9Sstevel@tonic-gate default_entry = 0;
1167c478bd9Sstevel@tonic-gate password = 0;
1177c478bd9Sstevel@tonic-gate fallback_entryno = -1;
1187c478bd9Sstevel@tonic-gate fallback_entries[0] = -1;
1197c478bd9Sstevel@tonic-gate grub_timeout = -1;
120b1b8ab34Slling current_rootpool[0] = '\0';
121b1b8ab34Slling current_bootfs[0] = '\0';
122e7cbe64fSgw current_bootpath[0] = '\0';
123b1b8ab34Slling current_bootfs_obj = 0;
124051aabe6Staylor current_devid[0] = '\0';
125*1a065e93SAndrew Stormont current_bootguid = 0;
126*1a065e93SAndrew Stormont current_bootvdev = 0;
127b1b8ab34Slling is_zfs_mount = 0;
1287c478bd9Sstevel@tonic-gate }
1297c478bd9Sstevel@tonic-gate
1307c478bd9Sstevel@tonic-gate /* Check a password for correctness. Returns 0 if password was
1317c478bd9Sstevel@tonic-gate correct, and a value != 0 for error, similarly to strcmp. */
1327c478bd9Sstevel@tonic-gate int
check_password(char * entered,char * expected,password_t type)1337c478bd9Sstevel@tonic-gate check_password (char *entered, char* expected, password_t type)
1347c478bd9Sstevel@tonic-gate {
1357c478bd9Sstevel@tonic-gate switch (type)
1367c478bd9Sstevel@tonic-gate {
1377c478bd9Sstevel@tonic-gate case PASSWORD_PLAIN:
1387c478bd9Sstevel@tonic-gate return strcmp (entered, expected);
1397c478bd9Sstevel@tonic-gate
1407c478bd9Sstevel@tonic-gate #ifdef USE_MD5_PASSWORDS
1417c478bd9Sstevel@tonic-gate case PASSWORD_MD5:
1427c478bd9Sstevel@tonic-gate return check_md5_password (entered, expected);
1437c478bd9Sstevel@tonic-gate #endif
1447c478bd9Sstevel@tonic-gate default:
1457c478bd9Sstevel@tonic-gate /* unsupported password type: be secure */
1467c478bd9Sstevel@tonic-gate return 1;
1477c478bd9Sstevel@tonic-gate }
1487c478bd9Sstevel@tonic-gate }
1497c478bd9Sstevel@tonic-gate
1507c478bd9Sstevel@tonic-gate /* Print which sector is read when loading a file. */
1517c478bd9Sstevel@tonic-gate static void
disk_read_print_func(unsigned long long sector,int offset,int length)1529890706eSHans Rosenfeld disk_read_print_func(unsigned long long sector, int offset, int length)
1537c478bd9Sstevel@tonic-gate {
1549890706eSHans Rosenfeld grub_printf ("[%llu,%d,%d]", sector, offset, length);
1557c478bd9Sstevel@tonic-gate }
1567c478bd9Sstevel@tonic-gate
1577c478bd9Sstevel@tonic-gate
1587c478bd9Sstevel@tonic-gate /* blocklist */
1597c478bd9Sstevel@tonic-gate static int
blocklist_func(char * arg,int flags)1607c478bd9Sstevel@tonic-gate blocklist_func (char *arg, int flags)
1617c478bd9Sstevel@tonic-gate {
1627c478bd9Sstevel@tonic-gate char *dummy = (char *) RAW_ADDR (0x100000);
1639890706eSHans Rosenfeld unsigned long long start_sector = 0;
1647c478bd9Sstevel@tonic-gate int num_sectors = 0;
1657c478bd9Sstevel@tonic-gate int num_entries = 0;
1667c478bd9Sstevel@tonic-gate int last_length = 0;
1677c478bd9Sstevel@tonic-gate
1689890706eSHans Rosenfeld auto void disk_read_blocklist_func (unsigned long long sector, int offset,
1691b8adde7SWilliam Kucharski int length);
1701b8adde7SWilliam Kucharski
1717c478bd9Sstevel@tonic-gate /* Collect contiguous blocks into one entry as many as possible,
1727c478bd9Sstevel@tonic-gate and print the blocklist notation on the screen. */
1739890706eSHans Rosenfeld auto void disk_read_blocklist_func (unsigned long long sector, int offset,
1741b8adde7SWilliam Kucharski int length)
1757c478bd9Sstevel@tonic-gate {
1767c478bd9Sstevel@tonic-gate if (num_sectors > 0)
1777c478bd9Sstevel@tonic-gate {
1787c478bd9Sstevel@tonic-gate if (start_sector + num_sectors == sector
1797c478bd9Sstevel@tonic-gate && offset == 0 && last_length == SECTOR_SIZE)
1807c478bd9Sstevel@tonic-gate {
1817c478bd9Sstevel@tonic-gate num_sectors++;
1827c478bd9Sstevel@tonic-gate last_length = length;
1837c478bd9Sstevel@tonic-gate return;
1847c478bd9Sstevel@tonic-gate }
1857c478bd9Sstevel@tonic-gate else
1867c478bd9Sstevel@tonic-gate {
1877c478bd9Sstevel@tonic-gate if (last_length == SECTOR_SIZE)
1882e1aefd1SJoshua M. Clulow grub_printf ("%s%llu+%d", num_entries ? "," : "",
1897c478bd9Sstevel@tonic-gate start_sector - part_start, num_sectors);
1907c478bd9Sstevel@tonic-gate else if (num_sectors > 1)
1912e1aefd1SJoshua M. Clulow grub_printf ("%s%llu+%d,%lld[0-%d]", num_entries ? "," : "",
1927c478bd9Sstevel@tonic-gate start_sector - part_start, num_sectors-1,
1937c478bd9Sstevel@tonic-gate start_sector + num_sectors-1 - part_start,
1947c478bd9Sstevel@tonic-gate last_length);
1957c478bd9Sstevel@tonic-gate else
1962e1aefd1SJoshua M. Clulow grub_printf ("%s%llu[0-%d]", num_entries ? "," : "",
1977c478bd9Sstevel@tonic-gate start_sector - part_start, last_length);
1987c478bd9Sstevel@tonic-gate num_entries++;
1997c478bd9Sstevel@tonic-gate num_sectors = 0;
2007c478bd9Sstevel@tonic-gate }
2017c478bd9Sstevel@tonic-gate }
2027c478bd9Sstevel@tonic-gate
2037c478bd9Sstevel@tonic-gate if (offset > 0)
2047c478bd9Sstevel@tonic-gate {
2059890706eSHans Rosenfeld grub_printf("%s%llu[%d-%d]", num_entries ? "," : "",
2067c478bd9Sstevel@tonic-gate sector-part_start, offset, offset+length);
2077c478bd9Sstevel@tonic-gate num_entries++;
2087c478bd9Sstevel@tonic-gate }
2097c478bd9Sstevel@tonic-gate else
2107c478bd9Sstevel@tonic-gate {
2117c478bd9Sstevel@tonic-gate start_sector = sector;
2127c478bd9Sstevel@tonic-gate num_sectors = 1;
2137c478bd9Sstevel@tonic-gate last_length = length;
2147c478bd9Sstevel@tonic-gate }
2157c478bd9Sstevel@tonic-gate }
2167c478bd9Sstevel@tonic-gate
2177c478bd9Sstevel@tonic-gate /* Open the file. */
2187c478bd9Sstevel@tonic-gate if (! grub_open (arg))
2197c478bd9Sstevel@tonic-gate return 1;
2207c478bd9Sstevel@tonic-gate
2217c478bd9Sstevel@tonic-gate /* Print the device name. */
2227c478bd9Sstevel@tonic-gate grub_printf ("(%cd%d",
2237c478bd9Sstevel@tonic-gate (current_drive & 0x80) ? 'h' : 'f',
2247c478bd9Sstevel@tonic-gate current_drive & ~0x80);
2257c478bd9Sstevel@tonic-gate
2267c478bd9Sstevel@tonic-gate if ((current_partition & 0xFF0000) != 0xFF0000)
2277c478bd9Sstevel@tonic-gate grub_printf (",%d", (current_partition >> 16) & 0xFF);
2287c478bd9Sstevel@tonic-gate
2297c478bd9Sstevel@tonic-gate if ((current_partition & 0x00FF00) != 0x00FF00)
2307c478bd9Sstevel@tonic-gate grub_printf (",%c", 'a' + ((current_partition >> 8) & 0xFF));
2317c478bd9Sstevel@tonic-gate
2327c478bd9Sstevel@tonic-gate grub_printf (")");
2337c478bd9Sstevel@tonic-gate
2347c478bd9Sstevel@tonic-gate /* Read in the whole file to DUMMY. */
2357c478bd9Sstevel@tonic-gate disk_read_hook = disk_read_blocklist_func;
2367c478bd9Sstevel@tonic-gate if (! grub_read (dummy, -1))
2377c478bd9Sstevel@tonic-gate goto fail;
2387c478bd9Sstevel@tonic-gate
2397c478bd9Sstevel@tonic-gate /* The last entry may not be printed yet. Don't check if it is a
2407c478bd9Sstevel@tonic-gate * full sector, since it doesn't matter if we read too much. */
2417c478bd9Sstevel@tonic-gate if (num_sectors > 0)
2422e1aefd1SJoshua M. Clulow grub_printf ("%s%llu+%d", num_entries ? "," : "",
2437c478bd9Sstevel@tonic-gate start_sector - part_start, num_sectors);
2447c478bd9Sstevel@tonic-gate
2457c478bd9Sstevel@tonic-gate grub_printf ("\n");
2467c478bd9Sstevel@tonic-gate
2477c478bd9Sstevel@tonic-gate fail:
2487c478bd9Sstevel@tonic-gate disk_read_hook = 0;
2497c478bd9Sstevel@tonic-gate grub_close ();
2507c478bd9Sstevel@tonic-gate return errnum;
2517c478bd9Sstevel@tonic-gate }
2527c478bd9Sstevel@tonic-gate
2537c478bd9Sstevel@tonic-gate static struct builtin builtin_blocklist =
2547c478bd9Sstevel@tonic-gate {
2557c478bd9Sstevel@tonic-gate "blocklist",
2567c478bd9Sstevel@tonic-gate blocklist_func,
2577c478bd9Sstevel@tonic-gate BUILTIN_CMDLINE | BUILTIN_HELP_LIST,
2587c478bd9Sstevel@tonic-gate "blocklist FILE",
2597c478bd9Sstevel@tonic-gate "Print the blocklist notation of the file FILE."
2607c478bd9Sstevel@tonic-gate };
2617c478bd9Sstevel@tonic-gate
2627c478bd9Sstevel@tonic-gate /* boot */
2637c478bd9Sstevel@tonic-gate static int
boot_func(char * arg,int flags)2647c478bd9Sstevel@tonic-gate boot_func (char *arg, int flags)
2657c478bd9Sstevel@tonic-gate {
2667c478bd9Sstevel@tonic-gate /* Clear the int15 handler if we can boot the kernel successfully.
2677c478bd9Sstevel@tonic-gate This assumes that the boot code never fails only if KERNEL_TYPE is
2687c478bd9Sstevel@tonic-gate not KERNEL_TYPE_NONE. Is this assumption is bad? */
2697c478bd9Sstevel@tonic-gate if (kernel_type != KERNEL_TYPE_NONE)
2707c478bd9Sstevel@tonic-gate unset_int15_handler ();
2717c478bd9Sstevel@tonic-gate
2727c478bd9Sstevel@tonic-gate #ifdef SUPPORT_NETBOOT
2737c478bd9Sstevel@tonic-gate /* Shut down the networking. */
2747c478bd9Sstevel@tonic-gate cleanup_net ();
2757c478bd9Sstevel@tonic-gate #endif
2767c478bd9Sstevel@tonic-gate
2777c478bd9Sstevel@tonic-gate switch (kernel_type)
2787c478bd9Sstevel@tonic-gate {
2797c478bd9Sstevel@tonic-gate case KERNEL_TYPE_FREEBSD:
2807c478bd9Sstevel@tonic-gate case KERNEL_TYPE_NETBSD:
2817c478bd9Sstevel@tonic-gate /* *BSD */
2827c478bd9Sstevel@tonic-gate bsd_boot (kernel_type, bootdev, (char *) mbi.cmdline);
2837c478bd9Sstevel@tonic-gate break;
2847c478bd9Sstevel@tonic-gate
2857c478bd9Sstevel@tonic-gate case KERNEL_TYPE_LINUX:
2867c478bd9Sstevel@tonic-gate /* Linux */
2877c478bd9Sstevel@tonic-gate linux_boot ();
2887c478bd9Sstevel@tonic-gate break;
2897c478bd9Sstevel@tonic-gate
2907c478bd9Sstevel@tonic-gate case KERNEL_TYPE_BIG_LINUX:
2917c478bd9Sstevel@tonic-gate /* Big Linux */
2927c478bd9Sstevel@tonic-gate big_linux_boot ();
2937c478bd9Sstevel@tonic-gate break;
2947c478bd9Sstevel@tonic-gate
2957c478bd9Sstevel@tonic-gate case KERNEL_TYPE_CHAINLOADER:
2967c478bd9Sstevel@tonic-gate /* Chainloader */
2977c478bd9Sstevel@tonic-gate
2987c478bd9Sstevel@tonic-gate /* Check if we should set the int13 handler. */
2997c478bd9Sstevel@tonic-gate if (bios_drive_map[0] != 0)
3007c478bd9Sstevel@tonic-gate {
3017c478bd9Sstevel@tonic-gate int i;
3027c478bd9Sstevel@tonic-gate
3037c478bd9Sstevel@tonic-gate /* Search for SAVED_DRIVE. */
3047c478bd9Sstevel@tonic-gate for (i = 0; i < DRIVE_MAP_SIZE; i++)
3057c478bd9Sstevel@tonic-gate {
3067c478bd9Sstevel@tonic-gate if (! bios_drive_map[i])
3077c478bd9Sstevel@tonic-gate break;
3087c478bd9Sstevel@tonic-gate else if ((bios_drive_map[i] & 0xFF) == saved_drive)
3097c478bd9Sstevel@tonic-gate {
3107c478bd9Sstevel@tonic-gate /* Exchage SAVED_DRIVE with the mapped drive. */
3117c478bd9Sstevel@tonic-gate saved_drive = (bios_drive_map[i] >> 8) & 0xFF;
3127c478bd9Sstevel@tonic-gate break;
3137c478bd9Sstevel@tonic-gate }
3147c478bd9Sstevel@tonic-gate }
3157c478bd9Sstevel@tonic-gate
3167c478bd9Sstevel@tonic-gate /* Set the handler. This is somewhat dangerous. */
3177c478bd9Sstevel@tonic-gate set_int13_handler (bios_drive_map);
3187c478bd9Sstevel@tonic-gate }
3197c478bd9Sstevel@tonic-gate
3207c478bd9Sstevel@tonic-gate gateA20 (0);
3217c478bd9Sstevel@tonic-gate boot_drive = saved_drive;
3227c478bd9Sstevel@tonic-gate chain_stage1 (0, BOOTSEC_LOCATION, boot_part_addr);
3237c478bd9Sstevel@tonic-gate break;
3247c478bd9Sstevel@tonic-gate
3257c478bd9Sstevel@tonic-gate case KERNEL_TYPE_MULTIBOOT:
3267c478bd9Sstevel@tonic-gate /* Multiboot */
3277c478bd9Sstevel@tonic-gate #ifdef SUPPORT_NETBOOT
3287c478bd9Sstevel@tonic-gate #ifdef SOLARIS_NETBOOT
3297c478bd9Sstevel@tonic-gate if (current_drive == NETWORK_DRIVE) {
3307c478bd9Sstevel@tonic-gate /*
3317c478bd9Sstevel@tonic-gate * XXX Solaris hack: use drive_info to pass network information
3327c478bd9Sstevel@tonic-gate * Turn off the flag bit to the loader is technically
3337c478bd9Sstevel@tonic-gate * multiboot compliant.
3347c478bd9Sstevel@tonic-gate */
3357c478bd9Sstevel@tonic-gate mbi.flags &= ~MB_INFO_DRIVE_INFO;
3367c478bd9Sstevel@tonic-gate mbi.drives_length = dhcpack_length;
3377c478bd9Sstevel@tonic-gate mbi.drives_addr = dhcpack_buf;
3387c478bd9Sstevel@tonic-gate }
3397c478bd9Sstevel@tonic-gate #endif /* SOLARIS_NETBOOT */
3407c478bd9Sstevel@tonic-gate #endif
3417c478bd9Sstevel@tonic-gate multi_boot ((int) entry_addr, (int) &mbi);
3427c478bd9Sstevel@tonic-gate break;
3437c478bd9Sstevel@tonic-gate
3447c478bd9Sstevel@tonic-gate default:
3457c478bd9Sstevel@tonic-gate errnum = ERR_BOOT_COMMAND;
3467c478bd9Sstevel@tonic-gate return 1;
3477c478bd9Sstevel@tonic-gate }
3487c478bd9Sstevel@tonic-gate
3497c478bd9Sstevel@tonic-gate return 0;
3507c478bd9Sstevel@tonic-gate }
3517c478bd9Sstevel@tonic-gate
3527c478bd9Sstevel@tonic-gate static struct builtin builtin_boot =
3537c478bd9Sstevel@tonic-gate {
3547c478bd9Sstevel@tonic-gate "boot",
3557c478bd9Sstevel@tonic-gate boot_func,
3567c478bd9Sstevel@tonic-gate BUILTIN_CMDLINE | BUILTIN_HELP_LIST,
3577c478bd9Sstevel@tonic-gate "boot",
3587c478bd9Sstevel@tonic-gate "Boot the OS/chain-loader which has been loaded."
3597c478bd9Sstevel@tonic-gate };
3607c478bd9Sstevel@tonic-gate
3617c478bd9Sstevel@tonic-gate
3627c478bd9Sstevel@tonic-gate #ifdef SUPPORT_NETBOOT
3637c478bd9Sstevel@tonic-gate /* bootp */
3647c478bd9Sstevel@tonic-gate static int
bootp_func(char * arg,int flags)3657c478bd9Sstevel@tonic-gate bootp_func (char *arg, int flags)
3667c478bd9Sstevel@tonic-gate {
3677c478bd9Sstevel@tonic-gate int with_configfile = 0;
3687c478bd9Sstevel@tonic-gate
3697c478bd9Sstevel@tonic-gate if (grub_memcmp (arg, "--with-configfile", sizeof ("--with-configfile") - 1)
3707c478bd9Sstevel@tonic-gate == 0)
3717c478bd9Sstevel@tonic-gate {
3727c478bd9Sstevel@tonic-gate with_configfile = 1;
3737c478bd9Sstevel@tonic-gate arg = skip_to (0, arg);
3747c478bd9Sstevel@tonic-gate }
3757c478bd9Sstevel@tonic-gate
3767c478bd9Sstevel@tonic-gate if (! bootp ())
3777c478bd9Sstevel@tonic-gate {
3787c478bd9Sstevel@tonic-gate if (errnum == ERR_NONE)
3797c478bd9Sstevel@tonic-gate errnum = ERR_DEV_VALUES;
3807c478bd9Sstevel@tonic-gate
3817c478bd9Sstevel@tonic-gate return 1;
3827c478bd9Sstevel@tonic-gate }
3837c478bd9Sstevel@tonic-gate
3847c478bd9Sstevel@tonic-gate /* Notify the configuration. */
3857c478bd9Sstevel@tonic-gate print_network_configuration ();
3867c478bd9Sstevel@tonic-gate
3877c478bd9Sstevel@tonic-gate /* XXX: this can cause an endless loop, but there is no easy way to
3887c478bd9Sstevel@tonic-gate detect such a loop unfortunately. */
3897c478bd9Sstevel@tonic-gate if (with_configfile)
3907c478bd9Sstevel@tonic-gate configfile_func (config_file, flags);
3917c478bd9Sstevel@tonic-gate
3927c478bd9Sstevel@tonic-gate return 0;
3937c478bd9Sstevel@tonic-gate }
3947c478bd9Sstevel@tonic-gate
3957c478bd9Sstevel@tonic-gate static struct builtin builtin_bootp =
3967c478bd9Sstevel@tonic-gate {
3977c478bd9Sstevel@tonic-gate "bootp",
3987c478bd9Sstevel@tonic-gate bootp_func,
3997c478bd9Sstevel@tonic-gate BUILTIN_CMDLINE | BUILTIN_MENU | BUILTIN_HELP_LIST,
4007c478bd9Sstevel@tonic-gate "bootp [--with-configfile]",
4017c478bd9Sstevel@tonic-gate "Initialize a network device via BOOTP. If the option `--with-configfile'"
4027c478bd9Sstevel@tonic-gate " is given, try to load a configuration file specified by the 150 vendor"
4037c478bd9Sstevel@tonic-gate " tag."
4047c478bd9Sstevel@tonic-gate };
4057c478bd9Sstevel@tonic-gate #endif /* SUPPORT_NETBOOT */
4067c478bd9Sstevel@tonic-gate
4077c478bd9Sstevel@tonic-gate
4087c478bd9Sstevel@tonic-gate /* cat */
4097c478bd9Sstevel@tonic-gate static int
cat_func(char * arg,int flags)4107c478bd9Sstevel@tonic-gate cat_func (char *arg, int flags)
4117c478bd9Sstevel@tonic-gate {
4127c478bd9Sstevel@tonic-gate char c;
4137c478bd9Sstevel@tonic-gate
4147c478bd9Sstevel@tonic-gate if (! grub_open (arg))
4157c478bd9Sstevel@tonic-gate return 1;
4167c478bd9Sstevel@tonic-gate
4177c478bd9Sstevel@tonic-gate while (grub_read (&c, 1))
4187c478bd9Sstevel@tonic-gate {
4197c478bd9Sstevel@tonic-gate /* Because running "cat" with a binary file can confuse the terminal,
4207c478bd9Sstevel@tonic-gate print only some characters as they are. */
4217c478bd9Sstevel@tonic-gate if (grub_isspace (c) || (c >= ' ' && c <= '~'))
4227c478bd9Sstevel@tonic-gate grub_putchar (c);
4237c478bd9Sstevel@tonic-gate else
4247c478bd9Sstevel@tonic-gate grub_putchar ('?');
4257c478bd9Sstevel@tonic-gate }
4267c478bd9Sstevel@tonic-gate
4277c478bd9Sstevel@tonic-gate grub_close ();
4287c478bd9Sstevel@tonic-gate return 0;
4297c478bd9Sstevel@tonic-gate }
4307c478bd9Sstevel@tonic-gate
4317c478bd9Sstevel@tonic-gate static struct builtin builtin_cat =
4327c478bd9Sstevel@tonic-gate {
4337c478bd9Sstevel@tonic-gate "cat",
4347c478bd9Sstevel@tonic-gate cat_func,
4357c478bd9Sstevel@tonic-gate BUILTIN_CMDLINE | BUILTIN_HELP_LIST,
4367c478bd9Sstevel@tonic-gate "cat FILE",
4377c478bd9Sstevel@tonic-gate "Print the contents of the file FILE."
4387c478bd9Sstevel@tonic-gate };
4397c478bd9Sstevel@tonic-gate
4407c478bd9Sstevel@tonic-gate
4417c478bd9Sstevel@tonic-gate /* chainloader */
4427c478bd9Sstevel@tonic-gate static int
chainloader_func(char * arg,int flags)4437c478bd9Sstevel@tonic-gate chainloader_func (char *arg, int flags)
4447c478bd9Sstevel@tonic-gate {
4457c478bd9Sstevel@tonic-gate int force = 0;
4467c478bd9Sstevel@tonic-gate char *file = arg;
4477c478bd9Sstevel@tonic-gate
4487c478bd9Sstevel@tonic-gate /* If the option `--force' is specified? */
4497c478bd9Sstevel@tonic-gate if (substring ("--force", arg) <= 0)
4507c478bd9Sstevel@tonic-gate {
4517c478bd9Sstevel@tonic-gate force = 1;
4527c478bd9Sstevel@tonic-gate file = skip_to (0, arg);
4537c478bd9Sstevel@tonic-gate }
4547c478bd9Sstevel@tonic-gate
4557c478bd9Sstevel@tonic-gate /* Open the file. */
4567c478bd9Sstevel@tonic-gate if (! grub_open (file))
4577c478bd9Sstevel@tonic-gate {
4587c478bd9Sstevel@tonic-gate kernel_type = KERNEL_TYPE_NONE;
4597c478bd9Sstevel@tonic-gate return 1;
4607c478bd9Sstevel@tonic-gate }
4617c478bd9Sstevel@tonic-gate
4627c478bd9Sstevel@tonic-gate /* Read the first block. */
4637c478bd9Sstevel@tonic-gate if (grub_read ((char *) BOOTSEC_LOCATION, SECTOR_SIZE) != SECTOR_SIZE)
4647c478bd9Sstevel@tonic-gate {
4657c478bd9Sstevel@tonic-gate grub_close ();
4667c478bd9Sstevel@tonic-gate kernel_type = KERNEL_TYPE_NONE;
4677c478bd9Sstevel@tonic-gate
4687c478bd9Sstevel@tonic-gate /* This below happens, if a file whose size is less than 512 bytes
4697c478bd9Sstevel@tonic-gate is loaded. */
4707c478bd9Sstevel@tonic-gate if (errnum == ERR_NONE)
4717c478bd9Sstevel@tonic-gate errnum = ERR_EXEC_FORMAT;
4727c478bd9Sstevel@tonic-gate
4737c478bd9Sstevel@tonic-gate return 1;
4747c478bd9Sstevel@tonic-gate }
4757c478bd9Sstevel@tonic-gate
4767c478bd9Sstevel@tonic-gate /* If not loading it forcibly, check for the signature. */
4777c478bd9Sstevel@tonic-gate if (! force
4787c478bd9Sstevel@tonic-gate && (*((unsigned short *) (BOOTSEC_LOCATION + BOOTSEC_SIG_OFFSET))
4797c478bd9Sstevel@tonic-gate != BOOTSEC_SIGNATURE))
4807c478bd9Sstevel@tonic-gate {
4817c478bd9Sstevel@tonic-gate grub_close ();
4827c478bd9Sstevel@tonic-gate errnum = ERR_EXEC_FORMAT;
4837c478bd9Sstevel@tonic-gate kernel_type = KERNEL_TYPE_NONE;
4847c478bd9Sstevel@tonic-gate return 1;
4857c478bd9Sstevel@tonic-gate }
4867c478bd9Sstevel@tonic-gate
4877c478bd9Sstevel@tonic-gate grub_close ();
4887c478bd9Sstevel@tonic-gate kernel_type = KERNEL_TYPE_CHAINLOADER;
4897c478bd9Sstevel@tonic-gate
4907c478bd9Sstevel@tonic-gate /* XXX: Windows evil hack. For now, only the first five letters are
4917c478bd9Sstevel@tonic-gate checked. */
4927c478bd9Sstevel@tonic-gate if (IS_PC_SLICE_TYPE_FAT (current_slice)
4937c478bd9Sstevel@tonic-gate && ! grub_memcmp ((char *) BOOTSEC_LOCATION + BOOTSEC_BPB_SYSTEM_ID,
4947c478bd9Sstevel@tonic-gate "MSWIN", 5))
4957c478bd9Sstevel@tonic-gate *((unsigned long *) (BOOTSEC_LOCATION + BOOTSEC_BPB_HIDDEN_SECTORS))
4967c478bd9Sstevel@tonic-gate = part_start;
4977c478bd9Sstevel@tonic-gate
4987c478bd9Sstevel@tonic-gate errnum = ERR_NONE;
4997c478bd9Sstevel@tonic-gate
5007c478bd9Sstevel@tonic-gate return 0;
5017c478bd9Sstevel@tonic-gate }
5027c478bd9Sstevel@tonic-gate
5037c478bd9Sstevel@tonic-gate static struct builtin builtin_chainloader =
5047c478bd9Sstevel@tonic-gate {
5057c478bd9Sstevel@tonic-gate "chainloader",
5067c478bd9Sstevel@tonic-gate chainloader_func,
5077c478bd9Sstevel@tonic-gate BUILTIN_CMDLINE | BUILTIN_HELP_LIST,
5087c478bd9Sstevel@tonic-gate "chainloader [--force] FILE",
5097c478bd9Sstevel@tonic-gate "Load the chain-loader FILE. If --force is specified, then load it"
5107c478bd9Sstevel@tonic-gate " forcibly, whether the boot loader signature is present or not."
5117c478bd9Sstevel@tonic-gate };
5127c478bd9Sstevel@tonic-gate
5137c478bd9Sstevel@tonic-gate
5147c478bd9Sstevel@tonic-gate /* This function could be used to debug new filesystem code. Put a file
5157c478bd9Sstevel@tonic-gate in the new filesystem and the same file in a well-tested filesystem.
5167c478bd9Sstevel@tonic-gate Then, run "cmp" with the files. If no output is obtained, probably
5177c478bd9Sstevel@tonic-gate the code is good, otherwise investigate what's wrong... */
5187c478bd9Sstevel@tonic-gate /* cmp FILE1 FILE2 */
5197c478bd9Sstevel@tonic-gate static int
cmp_func(char * arg,int flags)5207c478bd9Sstevel@tonic-gate cmp_func (char *arg, int flags)
5217c478bd9Sstevel@tonic-gate {
5227c478bd9Sstevel@tonic-gate /* The filenames. */
5237c478bd9Sstevel@tonic-gate char *file1, *file2;
5247c478bd9Sstevel@tonic-gate /* The addresses. */
5257c478bd9Sstevel@tonic-gate char *addr1, *addr2;
5267c478bd9Sstevel@tonic-gate int i;
5277c478bd9Sstevel@tonic-gate /* The size of the file. */
5287c478bd9Sstevel@tonic-gate int size;
5297c478bd9Sstevel@tonic-gate
5307c478bd9Sstevel@tonic-gate /* Get the filenames from ARG. */
5317c478bd9Sstevel@tonic-gate file1 = arg;
5327c478bd9Sstevel@tonic-gate file2 = skip_to (0, arg);
5337c478bd9Sstevel@tonic-gate if (! *file1 || ! *file2)
5347c478bd9Sstevel@tonic-gate {
5357c478bd9Sstevel@tonic-gate errnum = ERR_BAD_ARGUMENT;
5367c478bd9Sstevel@tonic-gate return 1;
5377c478bd9Sstevel@tonic-gate }
5387c478bd9Sstevel@tonic-gate
5397c478bd9Sstevel@tonic-gate /* Terminate the filenames for convenience. */
5407c478bd9Sstevel@tonic-gate nul_terminate (file1);
5417c478bd9Sstevel@tonic-gate nul_terminate (file2);
5427c478bd9Sstevel@tonic-gate
5437c478bd9Sstevel@tonic-gate /* Read the whole data from FILE1. */
5447c478bd9Sstevel@tonic-gate addr1 = (char *) RAW_ADDR (0x100000);
5457c478bd9Sstevel@tonic-gate if (! grub_open (file1))
5467c478bd9Sstevel@tonic-gate return 1;
5477c478bd9Sstevel@tonic-gate
5487c478bd9Sstevel@tonic-gate /* Get the size. */
5497c478bd9Sstevel@tonic-gate size = filemax;
5507c478bd9Sstevel@tonic-gate if (grub_read (addr1, -1) != size)
5517c478bd9Sstevel@tonic-gate {
5527c478bd9Sstevel@tonic-gate grub_close ();
5537c478bd9Sstevel@tonic-gate return 1;
5547c478bd9Sstevel@tonic-gate }
5557c478bd9Sstevel@tonic-gate
5567c478bd9Sstevel@tonic-gate grub_close ();
5577c478bd9Sstevel@tonic-gate
5587c478bd9Sstevel@tonic-gate /* Read the whole data from FILE2. */
5597c478bd9Sstevel@tonic-gate addr2 = addr1 + size;
5607c478bd9Sstevel@tonic-gate if (! grub_open (file2))
5617c478bd9Sstevel@tonic-gate return 1;
5627c478bd9Sstevel@tonic-gate
5637c478bd9Sstevel@tonic-gate /* Check if the size of FILE2 is equal to the one of FILE2. */
5647c478bd9Sstevel@tonic-gate if (size != filemax)
5657c478bd9Sstevel@tonic-gate {
5667c478bd9Sstevel@tonic-gate grub_printf ("Differ in size: 0x%x [%s], 0x%x [%s]\n",
5677c478bd9Sstevel@tonic-gate size, file1, filemax, file2);
5687c478bd9Sstevel@tonic-gate grub_close ();
5697c478bd9Sstevel@tonic-gate return 0;
5707c478bd9Sstevel@tonic-gate }
5717c478bd9Sstevel@tonic-gate
5727c478bd9Sstevel@tonic-gate if (! grub_read (addr2, -1))
5737c478bd9Sstevel@tonic-gate {
5747c478bd9Sstevel@tonic-gate grub_close ();
5757c478bd9Sstevel@tonic-gate return 1;
5767c478bd9Sstevel@tonic-gate }
5777c478bd9Sstevel@tonic-gate
5787c478bd9Sstevel@tonic-gate grub_close ();
5797c478bd9Sstevel@tonic-gate
5807c478bd9Sstevel@tonic-gate /* Now compare ADDR1 with ADDR2. */
5817c478bd9Sstevel@tonic-gate for (i = 0; i < size; i++)
5827c478bd9Sstevel@tonic-gate {
5837c478bd9Sstevel@tonic-gate if (addr1[i] != addr2[i])
5847c478bd9Sstevel@tonic-gate grub_printf ("Differ at the offset %d: 0x%x [%s], 0x%x [%s]\n",
5857c478bd9Sstevel@tonic-gate i, (unsigned) addr1[i], file1,
5867c478bd9Sstevel@tonic-gate (unsigned) addr2[i], file2);
5877c478bd9Sstevel@tonic-gate }
5887c478bd9Sstevel@tonic-gate
5897c478bd9Sstevel@tonic-gate return 0;
5907c478bd9Sstevel@tonic-gate }
5917c478bd9Sstevel@tonic-gate
5927c478bd9Sstevel@tonic-gate static struct builtin builtin_cmp =
5937c478bd9Sstevel@tonic-gate {
5947c478bd9Sstevel@tonic-gate "cmp",
5957c478bd9Sstevel@tonic-gate cmp_func,
5967c478bd9Sstevel@tonic-gate BUILTIN_CMDLINE,
5977c478bd9Sstevel@tonic-gate "cmp FILE1 FILE2",
5987c478bd9Sstevel@tonic-gate "Compare the file FILE1 with the FILE2 and inform the different values"
5997c478bd9Sstevel@tonic-gate " if any."
6007c478bd9Sstevel@tonic-gate };
6017c478bd9Sstevel@tonic-gate
6027c478bd9Sstevel@tonic-gate
6037c478bd9Sstevel@tonic-gate /* color */
6047c478bd9Sstevel@tonic-gate /* Set new colors used for the menu interface. Support two methods to
6057c478bd9Sstevel@tonic-gate specify a color name: a direct integer representation and a symbolic
6067c478bd9Sstevel@tonic-gate color name. An example of the latter is "blink-light-gray/blue". */
6077c478bd9Sstevel@tonic-gate static int
color_func(char * arg,int flags)6087c478bd9Sstevel@tonic-gate color_func (char *arg, int flags)
6097c478bd9Sstevel@tonic-gate {
6107c478bd9Sstevel@tonic-gate char *normal;
6117c478bd9Sstevel@tonic-gate char *highlight;
6127c478bd9Sstevel@tonic-gate int new_normal_color;
6137c478bd9Sstevel@tonic-gate int new_highlight_color;
6147c478bd9Sstevel@tonic-gate static char *color_list[16] =
6157c478bd9Sstevel@tonic-gate {
6167c478bd9Sstevel@tonic-gate "black",
6177c478bd9Sstevel@tonic-gate "blue",
6187c478bd9Sstevel@tonic-gate "green",
6197c478bd9Sstevel@tonic-gate "cyan",
6207c478bd9Sstevel@tonic-gate "red",
6217c478bd9Sstevel@tonic-gate "magenta",
6227c478bd9Sstevel@tonic-gate "brown",
6237c478bd9Sstevel@tonic-gate "light-gray",
6247c478bd9Sstevel@tonic-gate "dark-gray",
6257c478bd9Sstevel@tonic-gate "light-blue",
6267c478bd9Sstevel@tonic-gate "light-green",
6277c478bd9Sstevel@tonic-gate "light-cyan",
6287c478bd9Sstevel@tonic-gate "light-red",
6297c478bd9Sstevel@tonic-gate "light-magenta",
6307c478bd9Sstevel@tonic-gate "yellow",
6317c478bd9Sstevel@tonic-gate "white"
6327c478bd9Sstevel@tonic-gate };
6337c478bd9Sstevel@tonic-gate
6341b8adde7SWilliam Kucharski auto int color_number (char *str);
6351b8adde7SWilliam Kucharski
6367c478bd9Sstevel@tonic-gate /* Convert the color name STR into the magical number. */
6371b8adde7SWilliam Kucharski auto int color_number (char *str)
6387c478bd9Sstevel@tonic-gate {
6397c478bd9Sstevel@tonic-gate char *ptr;
6407c478bd9Sstevel@tonic-gate int i;
6417c478bd9Sstevel@tonic-gate int color = 0;
6427c478bd9Sstevel@tonic-gate
6437c478bd9Sstevel@tonic-gate /* Find the separator. */
6447c478bd9Sstevel@tonic-gate for (ptr = str; *ptr && *ptr != '/'; ptr++)
6457c478bd9Sstevel@tonic-gate ;
6467c478bd9Sstevel@tonic-gate
6477c478bd9Sstevel@tonic-gate /* If not found, return -1. */
6487c478bd9Sstevel@tonic-gate if (! *ptr)
6497c478bd9Sstevel@tonic-gate return -1;
6507c478bd9Sstevel@tonic-gate
6517c478bd9Sstevel@tonic-gate /* Terminate the string STR. */
6527c478bd9Sstevel@tonic-gate *ptr++ = 0;
6537c478bd9Sstevel@tonic-gate
6547c478bd9Sstevel@tonic-gate /* If STR contains the prefix "blink-", then set the `blink' bit
6557c478bd9Sstevel@tonic-gate in COLOR. */
6567c478bd9Sstevel@tonic-gate if (substring ("blink-", str) <= 0)
6577c478bd9Sstevel@tonic-gate {
6587c478bd9Sstevel@tonic-gate color = 0x80;
6597c478bd9Sstevel@tonic-gate str += 6;
6607c478bd9Sstevel@tonic-gate }
6617c478bd9Sstevel@tonic-gate
6627c478bd9Sstevel@tonic-gate /* Search for the color name. */
6637c478bd9Sstevel@tonic-gate for (i = 0; i < 16; i++)
6647c478bd9Sstevel@tonic-gate if (grub_strcmp (color_list[i], str) == 0)
6657c478bd9Sstevel@tonic-gate {
6667c478bd9Sstevel@tonic-gate color |= i;
6677c478bd9Sstevel@tonic-gate break;
6687c478bd9Sstevel@tonic-gate }
6697c478bd9Sstevel@tonic-gate
6707c478bd9Sstevel@tonic-gate if (i == 16)
6717c478bd9Sstevel@tonic-gate return -1;
6727c478bd9Sstevel@tonic-gate
6737c478bd9Sstevel@tonic-gate str = ptr;
6747c478bd9Sstevel@tonic-gate nul_terminate (str);
6757c478bd9Sstevel@tonic-gate
6767c478bd9Sstevel@tonic-gate /* Search for the color name. */
6777c478bd9Sstevel@tonic-gate for (i = 0; i < 8; i++)
6787c478bd9Sstevel@tonic-gate if (grub_strcmp (color_list[i], str) == 0)
6797c478bd9Sstevel@tonic-gate {
6807c478bd9Sstevel@tonic-gate color |= i << 4;
6817c478bd9Sstevel@tonic-gate break;
6827c478bd9Sstevel@tonic-gate }
6837c478bd9Sstevel@tonic-gate
6847c478bd9Sstevel@tonic-gate if (i == 8)
6857c478bd9Sstevel@tonic-gate return -1;
6867c478bd9Sstevel@tonic-gate
6877c478bd9Sstevel@tonic-gate return color;
6887c478bd9Sstevel@tonic-gate }
6897c478bd9Sstevel@tonic-gate
6907c478bd9Sstevel@tonic-gate normal = arg;
6917c478bd9Sstevel@tonic-gate highlight = skip_to (0, arg);
6927c478bd9Sstevel@tonic-gate
6937c478bd9Sstevel@tonic-gate new_normal_color = color_number (normal);
6947c478bd9Sstevel@tonic-gate if (new_normal_color < 0 && ! safe_parse_maxint (&normal, &new_normal_color))
6957c478bd9Sstevel@tonic-gate return 1;
6967c478bd9Sstevel@tonic-gate
6977c478bd9Sstevel@tonic-gate /* The second argument is optional, so set highlight_color
6987c478bd9Sstevel@tonic-gate to inverted NORMAL_COLOR. */
6997c478bd9Sstevel@tonic-gate if (! *highlight)
7007c478bd9Sstevel@tonic-gate new_highlight_color = ((new_normal_color >> 4)
7017c478bd9Sstevel@tonic-gate | ((new_normal_color & 0xf) << 4));
7027c478bd9Sstevel@tonic-gate else
7037c478bd9Sstevel@tonic-gate {
7047c478bd9Sstevel@tonic-gate new_highlight_color = color_number (highlight);
7057c478bd9Sstevel@tonic-gate if (new_highlight_color < 0
7067c478bd9Sstevel@tonic-gate && ! safe_parse_maxint (&highlight, &new_highlight_color))
7077c478bd9Sstevel@tonic-gate return 1;
7087c478bd9Sstevel@tonic-gate }
7097c478bd9Sstevel@tonic-gate
7107c478bd9Sstevel@tonic-gate if (current_term->setcolor)
7117c478bd9Sstevel@tonic-gate current_term->setcolor (new_normal_color, new_highlight_color);
7127c478bd9Sstevel@tonic-gate
7137c478bd9Sstevel@tonic-gate return 0;
7147c478bd9Sstevel@tonic-gate }
7157c478bd9Sstevel@tonic-gate
7167c478bd9Sstevel@tonic-gate static struct builtin builtin_color =
7177c478bd9Sstevel@tonic-gate {
7187c478bd9Sstevel@tonic-gate "color",
7197c478bd9Sstevel@tonic-gate color_func,
7207c478bd9Sstevel@tonic-gate BUILTIN_CMDLINE | BUILTIN_MENU | BUILTIN_HELP_LIST,
7217c478bd9Sstevel@tonic-gate "color NORMAL [HIGHLIGHT]",
7227c478bd9Sstevel@tonic-gate "Change the menu colors. The color NORMAL is used for most"
7237c478bd9Sstevel@tonic-gate " lines in the menu, and the color HIGHLIGHT is used to highlight the"
7247c478bd9Sstevel@tonic-gate " line where the cursor points. If you omit HIGHLIGHT, then the"
7257c478bd9Sstevel@tonic-gate " inverted color of NORMAL is used for the highlighted line."
7267c478bd9Sstevel@tonic-gate " The format of a color is \"FG/BG\". FG and BG are symbolic color names."
7277c478bd9Sstevel@tonic-gate " A symbolic color name must be one of these: black, blue, green,"
7287c478bd9Sstevel@tonic-gate " cyan, red, magenta, brown, light-gray, dark-gray, light-blue,"
7297c478bd9Sstevel@tonic-gate " light-green, light-cyan, light-red, light-magenta, yellow and white."
7307c478bd9Sstevel@tonic-gate " But only the first eight names can be used for BG. You can prefix"
7317c478bd9Sstevel@tonic-gate " \"blink-\" to FG if you want a blinking foreground color."
7327c478bd9Sstevel@tonic-gate };
7337c478bd9Sstevel@tonic-gate
7347c478bd9Sstevel@tonic-gate
7357c478bd9Sstevel@tonic-gate /* configfile */
7367c478bd9Sstevel@tonic-gate static int
configfile_func(char * arg,int flags)7377c478bd9Sstevel@tonic-gate configfile_func (char *arg, int flags)
7387c478bd9Sstevel@tonic-gate {
7397c478bd9Sstevel@tonic-gate char *new_config = config_file;
7407c478bd9Sstevel@tonic-gate
7417c478bd9Sstevel@tonic-gate /* Check if the file ARG is present. */
7427c478bd9Sstevel@tonic-gate if (! grub_open (arg))
7437c478bd9Sstevel@tonic-gate return 1;
7447c478bd9Sstevel@tonic-gate
7457c478bd9Sstevel@tonic-gate grub_close ();
7467c478bd9Sstevel@tonic-gate
7477c478bd9Sstevel@tonic-gate /* Copy ARG to CONFIG_FILE. */
7487c478bd9Sstevel@tonic-gate while ((*new_config++ = *arg++) != 0)
7497c478bd9Sstevel@tonic-gate ;
7507c478bd9Sstevel@tonic-gate
7517c478bd9Sstevel@tonic-gate #ifdef GRUB_UTIL
7527c478bd9Sstevel@tonic-gate /* Force to load the configuration file. */
7537c478bd9Sstevel@tonic-gate use_config_file = 1;
7547c478bd9Sstevel@tonic-gate #endif
7557c478bd9Sstevel@tonic-gate
7567c478bd9Sstevel@tonic-gate /* Make sure that the user will not be authoritative. */
7577c478bd9Sstevel@tonic-gate auth = 0;
7587c478bd9Sstevel@tonic-gate
7597c478bd9Sstevel@tonic-gate /* Restart cmain. */
7607c478bd9Sstevel@tonic-gate grub_longjmp (restart_env, 0);
7617c478bd9Sstevel@tonic-gate
7627c478bd9Sstevel@tonic-gate /* Never reach here. */
7637c478bd9Sstevel@tonic-gate return 0;
7647c478bd9Sstevel@tonic-gate }
7657c478bd9Sstevel@tonic-gate
7667c478bd9Sstevel@tonic-gate static struct builtin builtin_configfile =
7677c478bd9Sstevel@tonic-gate {
7687c478bd9Sstevel@tonic-gate "configfile",
7697c478bd9Sstevel@tonic-gate configfile_func,
7707c478bd9Sstevel@tonic-gate BUILTIN_CMDLINE | BUILTIN_HELP_LIST,
7717c478bd9Sstevel@tonic-gate "configfile FILE",
7727c478bd9Sstevel@tonic-gate "Load FILE as the configuration file."
7737c478bd9Sstevel@tonic-gate };
7747c478bd9Sstevel@tonic-gate
7757c478bd9Sstevel@tonic-gate
7767c478bd9Sstevel@tonic-gate /* debug */
7777c478bd9Sstevel@tonic-gate static int
debug_func(char * arg,int flags)7787c478bd9Sstevel@tonic-gate debug_func (char *arg, int flags)
7797c478bd9Sstevel@tonic-gate {
7807c478bd9Sstevel@tonic-gate if (debug)
7817c478bd9Sstevel@tonic-gate {
7827c478bd9Sstevel@tonic-gate debug = 0;
7837c478bd9Sstevel@tonic-gate grub_printf (" Debug mode is turned off\n");
7847c478bd9Sstevel@tonic-gate }
7857c478bd9Sstevel@tonic-gate else
7867c478bd9Sstevel@tonic-gate {
7877c478bd9Sstevel@tonic-gate debug = 1;
7887c478bd9Sstevel@tonic-gate grub_printf (" Debug mode is turned on\n");
7897c478bd9Sstevel@tonic-gate }
7907c478bd9Sstevel@tonic-gate
7917c478bd9Sstevel@tonic-gate return 0;
7927c478bd9Sstevel@tonic-gate }
7937c478bd9Sstevel@tonic-gate
7947c478bd9Sstevel@tonic-gate static struct builtin builtin_debug =
7957c478bd9Sstevel@tonic-gate {
7967c478bd9Sstevel@tonic-gate "debug",
7977c478bd9Sstevel@tonic-gate debug_func,
7987c478bd9Sstevel@tonic-gate BUILTIN_CMDLINE,
7997c478bd9Sstevel@tonic-gate "debug",
8007c478bd9Sstevel@tonic-gate "Turn on/off the debug mode."
8017c478bd9Sstevel@tonic-gate };
8027c478bd9Sstevel@tonic-gate
8037c478bd9Sstevel@tonic-gate
8047c478bd9Sstevel@tonic-gate /* default */
8057c478bd9Sstevel@tonic-gate static int
default_func(char * arg,int flags)8067c478bd9Sstevel@tonic-gate default_func (char *arg, int flags)
8077c478bd9Sstevel@tonic-gate {
8087c478bd9Sstevel@tonic-gate #ifndef SUPPORT_DISKLESS
8097c478bd9Sstevel@tonic-gate if (grub_strcmp (arg, "saved") == 0)
8107c478bd9Sstevel@tonic-gate {
8117c478bd9Sstevel@tonic-gate default_entry = saved_entryno;
8127c478bd9Sstevel@tonic-gate return 0;
8137c478bd9Sstevel@tonic-gate }
8147c478bd9Sstevel@tonic-gate #endif /* SUPPORT_DISKLESS */
8157c478bd9Sstevel@tonic-gate
8167c478bd9Sstevel@tonic-gate if (! safe_parse_maxint (&arg, &default_entry))
8177c478bd9Sstevel@tonic-gate return 1;
8187c478bd9Sstevel@tonic-gate
8197c478bd9Sstevel@tonic-gate return 0;
8207c478bd9Sstevel@tonic-gate }
8217c478bd9Sstevel@tonic-gate
8227c478bd9Sstevel@tonic-gate static struct builtin builtin_default =
8237c478bd9Sstevel@tonic-gate {
8247c478bd9Sstevel@tonic-gate "default",
8257c478bd9Sstevel@tonic-gate default_func,
8267c478bd9Sstevel@tonic-gate BUILTIN_MENU,
8277c478bd9Sstevel@tonic-gate #if 0
8287c478bd9Sstevel@tonic-gate "default [NUM | `saved']",
8297c478bd9Sstevel@tonic-gate "Set the default entry to entry number NUM (if not specified, it is"
8307c478bd9Sstevel@tonic-gate " 0, the first entry) or the entry number saved by savedefault."
8317c478bd9Sstevel@tonic-gate #endif
8327c478bd9Sstevel@tonic-gate };
8337c478bd9Sstevel@tonic-gate
8347c478bd9Sstevel@tonic-gate
8357c478bd9Sstevel@tonic-gate #ifdef GRUB_UTIL
8367c478bd9Sstevel@tonic-gate /* device */
8377c478bd9Sstevel@tonic-gate static int
device_func(char * arg,int flags)8387c478bd9Sstevel@tonic-gate device_func (char *arg, int flags)
8397c478bd9Sstevel@tonic-gate {
8407c478bd9Sstevel@tonic-gate char *drive = arg;
8417c478bd9Sstevel@tonic-gate char *device;
8427c478bd9Sstevel@tonic-gate
8437c478bd9Sstevel@tonic-gate /* Get the drive number from DRIVE. */
8447c478bd9Sstevel@tonic-gate if (! set_device (drive))
8457c478bd9Sstevel@tonic-gate return 1;
8467c478bd9Sstevel@tonic-gate
8477c478bd9Sstevel@tonic-gate /* Get the device argument. */
8487c478bd9Sstevel@tonic-gate device = skip_to (0, drive);
8497c478bd9Sstevel@tonic-gate
8507c478bd9Sstevel@tonic-gate /* Terminate DEVICE. */
8517c478bd9Sstevel@tonic-gate nul_terminate (device);
8527c478bd9Sstevel@tonic-gate
8537c478bd9Sstevel@tonic-gate if (! *device || ! check_device (device))
8547c478bd9Sstevel@tonic-gate {
8557c478bd9Sstevel@tonic-gate errnum = ERR_FILE_NOT_FOUND;
8567c478bd9Sstevel@tonic-gate return 1;
8577c478bd9Sstevel@tonic-gate }
8587c478bd9Sstevel@tonic-gate
8597c478bd9Sstevel@tonic-gate assign_device_name (current_drive, device);
8607c478bd9Sstevel@tonic-gate
8617c478bd9Sstevel@tonic-gate return 0;
8627c478bd9Sstevel@tonic-gate }
8637c478bd9Sstevel@tonic-gate
8647c478bd9Sstevel@tonic-gate static struct builtin builtin_device =
8657c478bd9Sstevel@tonic-gate {
8667c478bd9Sstevel@tonic-gate "device",
8677c478bd9Sstevel@tonic-gate device_func,
8687c478bd9Sstevel@tonic-gate BUILTIN_MENU | BUILTIN_CMDLINE | BUILTIN_HELP_LIST,
8697c478bd9Sstevel@tonic-gate "device DRIVE DEVICE",
8707c478bd9Sstevel@tonic-gate "Specify DEVICE as the actual drive for a BIOS drive DRIVE. This command"
8717c478bd9Sstevel@tonic-gate " can be used only in the grub shell."
8727c478bd9Sstevel@tonic-gate };
8737c478bd9Sstevel@tonic-gate #endif /* GRUB_UTIL */
8747c478bd9Sstevel@tonic-gate
8757c478bd9Sstevel@tonic-gate #ifdef SUPPORT_NETBOOT
8767c478bd9Sstevel@tonic-gate /* Debug Function for RPC */
8777c478bd9Sstevel@tonic-gate #ifdef RPC_DEBUG
8787c478bd9Sstevel@tonic-gate /* portmap */
8797c478bd9Sstevel@tonic-gate static int
portmap_func(char * arg,int flags)8807c478bd9Sstevel@tonic-gate portmap_func (char *arg, int flags)
8817c478bd9Sstevel@tonic-gate {
8827c478bd9Sstevel@tonic-gate int port, prog, ver;
8837c478bd9Sstevel@tonic-gate if (! grub_eth_probe ()){
8847c478bd9Sstevel@tonic-gate grub_printf ("No ethernet card found.\n");
8857c478bd9Sstevel@tonic-gate errnum = ERR_DEV_VALUES;
8867c478bd9Sstevel@tonic-gate return 1;
8877c478bd9Sstevel@tonic-gate }
8887c478bd9Sstevel@tonic-gate if ((prog = getdec(&arg)) == -1){
8897c478bd9Sstevel@tonic-gate grub_printf("Error prog number\n");
8907c478bd9Sstevel@tonic-gate return 1;
8917c478bd9Sstevel@tonic-gate }
8927c478bd9Sstevel@tonic-gate arg = skip_to (0, arg);
8937c478bd9Sstevel@tonic-gate if ((ver = getdec(&arg)) == -1){
8947c478bd9Sstevel@tonic-gate grub_printf("Error ver number\n");
8957c478bd9Sstevel@tonic-gate return 1;
8967c478bd9Sstevel@tonic-gate }
8977c478bd9Sstevel@tonic-gate port = __pmapudp_getport(ARP_SERVER, prog, ver);
8987c478bd9Sstevel@tonic-gate printf("portmap getport %d", port);
8997c478bd9Sstevel@tonic-gate return 0;
9007c478bd9Sstevel@tonic-gate }
9017c478bd9Sstevel@tonic-gate
9027c478bd9Sstevel@tonic-gate static struct builtin builtin_portmap =
9037c478bd9Sstevel@tonic-gate {
9047c478bd9Sstevel@tonic-gate "portmap",
9057c478bd9Sstevel@tonic-gate portmap_func,
9067c478bd9Sstevel@tonic-gate BUILTIN_CMDLINE | BUILTIN_HELP_LIST,
9077c478bd9Sstevel@tonic-gate "portmap prog_number vers_number",
9087c478bd9Sstevel@tonic-gate "Do portmap with the prog_number and vers_number"
9097c478bd9Sstevel@tonic-gate };
9107c478bd9Sstevel@tonic-gate #endif /* RPC_DEBUG */
9117c478bd9Sstevel@tonic-gate
9127c478bd9Sstevel@tonic-gate /* dhcp */
9137c478bd9Sstevel@tonic-gate static int
dhcp_func(char * arg,int flags)9147c478bd9Sstevel@tonic-gate dhcp_func (char *arg, int flags)
9157c478bd9Sstevel@tonic-gate {
9167c478bd9Sstevel@tonic-gate int with_configfile = 0;
9177c478bd9Sstevel@tonic-gate
9187c478bd9Sstevel@tonic-gate if (grub_memcmp (arg, "--with-configfile", sizeof ("--with-configfile") - 1)
9197c478bd9Sstevel@tonic-gate == 0)
9207c478bd9Sstevel@tonic-gate {
9217c478bd9Sstevel@tonic-gate with_configfile = 1;
9227c478bd9Sstevel@tonic-gate arg = skip_to (0, arg);
9237c478bd9Sstevel@tonic-gate }
9247c478bd9Sstevel@tonic-gate
9257c478bd9Sstevel@tonic-gate if (! dhcp ())
9267c478bd9Sstevel@tonic-gate {
9277c478bd9Sstevel@tonic-gate if (errnum == ERR_NONE)
9287c478bd9Sstevel@tonic-gate errnum = ERR_DEV_VALUES;
9297c478bd9Sstevel@tonic-gate
9307c478bd9Sstevel@tonic-gate return 1;
9317c478bd9Sstevel@tonic-gate }
9327c478bd9Sstevel@tonic-gate
9337c478bd9Sstevel@tonic-gate /* Notify the configuration. */
9347c478bd9Sstevel@tonic-gate print_network_configuration ();
9357c478bd9Sstevel@tonic-gate
9367c478bd9Sstevel@tonic-gate /* XXX: this can cause an endless loop, but there is no easy way to
9377c478bd9Sstevel@tonic-gate detect such a loop unfortunately. */
9387c478bd9Sstevel@tonic-gate if (with_configfile)
9397c478bd9Sstevel@tonic-gate configfile_func (config_file, flags);
9407c478bd9Sstevel@tonic-gate else
9417c478bd9Sstevel@tonic-gate solaris_config_file();
9427c478bd9Sstevel@tonic-gate
9437c478bd9Sstevel@tonic-gate return 0;
9447c478bd9Sstevel@tonic-gate }
9457c478bd9Sstevel@tonic-gate
9462506833eSJan Setje-Eilers static int
test_config_file(char * menufile)9472506833eSJan Setje-Eilers test_config_file(char *menufile)
9482506833eSJan Setje-Eilers {
9492506833eSJan Setje-Eilers int err;
9502506833eSJan Setje-Eilers
9512506833eSJan Setje-Eilers /*
9522506833eSJan Setje-Eilers * If the file exists, make it the default. Else, fallback
9532506833eSJan Setje-Eilers * to what it was. Make sure we don't change errnum in the
9542506833eSJan Setje-Eilers * process.
9552506833eSJan Setje-Eilers */
9562506833eSJan Setje-Eilers err = errnum;
9572506833eSJan Setje-Eilers if (grub_open(menufile)) {
9582506833eSJan Setje-Eilers grub_strcpy(config_file, menufile);
9592506833eSJan Setje-Eilers grub_close();
9602506833eSJan Setje-Eilers errnum = err;
9612506833eSJan Setje-Eilers return (1);
9622506833eSJan Setje-Eilers }
9632506833eSJan Setje-Eilers errnum = err;
9642506833eSJan Setje-Eilers return (0);
9652506833eSJan Setje-Eilers }
9662506833eSJan Setje-Eilers
solaris_config_file(void)9677c478bd9Sstevel@tonic-gate static void solaris_config_file (void)
9687c478bd9Sstevel@tonic-gate {
9697c478bd9Sstevel@tonic-gate static char menufile[64];
9707c478bd9Sstevel@tonic-gate static char hexdigit[] = "0123456789ABCDEF";
9717c478bd9Sstevel@tonic-gate char *c = menufile;
9727c478bd9Sstevel@tonic-gate int i;
9737c478bd9Sstevel@tonic-gate
9742506833eSJan Setje-Eilers /*
9752506833eSJan Setje-Eilers * if DHCP option 150 has been provided, config_file will
9762506833eSJan Setje-Eilers * already contain the string, try it.
9772506833eSJan Setje-Eilers */
9782506833eSJan Setje-Eilers if (configfile_origin == CFG_150) {
9792506833eSJan Setje-Eilers if (test_config_file(config_file))
9802506833eSJan Setje-Eilers return;
9812506833eSJan Setje-Eilers }
9827c478bd9Sstevel@tonic-gate
9832506833eSJan Setje-Eilers /*
9842506833eSJan Setje-Eilers * try to find host (MAC address) specific configfile:
9852506833eSJan Setje-Eilers * menu.lst.01<ether_addr>
9862506833eSJan Setje-Eilers */
9872269adc8Sszhou grub_strcpy(c, "menu.lst.01");
9887c478bd9Sstevel@tonic-gate c += grub_strlen(c);
9897c478bd9Sstevel@tonic-gate for (i = 0; i < ETH_ALEN; i++) {
9907c478bd9Sstevel@tonic-gate unsigned char b = arptable[ARP_CLIENT].node[i];
9917c478bd9Sstevel@tonic-gate *c++ = hexdigit[b >> 4];
9927c478bd9Sstevel@tonic-gate *c++ = hexdigit[b & 0xf];
9937c478bd9Sstevel@tonic-gate }
9947c478bd9Sstevel@tonic-gate *c = 0;
9952506833eSJan Setje-Eilers configfile_origin = CFG_MAC;
9962506833eSJan Setje-Eilers if (test_config_file(menufile))
9972506833eSJan Setje-Eilers return;
9987c478bd9Sstevel@tonic-gate
9996759d08fScasper /*
10002506833eSJan Setje-Eilers * try to find a configfile derived from the DHCP/bootp
10012506833eSJan Setje-Eilers * BootFile string: menu.lst.<BootFile>
10027c478bd9Sstevel@tonic-gate */
10032506833eSJan Setje-Eilers if (bootfile != NULL && bootfile[0] != 0) {
10042506833eSJan Setje-Eilers c = menufile;
10052506833eSJan Setje-Eilers grub_strcpy(c, "menu.lst.");
10062506833eSJan Setje-Eilers c += grub_strlen("menu.lst.");
10072506833eSJan Setje-Eilers i = grub_strlen("pxegrub.");
10082506833eSJan Setje-Eilers if (grub_memcmp(bootfile, "pxegrub.", i) == 0)
10092506833eSJan Setje-Eilers grub_strcpy(c, bootfile + i);
10102506833eSJan Setje-Eilers else
10112506833eSJan Setje-Eilers grub_strcpy(c, bootfile);
10122506833eSJan Setje-Eilers configfile_origin = CFG_BOOTFILE;
10132506833eSJan Setje-Eilers if (test_config_file(menufile))
10142506833eSJan Setje-Eilers return;
10157c478bd9Sstevel@tonic-gate }
10162506833eSJan Setje-Eilers
10172506833eSJan Setje-Eilers /*
10182506833eSJan Setje-Eilers * Default to hard coded "/boot/grub/menu.lst" config file.
10192506833eSJan Setje-Eilers * This is the last resort, so there's no need to test it,
10202506833eSJan Setje-Eilers * as there's nothing else to try.
10212506833eSJan Setje-Eilers */
10222506833eSJan Setje-Eilers char *cp = config_file;
10232506833eSJan Setje-Eilers /* skip leading slashes for tftp */
10242506833eSJan Setje-Eilers while (*cp == '/')
10252506833eSJan Setje-Eilers ++cp;
10262506833eSJan Setje-Eilers grub_memmove (config_file, cp, strlen(cp) + 1);
10272506833eSJan Setje-Eilers configfile_origin = CFG_HARDCODED;
10287c478bd9Sstevel@tonic-gate }
10297c478bd9Sstevel@tonic-gate
10307c478bd9Sstevel@tonic-gate static struct builtin builtin_dhcp =
10317c478bd9Sstevel@tonic-gate {
10327c478bd9Sstevel@tonic-gate "dhcp",
10337c478bd9Sstevel@tonic-gate dhcp_func,
10347c478bd9Sstevel@tonic-gate BUILTIN_CMDLINE | BUILTIN_MENU | BUILTIN_HELP_LIST,
10357c478bd9Sstevel@tonic-gate "dhcp",
10367c478bd9Sstevel@tonic-gate "Initialize a network device via DHCP."
10377c478bd9Sstevel@tonic-gate };
10387c478bd9Sstevel@tonic-gate #endif /* SUPPORT_NETBOOT */
10397c478bd9Sstevel@tonic-gate
10407c478bd9Sstevel@tonic-gate static int terminal_func (char *arg, int flags);
10417c478bd9Sstevel@tonic-gate
verbose_func(char * arg,int flags)10421fac5a60Ssetje static int verbose_func(char *arg, int flags) {
10431fac5a60Ssetje
10441fac5a60Ssetje if (grub_strcmp(arg, "off") == 0) {
10451fac5a60Ssetje silent.status = DEFER_SILENT;
10461fac5a60Ssetje return;
10471fac5a60Ssetje } else
10481fac5a60Ssetje if (flags == BUILTIN_CMDLINE) {
10491fac5a60Ssetje silent.status = DEFER_VERBOSE;
10501fac5a60Ssetje return;
10511fac5a60Ssetje }
10521fac5a60Ssetje
10531fac5a60Ssetje silent.status = VERBOSE;
10541fac5a60Ssetje
1055ae115bc7Smrj /* get back to text console */
10561fac5a60Ssetje if (current_term->shutdown) {
10571fac5a60Ssetje (*current_term->shutdown)();
10581fac5a60Ssetje current_term = term_table; /* assumption: console is first */
10591fac5a60Ssetje }
10601fac5a60Ssetje
10611fac5a60Ssetje /* dump the buffer */
10621fac5a60Ssetje if (!silent.looped) {
10631fac5a60Ssetje /* if the buffer hasn't looped, just print it */
10641fac5a60Ssetje printf("%s", silent.buffer);
10651fac5a60Ssetje } else {
10661fac5a60Ssetje /*
10671fac5a60Ssetje * If the buffer has looped, first print the oldest part of the buffer,
10681fac5a60Ssetje * which is one past the current null. Then print the newer part which
10691fac5a60Ssetje * starts at the beginning of the buffer.
10701fac5a60Ssetje */
10711fac5a60Ssetje printf("%s", silent.buffer_start + 1);
10721fac5a60Ssetje printf("%s", silent.buffer);
10731fac5a60Ssetje }
10741fac5a60Ssetje
10751fac5a60Ssetje return 0;
10761fac5a60Ssetje }
10771fac5a60Ssetje
10781fac5a60Ssetje static struct builtin builtin_verbose =
10791fac5a60Ssetje {
10801fac5a60Ssetje "verbose",
10811fac5a60Ssetje verbose_func,
10821fac5a60Ssetje BUILTIN_CMDLINE | BUILTIN_MENU | BUILTIN_SCRIPT | BUILTIN_HELP_LIST,
10831fac5a60Ssetje "verbose",
10841fac5a60Ssetje "Verbose output during menu entry (script) execution."
10851fac5a60Ssetje };
10861fac5a60Ssetje
10877c478bd9Sstevel@tonic-gate #ifdef SUPPORT_GRAPHICS
10887c478bd9Sstevel@tonic-gate
splashimage_func(char * arg,int flags)10897c478bd9Sstevel@tonic-gate static int splashimage_func(char *arg, int flags) {
10907c478bd9Sstevel@tonic-gate char splashimage[64];
10917c478bd9Sstevel@tonic-gate int i;
10921fac5a60Ssetje
10937c478bd9Sstevel@tonic-gate /* filename can only be 64 characters due to our buffer size */
10947c478bd9Sstevel@tonic-gate if (strlen(arg) > 63)
10957c478bd9Sstevel@tonic-gate return 1;
10967c478bd9Sstevel@tonic-gate
10971fac5a60Ssetje if (flags == BUILTIN_SCRIPT)
10981fac5a60Ssetje flags = BUILTIN_CMDLINE;
10991fac5a60Ssetje
1100a6e28364SSuhasini Peddada if (flags == BUILTIN_CMDLINE) {
1101a6e28364SSuhasini Peddada if (!grub_open(arg))
1102a6e28364SSuhasini Peddada return 1;
1103a6e28364SSuhasini Peddada grub_close();
1104a6e28364SSuhasini Peddada }
11057c478bd9Sstevel@tonic-gate
1106a6e28364SSuhasini Peddada strcpy(splashimage, arg);
110741c4174fSWilliam Kucharski
11087c478bd9Sstevel@tonic-gate /* get rid of TERM_NEED_INIT from the graphics terminal. */
11097c478bd9Sstevel@tonic-gate for (i = 0; term_table[i].name; i++) {
11107c478bd9Sstevel@tonic-gate if (grub_strcmp (term_table[i].name, "graphics") == 0) {
11117c478bd9Sstevel@tonic-gate term_table[i].flags &= ~TERM_NEED_INIT;
11127c478bd9Sstevel@tonic-gate break;
11137c478bd9Sstevel@tonic-gate }
11147c478bd9Sstevel@tonic-gate }
11159b4e3ac2SWilliam Kucharski
1116a6e28364SSuhasini Peddada graphics_set_splash(splashimage);
1117a6e28364SSuhasini Peddada
11187c478bd9Sstevel@tonic-gate if (flags == BUILTIN_CMDLINE && graphics_inited) {
11191fac5a60Ssetje /*
11201fac5a60Ssetje * calling graphics_end() here flickers the screen black. OTOH not
11211fac5a60Ssetje * calling it gets us odd plane interlacing / early palette switching ?
11221fac5a60Ssetje * ideally one should figure out how to double buffer and switch...
11231fac5a60Ssetje */
11247c478bd9Sstevel@tonic-gate graphics_end();
11257c478bd9Sstevel@tonic-gate graphics_init();
11267c478bd9Sstevel@tonic-gate graphics_cls();
11277c478bd9Sstevel@tonic-gate }
11287c478bd9Sstevel@tonic-gate
11299b4e3ac2SWilliam Kucharski /*
11309b4e3ac2SWilliam Kucharski * This call does not explicitly initialize graphics mode, but rather
11319b4e3ac2SWilliam Kucharski * simply sets the terminal type unless we're in command line mode and
11329b4e3ac2SWilliam Kucharski * call this function while in terminal mode.
11339b4e3ac2SWilliam Kucharski */
11347c478bd9Sstevel@tonic-gate terminal_func("graphics", flags);
11357c478bd9Sstevel@tonic-gate
11361fac5a60Ssetje reset_term = 0;
11371fac5a60Ssetje
11387c478bd9Sstevel@tonic-gate return 0;
11397c478bd9Sstevel@tonic-gate }
11407c478bd9Sstevel@tonic-gate
11417c478bd9Sstevel@tonic-gate static struct builtin builtin_splashimage =
11427c478bd9Sstevel@tonic-gate {
11437c478bd9Sstevel@tonic-gate "splashimage",
11447c478bd9Sstevel@tonic-gate splashimage_func,
11451fac5a60Ssetje BUILTIN_CMDLINE | BUILTIN_MENU | BUILTIN_SCRIPT | BUILTIN_HELP_LIST,
11467c478bd9Sstevel@tonic-gate "splashimage FILE",
11477c478bd9Sstevel@tonic-gate "Load FILE as the background image when in graphics mode."
11487c478bd9Sstevel@tonic-gate };
11497c478bd9Sstevel@tonic-gate
11507c478bd9Sstevel@tonic-gate
11517c478bd9Sstevel@tonic-gate /* foreground */
11527c478bd9Sstevel@tonic-gate static int
foreground_func(char * arg,int flags)11537c478bd9Sstevel@tonic-gate foreground_func(char *arg, int flags)
11547c478bd9Sstevel@tonic-gate {
11557c478bd9Sstevel@tonic-gate if (grub_strlen(arg) == 6) {
11567c478bd9Sstevel@tonic-gate int r = ((hex(arg[0]) << 4) | hex(arg[1])) >> 2;
11577c478bd9Sstevel@tonic-gate int g = ((hex(arg[2]) << 4) | hex(arg[3])) >> 2;
11587c478bd9Sstevel@tonic-gate int b = ((hex(arg[4]) << 4) | hex(arg[5])) >> 2;
11597c478bd9Sstevel@tonic-gate
11607c478bd9Sstevel@tonic-gate foreground = (r << 16) | (g << 8) | b;
11617c478bd9Sstevel@tonic-gate if (graphics_inited)
11627c478bd9Sstevel@tonic-gate graphics_set_palette(15, r, g, b);
11637c478bd9Sstevel@tonic-gate
11647c478bd9Sstevel@tonic-gate return (0);
11657c478bd9Sstevel@tonic-gate }
11667c478bd9Sstevel@tonic-gate
11677c478bd9Sstevel@tonic-gate return (1);
11687c478bd9Sstevel@tonic-gate }
11697c478bd9Sstevel@tonic-gate
11707c478bd9Sstevel@tonic-gate static struct builtin builtin_foreground =
11717c478bd9Sstevel@tonic-gate {
11727c478bd9Sstevel@tonic-gate "foreground",
11737c478bd9Sstevel@tonic-gate foreground_func,
117467ce1dadSJan Setje-Eilers BUILTIN_CMDLINE | BUILTIN_MENU | BUILTIN_HELP_LIST | BUILTIN_SCRIPT,
11757c478bd9Sstevel@tonic-gate "foreground RRGGBB",
11767c478bd9Sstevel@tonic-gate "Sets the foreground color when in graphics mode."
11777c478bd9Sstevel@tonic-gate "RR is red, GG is green, and BB blue. Numbers must be in hexadecimal."
11787c478bd9Sstevel@tonic-gate };
11797c478bd9Sstevel@tonic-gate
11807c478bd9Sstevel@tonic-gate
11817c478bd9Sstevel@tonic-gate /* background */
11827c478bd9Sstevel@tonic-gate static int
background_func(char * arg,int flags)11837c478bd9Sstevel@tonic-gate background_func(char *arg, int flags)
11847c478bd9Sstevel@tonic-gate {
11857c478bd9Sstevel@tonic-gate if (grub_strlen(arg) == 6) {
11867c478bd9Sstevel@tonic-gate int r = ((hex(arg[0]) << 4) | hex(arg[1])) >> 2;
11877c478bd9Sstevel@tonic-gate int g = ((hex(arg[2]) << 4) | hex(arg[3])) >> 2;
11887c478bd9Sstevel@tonic-gate int b = ((hex(arg[4]) << 4) | hex(arg[5])) >> 2;
11897c478bd9Sstevel@tonic-gate
11907c478bd9Sstevel@tonic-gate background = (r << 16) | (g << 8) | b;
11917c478bd9Sstevel@tonic-gate if (graphics_inited)
11927c478bd9Sstevel@tonic-gate graphics_set_palette(0, r, g, b);
11937c478bd9Sstevel@tonic-gate return (0);
11947c478bd9Sstevel@tonic-gate }
11957c478bd9Sstevel@tonic-gate
11967c478bd9Sstevel@tonic-gate return (1);
11977c478bd9Sstevel@tonic-gate }
11987c478bd9Sstevel@tonic-gate
11997c478bd9Sstevel@tonic-gate static struct builtin builtin_background =
12007c478bd9Sstevel@tonic-gate {
12017c478bd9Sstevel@tonic-gate "background",
12027c478bd9Sstevel@tonic-gate background_func,
120367ce1dadSJan Setje-Eilers BUILTIN_CMDLINE | BUILTIN_MENU | BUILTIN_HELP_LIST | BUILTIN_SCRIPT,
12047c478bd9Sstevel@tonic-gate "background RRGGBB",
12057c478bd9Sstevel@tonic-gate "Sets the background color when in graphics mode."
12067c478bd9Sstevel@tonic-gate "RR is red, GG is green, and BB blue. Numbers must be in hexadecimal."
12077c478bd9Sstevel@tonic-gate };
12087c478bd9Sstevel@tonic-gate
12097c478bd9Sstevel@tonic-gate #endif /* SUPPORT_GRAPHICS */
12107c478bd9Sstevel@tonic-gate
12117c478bd9Sstevel@tonic-gate
12127c478bd9Sstevel@tonic-gate /* clear */
12137c478bd9Sstevel@tonic-gate static int
clear_func()12147c478bd9Sstevel@tonic-gate clear_func()
12157c478bd9Sstevel@tonic-gate {
12167c478bd9Sstevel@tonic-gate if (current_term->cls)
12177c478bd9Sstevel@tonic-gate current_term->cls();
12187c478bd9Sstevel@tonic-gate
12197c478bd9Sstevel@tonic-gate return 0;
12207c478bd9Sstevel@tonic-gate }
12217c478bd9Sstevel@tonic-gate
12227c478bd9Sstevel@tonic-gate static struct builtin builtin_clear =
12237c478bd9Sstevel@tonic-gate {
12247c478bd9Sstevel@tonic-gate "clear",
12257c478bd9Sstevel@tonic-gate clear_func,
12267c478bd9Sstevel@tonic-gate BUILTIN_CMDLINE | BUILTIN_HELP_LIST,
12277c478bd9Sstevel@tonic-gate "clear",
12287c478bd9Sstevel@tonic-gate "Clear the screen"
12297c478bd9Sstevel@tonic-gate };
12307c478bd9Sstevel@tonic-gate
12317c478bd9Sstevel@tonic-gate /* displayapm */
12327c478bd9Sstevel@tonic-gate static int
displayapm_func(char * arg,int flags)12337c478bd9Sstevel@tonic-gate displayapm_func (char *arg, int flags)
12347c478bd9Sstevel@tonic-gate {
12357c478bd9Sstevel@tonic-gate if (mbi.flags & MB_INFO_APM_TABLE)
12367c478bd9Sstevel@tonic-gate {
12377c478bd9Sstevel@tonic-gate grub_printf ("APM BIOS information:\n"
12387c478bd9Sstevel@tonic-gate " Version: 0x%x\n"
12397c478bd9Sstevel@tonic-gate " 32-bit CS: 0x%x\n"
12407c478bd9Sstevel@tonic-gate " Offset: 0x%x\n"
12417c478bd9Sstevel@tonic-gate " 16-bit CS: 0x%x\n"
12427c478bd9Sstevel@tonic-gate " 16-bit DS: 0x%x\n"
12437c478bd9Sstevel@tonic-gate " 32-bit CS length: 0x%x\n"
12447c478bd9Sstevel@tonic-gate " 16-bit CS length: 0x%x\n"
12457c478bd9Sstevel@tonic-gate " 16-bit DS length: 0x%x\n",
12467c478bd9Sstevel@tonic-gate (unsigned) apm_bios_info.version,
12477c478bd9Sstevel@tonic-gate (unsigned) apm_bios_info.cseg,
12487c478bd9Sstevel@tonic-gate apm_bios_info.offset,
12497c478bd9Sstevel@tonic-gate (unsigned) apm_bios_info.cseg_16,
12507c478bd9Sstevel@tonic-gate (unsigned) apm_bios_info.dseg_16,
12517c478bd9Sstevel@tonic-gate (unsigned) apm_bios_info.cseg_len,
12527c478bd9Sstevel@tonic-gate (unsigned) apm_bios_info.cseg_16_len,
12537c478bd9Sstevel@tonic-gate (unsigned) apm_bios_info.dseg_16_len);
12547c478bd9Sstevel@tonic-gate }
12557c478bd9Sstevel@tonic-gate else
12567c478bd9Sstevel@tonic-gate {
12577c478bd9Sstevel@tonic-gate grub_printf ("No APM BIOS found or probe failed\n");
12587c478bd9Sstevel@tonic-gate }
12597c478bd9Sstevel@tonic-gate
12607c478bd9Sstevel@tonic-gate return 0;
12617c478bd9Sstevel@tonic-gate }
12627c478bd9Sstevel@tonic-gate
12637c478bd9Sstevel@tonic-gate static struct builtin builtin_displayapm =
12647c478bd9Sstevel@tonic-gate {
12657c478bd9Sstevel@tonic-gate "displayapm",
12667c478bd9Sstevel@tonic-gate displayapm_func,
12677c478bd9Sstevel@tonic-gate BUILTIN_CMDLINE | BUILTIN_HELP_LIST,
12687c478bd9Sstevel@tonic-gate "displayapm",
12697c478bd9Sstevel@tonic-gate "Display APM BIOS information."
12707c478bd9Sstevel@tonic-gate };
12717c478bd9Sstevel@tonic-gate
12727c478bd9Sstevel@tonic-gate
12737c478bd9Sstevel@tonic-gate /* displaymem */
12747c478bd9Sstevel@tonic-gate static int
displaymem_func(char * arg,int flags)12757c478bd9Sstevel@tonic-gate displaymem_func (char *arg, int flags)
12767c478bd9Sstevel@tonic-gate {
12777c478bd9Sstevel@tonic-gate if (get_eisamemsize () != -1)
12787c478bd9Sstevel@tonic-gate grub_printf (" EISA Memory BIOS Interface is present\n");
12797c478bd9Sstevel@tonic-gate if (get_mmap_entry ((void *) SCRATCHADDR, 0) != 0
12807c478bd9Sstevel@tonic-gate || *((int *) SCRATCHADDR) != 0)
12817c478bd9Sstevel@tonic-gate grub_printf (" Address Map BIOS Interface is present\n");
12827c478bd9Sstevel@tonic-gate
12837c478bd9Sstevel@tonic-gate grub_printf (" Lower memory: %uK, "
12847c478bd9Sstevel@tonic-gate "Upper memory (to first chipset hole): %uK\n",
12857c478bd9Sstevel@tonic-gate mbi.mem_lower, mbi.mem_upper);
12867c478bd9Sstevel@tonic-gate
1287342440ecSPrasad Singamsetty if (min_mem64 != 0)
1288342440ecSPrasad Singamsetty grub_printf (" Memory limit for 64-bit ISADIR expansion: %uMB\n",
1289342440ecSPrasad Singamsetty min_mem64);
1290342440ecSPrasad Singamsetty
12917c478bd9Sstevel@tonic-gate if (mbi.flags & MB_INFO_MEM_MAP)
12927c478bd9Sstevel@tonic-gate {
12937c478bd9Sstevel@tonic-gate struct AddrRangeDesc *map = (struct AddrRangeDesc *) mbi.mmap_addr;
12947c478bd9Sstevel@tonic-gate int end_addr = mbi.mmap_addr + mbi.mmap_length;
12957c478bd9Sstevel@tonic-gate
12967c478bd9Sstevel@tonic-gate grub_printf (" [Address Range Descriptor entries "
12977c478bd9Sstevel@tonic-gate "immediately follow (values are 64-bit)]\n");
12987c478bd9Sstevel@tonic-gate while (end_addr > (int) map)
12997c478bd9Sstevel@tonic-gate {
13007c478bd9Sstevel@tonic-gate char *str;
13017c478bd9Sstevel@tonic-gate
13027c478bd9Sstevel@tonic-gate if (map->Type == MB_ARD_MEMORY)
13037c478bd9Sstevel@tonic-gate str = "Usable RAM";
13047c478bd9Sstevel@tonic-gate else
13057c478bd9Sstevel@tonic-gate str = "Reserved";
13067c478bd9Sstevel@tonic-gate grub_printf (" %s: Base Address: 0x%x X 4GB + 0x%x,\n"
1307342440ecSPrasad Singamsetty " Length: 0x%x X 4GB + 0x%x bytes\n",
1308342440ecSPrasad Singamsetty str,
1309342440ecSPrasad Singamsetty (unsigned long) (map->BaseAddr >> 32),
1310342440ecSPrasad Singamsetty (unsigned long) (map->BaseAddr & 0xFFFFFFFF),
1311342440ecSPrasad Singamsetty (unsigned long) (map->Length >> 32),
1312342440ecSPrasad Singamsetty (unsigned long) (map->Length & 0xFFFFFFFF));
13137c478bd9Sstevel@tonic-gate
13147c478bd9Sstevel@tonic-gate map = ((struct AddrRangeDesc *) (((int) map) + 4 + map->size));
13157c478bd9Sstevel@tonic-gate }
13167c478bd9Sstevel@tonic-gate }
13177c478bd9Sstevel@tonic-gate
13187c478bd9Sstevel@tonic-gate return 0;
13197c478bd9Sstevel@tonic-gate }
13207c478bd9Sstevel@tonic-gate
13217c478bd9Sstevel@tonic-gate static struct builtin builtin_displaymem =
13227c478bd9Sstevel@tonic-gate {
13237c478bd9Sstevel@tonic-gate "displaymem",
13247c478bd9Sstevel@tonic-gate displaymem_func,
13257c478bd9Sstevel@tonic-gate BUILTIN_CMDLINE | BUILTIN_HELP_LIST,
13267c478bd9Sstevel@tonic-gate "displaymem",
13277c478bd9Sstevel@tonic-gate "Display what GRUB thinks the system address space map of the"
13287c478bd9Sstevel@tonic-gate " machine is, including all regions of physical RAM installed."
13297c478bd9Sstevel@tonic-gate };
13307c478bd9Sstevel@tonic-gate
13317c478bd9Sstevel@tonic-gate
13327c478bd9Sstevel@tonic-gate /* dump FROM TO */
13337c478bd9Sstevel@tonic-gate #ifdef GRUB_UTIL
13347c478bd9Sstevel@tonic-gate static int
dump_func(char * arg,int flags)13357c478bd9Sstevel@tonic-gate dump_func (char *arg, int flags)
13367c478bd9Sstevel@tonic-gate {
13377c478bd9Sstevel@tonic-gate char *from, *to;
13387c478bd9Sstevel@tonic-gate FILE *fp;
13397c478bd9Sstevel@tonic-gate char c;
13407c478bd9Sstevel@tonic-gate
13417c478bd9Sstevel@tonic-gate from = arg;
13427c478bd9Sstevel@tonic-gate to = skip_to (0, arg);
13437c478bd9Sstevel@tonic-gate if (! *from || ! *to)
13447c478bd9Sstevel@tonic-gate {
13457c478bd9Sstevel@tonic-gate errnum = ERR_BAD_ARGUMENT;
13467c478bd9Sstevel@tonic-gate return 1;
13477c478bd9Sstevel@tonic-gate }
13487c478bd9Sstevel@tonic-gate
13497c478bd9Sstevel@tonic-gate nul_terminate (from);
13507c478bd9Sstevel@tonic-gate nul_terminate (to);
13517c478bd9Sstevel@tonic-gate
13527c478bd9Sstevel@tonic-gate if (! grub_open (from))
13537c478bd9Sstevel@tonic-gate return 1;
13547c478bd9Sstevel@tonic-gate
13557c478bd9Sstevel@tonic-gate fp = fopen (to, "w");
13567c478bd9Sstevel@tonic-gate if (! fp)
13577c478bd9Sstevel@tonic-gate {
13587c478bd9Sstevel@tonic-gate errnum = ERR_WRITE;
13597c478bd9Sstevel@tonic-gate return 1;
13607c478bd9Sstevel@tonic-gate }
13617c478bd9Sstevel@tonic-gate
13627c478bd9Sstevel@tonic-gate while (grub_read (&c, 1))
13637c478bd9Sstevel@tonic-gate if (fputc (c, fp) == EOF)
13647c478bd9Sstevel@tonic-gate {
13657c478bd9Sstevel@tonic-gate errnum = ERR_WRITE;
13667c478bd9Sstevel@tonic-gate fclose (fp);
13677c478bd9Sstevel@tonic-gate return 1;
13687c478bd9Sstevel@tonic-gate }
13697c478bd9Sstevel@tonic-gate
13707c478bd9Sstevel@tonic-gate if (fclose (fp) == EOF)
13717c478bd9Sstevel@tonic-gate {
13727c478bd9Sstevel@tonic-gate errnum = ERR_WRITE;
13737c478bd9Sstevel@tonic-gate return 1;
13747c478bd9Sstevel@tonic-gate }
13757c478bd9Sstevel@tonic-gate
13767c478bd9Sstevel@tonic-gate grub_close ();
13777c478bd9Sstevel@tonic-gate return 0;
13787c478bd9Sstevel@tonic-gate }
13797c478bd9Sstevel@tonic-gate
13807c478bd9Sstevel@tonic-gate static struct builtin builtin_dump =
13817c478bd9Sstevel@tonic-gate {
13827c478bd9Sstevel@tonic-gate "dump",
13837c478bd9Sstevel@tonic-gate dump_func,
13847c478bd9Sstevel@tonic-gate BUILTIN_CMDLINE,
13857c478bd9Sstevel@tonic-gate "dump FROM TO",
13867c478bd9Sstevel@tonic-gate "Dump the contents of the file FROM to the file TO. FROM must be"
13877c478bd9Sstevel@tonic-gate " a GRUB file and TO must be an OS file."
13887c478bd9Sstevel@tonic-gate };
13897c478bd9Sstevel@tonic-gate #endif /* GRUB_UTIL */
13907c478bd9Sstevel@tonic-gate
13917c478bd9Sstevel@tonic-gate
13927c478bd9Sstevel@tonic-gate static char embed_info[32];
13937c478bd9Sstevel@tonic-gate /* embed */
13947c478bd9Sstevel@tonic-gate /* Embed a Stage 1.5 in the first cylinder after MBR or in the
13957c478bd9Sstevel@tonic-gate bootloader block in a FFS. */
13967c478bd9Sstevel@tonic-gate static int
embed_func(char * arg,int flags)13977c478bd9Sstevel@tonic-gate embed_func (char *arg, int flags)
13987c478bd9Sstevel@tonic-gate {
13997c478bd9Sstevel@tonic-gate char *stage1_5;
14007c478bd9Sstevel@tonic-gate char *device;
14017c478bd9Sstevel@tonic-gate char *stage1_5_buffer = (char *) RAW_ADDR (0x100000);
14027c478bd9Sstevel@tonic-gate int len, size;
14032e1aefd1SJoshua M. Clulow unsigned long long sector;
14047c478bd9Sstevel@tonic-gate
14057c478bd9Sstevel@tonic-gate stage1_5 = arg;
14067c478bd9Sstevel@tonic-gate device = skip_to (0, stage1_5);
14077c478bd9Sstevel@tonic-gate
14087c478bd9Sstevel@tonic-gate /* Open a Stage 1.5. */
14097c478bd9Sstevel@tonic-gate if (! grub_open (stage1_5))
14107c478bd9Sstevel@tonic-gate return 1;
14117c478bd9Sstevel@tonic-gate
14127c478bd9Sstevel@tonic-gate /* Read the whole of the Stage 1.5. */
14137c478bd9Sstevel@tonic-gate len = grub_read (stage1_5_buffer, -1);
14147c478bd9Sstevel@tonic-gate grub_close ();
14157c478bd9Sstevel@tonic-gate
14167c478bd9Sstevel@tonic-gate if (errnum)
14177c478bd9Sstevel@tonic-gate return 1;
14187c478bd9Sstevel@tonic-gate
14197c478bd9Sstevel@tonic-gate size = (len + SECTOR_SIZE - 1) / SECTOR_SIZE;
14207c478bd9Sstevel@tonic-gate
14217c478bd9Sstevel@tonic-gate /* Get the device where the Stage 1.5 will be embedded. */
14227c478bd9Sstevel@tonic-gate set_device (device);
14237c478bd9Sstevel@tonic-gate if (errnum)
14247c478bd9Sstevel@tonic-gate return 1;
14257c478bd9Sstevel@tonic-gate
14267c478bd9Sstevel@tonic-gate if (current_partition == 0xFFFFFF)
14277c478bd9Sstevel@tonic-gate {
14287c478bd9Sstevel@tonic-gate /* Embed it after the MBR. */
14297c478bd9Sstevel@tonic-gate
14307c478bd9Sstevel@tonic-gate char mbr[SECTOR_SIZE];
14317c478bd9Sstevel@tonic-gate char ezbios_check[2*SECTOR_SIZE];
14327c478bd9Sstevel@tonic-gate int i;
14337c478bd9Sstevel@tonic-gate
14347c478bd9Sstevel@tonic-gate /* Open the partition. */
14357c478bd9Sstevel@tonic-gate if (! open_partition ())
14367c478bd9Sstevel@tonic-gate return 1;
14377c478bd9Sstevel@tonic-gate
14387c478bd9Sstevel@tonic-gate /* No floppy has MBR. */
14397c478bd9Sstevel@tonic-gate if (! (current_drive & 0x80))
14407c478bd9Sstevel@tonic-gate {
14417c478bd9Sstevel@tonic-gate errnum = ERR_DEV_VALUES;
14427c478bd9Sstevel@tonic-gate return 1;
14437c478bd9Sstevel@tonic-gate }
14447c478bd9Sstevel@tonic-gate
14457c478bd9Sstevel@tonic-gate /* Read the MBR of CURRENT_DRIVE. */
14467c478bd9Sstevel@tonic-gate if (! rawread (current_drive, PC_MBR_SECTOR, 0, SECTOR_SIZE, mbr))
14477c478bd9Sstevel@tonic-gate return 1;
14487c478bd9Sstevel@tonic-gate
14497c478bd9Sstevel@tonic-gate /* Sanity check. */
14507c478bd9Sstevel@tonic-gate if (! PC_MBR_CHECK_SIG (mbr))
14517c478bd9Sstevel@tonic-gate {
14527c478bd9Sstevel@tonic-gate errnum = ERR_BAD_PART_TABLE;
14537c478bd9Sstevel@tonic-gate return 1;
14547c478bd9Sstevel@tonic-gate }
14557c478bd9Sstevel@tonic-gate
14567c478bd9Sstevel@tonic-gate /* Check if the disk can store the Stage 1.5. */
14577c478bd9Sstevel@tonic-gate for (i = 0; i < 4; i++)
14587c478bd9Sstevel@tonic-gate if (PC_SLICE_TYPE (mbr, i) && PC_SLICE_START (mbr, i) - 1 < size)
14597c478bd9Sstevel@tonic-gate {
14607c478bd9Sstevel@tonic-gate errnum = ERR_NO_DISK_SPACE;
14617c478bd9Sstevel@tonic-gate return 1;
14627c478bd9Sstevel@tonic-gate }
14637c478bd9Sstevel@tonic-gate
14647c478bd9Sstevel@tonic-gate /* Check for EZ-BIOS signature. It should be in the third
14657c478bd9Sstevel@tonic-gate * sector, but due to remapping it can appear in the second, so
14667c478bd9Sstevel@tonic-gate * load and check both.
14677c478bd9Sstevel@tonic-gate */
14687c478bd9Sstevel@tonic-gate if (! rawread (current_drive, 1, 0, 2 * SECTOR_SIZE, ezbios_check))
14697c478bd9Sstevel@tonic-gate return 1;
14707c478bd9Sstevel@tonic-gate
14717c478bd9Sstevel@tonic-gate if (! memcmp (ezbios_check + 3, "AERMH", 5)
14727c478bd9Sstevel@tonic-gate || ! memcmp (ezbios_check + 512 + 3, "AERMH", 5))
14737c478bd9Sstevel@tonic-gate {
14747c478bd9Sstevel@tonic-gate /* The space after the MBR is used by EZ-BIOS which we must
14757c478bd9Sstevel@tonic-gate * not overwrite.
14767c478bd9Sstevel@tonic-gate */
14777c478bd9Sstevel@tonic-gate errnum = ERR_NO_DISK_SPACE;
14787c478bd9Sstevel@tonic-gate return 1;
14797c478bd9Sstevel@tonic-gate }
14807c478bd9Sstevel@tonic-gate
14817c478bd9Sstevel@tonic-gate sector = 1;
14827c478bd9Sstevel@tonic-gate }
14837c478bd9Sstevel@tonic-gate else
14847c478bd9Sstevel@tonic-gate {
14857c478bd9Sstevel@tonic-gate /* Embed it in the bootloader block in the filesystem. */
14862e1aefd1SJoshua M. Clulow unsigned long long start_sector;
14877c478bd9Sstevel@tonic-gate
14887c478bd9Sstevel@tonic-gate /* Open the partition. */
14897c478bd9Sstevel@tonic-gate if (! open_device ())
14907c478bd9Sstevel@tonic-gate return 1;
14917c478bd9Sstevel@tonic-gate
14927c478bd9Sstevel@tonic-gate /* Check if the current slice supports embedding. */
14937c478bd9Sstevel@tonic-gate if (fsys_table[fsys_type].embed_func == 0
14947c478bd9Sstevel@tonic-gate || ! fsys_table[fsys_type].embed_func (&start_sector, size))
14957c478bd9Sstevel@tonic-gate {
14967c478bd9Sstevel@tonic-gate errnum = ERR_DEV_VALUES;
14977c478bd9Sstevel@tonic-gate return 1;
14987c478bd9Sstevel@tonic-gate }
14997c478bd9Sstevel@tonic-gate
15007c478bd9Sstevel@tonic-gate sector = part_start + start_sector;
15017c478bd9Sstevel@tonic-gate }
15027c478bd9Sstevel@tonic-gate
15037c478bd9Sstevel@tonic-gate /* Clear the cache. */
1504342440ecSPrasad Singamsetty buf_track = BUF_CACHE_INVALID;
15057c478bd9Sstevel@tonic-gate
15067c478bd9Sstevel@tonic-gate /* Now perform the embedding. */
15077c478bd9Sstevel@tonic-gate if (! devwrite (sector - part_start, size, stage1_5_buffer))
15087c478bd9Sstevel@tonic-gate return 1;
15097c478bd9Sstevel@tonic-gate
15107c478bd9Sstevel@tonic-gate grub_printf (" %d sectors are embedded.\n", size);
15112e1aefd1SJoshua M. Clulow grub_sprintf (embed_info, "%llu+%d", sector - part_start, size);
15127c478bd9Sstevel@tonic-gate return 0;
15137c478bd9Sstevel@tonic-gate }
15147c478bd9Sstevel@tonic-gate
15157c478bd9Sstevel@tonic-gate static struct builtin builtin_embed =
15167c478bd9Sstevel@tonic-gate {
15177c478bd9Sstevel@tonic-gate "embed",
15187c478bd9Sstevel@tonic-gate embed_func,
15197c478bd9Sstevel@tonic-gate BUILTIN_CMDLINE,
15207c478bd9Sstevel@tonic-gate "embed STAGE1_5 DEVICE",
15217c478bd9Sstevel@tonic-gate "Embed the Stage 1.5 STAGE1_5 in the sectors after MBR if DEVICE"
15227c478bd9Sstevel@tonic-gate " is a drive, or in the \"bootloader\" area if DEVICE is a FFS partition."
15237c478bd9Sstevel@tonic-gate " Print the number of sectors which STAGE1_5 occupies if successful."
15247c478bd9Sstevel@tonic-gate };
15257c478bd9Sstevel@tonic-gate
15267c478bd9Sstevel@tonic-gate
15277c478bd9Sstevel@tonic-gate /* fallback */
15287c478bd9Sstevel@tonic-gate static int
fallback_func(char * arg,int flags)15297c478bd9Sstevel@tonic-gate fallback_func (char *arg, int flags)
15307c478bd9Sstevel@tonic-gate {
15317c478bd9Sstevel@tonic-gate int i = 0;
15327c478bd9Sstevel@tonic-gate
15337c478bd9Sstevel@tonic-gate while (*arg)
15347c478bd9Sstevel@tonic-gate {
15357c478bd9Sstevel@tonic-gate int entry;
15367c478bd9Sstevel@tonic-gate int j;
15377c478bd9Sstevel@tonic-gate
15387c478bd9Sstevel@tonic-gate if (! safe_parse_maxint (&arg, &entry))
15397c478bd9Sstevel@tonic-gate return 1;
15407c478bd9Sstevel@tonic-gate
15417c478bd9Sstevel@tonic-gate /* Remove duplications to prevent infinite looping. */
15427c478bd9Sstevel@tonic-gate for (j = 0; j < i; j++)
15437c478bd9Sstevel@tonic-gate if (entry == fallback_entries[j])
15447c478bd9Sstevel@tonic-gate break;
15457c478bd9Sstevel@tonic-gate if (j != i)
15467c478bd9Sstevel@tonic-gate continue;
15477c478bd9Sstevel@tonic-gate
15487c478bd9Sstevel@tonic-gate fallback_entries[i++] = entry;
15497c478bd9Sstevel@tonic-gate if (i == MAX_FALLBACK_ENTRIES)
15507c478bd9Sstevel@tonic-gate break;
15517c478bd9Sstevel@tonic-gate
15527c478bd9Sstevel@tonic-gate arg = skip_to (0, arg);
15537c478bd9Sstevel@tonic-gate }
15547c478bd9Sstevel@tonic-gate
15557c478bd9Sstevel@tonic-gate if (i < MAX_FALLBACK_ENTRIES)
15567c478bd9Sstevel@tonic-gate fallback_entries[i] = -1;
15577c478bd9Sstevel@tonic-gate
15587c478bd9Sstevel@tonic-gate fallback_entryno = (i == 0) ? -1 : 0;
15597c478bd9Sstevel@tonic-gate
15607c478bd9Sstevel@tonic-gate return 0;
15617c478bd9Sstevel@tonic-gate }
15627c478bd9Sstevel@tonic-gate
15637c478bd9Sstevel@tonic-gate static struct builtin builtin_fallback =
15647c478bd9Sstevel@tonic-gate {
15657c478bd9Sstevel@tonic-gate "fallback",
15667c478bd9Sstevel@tonic-gate fallback_func,
15677c478bd9Sstevel@tonic-gate BUILTIN_MENU,
15687c478bd9Sstevel@tonic-gate #if 0
15697c478bd9Sstevel@tonic-gate "fallback NUM...",
15707c478bd9Sstevel@tonic-gate "Go into unattended boot mode: if the default boot entry has any"
15717c478bd9Sstevel@tonic-gate " errors, instead of waiting for the user to do anything, it"
15727c478bd9Sstevel@tonic-gate " immediately starts over using the NUM entry (same numbering as the"
15737c478bd9Sstevel@tonic-gate " `default' command). This obviously won't help if the machine"
15747c478bd9Sstevel@tonic-gate " was rebooted by a kernel that GRUB loaded."
15757c478bd9Sstevel@tonic-gate #endif
15767c478bd9Sstevel@tonic-gate };
15777c478bd9Sstevel@tonic-gate
15787c478bd9Sstevel@tonic-gate
1579051aabe6Staylor
1580051aabe6Staylor void
set_root(char * root,unsigned long drive,unsigned long part)1581051aabe6Staylor set_root (char *root, unsigned long drive, unsigned long part)
1582051aabe6Staylor {
1583051aabe6Staylor int bsd_part = (part >> 8) & 0xFF;
1584051aabe6Staylor int pc_slice = part >> 16;
1585051aabe6Staylor
1586051aabe6Staylor if (bsd_part == 0xFF) {
1587051aabe6Staylor grub_sprintf (root, "(hd%d,%d)\n", drive - 0x80, pc_slice);
1588051aabe6Staylor } else {
1589051aabe6Staylor grub_sprintf (root, "(hd%d,%d,%c)\n",
1590051aabe6Staylor drive - 0x80, pc_slice, bsd_part + 'a');
1591051aabe6Staylor }
1592051aabe6Staylor }
1593051aabe6Staylor
15947c478bd9Sstevel@tonic-gate static int
find_common(char * arg,char * root,int for_root,int flags)1595eb2bd662Svikram find_common (char *arg, char *root, int for_root, int flags)
15967c478bd9Sstevel@tonic-gate {
1597eb2bd662Svikram char *filename = NULL;
1598eb2bd662Svikram static char argpart[32];
1599eb2bd662Svikram static char device[32];
1600eb2bd662Svikram char *tmp_argpart = NULL;
16017c478bd9Sstevel@tonic-gate unsigned long drive;
16027c478bd9Sstevel@tonic-gate unsigned long tmp_drive = saved_drive;
16037c478bd9Sstevel@tonic-gate unsigned long tmp_partition = saved_partition;
16047c478bd9Sstevel@tonic-gate int got_file = 0;
1605eb2bd662Svikram static char bootsign[BOOTSIGN_LEN];
1606eb2bd662Svikram
1607eb2bd662Svikram /*
1608eb2bd662Svikram * If argument has partition information (findroot command only), then
1609eb2bd662Svikram * it can't be a floppy
1610eb2bd662Svikram */
1611eb2bd662Svikram if (for_root && arg[0] == '(') {
1612eb2bd662Svikram tmp_argpart = grub_strchr(arg + 1, ',');
1613eb2bd662Svikram if (tmp_argpart == NULL)
1614eb2bd662Svikram goto out;
1615eb2bd662Svikram grub_strcpy(argpart, tmp_argpart);
1616eb2bd662Svikram *tmp_argpart = '\0';
1617eb2bd662Svikram arg++;
1618eb2bd662Svikram grub_sprintf(bootsign, "%s/%s", BOOTSIGN_DIR, arg);
1619eb2bd662Svikram filename = bootsign;
1620eb2bd662Svikram goto harddisk;
162121ecdf64SLin Ling } else if (for_root && !grub_strchr(arg, '/')) {
1622eb2bd662Svikram /* Boot signature without partition/slice information */
1623eb2bd662Svikram grub_sprintf(bootsign, "%s/%s", BOOTSIGN_DIR, arg);
1624eb2bd662Svikram filename = bootsign;
1625eb2bd662Svikram } else {
1626eb2bd662Svikram /* plain vanilla find cmd */
1627eb2bd662Svikram filename = arg;
1628eb2bd662Svikram }
16297c478bd9Sstevel@tonic-gate
16307c478bd9Sstevel@tonic-gate /* Floppies. */
16317c478bd9Sstevel@tonic-gate for (drive = 0; drive < 8; drive++)
16327c478bd9Sstevel@tonic-gate {
16337c478bd9Sstevel@tonic-gate current_drive = drive;
16347c478bd9Sstevel@tonic-gate current_partition = 0xFFFFFF;
16357c478bd9Sstevel@tonic-gate
16367c478bd9Sstevel@tonic-gate if (open_device ())
16377c478bd9Sstevel@tonic-gate {
16387c478bd9Sstevel@tonic-gate saved_drive = current_drive;
16397c478bd9Sstevel@tonic-gate saved_partition = current_partition;
16407c478bd9Sstevel@tonic-gate if (grub_open (filename))
16417c478bd9Sstevel@tonic-gate {
16427c478bd9Sstevel@tonic-gate grub_close ();
16437c478bd9Sstevel@tonic-gate got_file = 1;
1644eb2bd662Svikram if (for_root) {
1645eb2bd662Svikram grub_sprintf(root, "(fd%d)", drive);
1646eb2bd662Svikram goto out;
1647eb2bd662Svikram } else
1648eb2bd662Svikram grub_printf (" (fd%d)\n", drive);
16497c478bd9Sstevel@tonic-gate }
16507c478bd9Sstevel@tonic-gate }
16517c478bd9Sstevel@tonic-gate
16527c478bd9Sstevel@tonic-gate errnum = ERR_NONE;
16537c478bd9Sstevel@tonic-gate }
16547c478bd9Sstevel@tonic-gate
1655eb2bd662Svikram harddisk:
16567c478bd9Sstevel@tonic-gate /* Hard disks. */
16577c478bd9Sstevel@tonic-gate for (drive = 0x80; drive < 0x88; drive++)
16587c478bd9Sstevel@tonic-gate {
16597c478bd9Sstevel@tonic-gate unsigned long part = 0xFFFFFF;
16609890706eSHans Rosenfeld unsigned long long start, len, offset, ext_offset, gpt_offset;
166144bc9120SRichard Yao int type, entry, gpt_count, gpt_size;
16627c478bd9Sstevel@tonic-gate char buf[SECTOR_SIZE];
16637c478bd9Sstevel@tonic-gate
1664eb2bd662Svikram if (for_root && tmp_argpart) {
1665051aabe6Staylor grub_sprintf(device, "(hd%d%s", drive - 0x80, argpart);
1666eb2bd662Svikram set_device(device);
1667eb2bd662Svikram errnum = ERR_NONE;
1668eb2bd662Svikram part = current_partition;
1669eb2bd662Svikram if (open_device ()) {
1670eb2bd662Svikram saved_drive = current_drive;
1671eb2bd662Svikram saved_partition = current_partition;
1672eb2bd662Svikram errnum = ERR_NONE;
1673eb2bd662Svikram if (grub_open (filename)) {
1674eb2bd662Svikram grub_close ();
1675eb2bd662Svikram got_file = 1;
1676051aabe6Staylor if (is_zfs_mount == 0) {
1677051aabe6Staylor set_root(root, current_drive, current_partition);
1678051aabe6Staylor goto out;
1679051aabe6Staylor } else {
1680051aabe6Staylor best_drive = current_drive;
1681051aabe6Staylor best_part = current_partition;
1682051aabe6Staylor }
1683eb2bd662Svikram }
1684eb2bd662Svikram }
1685eb2bd662Svikram errnum = ERR_NONE;
1686eb2bd662Svikram continue;
1687eb2bd662Svikram }
16887c478bd9Sstevel@tonic-gate current_drive = drive;
16897c478bd9Sstevel@tonic-gate while (next_partition (drive, 0xFFFFFF, &part, &type,
16907c478bd9Sstevel@tonic-gate &start, &len, &offset, &entry,
169144bc9120SRichard Yao &ext_offset, &gpt_offset,
169244bc9120SRichard Yao &gpt_count, &gpt_size, buf))
16937c478bd9Sstevel@tonic-gate {
16947c478bd9Sstevel@tonic-gate if (type != PC_SLICE_TYPE_NONE
16957c478bd9Sstevel@tonic-gate && ! IS_PC_SLICE_TYPE_BSD (type)
16967c478bd9Sstevel@tonic-gate && ! IS_PC_SLICE_TYPE_EXTENDED (type))
16977c478bd9Sstevel@tonic-gate {
16987c478bd9Sstevel@tonic-gate current_partition = part;
16997c478bd9Sstevel@tonic-gate if (open_device ())
17007c478bd9Sstevel@tonic-gate {
17017c478bd9Sstevel@tonic-gate saved_drive = current_drive;
17027c478bd9Sstevel@tonic-gate saved_partition = current_partition;
17037c478bd9Sstevel@tonic-gate if (grub_open (filename))
17047c478bd9Sstevel@tonic-gate {
1705051aabe6Staylor char tmproot[32];
1706051aabe6Staylor
17077c478bd9Sstevel@tonic-gate grub_close ();
1708eb2bd662Svikram got_file = 1;
1709051aabe6Staylor set_root(tmproot, drive, part);
1710051aabe6Staylor if (for_root) {
1711051aabe6Staylor grub_memcpy(root, tmproot, sizeof(tmproot));
1712051aabe6Staylor if (is_zfs_mount == 0) {
1713051aabe6Staylor goto out;
1714051aabe6Staylor } else {
1715051aabe6Staylor best_drive = current_drive;
1716051aabe6Staylor best_part = current_partition;
1717051aabe6Staylor }
1718eb2bd662Svikram } else {
1719051aabe6Staylor grub_printf("%s", tmproot);
1720eb2bd662Svikram }
17217c478bd9Sstevel@tonic-gate }
17227c478bd9Sstevel@tonic-gate }
17237c478bd9Sstevel@tonic-gate }
17247c478bd9Sstevel@tonic-gate
17257c478bd9Sstevel@tonic-gate /* We want to ignore any error here. */
17267c478bd9Sstevel@tonic-gate errnum = ERR_NONE;
17277c478bd9Sstevel@tonic-gate }
17287c478bd9Sstevel@tonic-gate
17297c478bd9Sstevel@tonic-gate /* next_partition always sets ERRNUM in the last call, so clear
17307c478bd9Sstevel@tonic-gate it. */
17317c478bd9Sstevel@tonic-gate errnum = ERR_NONE;
17327c478bd9Sstevel@tonic-gate }
17337c478bd9Sstevel@tonic-gate
1734eb2bd662Svikram out:
1735051aabe6Staylor if (is_zfs_mount && for_root) {
1736051aabe6Staylor set_root(root, best_drive, best_part);
1737051aabe6Staylor buf_drive = -1;
1738051aabe6Staylor } else {
1739051aabe6Staylor saved_drive = tmp_drive;
1740051aabe6Staylor saved_partition = tmp_partition;
1741051aabe6Staylor }
1742eb2bd662Svikram if (tmp_argpart)
1743eb2bd662Svikram *tmp_argpart = ',';
17447c478bd9Sstevel@tonic-gate
17457c478bd9Sstevel@tonic-gate if (got_file)
17467c478bd9Sstevel@tonic-gate {
17477c478bd9Sstevel@tonic-gate errnum = ERR_NONE;
17487c478bd9Sstevel@tonic-gate return 0;
17497c478bd9Sstevel@tonic-gate }
17507c478bd9Sstevel@tonic-gate
17517c478bd9Sstevel@tonic-gate errnum = ERR_FILE_NOT_FOUND;
17527c478bd9Sstevel@tonic-gate return 1;
17537c478bd9Sstevel@tonic-gate }
17547c478bd9Sstevel@tonic-gate
1755eb2bd662Svikram /* find */
1756eb2bd662Svikram /* Search for the filename ARG in all of partitions. */
1757eb2bd662Svikram static int
find_func(char * arg,int flags)1758eb2bd662Svikram find_func (char *arg, int flags)
1759eb2bd662Svikram {
1760eb2bd662Svikram return (find_common(arg, NULL, 0, flags));
1761eb2bd662Svikram }
1762eb2bd662Svikram
17637c478bd9Sstevel@tonic-gate static struct builtin builtin_find =
17647c478bd9Sstevel@tonic-gate {
17657c478bd9Sstevel@tonic-gate "find",
17667c478bd9Sstevel@tonic-gate find_func,
17677c478bd9Sstevel@tonic-gate BUILTIN_CMDLINE | BUILTIN_HELP_LIST,
17687c478bd9Sstevel@tonic-gate "find FILENAME",
17697c478bd9Sstevel@tonic-gate "Search for the filename FILENAME in all of partitions and print the list of"
17707c478bd9Sstevel@tonic-gate " the devices which contain the file."
17717c478bd9Sstevel@tonic-gate };
17727c478bd9Sstevel@tonic-gate
17737c478bd9Sstevel@tonic-gate
17747c478bd9Sstevel@tonic-gate /* fstest */
17757c478bd9Sstevel@tonic-gate static int
fstest_func(char * arg,int flags)17767c478bd9Sstevel@tonic-gate fstest_func (char *arg, int flags)
17777c478bd9Sstevel@tonic-gate {
17787c478bd9Sstevel@tonic-gate if (disk_read_hook)
17797c478bd9Sstevel@tonic-gate {
17807c478bd9Sstevel@tonic-gate disk_read_hook = NULL;
17817c478bd9Sstevel@tonic-gate printf (" Filesystem tracing is now off\n");
17827c478bd9Sstevel@tonic-gate }
17837c478bd9Sstevel@tonic-gate else
17847c478bd9Sstevel@tonic-gate {
17857c478bd9Sstevel@tonic-gate disk_read_hook = disk_read_print_func;
17867c478bd9Sstevel@tonic-gate printf (" Filesystem tracing is now on\n");
17877c478bd9Sstevel@tonic-gate }
17887c478bd9Sstevel@tonic-gate
17897c478bd9Sstevel@tonic-gate return 0;
17907c478bd9Sstevel@tonic-gate }
17917c478bd9Sstevel@tonic-gate
17927c478bd9Sstevel@tonic-gate static struct builtin builtin_fstest =
17937c478bd9Sstevel@tonic-gate {
17947c478bd9Sstevel@tonic-gate "fstest",
17957c478bd9Sstevel@tonic-gate fstest_func,
17967c478bd9Sstevel@tonic-gate BUILTIN_CMDLINE,
17977c478bd9Sstevel@tonic-gate "fstest",
17987c478bd9Sstevel@tonic-gate "Toggle filesystem test mode."
17997c478bd9Sstevel@tonic-gate };
18007c478bd9Sstevel@tonic-gate
18017c478bd9Sstevel@tonic-gate
18027c478bd9Sstevel@tonic-gate /* geometry */
18037c478bd9Sstevel@tonic-gate static int
geometry_func(char * arg,int flags)18047c478bd9Sstevel@tonic-gate geometry_func (char *arg, int flags)
18057c478bd9Sstevel@tonic-gate {
18067c478bd9Sstevel@tonic-gate struct geometry geom;
18077c478bd9Sstevel@tonic-gate char *msg;
18087c478bd9Sstevel@tonic-gate char *device = arg;
18097c478bd9Sstevel@tonic-gate #ifdef GRUB_UTIL
18107c478bd9Sstevel@tonic-gate char *ptr;
18117c478bd9Sstevel@tonic-gate #endif
18127c478bd9Sstevel@tonic-gate
18137c478bd9Sstevel@tonic-gate /* Get the device number. */
18147c478bd9Sstevel@tonic-gate set_device (device);
18157c478bd9Sstevel@tonic-gate if (errnum)
18167c478bd9Sstevel@tonic-gate return 1;
18177c478bd9Sstevel@tonic-gate
18187c478bd9Sstevel@tonic-gate /* Check for the geometry. */
18197c478bd9Sstevel@tonic-gate if (get_diskinfo (current_drive, &geom))
18207c478bd9Sstevel@tonic-gate {
18217c478bd9Sstevel@tonic-gate errnum = ERR_NO_DISK;
18227c478bd9Sstevel@tonic-gate return 1;
18237c478bd9Sstevel@tonic-gate }
18247c478bd9Sstevel@tonic-gate
18257c478bd9Sstevel@tonic-gate /* Attempt to read the first sector, because some BIOSes turns out not
18267c478bd9Sstevel@tonic-gate to support LBA even though they set the bit 0 in the support
18277c478bd9Sstevel@tonic-gate bitmap, only after reading something actually. */
18287c478bd9Sstevel@tonic-gate if (biosdisk (BIOSDISK_READ, current_drive, &geom, 0, 1, SCRATCHSEG))
18297c478bd9Sstevel@tonic-gate {
18307c478bd9Sstevel@tonic-gate errnum = ERR_READ;
18317c478bd9Sstevel@tonic-gate return 1;
18327c478bd9Sstevel@tonic-gate }
18337c478bd9Sstevel@tonic-gate
18347c478bd9Sstevel@tonic-gate #ifdef GRUB_UTIL
18357c478bd9Sstevel@tonic-gate ptr = skip_to (0, device);
18367c478bd9Sstevel@tonic-gate if (*ptr)
18377c478bd9Sstevel@tonic-gate {
18387c478bd9Sstevel@tonic-gate char *cylinder, *head, *sector, *total_sector;
18397c478bd9Sstevel@tonic-gate int num_cylinder, num_head, num_sector, num_total_sector;
18407c478bd9Sstevel@tonic-gate
18417c478bd9Sstevel@tonic-gate cylinder = ptr;
18427c478bd9Sstevel@tonic-gate head = skip_to (0, cylinder);
18437c478bd9Sstevel@tonic-gate sector = skip_to (0, head);
18447c478bd9Sstevel@tonic-gate total_sector = skip_to (0, sector);
18457c478bd9Sstevel@tonic-gate if (! safe_parse_maxint (&cylinder, &num_cylinder)
18467c478bd9Sstevel@tonic-gate || ! safe_parse_maxint (&head, &num_head)
18477c478bd9Sstevel@tonic-gate || ! safe_parse_maxint (§or, &num_sector))
18487c478bd9Sstevel@tonic-gate return 1;
18497c478bd9Sstevel@tonic-gate
18507c478bd9Sstevel@tonic-gate disks[current_drive].cylinders = num_cylinder;
18517c478bd9Sstevel@tonic-gate disks[current_drive].heads = num_head;
18527c478bd9Sstevel@tonic-gate disks[current_drive].sectors = num_sector;
18537c478bd9Sstevel@tonic-gate
18547c478bd9Sstevel@tonic-gate if (safe_parse_maxint (&total_sector, &num_total_sector))
18557c478bd9Sstevel@tonic-gate disks[current_drive].total_sectors = num_total_sector;
18567c478bd9Sstevel@tonic-gate else
18577c478bd9Sstevel@tonic-gate disks[current_drive].total_sectors
18587c478bd9Sstevel@tonic-gate = num_cylinder * num_head * num_sector;
18597c478bd9Sstevel@tonic-gate errnum = 0;
18607c478bd9Sstevel@tonic-gate
18617c478bd9Sstevel@tonic-gate geom = disks[current_drive];
18627c478bd9Sstevel@tonic-gate buf_drive = -1;
18637c478bd9Sstevel@tonic-gate }
18647c478bd9Sstevel@tonic-gate #endif /* GRUB_UTIL */
18657c478bd9Sstevel@tonic-gate
18667c478bd9Sstevel@tonic-gate #ifdef GRUB_UTIL
18677c478bd9Sstevel@tonic-gate msg = device_map[current_drive];
18687c478bd9Sstevel@tonic-gate #else
18697c478bd9Sstevel@tonic-gate if (geom.flags & BIOSDISK_FLAG_LBA_EXTENSION)
18707c478bd9Sstevel@tonic-gate msg = "LBA";
18717c478bd9Sstevel@tonic-gate else
18727c478bd9Sstevel@tonic-gate msg = "CHS";
18737c478bd9Sstevel@tonic-gate #endif
18747c478bd9Sstevel@tonic-gate
18757c478bd9Sstevel@tonic-gate grub_printf ("drive 0x%x: C/H/S = %d/%d/%d, "
18769890706eSHans Rosenfeld "The number of sectors = %llu, %s\n",
18777c478bd9Sstevel@tonic-gate current_drive,
18787c478bd9Sstevel@tonic-gate geom.cylinders, geom.heads, geom.sectors,
18797c478bd9Sstevel@tonic-gate geom.total_sectors, msg);
18807c478bd9Sstevel@tonic-gate real_open_partition (1);
18817c478bd9Sstevel@tonic-gate
18827c478bd9Sstevel@tonic-gate return 0;
18837c478bd9Sstevel@tonic-gate }
18847c478bd9Sstevel@tonic-gate
18857c478bd9Sstevel@tonic-gate static struct builtin builtin_geometry =
18867c478bd9Sstevel@tonic-gate {
18877c478bd9Sstevel@tonic-gate "geometry",
18887c478bd9Sstevel@tonic-gate geometry_func,
18897c478bd9Sstevel@tonic-gate BUILTIN_CMDLINE | BUILTIN_HELP_LIST,
18907c478bd9Sstevel@tonic-gate "geometry DRIVE [CYLINDER HEAD SECTOR [TOTAL_SECTOR]]",
18917c478bd9Sstevel@tonic-gate "Print the information for a drive DRIVE. In the grub shell, you can"
18927c478bd9Sstevel@tonic-gate " set the geometry of the drive arbitrarily. The number of the cylinders,"
18937c478bd9Sstevel@tonic-gate " the one of the heads, the one of the sectors and the one of the total"
18947c478bd9Sstevel@tonic-gate " sectors are set to CYLINDER, HEAD, SECTOR and TOTAL_SECTOR,"
18957c478bd9Sstevel@tonic-gate " respectively. If you omit TOTAL_SECTOR, then it will be calculated based"
18967c478bd9Sstevel@tonic-gate " on the C/H/S values automatically."
18977c478bd9Sstevel@tonic-gate };
18987c478bd9Sstevel@tonic-gate
18997c478bd9Sstevel@tonic-gate
19007c478bd9Sstevel@tonic-gate /* halt */
19017c478bd9Sstevel@tonic-gate static int
halt_func(char * arg,int flags)19027c478bd9Sstevel@tonic-gate halt_func (char *arg, int flags)
19037c478bd9Sstevel@tonic-gate {
19047c478bd9Sstevel@tonic-gate int no_apm;
19057c478bd9Sstevel@tonic-gate
19067c478bd9Sstevel@tonic-gate no_apm = (grub_memcmp (arg, "--no-apm", 8) == 0);
19077c478bd9Sstevel@tonic-gate grub_halt (no_apm);
19087c478bd9Sstevel@tonic-gate
19097c478bd9Sstevel@tonic-gate /* Never reach here. */
19107c478bd9Sstevel@tonic-gate return 1;
19117c478bd9Sstevel@tonic-gate }
19127c478bd9Sstevel@tonic-gate
19137c478bd9Sstevel@tonic-gate static struct builtin builtin_halt =
19147c478bd9Sstevel@tonic-gate {
19157c478bd9Sstevel@tonic-gate "halt",
19167c478bd9Sstevel@tonic-gate halt_func,
19177c478bd9Sstevel@tonic-gate BUILTIN_CMDLINE | BUILTIN_HELP_LIST,
19187c478bd9Sstevel@tonic-gate "halt [--no-apm]",
19197c478bd9Sstevel@tonic-gate "Halt your system. If APM is avaiable on it, turn off the power using"
19207c478bd9Sstevel@tonic-gate " the APM BIOS, unless you specify the option `--no-apm'."
19217c478bd9Sstevel@tonic-gate };
19227c478bd9Sstevel@tonic-gate
19237c478bd9Sstevel@tonic-gate
19247c478bd9Sstevel@tonic-gate /* help */
19257c478bd9Sstevel@tonic-gate #define MAX_SHORT_DOC_LEN 39
19267c478bd9Sstevel@tonic-gate #define MAX_LONG_DOC_LEN 66
19277c478bd9Sstevel@tonic-gate
19287c478bd9Sstevel@tonic-gate static int
help_func(char * arg,int flags)19297c478bd9Sstevel@tonic-gate help_func (char *arg, int flags)
19307c478bd9Sstevel@tonic-gate {
19317c478bd9Sstevel@tonic-gate int all = 0;
19327c478bd9Sstevel@tonic-gate
19337c478bd9Sstevel@tonic-gate if (grub_memcmp (arg, "--all", sizeof ("--all") - 1) == 0)
19347c478bd9Sstevel@tonic-gate {
19357c478bd9Sstevel@tonic-gate all = 1;
19367c478bd9Sstevel@tonic-gate arg = skip_to (0, arg);
19377c478bd9Sstevel@tonic-gate }
19387c478bd9Sstevel@tonic-gate
19397c478bd9Sstevel@tonic-gate if (! *arg)
19407c478bd9Sstevel@tonic-gate {
19417c478bd9Sstevel@tonic-gate /* Invoked with no argument. Print the list of the short docs. */
19427c478bd9Sstevel@tonic-gate struct builtin **builtin;
19437c478bd9Sstevel@tonic-gate int left = 1;
19447c478bd9Sstevel@tonic-gate
19457c478bd9Sstevel@tonic-gate for (builtin = builtin_table; *builtin != 0; builtin++)
19467c478bd9Sstevel@tonic-gate {
19477c478bd9Sstevel@tonic-gate int len;
19487c478bd9Sstevel@tonic-gate int i;
19497c478bd9Sstevel@tonic-gate
19507c478bd9Sstevel@tonic-gate /* If this cannot be used in the command-line interface,
19517c478bd9Sstevel@tonic-gate skip this. */
19527c478bd9Sstevel@tonic-gate if (! ((*builtin)->flags & BUILTIN_CMDLINE))
19537c478bd9Sstevel@tonic-gate continue;
19547c478bd9Sstevel@tonic-gate
19557c478bd9Sstevel@tonic-gate /* If this doesn't need to be listed automatically and "--all"
19567c478bd9Sstevel@tonic-gate is not specified, skip this. */
19577c478bd9Sstevel@tonic-gate if (! all && ! ((*builtin)->flags & BUILTIN_HELP_LIST))
19587c478bd9Sstevel@tonic-gate continue;
19597c478bd9Sstevel@tonic-gate
19607c478bd9Sstevel@tonic-gate len = grub_strlen ((*builtin)->short_doc);
19617c478bd9Sstevel@tonic-gate /* If the length of SHORT_DOC is too long, truncate it. */
19627c478bd9Sstevel@tonic-gate if (len > MAX_SHORT_DOC_LEN - 1)
19637c478bd9Sstevel@tonic-gate len = MAX_SHORT_DOC_LEN - 1;
19647c478bd9Sstevel@tonic-gate
19657c478bd9Sstevel@tonic-gate for (i = 0; i < len; i++)
19667c478bd9Sstevel@tonic-gate grub_putchar ((*builtin)->short_doc[i]);
19677c478bd9Sstevel@tonic-gate
19687c478bd9Sstevel@tonic-gate for (; i < MAX_SHORT_DOC_LEN; i++)
19697c478bd9Sstevel@tonic-gate grub_putchar (' ');
19707c478bd9Sstevel@tonic-gate
19717c478bd9Sstevel@tonic-gate if (! left)
19727c478bd9Sstevel@tonic-gate grub_putchar ('\n');
19737c478bd9Sstevel@tonic-gate
19747c478bd9Sstevel@tonic-gate left = ! left;
19757c478bd9Sstevel@tonic-gate }
19767c478bd9Sstevel@tonic-gate
19777c478bd9Sstevel@tonic-gate /* If the last entry was at the left column, no newline was printed
19787c478bd9Sstevel@tonic-gate at the end. */
19797c478bd9Sstevel@tonic-gate if (! left)
19807c478bd9Sstevel@tonic-gate grub_putchar ('\n');
19817c478bd9Sstevel@tonic-gate }
19827c478bd9Sstevel@tonic-gate else
19837c478bd9Sstevel@tonic-gate {
19847c478bd9Sstevel@tonic-gate /* Invoked with one or more patterns. */
19857c478bd9Sstevel@tonic-gate do
19867c478bd9Sstevel@tonic-gate {
19877c478bd9Sstevel@tonic-gate struct builtin **builtin;
19887c478bd9Sstevel@tonic-gate char *next_arg;
19897c478bd9Sstevel@tonic-gate
19907c478bd9Sstevel@tonic-gate /* Get the next argument. */
19917c478bd9Sstevel@tonic-gate next_arg = skip_to (0, arg);
19927c478bd9Sstevel@tonic-gate
19937c478bd9Sstevel@tonic-gate /* Terminate ARG. */
19947c478bd9Sstevel@tonic-gate nul_terminate (arg);
19957c478bd9Sstevel@tonic-gate
19967c478bd9Sstevel@tonic-gate for (builtin = builtin_table; *builtin; builtin++)
19977c478bd9Sstevel@tonic-gate {
19987c478bd9Sstevel@tonic-gate /* Skip this if this is only for the configuration file. */
19997c478bd9Sstevel@tonic-gate if (! ((*builtin)->flags & BUILTIN_CMDLINE))
20007c478bd9Sstevel@tonic-gate continue;
20017c478bd9Sstevel@tonic-gate
20027c478bd9Sstevel@tonic-gate if (substring (arg, (*builtin)->name) < 1)
20037c478bd9Sstevel@tonic-gate {
20047c478bd9Sstevel@tonic-gate char *doc = (*builtin)->long_doc;
20057c478bd9Sstevel@tonic-gate
20067c478bd9Sstevel@tonic-gate /* At first, print the name and the short doc. */
20077c478bd9Sstevel@tonic-gate grub_printf ("%s: %s\n",
20087c478bd9Sstevel@tonic-gate (*builtin)->name, (*builtin)->short_doc);
20097c478bd9Sstevel@tonic-gate
20107c478bd9Sstevel@tonic-gate /* Print the long doc. */
20117c478bd9Sstevel@tonic-gate while (*doc)
20127c478bd9Sstevel@tonic-gate {
20137c478bd9Sstevel@tonic-gate int len = grub_strlen (doc);
20147c478bd9Sstevel@tonic-gate int i;
20157c478bd9Sstevel@tonic-gate
20167c478bd9Sstevel@tonic-gate /* If LEN is too long, fold DOC. */
20177c478bd9Sstevel@tonic-gate if (len > MAX_LONG_DOC_LEN)
20187c478bd9Sstevel@tonic-gate {
20197c478bd9Sstevel@tonic-gate /* Fold this line at the position of a space. */
20207c478bd9Sstevel@tonic-gate for (len = MAX_LONG_DOC_LEN; len > 0; len--)
20217c478bd9Sstevel@tonic-gate if (doc[len - 1] == ' ')
20227c478bd9Sstevel@tonic-gate break;
20237c478bd9Sstevel@tonic-gate }
20247c478bd9Sstevel@tonic-gate
20257c478bd9Sstevel@tonic-gate grub_printf (" ");
20267c478bd9Sstevel@tonic-gate for (i = 0; i < len; i++)
20277c478bd9Sstevel@tonic-gate grub_putchar (*doc++);
20287c478bd9Sstevel@tonic-gate grub_putchar ('\n');
20297c478bd9Sstevel@tonic-gate }
20307c478bd9Sstevel@tonic-gate }
20317c478bd9Sstevel@tonic-gate }
20327c478bd9Sstevel@tonic-gate
20337c478bd9Sstevel@tonic-gate arg = next_arg;
20347c478bd9Sstevel@tonic-gate }
20357c478bd9Sstevel@tonic-gate while (*arg);
20367c478bd9Sstevel@tonic-gate }
20377c478bd9Sstevel@tonic-gate
20387c478bd9Sstevel@tonic-gate return 0;
20397c478bd9Sstevel@tonic-gate }
20407c478bd9Sstevel@tonic-gate
20417c478bd9Sstevel@tonic-gate static struct builtin builtin_help =
20427c478bd9Sstevel@tonic-gate {
20437c478bd9Sstevel@tonic-gate "help",
20447c478bd9Sstevel@tonic-gate help_func,
20457c478bd9Sstevel@tonic-gate BUILTIN_CMDLINE | BUILTIN_HELP_LIST,
20467c478bd9Sstevel@tonic-gate "help [--all] [PATTERN ...]",
20477c478bd9Sstevel@tonic-gate "Display helpful information about builtin commands. Not all commands"
20487c478bd9Sstevel@tonic-gate " aren't shown without the option `--all'."
20497c478bd9Sstevel@tonic-gate };
20507c478bd9Sstevel@tonic-gate
20517c478bd9Sstevel@tonic-gate
20527c478bd9Sstevel@tonic-gate /* hiddenmenu */
20537c478bd9Sstevel@tonic-gate static int
hiddenmenu_func(char * arg,int flags)20547c478bd9Sstevel@tonic-gate hiddenmenu_func (char *arg, int flags)
20557c478bd9Sstevel@tonic-gate {
20567c478bd9Sstevel@tonic-gate show_menu = 0;
20577c478bd9Sstevel@tonic-gate return 0;
20587c478bd9Sstevel@tonic-gate }
20597c478bd9Sstevel@tonic-gate
20607c478bd9Sstevel@tonic-gate static struct builtin builtin_hiddenmenu =
20617c478bd9Sstevel@tonic-gate {
20627c478bd9Sstevel@tonic-gate "hiddenmenu",
20637c478bd9Sstevel@tonic-gate hiddenmenu_func,
20647c478bd9Sstevel@tonic-gate BUILTIN_MENU,
20657c478bd9Sstevel@tonic-gate #if 0
20667c478bd9Sstevel@tonic-gate "hiddenmenu",
20677c478bd9Sstevel@tonic-gate "Hide the menu."
20687c478bd9Sstevel@tonic-gate #endif
20697c478bd9Sstevel@tonic-gate };
20707c478bd9Sstevel@tonic-gate
20717c478bd9Sstevel@tonic-gate
20727c478bd9Sstevel@tonic-gate /* hide */
20737c478bd9Sstevel@tonic-gate static int
hide_func(char * arg,int flags)20747c478bd9Sstevel@tonic-gate hide_func (char *arg, int flags)
20757c478bd9Sstevel@tonic-gate {
20767c478bd9Sstevel@tonic-gate if (! set_device (arg))
20777c478bd9Sstevel@tonic-gate return 1;
20787c478bd9Sstevel@tonic-gate
20797c478bd9Sstevel@tonic-gate if (! set_partition_hidden_flag (1))
20807c478bd9Sstevel@tonic-gate return 1;
20817c478bd9Sstevel@tonic-gate
20827c478bd9Sstevel@tonic-gate return 0;
20837c478bd9Sstevel@tonic-gate }
20847c478bd9Sstevel@tonic-gate
20857c478bd9Sstevel@tonic-gate static struct builtin builtin_hide =
20867c478bd9Sstevel@tonic-gate {
20877c478bd9Sstevel@tonic-gate "hide",
20887c478bd9Sstevel@tonic-gate hide_func,
20897c478bd9Sstevel@tonic-gate BUILTIN_CMDLINE | BUILTIN_MENU | BUILTIN_HELP_LIST,
20907c478bd9Sstevel@tonic-gate "hide PARTITION",
20917c478bd9Sstevel@tonic-gate "Hide PARTITION by setting the \"hidden\" bit in"
20927c478bd9Sstevel@tonic-gate " its partition type code."
20937c478bd9Sstevel@tonic-gate };
20947c478bd9Sstevel@tonic-gate
20957c478bd9Sstevel@tonic-gate
20967c478bd9Sstevel@tonic-gate #ifdef SUPPORT_NETBOOT
20977c478bd9Sstevel@tonic-gate /* ifconfig */
20987c478bd9Sstevel@tonic-gate static int
ifconfig_func(char * arg,int flags)20997c478bd9Sstevel@tonic-gate ifconfig_func (char *arg, int flags)
21007c478bd9Sstevel@tonic-gate {
21017c478bd9Sstevel@tonic-gate char *svr = 0, *ip = 0, *gw = 0, *sm = 0;
21027c478bd9Sstevel@tonic-gate
21037c478bd9Sstevel@tonic-gate if (! grub_eth_probe ())
21047c478bd9Sstevel@tonic-gate {
21057c478bd9Sstevel@tonic-gate grub_printf ("No ethernet card found.\n");
21067c478bd9Sstevel@tonic-gate errnum = ERR_DEV_VALUES;
21077c478bd9Sstevel@tonic-gate return 1;
21087c478bd9Sstevel@tonic-gate }
21097c478bd9Sstevel@tonic-gate
21107c478bd9Sstevel@tonic-gate while (*arg)
21117c478bd9Sstevel@tonic-gate {
21127c478bd9Sstevel@tonic-gate if (! grub_memcmp ("--server=", arg, sizeof ("--server=") - 1))
21137c478bd9Sstevel@tonic-gate svr = arg + sizeof("--server=") - 1;
21147c478bd9Sstevel@tonic-gate else if (! grub_memcmp ("--address=", arg, sizeof ("--address=") - 1))
21157c478bd9Sstevel@tonic-gate ip = arg + sizeof ("--address=") - 1;
21167c478bd9Sstevel@tonic-gate else if (! grub_memcmp ("--gateway=", arg, sizeof ("--gateway=") - 1))
21177c478bd9Sstevel@tonic-gate gw = arg + sizeof ("--gateway=") - 1;
21187c478bd9Sstevel@tonic-gate else if (! grub_memcmp ("--mask=", arg, sizeof("--mask=") - 1))
21197c478bd9Sstevel@tonic-gate sm = arg + sizeof ("--mask=") - 1;
21207c478bd9Sstevel@tonic-gate else
21217c478bd9Sstevel@tonic-gate {
21227c478bd9Sstevel@tonic-gate errnum = ERR_BAD_ARGUMENT;
21237c478bd9Sstevel@tonic-gate return 1;
21247c478bd9Sstevel@tonic-gate }
21257c478bd9Sstevel@tonic-gate
21267c478bd9Sstevel@tonic-gate arg = skip_to (0, arg);
21277c478bd9Sstevel@tonic-gate }
21287c478bd9Sstevel@tonic-gate
21297c478bd9Sstevel@tonic-gate if (! ifconfig (ip, sm, gw, svr))
21307c478bd9Sstevel@tonic-gate {
21317c478bd9Sstevel@tonic-gate errnum = ERR_BAD_ARGUMENT;
21327c478bd9Sstevel@tonic-gate return 1;
21337c478bd9Sstevel@tonic-gate }
21347c478bd9Sstevel@tonic-gate
21357c478bd9Sstevel@tonic-gate print_network_configuration ();
21367c478bd9Sstevel@tonic-gate return 0;
21377c478bd9Sstevel@tonic-gate }
21387c478bd9Sstevel@tonic-gate
21397c478bd9Sstevel@tonic-gate static struct builtin builtin_ifconfig =
21407c478bd9Sstevel@tonic-gate {
21417c478bd9Sstevel@tonic-gate "ifconfig",
21427c478bd9Sstevel@tonic-gate ifconfig_func,
21437c478bd9Sstevel@tonic-gate BUILTIN_CMDLINE | BUILTIN_MENU | BUILTIN_HELP_LIST,
21447c478bd9Sstevel@tonic-gate "ifconfig [--address=IP] [--gateway=IP] [--mask=MASK] [--server=IP]",
21457c478bd9Sstevel@tonic-gate "Configure the IP address, the netmask, the gateway and the server"
21467c478bd9Sstevel@tonic-gate " address or print current network configuration."
21477c478bd9Sstevel@tonic-gate };
21487c478bd9Sstevel@tonic-gate #endif /* SUPPORT_NETBOOT */
21497c478bd9Sstevel@tonic-gate
21507c478bd9Sstevel@tonic-gate
21517c478bd9Sstevel@tonic-gate /* impsprobe */
21527c478bd9Sstevel@tonic-gate static int
impsprobe_func(char * arg,int flags)21537c478bd9Sstevel@tonic-gate impsprobe_func (char *arg, int flags)
21547c478bd9Sstevel@tonic-gate {
21557c478bd9Sstevel@tonic-gate #ifdef GRUB_UTIL
21567c478bd9Sstevel@tonic-gate /* In the grub shell, we cannot probe IMPS. */
21577c478bd9Sstevel@tonic-gate errnum = ERR_UNRECOGNIZED;
21587c478bd9Sstevel@tonic-gate return 1;
21597c478bd9Sstevel@tonic-gate #else /* ! GRUB_UTIL */
21607c478bd9Sstevel@tonic-gate if (!imps_probe ())
21617c478bd9Sstevel@tonic-gate printf (" No MPS information found or probe failed\n");
21627c478bd9Sstevel@tonic-gate
21637c478bd9Sstevel@tonic-gate return 0;
21647c478bd9Sstevel@tonic-gate #endif /* ! GRUB_UTIL */
21657c478bd9Sstevel@tonic-gate }
21667c478bd9Sstevel@tonic-gate
21677c478bd9Sstevel@tonic-gate static struct builtin builtin_impsprobe =
21687c478bd9Sstevel@tonic-gate {
21697c478bd9Sstevel@tonic-gate "impsprobe",
21707c478bd9Sstevel@tonic-gate impsprobe_func,
21717c478bd9Sstevel@tonic-gate BUILTIN_CMDLINE,
21727c478bd9Sstevel@tonic-gate "impsprobe",
21737c478bd9Sstevel@tonic-gate "Probe the Intel Multiprocessor Specification 1.1 or 1.4"
21747c478bd9Sstevel@tonic-gate " configuration table and boot the various CPUs which are found into"
21757c478bd9Sstevel@tonic-gate " a tight loop."
21767c478bd9Sstevel@tonic-gate };
21777c478bd9Sstevel@tonic-gate
21787c478bd9Sstevel@tonic-gate /* initrd */
21797c478bd9Sstevel@tonic-gate static int
initrd_func(char * arg,int flags)21807c478bd9Sstevel@tonic-gate initrd_func (char *arg, int flags)
21817c478bd9Sstevel@tonic-gate {
21827c478bd9Sstevel@tonic-gate switch (kernel_type)
21837c478bd9Sstevel@tonic-gate {
21847c478bd9Sstevel@tonic-gate case KERNEL_TYPE_LINUX:
21857c478bd9Sstevel@tonic-gate case KERNEL_TYPE_BIG_LINUX:
21867c478bd9Sstevel@tonic-gate if (! load_initrd (arg))
21877c478bd9Sstevel@tonic-gate return 1;
21887c478bd9Sstevel@tonic-gate break;
21897c478bd9Sstevel@tonic-gate
21907c478bd9Sstevel@tonic-gate default:
21917c478bd9Sstevel@tonic-gate errnum = ERR_NEED_LX_KERNEL;
21927c478bd9Sstevel@tonic-gate return 1;
21937c478bd9Sstevel@tonic-gate }
21947c478bd9Sstevel@tonic-gate
21957c478bd9Sstevel@tonic-gate return 0;
21967c478bd9Sstevel@tonic-gate }
21977c478bd9Sstevel@tonic-gate
21987c478bd9Sstevel@tonic-gate static struct builtin builtin_initrd =
21997c478bd9Sstevel@tonic-gate {
22007c478bd9Sstevel@tonic-gate "initrd",
22017c478bd9Sstevel@tonic-gate initrd_func,
22027c478bd9Sstevel@tonic-gate BUILTIN_CMDLINE | BUILTIN_HELP_LIST,
22037c478bd9Sstevel@tonic-gate "initrd FILE [ARG ...]",
22047c478bd9Sstevel@tonic-gate "Load an initial ramdisk FILE for a Linux format boot image and set the"
22057c478bd9Sstevel@tonic-gate " appropriate parameters in the Linux setup area in memory."
22067c478bd9Sstevel@tonic-gate };
22077c478bd9Sstevel@tonic-gate
22087c478bd9Sstevel@tonic-gate
22097c478bd9Sstevel@tonic-gate /* install */
22107c478bd9Sstevel@tonic-gate static int
install_func(char * arg,int flags)22117c478bd9Sstevel@tonic-gate install_func (char *arg, int flags)
22127c478bd9Sstevel@tonic-gate {
22137c478bd9Sstevel@tonic-gate char *stage1_file, *dest_dev, *file, *addr;
22147c478bd9Sstevel@tonic-gate char *stage1_buffer = (char *) RAW_ADDR (0x100000);
22157c478bd9Sstevel@tonic-gate char *stage2_buffer = stage1_buffer + SECTOR_SIZE;
22167c478bd9Sstevel@tonic-gate char *old_sect = stage2_buffer + SECTOR_SIZE;
22177c478bd9Sstevel@tonic-gate char *stage2_first_buffer = old_sect + SECTOR_SIZE;
22187c478bd9Sstevel@tonic-gate char *stage2_second_buffer = stage2_first_buffer + SECTOR_SIZE;
22197c478bd9Sstevel@tonic-gate /* XXX: Probably SECTOR_SIZE is reasonable. */
22207c478bd9Sstevel@tonic-gate char *config_filename = stage2_second_buffer + SECTOR_SIZE;
22217c478bd9Sstevel@tonic-gate char *dummy = config_filename + SECTOR_SIZE;
22227c478bd9Sstevel@tonic-gate int new_drive = GRUB_INVALID_DRIVE;
2223342440ecSPrasad Singamsetty int dest_drive, dest_partition;
2224342440ecSPrasad Singamsetty unsigned int dest_sector;
22257c478bd9Sstevel@tonic-gate int src_drive, src_partition, src_part_start;
22267c478bd9Sstevel@tonic-gate int i;
22277c478bd9Sstevel@tonic-gate struct geometry dest_geom, src_geom;
22289890706eSHans Rosenfeld unsigned long long saved_sector;
22299890706eSHans Rosenfeld unsigned long long stage2_first_sector, stage2_second_sector;
22307c478bd9Sstevel@tonic-gate char *ptr;
22317c478bd9Sstevel@tonic-gate int installaddr, installlist;
22327c478bd9Sstevel@tonic-gate /* Point to the location of the name of a configuration file in Stage 2. */
22337c478bd9Sstevel@tonic-gate char *config_file_location;
22347c478bd9Sstevel@tonic-gate /* If FILE is a Stage 1.5? */
22357c478bd9Sstevel@tonic-gate int is_stage1_5 = 0;
22367c478bd9Sstevel@tonic-gate /* Must call grub_close? */
22377c478bd9Sstevel@tonic-gate int is_open = 0;
22387c478bd9Sstevel@tonic-gate /* If LBA is forced? */
22397c478bd9Sstevel@tonic-gate int is_force_lba = 0;
22407c478bd9Sstevel@tonic-gate /* Was the last sector full? */
22417c478bd9Sstevel@tonic-gate int last_length = SECTOR_SIZE;
22427c478bd9Sstevel@tonic-gate
22437c478bd9Sstevel@tonic-gate #ifdef GRUB_UTIL
22447c478bd9Sstevel@tonic-gate /* If the Stage 2 is in a partition mounted by an OS, this will store
22457c478bd9Sstevel@tonic-gate the filename under the OS. */
22467c478bd9Sstevel@tonic-gate char *stage2_os_file = 0;
22477c478bd9Sstevel@tonic-gate #endif /* GRUB_UTIL */
22487c478bd9Sstevel@tonic-gate
22499890706eSHans Rosenfeld auto void disk_read_savesect_func (unsigned long long sector, int offset,
22501b8adde7SWilliam Kucharski int length);
22519890706eSHans Rosenfeld auto void disk_read_blocklist_func (unsigned long long sector, int offset,
22521b8adde7SWilliam Kucharski int length);
22531b8adde7SWilliam Kucharski
22547c478bd9Sstevel@tonic-gate /* Save the first sector of Stage2 in STAGE2_SECT. */
22559890706eSHans Rosenfeld auto void disk_read_savesect_func (unsigned long long sector, int offset,
22561b8adde7SWilliam Kucharski int length)
22577c478bd9Sstevel@tonic-gate {
22587c478bd9Sstevel@tonic-gate if (debug)
22599890706eSHans Rosenfeld printf ("[%llu]", sector);
22607c478bd9Sstevel@tonic-gate
22617c478bd9Sstevel@tonic-gate /* ReiserFS has files which sometimes contain data not aligned
22627c478bd9Sstevel@tonic-gate on sector boundaries. Returning an error is better than
22637c478bd9Sstevel@tonic-gate silently failing. */
22647c478bd9Sstevel@tonic-gate if (offset != 0 || length != SECTOR_SIZE)
22657c478bd9Sstevel@tonic-gate errnum = ERR_UNALIGNED;
22667c478bd9Sstevel@tonic-gate
22677c478bd9Sstevel@tonic-gate saved_sector = sector;
22687c478bd9Sstevel@tonic-gate }
22697c478bd9Sstevel@tonic-gate
22707c478bd9Sstevel@tonic-gate /* Write SECTOR to INSTALLLIST, and update INSTALLADDR and
22717c478bd9Sstevel@tonic-gate INSTALLSECT. */
22729890706eSHans Rosenfeld auto void disk_read_blocklist_func (unsigned long long sector, int offset,
22731b8adde7SWilliam Kucharski int length)
22747c478bd9Sstevel@tonic-gate {
22757c478bd9Sstevel@tonic-gate if (debug)
22769890706eSHans Rosenfeld printf("[%llu]", sector);
22777c478bd9Sstevel@tonic-gate
22787c478bd9Sstevel@tonic-gate if (offset != 0 || last_length != SECTOR_SIZE)
22797c478bd9Sstevel@tonic-gate {
22807c478bd9Sstevel@tonic-gate /* We found a non-sector-aligned data block. */
22817c478bd9Sstevel@tonic-gate errnum = ERR_UNALIGNED;
22827c478bd9Sstevel@tonic-gate return;
22837c478bd9Sstevel@tonic-gate }
22847c478bd9Sstevel@tonic-gate
22857c478bd9Sstevel@tonic-gate last_length = length;
22867c478bd9Sstevel@tonic-gate
22877c478bd9Sstevel@tonic-gate if (*((unsigned long *) (installlist - 4))
22887c478bd9Sstevel@tonic-gate + *((unsigned short *) installlist) != sector
22897c478bd9Sstevel@tonic-gate || installlist == (int) stage2_first_buffer + SECTOR_SIZE + 4)
22907c478bd9Sstevel@tonic-gate {
22917c478bd9Sstevel@tonic-gate installlist -= 8;
22927c478bd9Sstevel@tonic-gate
22937c478bd9Sstevel@tonic-gate if (*((unsigned long *) (installlist - 8)))
22947c478bd9Sstevel@tonic-gate errnum = ERR_WONT_FIT;
22957c478bd9Sstevel@tonic-gate else
22967c478bd9Sstevel@tonic-gate {
22977c478bd9Sstevel@tonic-gate *((unsigned short *) (installlist + 2)) = (installaddr >> 4);
22987c478bd9Sstevel@tonic-gate *((unsigned long *) (installlist - 4)) = sector;
22997c478bd9Sstevel@tonic-gate }
23007c478bd9Sstevel@tonic-gate }
23017c478bd9Sstevel@tonic-gate
23027c478bd9Sstevel@tonic-gate *((unsigned short *) installlist) += 1;
23037c478bd9Sstevel@tonic-gate installaddr += 512;
23047c478bd9Sstevel@tonic-gate }
23057c478bd9Sstevel@tonic-gate
23067c478bd9Sstevel@tonic-gate /* First, check the GNU-style long option. */
23077c478bd9Sstevel@tonic-gate while (1)
23087c478bd9Sstevel@tonic-gate {
23097c478bd9Sstevel@tonic-gate if (grub_memcmp ("--force-lba", arg, sizeof ("--force-lba") - 1) == 0)
23107c478bd9Sstevel@tonic-gate {
23117c478bd9Sstevel@tonic-gate is_force_lba = 1;
23127c478bd9Sstevel@tonic-gate arg = skip_to (0, arg);
23137c478bd9Sstevel@tonic-gate }
23147c478bd9Sstevel@tonic-gate #ifdef GRUB_UTIL
23157c478bd9Sstevel@tonic-gate else if (grub_memcmp ("--stage2=", arg, sizeof ("--stage2=") - 1) == 0)
23167c478bd9Sstevel@tonic-gate {
23177c478bd9Sstevel@tonic-gate stage2_os_file = arg + sizeof ("--stage2=") - 1;
23187c478bd9Sstevel@tonic-gate arg = skip_to (0, arg);
23197c478bd9Sstevel@tonic-gate nul_terminate (stage2_os_file);
23207c478bd9Sstevel@tonic-gate }
23217c478bd9Sstevel@tonic-gate #endif /* GRUB_UTIL */
23227c478bd9Sstevel@tonic-gate else
23237c478bd9Sstevel@tonic-gate break;
23247c478bd9Sstevel@tonic-gate }
23257c478bd9Sstevel@tonic-gate
23267c478bd9Sstevel@tonic-gate stage1_file = arg;
23277c478bd9Sstevel@tonic-gate dest_dev = skip_to (0, stage1_file);
23287c478bd9Sstevel@tonic-gate if (*dest_dev == 'd')
23297c478bd9Sstevel@tonic-gate {
23307c478bd9Sstevel@tonic-gate new_drive = 0;
23317c478bd9Sstevel@tonic-gate dest_dev = skip_to (0, dest_dev);
23327c478bd9Sstevel@tonic-gate }
23337c478bd9Sstevel@tonic-gate file = skip_to (0, dest_dev);
23347c478bd9Sstevel@tonic-gate addr = skip_to (0, file);
23357c478bd9Sstevel@tonic-gate
23367c478bd9Sstevel@tonic-gate /* Get the installation address. */
23377c478bd9Sstevel@tonic-gate if (! safe_parse_maxint (&addr, &installaddr))
23387c478bd9Sstevel@tonic-gate {
23397c478bd9Sstevel@tonic-gate /* ADDR is not specified. */
23407c478bd9Sstevel@tonic-gate installaddr = 0;
23417c478bd9Sstevel@tonic-gate ptr = addr;
23427c478bd9Sstevel@tonic-gate errnum = 0;
23437c478bd9Sstevel@tonic-gate }
23447c478bd9Sstevel@tonic-gate else
23457c478bd9Sstevel@tonic-gate ptr = skip_to (0, addr);
23467c478bd9Sstevel@tonic-gate
23477c478bd9Sstevel@tonic-gate #ifndef NO_DECOMPRESSION
23487c478bd9Sstevel@tonic-gate /* Do not decompress Stage 1 or Stage 2. */
23497c478bd9Sstevel@tonic-gate no_decompression = 1;
23507c478bd9Sstevel@tonic-gate #endif
23517c478bd9Sstevel@tonic-gate
23527c478bd9Sstevel@tonic-gate /* Read Stage 1. */
23537c478bd9Sstevel@tonic-gate is_open = grub_open (stage1_file);
23547c478bd9Sstevel@tonic-gate if (! is_open
23557c478bd9Sstevel@tonic-gate || ! grub_read (stage1_buffer, SECTOR_SIZE) == SECTOR_SIZE)
23567c478bd9Sstevel@tonic-gate goto fail;
23577c478bd9Sstevel@tonic-gate
23587c478bd9Sstevel@tonic-gate /* Read the old sector from DEST_DEV. */
23597c478bd9Sstevel@tonic-gate if (! set_device (dest_dev)
23607c478bd9Sstevel@tonic-gate || ! open_partition ()
23617c478bd9Sstevel@tonic-gate || ! devread (0, 0, SECTOR_SIZE, old_sect))
23627c478bd9Sstevel@tonic-gate goto fail;
23637c478bd9Sstevel@tonic-gate
23647c478bd9Sstevel@tonic-gate /* Store the information for the destination device. */
23657c478bd9Sstevel@tonic-gate dest_drive = current_drive;
23667c478bd9Sstevel@tonic-gate dest_partition = current_partition;
23677c478bd9Sstevel@tonic-gate dest_geom = buf_geom;
23687c478bd9Sstevel@tonic-gate dest_sector = part_start;
23697c478bd9Sstevel@tonic-gate
23707c478bd9Sstevel@tonic-gate /* Copy the possible DOS BPB, 59 bytes at byte offset 3. */
23717c478bd9Sstevel@tonic-gate grub_memmove (stage1_buffer + BOOTSEC_BPB_OFFSET,
23727c478bd9Sstevel@tonic-gate old_sect + BOOTSEC_BPB_OFFSET,
23737c478bd9Sstevel@tonic-gate BOOTSEC_BPB_LENGTH);
23747c478bd9Sstevel@tonic-gate
23757c478bd9Sstevel@tonic-gate /* If for a hard disk, copy the possible MBR/extended part table. */
23767c478bd9Sstevel@tonic-gate if (dest_drive & 0x80)
23777c478bd9Sstevel@tonic-gate grub_memmove (stage1_buffer + STAGE1_WINDOWS_NT_MAGIC,
23787c478bd9Sstevel@tonic-gate old_sect + STAGE1_WINDOWS_NT_MAGIC,
23797c478bd9Sstevel@tonic-gate STAGE1_PARTEND - STAGE1_WINDOWS_NT_MAGIC);
23807c478bd9Sstevel@tonic-gate
23817c478bd9Sstevel@tonic-gate /* Check for the version and the signature of Stage 1. */
23827c478bd9Sstevel@tonic-gate if (*((short *)(stage1_buffer + STAGE1_VER_MAJ_OFFS)) != COMPAT_VERSION
23837c478bd9Sstevel@tonic-gate || (*((unsigned short *) (stage1_buffer + BOOTSEC_SIG_OFFSET))
23847c478bd9Sstevel@tonic-gate != BOOTSEC_SIGNATURE))
23857c478bd9Sstevel@tonic-gate {
23867c478bd9Sstevel@tonic-gate errnum = ERR_BAD_VERSION;
23877c478bd9Sstevel@tonic-gate goto fail;
23887c478bd9Sstevel@tonic-gate }
23897c478bd9Sstevel@tonic-gate
23907c478bd9Sstevel@tonic-gate /* This below is not true any longer. But should we leave this alone? */
23917c478bd9Sstevel@tonic-gate
23927c478bd9Sstevel@tonic-gate /* If DEST_DRIVE is a floppy, Stage 2 must have the iteration probe
23937c478bd9Sstevel@tonic-gate routine. */
23947c478bd9Sstevel@tonic-gate if (! (dest_drive & 0x80)
23957c478bd9Sstevel@tonic-gate && (*((unsigned char *) (stage1_buffer + BOOTSEC_PART_OFFSET)) == 0x80
23967c478bd9Sstevel@tonic-gate || stage1_buffer[BOOTSEC_PART_OFFSET] == 0))
23977c478bd9Sstevel@tonic-gate {
23987c478bd9Sstevel@tonic-gate errnum = ERR_BAD_VERSION;
23997c478bd9Sstevel@tonic-gate goto fail;
24007c478bd9Sstevel@tonic-gate }
24017c478bd9Sstevel@tonic-gate
24027c478bd9Sstevel@tonic-gate grub_close ();
24037c478bd9Sstevel@tonic-gate
24047c478bd9Sstevel@tonic-gate /* Open Stage 2. */
24057c478bd9Sstevel@tonic-gate is_open = grub_open (file);
24067c478bd9Sstevel@tonic-gate if (! is_open)
24077c478bd9Sstevel@tonic-gate goto fail;
24087c478bd9Sstevel@tonic-gate
24097c478bd9Sstevel@tonic-gate src_drive = current_drive;
24107c478bd9Sstevel@tonic-gate src_partition = current_partition;
24117c478bd9Sstevel@tonic-gate src_part_start = part_start;
24127c478bd9Sstevel@tonic-gate src_geom = buf_geom;
24137c478bd9Sstevel@tonic-gate
24147c478bd9Sstevel@tonic-gate if (! new_drive)
24157c478bd9Sstevel@tonic-gate new_drive = src_drive;
24167c478bd9Sstevel@tonic-gate else if (src_drive != dest_drive)
24177c478bd9Sstevel@tonic-gate grub_printf ("Warning: the option `d' was not used, but the Stage 1 will"
24187c478bd9Sstevel@tonic-gate " be installed on a\ndifferent drive than the drive where"
24197c478bd9Sstevel@tonic-gate " the Stage 2 resides.\n");
24207c478bd9Sstevel@tonic-gate
24217c478bd9Sstevel@tonic-gate /* Set the boot drive. */
24227c478bd9Sstevel@tonic-gate *((unsigned char *) (stage1_buffer + STAGE1_BOOT_DRIVE)) = new_drive;
24237c478bd9Sstevel@tonic-gate
24247c478bd9Sstevel@tonic-gate /* Set the "force LBA" flag. */
24257c478bd9Sstevel@tonic-gate *((unsigned char *) (stage1_buffer + STAGE1_FORCE_LBA)) = is_force_lba;
24267c478bd9Sstevel@tonic-gate
24271b8adde7SWilliam Kucharski /* If DEST_DRIVE is a hard disk, enable the workaround, which is
24281b8adde7SWilliam Kucharski for buggy BIOSes which don't pass boot drive correctly. Instead,
24291b8adde7SWilliam Kucharski they pass 0x00 or 0x01 even when booted from 0x80. */
24301b8adde7SWilliam Kucharski if (dest_drive & BIOS_FLAG_FIXED_DISK)
24311b8adde7SWilliam Kucharski /* Replace the jmp (2 bytes) with double nop's. */
24321b8adde7SWilliam Kucharski *((unsigned short *) (stage1_buffer + STAGE1_BOOT_DRIVE_CHECK))
24331b8adde7SWilliam Kucharski = 0x9090;
24341b8adde7SWilliam Kucharski
24357c478bd9Sstevel@tonic-gate /* Read the first sector of Stage 2. */
24367c478bd9Sstevel@tonic-gate disk_read_hook = disk_read_savesect_func;
24377c478bd9Sstevel@tonic-gate if (grub_read (stage2_first_buffer, SECTOR_SIZE) != SECTOR_SIZE)
24387c478bd9Sstevel@tonic-gate goto fail;
24397c478bd9Sstevel@tonic-gate
24407c478bd9Sstevel@tonic-gate stage2_first_sector = saved_sector;
24419890706eSHans Rosenfeld if (stage2_first_sector >= 0xffffffffUL) {
24429890706eSHans Rosenfeld grub_printf ("Error: stage2 first sector must be below 2TB\n");
24439890706eSHans Rosenfeld goto fail;
24449890706eSHans Rosenfeld }
24457c478bd9Sstevel@tonic-gate
24467c478bd9Sstevel@tonic-gate /* Read the second sector of Stage 2. */
24477c478bd9Sstevel@tonic-gate if (grub_read (stage2_second_buffer, SECTOR_SIZE) != SECTOR_SIZE)
24487c478bd9Sstevel@tonic-gate goto fail;
24497c478bd9Sstevel@tonic-gate
24507c478bd9Sstevel@tonic-gate stage2_second_sector = saved_sector;
24517c478bd9Sstevel@tonic-gate
24527c478bd9Sstevel@tonic-gate /* Check for the version of Stage 2. */
24537c478bd9Sstevel@tonic-gate if (*((short *) (stage2_second_buffer + STAGE2_VER_MAJ_OFFS))
24547c478bd9Sstevel@tonic-gate != COMPAT_VERSION)
24557c478bd9Sstevel@tonic-gate {
24567c478bd9Sstevel@tonic-gate errnum = ERR_BAD_VERSION;
24577c478bd9Sstevel@tonic-gate goto fail;
24587c478bd9Sstevel@tonic-gate }
24597c478bd9Sstevel@tonic-gate
24607c478bd9Sstevel@tonic-gate /* Check for the Stage 2 id. */
24617c478bd9Sstevel@tonic-gate if (stage2_second_buffer[STAGE2_STAGE2_ID] != STAGE2_ID_STAGE2)
24627c478bd9Sstevel@tonic-gate is_stage1_5 = 1;
24637c478bd9Sstevel@tonic-gate
24647c478bd9Sstevel@tonic-gate /* If INSTALLADDR is not specified explicitly in the command-line,
24657c478bd9Sstevel@tonic-gate determine it by the Stage 2 id. */
24667c478bd9Sstevel@tonic-gate if (! installaddr)
24677c478bd9Sstevel@tonic-gate {
24687c478bd9Sstevel@tonic-gate if (! is_stage1_5)
24697c478bd9Sstevel@tonic-gate /* Stage 2. */
24707c478bd9Sstevel@tonic-gate installaddr = 0x8000;
24717c478bd9Sstevel@tonic-gate else
24727c478bd9Sstevel@tonic-gate /* Stage 1.5. */
24737c478bd9Sstevel@tonic-gate installaddr = 0x2000;
24747c478bd9Sstevel@tonic-gate }
24757c478bd9Sstevel@tonic-gate
24767c478bd9Sstevel@tonic-gate *((unsigned long *) (stage1_buffer + STAGE1_STAGE2_SECTOR))
24777c478bd9Sstevel@tonic-gate = stage2_first_sector;
24787c478bd9Sstevel@tonic-gate *((unsigned short *) (stage1_buffer + STAGE1_STAGE2_ADDRESS))
24797c478bd9Sstevel@tonic-gate = installaddr;
24807c478bd9Sstevel@tonic-gate *((unsigned short *) (stage1_buffer + STAGE1_STAGE2_SEGMENT))
24817c478bd9Sstevel@tonic-gate = installaddr >> 4;
24827c478bd9Sstevel@tonic-gate
24837c478bd9Sstevel@tonic-gate i = (int) stage2_first_buffer + SECTOR_SIZE - 4;
24847c478bd9Sstevel@tonic-gate while (*((unsigned long *) i))
24857c478bd9Sstevel@tonic-gate {
24867c478bd9Sstevel@tonic-gate if (i < (int) stage2_first_buffer
24877c478bd9Sstevel@tonic-gate || (*((int *) (i - 4)) & 0x80000000)
24887c478bd9Sstevel@tonic-gate || *((unsigned short *) i) >= 0xA00
24897c478bd9Sstevel@tonic-gate || *((short *) (i + 2)) == 0)
24907c478bd9Sstevel@tonic-gate {
24917c478bd9Sstevel@tonic-gate errnum = ERR_BAD_VERSION;
24927c478bd9Sstevel@tonic-gate goto fail;
24937c478bd9Sstevel@tonic-gate }
24947c478bd9Sstevel@tonic-gate
24957c478bd9Sstevel@tonic-gate *((int *) i) = 0;
24967c478bd9Sstevel@tonic-gate *((int *) (i - 4)) = 0;
24977c478bd9Sstevel@tonic-gate i -= 8;
24987c478bd9Sstevel@tonic-gate }
24997c478bd9Sstevel@tonic-gate
25007c478bd9Sstevel@tonic-gate installlist = (int) stage2_first_buffer + SECTOR_SIZE + 4;
25017c478bd9Sstevel@tonic-gate installaddr += SECTOR_SIZE;
25027c478bd9Sstevel@tonic-gate
25037c478bd9Sstevel@tonic-gate /* Read the whole of Stage2 except for the first sector. */
25047c478bd9Sstevel@tonic-gate grub_seek (SECTOR_SIZE);
25057c478bd9Sstevel@tonic-gate
25067c478bd9Sstevel@tonic-gate disk_read_hook = disk_read_blocklist_func;
25077c478bd9Sstevel@tonic-gate if (! grub_read (dummy, -1))
25087c478bd9Sstevel@tonic-gate goto fail;
25097c478bd9Sstevel@tonic-gate
25107c478bd9Sstevel@tonic-gate disk_read_hook = 0;
25117c478bd9Sstevel@tonic-gate
25127c478bd9Sstevel@tonic-gate /* Find a string for the configuration filename. */
25137c478bd9Sstevel@tonic-gate config_file_location = stage2_second_buffer + STAGE2_VER_STR_OFFS;
25147c478bd9Sstevel@tonic-gate while (*(config_file_location++))
25157c478bd9Sstevel@tonic-gate ;
25167c478bd9Sstevel@tonic-gate
25177c478bd9Sstevel@tonic-gate /* Set the "force LBA" flag for Stage2. */
25187c478bd9Sstevel@tonic-gate *((unsigned char *) (stage2_second_buffer + STAGE2_FORCE_LBA))
25197c478bd9Sstevel@tonic-gate = is_force_lba;
25207c478bd9Sstevel@tonic-gate
25217c478bd9Sstevel@tonic-gate if (*ptr == 'p')
25227c478bd9Sstevel@tonic-gate {
25237c478bd9Sstevel@tonic-gate *((long *) (stage2_second_buffer + STAGE2_INSTALLPART))
25247c478bd9Sstevel@tonic-gate = src_partition;
25257c478bd9Sstevel@tonic-gate if (is_stage1_5)
25267c478bd9Sstevel@tonic-gate {
25277c478bd9Sstevel@tonic-gate /* Reset the device information in FILE if it is a Stage 1.5. */
25287c478bd9Sstevel@tonic-gate unsigned long device = 0xFFFFFFFF;
25297c478bd9Sstevel@tonic-gate
25307c478bd9Sstevel@tonic-gate grub_memmove (config_file_location, (char *) &device,
25317c478bd9Sstevel@tonic-gate sizeof (device));
25327c478bd9Sstevel@tonic-gate }
25337c478bd9Sstevel@tonic-gate
25347c478bd9Sstevel@tonic-gate ptr = skip_to (0, ptr);
25357c478bd9Sstevel@tonic-gate }
25367c478bd9Sstevel@tonic-gate
25377c478bd9Sstevel@tonic-gate if (*ptr)
25387c478bd9Sstevel@tonic-gate {
25397c478bd9Sstevel@tonic-gate grub_strcpy (config_filename, ptr);
25407c478bd9Sstevel@tonic-gate nul_terminate (config_filename);
25417c478bd9Sstevel@tonic-gate
25427c478bd9Sstevel@tonic-gate if (! is_stage1_5)
25437c478bd9Sstevel@tonic-gate /* If it is a Stage 2, just copy PTR to CONFIG_FILE_LOCATION. */
25447c478bd9Sstevel@tonic-gate grub_strcpy (config_file_location, ptr);
25457c478bd9Sstevel@tonic-gate else
25467c478bd9Sstevel@tonic-gate {
25477c478bd9Sstevel@tonic-gate char *real_config;
25487c478bd9Sstevel@tonic-gate unsigned long device;
25497c478bd9Sstevel@tonic-gate
25507c478bd9Sstevel@tonic-gate /* Translate the external device syntax to the internal device
25517c478bd9Sstevel@tonic-gate syntax. */
25527c478bd9Sstevel@tonic-gate if (! (real_config = set_device (ptr)))
25537c478bd9Sstevel@tonic-gate {
25547c478bd9Sstevel@tonic-gate /* The Stage 2 PTR does not contain the device name, so
25557c478bd9Sstevel@tonic-gate use the root device instead. */
25567c478bd9Sstevel@tonic-gate errnum = ERR_NONE;
25577c478bd9Sstevel@tonic-gate current_drive = saved_drive;
25587c478bd9Sstevel@tonic-gate current_partition = saved_partition;
25597c478bd9Sstevel@tonic-gate real_config = ptr;
25607c478bd9Sstevel@tonic-gate }
25617c478bd9Sstevel@tonic-gate
25627c478bd9Sstevel@tonic-gate if (current_drive == src_drive)
25637c478bd9Sstevel@tonic-gate {
25647c478bd9Sstevel@tonic-gate /* If the drive where the Stage 2 resides is the same as
25657c478bd9Sstevel@tonic-gate the one where the Stage 1.5 resides, do not embed the
25667c478bd9Sstevel@tonic-gate drive number. */
25677c478bd9Sstevel@tonic-gate current_drive = GRUB_INVALID_DRIVE;
25687c478bd9Sstevel@tonic-gate }
25697c478bd9Sstevel@tonic-gate
25707c478bd9Sstevel@tonic-gate device = (current_drive << 24) | current_partition;
25717c478bd9Sstevel@tonic-gate grub_memmove (config_file_location, (char *) &device,
25727c478bd9Sstevel@tonic-gate sizeof (device));
25737c478bd9Sstevel@tonic-gate grub_strcpy (config_file_location + sizeof (device),
25747c478bd9Sstevel@tonic-gate real_config);
25757c478bd9Sstevel@tonic-gate }
25767c478bd9Sstevel@tonic-gate
25777c478bd9Sstevel@tonic-gate /* If a Stage 1.5 is used, then we need to modify the Stage2. */
25787c478bd9Sstevel@tonic-gate if (is_stage1_5)
25797c478bd9Sstevel@tonic-gate {
25807c478bd9Sstevel@tonic-gate char *real_config_filename = skip_to (0, ptr);
25817c478bd9Sstevel@tonic-gate
25827c478bd9Sstevel@tonic-gate is_open = grub_open (config_filename);
25837c478bd9Sstevel@tonic-gate if (! is_open)
25847c478bd9Sstevel@tonic-gate goto fail;
25857c478bd9Sstevel@tonic-gate
25867c478bd9Sstevel@tonic-gate /* Skip the first sector. */
25877c478bd9Sstevel@tonic-gate grub_seek (SECTOR_SIZE);
25887c478bd9Sstevel@tonic-gate
25897c478bd9Sstevel@tonic-gate disk_read_hook = disk_read_savesect_func;
25907c478bd9Sstevel@tonic-gate if (grub_read (stage2_buffer, SECTOR_SIZE) != SECTOR_SIZE)
25917c478bd9Sstevel@tonic-gate goto fail;
25927c478bd9Sstevel@tonic-gate
25937c478bd9Sstevel@tonic-gate disk_read_hook = 0;
25947c478bd9Sstevel@tonic-gate grub_close ();
25957c478bd9Sstevel@tonic-gate is_open = 0;
25967c478bd9Sstevel@tonic-gate
25977c478bd9Sstevel@tonic-gate /* Sanity check. */
25987c478bd9Sstevel@tonic-gate if (*(stage2_buffer + STAGE2_STAGE2_ID) != STAGE2_ID_STAGE2)
25997c478bd9Sstevel@tonic-gate {
26007c478bd9Sstevel@tonic-gate errnum = ERR_BAD_VERSION;
26017c478bd9Sstevel@tonic-gate goto fail;
26027c478bd9Sstevel@tonic-gate }
26037c478bd9Sstevel@tonic-gate
26047c478bd9Sstevel@tonic-gate /* Set the "force LBA" flag for Stage2. */
26057c478bd9Sstevel@tonic-gate *(stage2_buffer + STAGE2_FORCE_LBA) = is_force_lba;
26067c478bd9Sstevel@tonic-gate
26077c478bd9Sstevel@tonic-gate /* If REAL_CONFIG_FILENAME is specified, copy it to the Stage2. */
26087c478bd9Sstevel@tonic-gate if (*real_config_filename)
26097c478bd9Sstevel@tonic-gate {
26107c478bd9Sstevel@tonic-gate /* Specified */
26117c478bd9Sstevel@tonic-gate char *location;
26127c478bd9Sstevel@tonic-gate
26137c478bd9Sstevel@tonic-gate /* Find a string for the configuration filename. */
26147c478bd9Sstevel@tonic-gate location = stage2_buffer + STAGE2_VER_STR_OFFS;
26157c478bd9Sstevel@tonic-gate while (*(location++))
26167c478bd9Sstevel@tonic-gate ;
26177c478bd9Sstevel@tonic-gate
26187c478bd9Sstevel@tonic-gate /* Copy the name. */
26197c478bd9Sstevel@tonic-gate grub_strcpy (location, real_config_filename);
26207c478bd9Sstevel@tonic-gate }
26217c478bd9Sstevel@tonic-gate
26227c478bd9Sstevel@tonic-gate /* Write it to the disk. */
2623342440ecSPrasad Singamsetty buf_track = BUF_CACHE_INVALID;
26247c478bd9Sstevel@tonic-gate
26257c478bd9Sstevel@tonic-gate #ifdef GRUB_UTIL
26267c478bd9Sstevel@tonic-gate /* In the grub shell, access the Stage 2 via the OS filesystem
26277c478bd9Sstevel@tonic-gate service, if possible. */
26287c478bd9Sstevel@tonic-gate if (stage2_os_file)
26297c478bd9Sstevel@tonic-gate {
26307c478bd9Sstevel@tonic-gate FILE *fp;
26317c478bd9Sstevel@tonic-gate
26327c478bd9Sstevel@tonic-gate fp = fopen (stage2_os_file, "r+");
26337c478bd9Sstevel@tonic-gate if (! fp)
26347c478bd9Sstevel@tonic-gate {
26357c478bd9Sstevel@tonic-gate errnum = ERR_FILE_NOT_FOUND;
26367c478bd9Sstevel@tonic-gate goto fail;
26377c478bd9Sstevel@tonic-gate }
26387c478bd9Sstevel@tonic-gate
26397c478bd9Sstevel@tonic-gate if (fseek (fp, SECTOR_SIZE, SEEK_SET) != 0)
26407c478bd9Sstevel@tonic-gate {
26417c478bd9Sstevel@tonic-gate fclose (fp);
26427c478bd9Sstevel@tonic-gate errnum = ERR_BAD_VERSION;
26437c478bd9Sstevel@tonic-gate goto fail;
26447c478bd9Sstevel@tonic-gate }
26457c478bd9Sstevel@tonic-gate
26467c478bd9Sstevel@tonic-gate if (fwrite (stage2_buffer, 1, SECTOR_SIZE, fp)
26477c478bd9Sstevel@tonic-gate != SECTOR_SIZE)
26487c478bd9Sstevel@tonic-gate {
26497c478bd9Sstevel@tonic-gate fclose (fp);
26507c478bd9Sstevel@tonic-gate errnum = ERR_WRITE;
26517c478bd9Sstevel@tonic-gate goto fail;
26527c478bd9Sstevel@tonic-gate }
26537c478bd9Sstevel@tonic-gate
26547c478bd9Sstevel@tonic-gate fclose (fp);
26557c478bd9Sstevel@tonic-gate }
26567c478bd9Sstevel@tonic-gate else
26577c478bd9Sstevel@tonic-gate #endif /* GRUB_UTIL */
26587c478bd9Sstevel@tonic-gate {
26597c478bd9Sstevel@tonic-gate if (! devwrite (saved_sector - part_start, 1, stage2_buffer))
26607c478bd9Sstevel@tonic-gate goto fail;
26617c478bd9Sstevel@tonic-gate }
26627c478bd9Sstevel@tonic-gate }
26637c478bd9Sstevel@tonic-gate }
26647c478bd9Sstevel@tonic-gate
26657c478bd9Sstevel@tonic-gate /* Clear the cache. */
2666342440ecSPrasad Singamsetty buf_track = BUF_CACHE_INVALID;
26677c478bd9Sstevel@tonic-gate
26687c478bd9Sstevel@tonic-gate /* Write the modified sectors of Stage2 to the disk. */
26697c478bd9Sstevel@tonic-gate #ifdef GRUB_UTIL
26707c478bd9Sstevel@tonic-gate if (! is_stage1_5 && stage2_os_file)
26717c478bd9Sstevel@tonic-gate {
26727c478bd9Sstevel@tonic-gate FILE *fp;
26737c478bd9Sstevel@tonic-gate
26747c478bd9Sstevel@tonic-gate fp = fopen (stage2_os_file, "r+");
26757c478bd9Sstevel@tonic-gate if (! fp)
26767c478bd9Sstevel@tonic-gate {
26777c478bd9Sstevel@tonic-gate errnum = ERR_FILE_NOT_FOUND;
26787c478bd9Sstevel@tonic-gate goto fail;
26797c478bd9Sstevel@tonic-gate }
26807c478bd9Sstevel@tonic-gate
26817c478bd9Sstevel@tonic-gate if (fwrite (stage2_first_buffer, 1, SECTOR_SIZE, fp) != SECTOR_SIZE)
26827c478bd9Sstevel@tonic-gate {
26837c478bd9Sstevel@tonic-gate fclose (fp);
26847c478bd9Sstevel@tonic-gate errnum = ERR_WRITE;
26857c478bd9Sstevel@tonic-gate goto fail;
26867c478bd9Sstevel@tonic-gate }
26877c478bd9Sstevel@tonic-gate
26887c478bd9Sstevel@tonic-gate if (fwrite (stage2_second_buffer, 1, SECTOR_SIZE, fp) != SECTOR_SIZE)
26897c478bd9Sstevel@tonic-gate {
26907c478bd9Sstevel@tonic-gate fclose (fp);
26917c478bd9Sstevel@tonic-gate errnum = ERR_WRITE;
26927c478bd9Sstevel@tonic-gate goto fail;
26937c478bd9Sstevel@tonic-gate }
26947c478bd9Sstevel@tonic-gate
26957c478bd9Sstevel@tonic-gate fclose (fp);
26967c478bd9Sstevel@tonic-gate }
26977c478bd9Sstevel@tonic-gate else
26987c478bd9Sstevel@tonic-gate #endif /* GRUB_UTIL */
26997c478bd9Sstevel@tonic-gate {
27007c478bd9Sstevel@tonic-gate /* The first. */
27017c478bd9Sstevel@tonic-gate current_drive = src_drive;
27027c478bd9Sstevel@tonic-gate current_partition = src_partition;
27037c478bd9Sstevel@tonic-gate
27047c478bd9Sstevel@tonic-gate if (! open_partition ())
27057c478bd9Sstevel@tonic-gate goto fail;
27067c478bd9Sstevel@tonic-gate
27077c478bd9Sstevel@tonic-gate if (! devwrite (stage2_first_sector - src_part_start, 1,
27087c478bd9Sstevel@tonic-gate stage2_first_buffer))
27097c478bd9Sstevel@tonic-gate goto fail;
27107c478bd9Sstevel@tonic-gate
27117c478bd9Sstevel@tonic-gate if (! devwrite (stage2_second_sector - src_part_start, 1,
27127c478bd9Sstevel@tonic-gate stage2_second_buffer))
27137c478bd9Sstevel@tonic-gate goto fail;
27147c478bd9Sstevel@tonic-gate }
27157c478bd9Sstevel@tonic-gate
27167c478bd9Sstevel@tonic-gate /* Write the modified sector of Stage 1 to the disk. */
27177c478bd9Sstevel@tonic-gate current_drive = dest_drive;
27187c478bd9Sstevel@tonic-gate current_partition = dest_partition;
27197c478bd9Sstevel@tonic-gate if (! open_partition ())
27207c478bd9Sstevel@tonic-gate goto fail;
27217c478bd9Sstevel@tonic-gate
27227c478bd9Sstevel@tonic-gate devwrite (0, 1, stage1_buffer);
27237c478bd9Sstevel@tonic-gate
27247c478bd9Sstevel@tonic-gate fail:
27257c478bd9Sstevel@tonic-gate if (is_open)
27267c478bd9Sstevel@tonic-gate grub_close ();
27277c478bd9Sstevel@tonic-gate
27287c478bd9Sstevel@tonic-gate disk_read_hook = 0;
27297c478bd9Sstevel@tonic-gate
27307c478bd9Sstevel@tonic-gate #ifndef NO_DECOMPRESSION
27317c478bd9Sstevel@tonic-gate no_decompression = 0;
27327c478bd9Sstevel@tonic-gate #endif
27337c478bd9Sstevel@tonic-gate
27347c478bd9Sstevel@tonic-gate return errnum;
27357c478bd9Sstevel@tonic-gate }
27367c478bd9Sstevel@tonic-gate
27377c478bd9Sstevel@tonic-gate static struct builtin builtin_install =
27387c478bd9Sstevel@tonic-gate {
27397c478bd9Sstevel@tonic-gate "install",
27407c478bd9Sstevel@tonic-gate install_func,
27417c478bd9Sstevel@tonic-gate BUILTIN_CMDLINE,
27427c478bd9Sstevel@tonic-gate "install [--stage2=STAGE2_FILE] [--force-lba] STAGE1 [d] DEVICE STAGE2 [ADDR] [p] [CONFIG_FILE] [REAL_CONFIG_FILE]",
27437c478bd9Sstevel@tonic-gate "Install STAGE1 on DEVICE, and install a blocklist for loading STAGE2"
27447c478bd9Sstevel@tonic-gate " as a Stage 2. If the option `d' is present, the Stage 1 will always"
27457c478bd9Sstevel@tonic-gate " look for the disk where STAGE2 was installed, rather than using"
27467c478bd9Sstevel@tonic-gate " the booting drive. The Stage 2 will be loaded at address ADDR, which"
27477c478bd9Sstevel@tonic-gate " will be determined automatically if you don't specify it. If"
27487c478bd9Sstevel@tonic-gate " the option `p' or CONFIG_FILE is present, then the first block"
27497c478bd9Sstevel@tonic-gate " of Stage 2 is patched with new values of the partition and name"
27507c478bd9Sstevel@tonic-gate " of the configuration file used by the true Stage 2 (for a Stage 1.5,"
27517c478bd9Sstevel@tonic-gate " this is the name of the true Stage 2) at boot time. If STAGE2 is a Stage"
27527c478bd9Sstevel@tonic-gate " 1.5 and REAL_CONFIG_FILE is present, then the Stage 2 CONFIG_FILE is"
27537c478bd9Sstevel@tonic-gate " patched with the configuration filename REAL_CONFIG_FILE."
27547c478bd9Sstevel@tonic-gate " If the option `--force-lba' is specified, disable some sanity checks"
27557c478bd9Sstevel@tonic-gate " for LBA mode. If the option `--stage2' is specified, rewrite the Stage"
27567c478bd9Sstevel@tonic-gate " 2 via your OS's filesystem instead of the raw device."
27577c478bd9Sstevel@tonic-gate };
27587c478bd9Sstevel@tonic-gate
27597c478bd9Sstevel@tonic-gate
27607c478bd9Sstevel@tonic-gate /* ioprobe */
27617c478bd9Sstevel@tonic-gate static int
ioprobe_func(char * arg,int flags)27627c478bd9Sstevel@tonic-gate ioprobe_func (char *arg, int flags)
27637c478bd9Sstevel@tonic-gate {
27647c478bd9Sstevel@tonic-gate #ifdef GRUB_UTIL
27657c478bd9Sstevel@tonic-gate
27667c478bd9Sstevel@tonic-gate errnum = ERR_UNRECOGNIZED;
27677c478bd9Sstevel@tonic-gate return 1;
27687c478bd9Sstevel@tonic-gate
27697c478bd9Sstevel@tonic-gate #else /* ! GRUB_UTIL */
27707c478bd9Sstevel@tonic-gate
27717c478bd9Sstevel@tonic-gate unsigned short *port;
27727c478bd9Sstevel@tonic-gate
27737c478bd9Sstevel@tonic-gate /* Get the drive number. */
27747c478bd9Sstevel@tonic-gate set_device (arg);
27757c478bd9Sstevel@tonic-gate if (errnum)
27767c478bd9Sstevel@tonic-gate return 1;
27777c478bd9Sstevel@tonic-gate
27787c478bd9Sstevel@tonic-gate /* Clean out IO_MAP. */
27797c478bd9Sstevel@tonic-gate grub_memset ((char *) io_map, 0, IO_MAP_SIZE * sizeof (unsigned short));
27807c478bd9Sstevel@tonic-gate
27817c478bd9Sstevel@tonic-gate /* Track the int13 handler. */
27827c478bd9Sstevel@tonic-gate track_int13 (current_drive);
27837c478bd9Sstevel@tonic-gate
27847c478bd9Sstevel@tonic-gate /* Print out the result. */
27857c478bd9Sstevel@tonic-gate for (port = io_map; *port != 0; port++)
27867c478bd9Sstevel@tonic-gate grub_printf (" 0x%x", (unsigned int) *port);
27877c478bd9Sstevel@tonic-gate
27887c478bd9Sstevel@tonic-gate return 0;
27897c478bd9Sstevel@tonic-gate
27907c478bd9Sstevel@tonic-gate #endif /* ! GRUB_UTIL */
27917c478bd9Sstevel@tonic-gate }
27927c478bd9Sstevel@tonic-gate
27937c478bd9Sstevel@tonic-gate static struct builtin builtin_ioprobe =
27947c478bd9Sstevel@tonic-gate {
27957c478bd9Sstevel@tonic-gate "ioprobe",
27967c478bd9Sstevel@tonic-gate ioprobe_func,
27977c478bd9Sstevel@tonic-gate BUILTIN_CMDLINE,
27987c478bd9Sstevel@tonic-gate "ioprobe DRIVE",
27997c478bd9Sstevel@tonic-gate "Probe I/O ports used for the drive DRIVE."
28007c478bd9Sstevel@tonic-gate };
28017c478bd9Sstevel@tonic-gate
28027c478bd9Sstevel@tonic-gate
28037c478bd9Sstevel@tonic-gate /* kernel */
28047c478bd9Sstevel@tonic-gate static int
kernel_func(char * arg,int flags)28057c478bd9Sstevel@tonic-gate kernel_func (char *arg, int flags)
28067c478bd9Sstevel@tonic-gate {
28077c478bd9Sstevel@tonic-gate int len;
28087c478bd9Sstevel@tonic-gate kernel_t suggested_type = KERNEL_TYPE_NONE;
28097c478bd9Sstevel@tonic-gate unsigned long load_flags = 0;
28107c478bd9Sstevel@tonic-gate
28117c478bd9Sstevel@tonic-gate #ifndef AUTO_LINUX_MEM_OPT
28127c478bd9Sstevel@tonic-gate load_flags |= KERNEL_LOAD_NO_MEM_OPTION;
28137c478bd9Sstevel@tonic-gate #endif
28147c478bd9Sstevel@tonic-gate
28157c478bd9Sstevel@tonic-gate /* Deal with GNU-style long options. */
28167c478bd9Sstevel@tonic-gate while (1)
28177c478bd9Sstevel@tonic-gate {
28187c478bd9Sstevel@tonic-gate /* If the option `--type=TYPE' is specified, convert the string to
28197c478bd9Sstevel@tonic-gate a kernel type. */
28207c478bd9Sstevel@tonic-gate if (grub_memcmp (arg, "--type=", 7) == 0)
28217c478bd9Sstevel@tonic-gate {
28227c478bd9Sstevel@tonic-gate arg += 7;
28237c478bd9Sstevel@tonic-gate
28247c478bd9Sstevel@tonic-gate if (grub_memcmp (arg, "netbsd", 6) == 0)
28257c478bd9Sstevel@tonic-gate suggested_type = KERNEL_TYPE_NETBSD;
28267c478bd9Sstevel@tonic-gate else if (grub_memcmp (arg, "freebsd", 7) == 0)
28277c478bd9Sstevel@tonic-gate suggested_type = KERNEL_TYPE_FREEBSD;
28287c478bd9Sstevel@tonic-gate else if (grub_memcmp (arg, "openbsd", 7) == 0)
28297c478bd9Sstevel@tonic-gate /* XXX: For now, OpenBSD is identical to NetBSD, from GRUB's
28307c478bd9Sstevel@tonic-gate point of view. */
28317c478bd9Sstevel@tonic-gate suggested_type = KERNEL_TYPE_NETBSD;
28327c478bd9Sstevel@tonic-gate else if (grub_memcmp (arg, "linux", 5) == 0)
28337c478bd9Sstevel@tonic-gate suggested_type = KERNEL_TYPE_LINUX;
28347c478bd9Sstevel@tonic-gate else if (grub_memcmp (arg, "biglinux", 8) == 0)
28357c478bd9Sstevel@tonic-gate suggested_type = KERNEL_TYPE_BIG_LINUX;
28367c478bd9Sstevel@tonic-gate else if (grub_memcmp (arg, "multiboot", 9) == 0)
28377c478bd9Sstevel@tonic-gate suggested_type = KERNEL_TYPE_MULTIBOOT;
28387c478bd9Sstevel@tonic-gate else
28397c478bd9Sstevel@tonic-gate {
28407c478bd9Sstevel@tonic-gate errnum = ERR_BAD_ARGUMENT;
28417c478bd9Sstevel@tonic-gate return 1;
28427c478bd9Sstevel@tonic-gate }
28437c478bd9Sstevel@tonic-gate }
28447c478bd9Sstevel@tonic-gate /* If the `--no-mem-option' is specified, don't pass a Linux's mem
28457c478bd9Sstevel@tonic-gate option automatically. If the kernel is another type, this flag
28467c478bd9Sstevel@tonic-gate has no effect. */
28477c478bd9Sstevel@tonic-gate else if (grub_memcmp (arg, "--no-mem-option", 15) == 0)
28487c478bd9Sstevel@tonic-gate load_flags |= KERNEL_LOAD_NO_MEM_OPTION;
28497c478bd9Sstevel@tonic-gate else
28507c478bd9Sstevel@tonic-gate break;
28517c478bd9Sstevel@tonic-gate
28527c478bd9Sstevel@tonic-gate /* Try the next. */
28537c478bd9Sstevel@tonic-gate arg = skip_to (0, arg);
28547c478bd9Sstevel@tonic-gate }
28557c478bd9Sstevel@tonic-gate
28567c478bd9Sstevel@tonic-gate len = grub_strlen (arg);
28577c478bd9Sstevel@tonic-gate
28587c478bd9Sstevel@tonic-gate /* Reset MB_CMDLINE. */
28597c478bd9Sstevel@tonic-gate mb_cmdline = (char *) MB_CMDLINE_BUF;
28607c478bd9Sstevel@tonic-gate if (len + 1 > MB_CMDLINE_BUFLEN)
28617c478bd9Sstevel@tonic-gate {
28627c478bd9Sstevel@tonic-gate errnum = ERR_WONT_FIT;
28637c478bd9Sstevel@tonic-gate return 1;
28647c478bd9Sstevel@tonic-gate }
28657c478bd9Sstevel@tonic-gate
28667c478bd9Sstevel@tonic-gate /* Copy the command-line to MB_CMDLINE. */
28677c478bd9Sstevel@tonic-gate grub_memmove (mb_cmdline, arg, len + 1);
28687c478bd9Sstevel@tonic-gate kernel_type = load_image (arg, mb_cmdline, suggested_type, load_flags);
28697c478bd9Sstevel@tonic-gate if (kernel_type == KERNEL_TYPE_NONE)
28707c478bd9Sstevel@tonic-gate return 1;
28717c478bd9Sstevel@tonic-gate
2872b1b8ab34Slling mb_cmdline += grub_strlen(mb_cmdline) + 1;
28737c478bd9Sstevel@tonic-gate return 0;
28747c478bd9Sstevel@tonic-gate }
28757c478bd9Sstevel@tonic-gate
28767c478bd9Sstevel@tonic-gate static struct builtin builtin_kernel =
28777c478bd9Sstevel@tonic-gate {
28787c478bd9Sstevel@tonic-gate "kernel",
28797c478bd9Sstevel@tonic-gate kernel_func,
28807c478bd9Sstevel@tonic-gate BUILTIN_CMDLINE | BUILTIN_HELP_LIST,
28817c478bd9Sstevel@tonic-gate "kernel [--no-mem-option] [--type=TYPE] FILE [ARG ...]",
28827c478bd9Sstevel@tonic-gate "Attempt to load the primary boot image from FILE. The rest of the"
28837c478bd9Sstevel@tonic-gate " line is passed verbatim as the \"kernel command line\". Any modules"
28847c478bd9Sstevel@tonic-gate " must be reloaded after using this command. The option --type is used"
28857c478bd9Sstevel@tonic-gate " to suggest what type of kernel to be loaded. TYPE must be either of"
28867c478bd9Sstevel@tonic-gate " \"netbsd\", \"freebsd\", \"openbsd\", \"linux\", \"biglinux\" and"
28877c478bd9Sstevel@tonic-gate " \"multiboot\". The option --no-mem-option tells GRUB not to pass a"
28887c478bd9Sstevel@tonic-gate " Linux's mem option automatically."
28897c478bd9Sstevel@tonic-gate };
28907c478bd9Sstevel@tonic-gate
2891342440ecSPrasad Singamsetty int
min_mem64_func(char * arg,int flags)2892342440ecSPrasad Singamsetty min_mem64_func(char *arg, int flags)
2893342440ecSPrasad Singamsetty {
2894342440ecSPrasad Singamsetty if (!safe_parse_maxint(&arg, &min_mem64))
2895342440ecSPrasad Singamsetty return (1);
2896342440ecSPrasad Singamsetty }
2897342440ecSPrasad Singamsetty
2898342440ecSPrasad Singamsetty static struct builtin builtin_min_mem64 =
2899342440ecSPrasad Singamsetty {
2900342440ecSPrasad Singamsetty "min_mem64",
2901342440ecSPrasad Singamsetty min_mem64_func,
2902342440ecSPrasad Singamsetty BUILTIN_CMDLINE | BUILTIN_MENU | BUILTIN_SCRIPT | BUILTIN_HELP_LIST,
2903342440ecSPrasad Singamsetty "min_mem64 <memory in MB>",
2904342440ecSPrasad Singamsetty "Sets minimum memory (in MB) required for $ISADIR to expand to amd64, "
2905342440ecSPrasad Singamsetty "even on 64-bit capable hardware."
2906342440ecSPrasad Singamsetty };
2907342440ecSPrasad Singamsetty
2908ae115bc7Smrj static int
kernel_dollar_func(char * arg,int flags)2909ae115bc7Smrj kernel_dollar_func (char *arg, int flags)
2910ae115bc7Smrj {
2911a5602e1bSKeith M Wesolowski int err;
2912a5602e1bSKeith M Wesolowski char newarg[MAX_CMDLINE];
2913b1b8ab34Slling
2914a5602e1bSKeith M Wesolowski /*
2915a5602e1bSKeith M Wesolowski * We're going to expand the arguments twice. The first expansion, which
2916a5602e1bSKeith M Wesolowski * occurs without the benefit of knowing the ZFS object ID of the filesystem
2917a5602e1bSKeith M Wesolowski * we're booting from (if we're booting from ZFS, of course), must be
2918a5602e1bSKeith M Wesolowski * sufficient to find and read the kernel. The second expansion will
2919a5602e1bSKeith M Wesolowski * then overwrite the command line actually set in the multiboot header with
2920a5602e1bSKeith M Wesolowski * the newly-expanded one. Since $ZFS-BOOTFS expands differently after
2921a5602e1bSKeith M Wesolowski * zfs_open() has been called (kernel_func() -> load_image() -> grub_open() ->
2922a5602e1bSKeith M Wesolowski * zfs_open()), we need to do the second expansion so that the kernel is
2923a5602e1bSKeith M Wesolowski * given the right object ID argument. Note that the pointer to the
2924a5602e1bSKeith M Wesolowski * command line set in the multiboot header is always MB_CMDLINE_BUF.
2925a5602e1bSKeith M Wesolowski */
2926b1b8ab34Slling grub_printf("loading '%s' ...\n", arg);
2927a5602e1bSKeith M Wesolowski if ((err = expand_string(arg, newarg, MAX_CMDLINE)) != 0) {
2928a5602e1bSKeith M Wesolowski errnum = err;
2929a5602e1bSKeith M Wesolowski return (1);
2930a5602e1bSKeith M Wesolowski }
2931b1b8ab34Slling
2932a5602e1bSKeith M Wesolowski if ((err = kernel_func(newarg, flags)) != 0)
2933a5602e1bSKeith M Wesolowski return (err);
2934b1b8ab34Slling
2935b1b8ab34Slling mb_cmdline = (char *)MB_CMDLINE_BUF;
2936a5602e1bSKeith M Wesolowski if ((err = expand_string(arg, mb_cmdline, MAX_CMDLINE)) != 0) {
2937a5602e1bSKeith M Wesolowski errnum = err;
2938a5602e1bSKeith M Wesolowski return (1);
2939ffb5616eSLin Ling }
2940b1b8ab34Slling
2941a5602e1bSKeith M Wesolowski grub_printf("loading '%s' ...\n", mb_cmdline);
2942b1b8ab34Slling mb_cmdline += grub_strlen(mb_cmdline) + 1;
2943b1b8ab34Slling return (0);
2944ae115bc7Smrj }
2945ae115bc7Smrj
2946ae115bc7Smrj static struct builtin builtin_kernel_dollar =
2947ae115bc7Smrj {
2948ae115bc7Smrj "kernel$",
2949ae115bc7Smrj kernel_dollar_func,
2950ae115bc7Smrj BUILTIN_CMDLINE | BUILTIN_HELP_LIST,
2951ae115bc7Smrj "kernel$ [--no-mem-option] [--type=TYPE] FILE [ARG ...]",
2952a5602e1bSKeith M Wesolowski " Just like kernel, but with variable expansion, including the legacy"
2953a5602e1bSKeith M Wesolowski " (and nonconforming) variables $ISADIR and $ZFS-BOOTFS."
2954ae115bc7Smrj };
2955ae115bc7Smrj
29567c478bd9Sstevel@tonic-gate
29577c478bd9Sstevel@tonic-gate /* lock */
29587c478bd9Sstevel@tonic-gate static int
lock_func(char * arg,int flags)29597c478bd9Sstevel@tonic-gate lock_func (char *arg, int flags)
29607c478bd9Sstevel@tonic-gate {
29617c478bd9Sstevel@tonic-gate if (! auth && password)
29627c478bd9Sstevel@tonic-gate {
29637c478bd9Sstevel@tonic-gate errnum = ERR_PRIVILEGED;
29647c478bd9Sstevel@tonic-gate return 1;
29657c478bd9Sstevel@tonic-gate }
29667c478bd9Sstevel@tonic-gate
29677c478bd9Sstevel@tonic-gate return 0;
29687c478bd9Sstevel@tonic-gate }
29697c478bd9Sstevel@tonic-gate
29707c478bd9Sstevel@tonic-gate static struct builtin builtin_lock =
29717c478bd9Sstevel@tonic-gate {
29727c478bd9Sstevel@tonic-gate "lock",
29737c478bd9Sstevel@tonic-gate lock_func,
29747c478bd9Sstevel@tonic-gate BUILTIN_CMDLINE,
29757c478bd9Sstevel@tonic-gate "lock",
29767c478bd9Sstevel@tonic-gate "Break a command execution unless the user is authenticated."
29777c478bd9Sstevel@tonic-gate };
29787c478bd9Sstevel@tonic-gate
29797c478bd9Sstevel@tonic-gate
29807c478bd9Sstevel@tonic-gate /* makeactive */
29817c478bd9Sstevel@tonic-gate static int
makeactive_func(char * arg,int flags)29827c478bd9Sstevel@tonic-gate makeactive_func (char *arg, int flags)
29837c478bd9Sstevel@tonic-gate {
29847c478bd9Sstevel@tonic-gate if (! make_saved_active ())
29857c478bd9Sstevel@tonic-gate return 1;
29867c478bd9Sstevel@tonic-gate
29877c478bd9Sstevel@tonic-gate return 0;
29887c478bd9Sstevel@tonic-gate }
29897c478bd9Sstevel@tonic-gate
29907c478bd9Sstevel@tonic-gate static struct builtin builtin_makeactive =
29917c478bd9Sstevel@tonic-gate {
29927c478bd9Sstevel@tonic-gate "makeactive",
29937c478bd9Sstevel@tonic-gate makeactive_func,
29947c478bd9Sstevel@tonic-gate BUILTIN_CMDLINE | BUILTIN_HELP_LIST,
29957c478bd9Sstevel@tonic-gate "makeactive",
29967c478bd9Sstevel@tonic-gate "Set the active partition on the root disk to GRUB's root device."
29977c478bd9Sstevel@tonic-gate " This command is limited to _primary_ PC partitions on a hard disk."
29987c478bd9Sstevel@tonic-gate };
29997c478bd9Sstevel@tonic-gate
30007c478bd9Sstevel@tonic-gate
30017c478bd9Sstevel@tonic-gate /* map */
30027c478bd9Sstevel@tonic-gate /* Map FROM_DRIVE to TO_DRIVE. */
30037c478bd9Sstevel@tonic-gate static int
map_func(char * arg,int flags)30047c478bd9Sstevel@tonic-gate map_func (char *arg, int flags)
30057c478bd9Sstevel@tonic-gate {
30067c478bd9Sstevel@tonic-gate char *to_drive;
30077c478bd9Sstevel@tonic-gate char *from_drive;
30087c478bd9Sstevel@tonic-gate unsigned long to, from;
30097c478bd9Sstevel@tonic-gate int i;
30107c478bd9Sstevel@tonic-gate
30117c478bd9Sstevel@tonic-gate to_drive = arg;
30127c478bd9Sstevel@tonic-gate from_drive = skip_to (0, arg);
30137c478bd9Sstevel@tonic-gate
30147c478bd9Sstevel@tonic-gate /* Get the drive number for TO_DRIVE. */
30157c478bd9Sstevel@tonic-gate set_device (to_drive);
30167c478bd9Sstevel@tonic-gate if (errnum)
30177c478bd9Sstevel@tonic-gate return 1;
30187c478bd9Sstevel@tonic-gate to = current_drive;
30197c478bd9Sstevel@tonic-gate
30207c478bd9Sstevel@tonic-gate /* Get the drive number for FROM_DRIVE. */
30217c478bd9Sstevel@tonic-gate set_device (from_drive);
30227c478bd9Sstevel@tonic-gate if (errnum)
30237c478bd9Sstevel@tonic-gate return 1;
30247c478bd9Sstevel@tonic-gate from = current_drive;
30257c478bd9Sstevel@tonic-gate
30267c478bd9Sstevel@tonic-gate /* Search for an empty slot in BIOS_DRIVE_MAP. */
30277c478bd9Sstevel@tonic-gate for (i = 0; i < DRIVE_MAP_SIZE; i++)
30287c478bd9Sstevel@tonic-gate {
30297c478bd9Sstevel@tonic-gate /* Perhaps the user wants to override the map. */
30307c478bd9Sstevel@tonic-gate if ((bios_drive_map[i] & 0xff) == from)
30317c478bd9Sstevel@tonic-gate break;
30327c478bd9Sstevel@tonic-gate
30337c478bd9Sstevel@tonic-gate if (! bios_drive_map[i])
30347c478bd9Sstevel@tonic-gate break;
30357c478bd9Sstevel@tonic-gate }
30367c478bd9Sstevel@tonic-gate
30377c478bd9Sstevel@tonic-gate if (i == DRIVE_MAP_SIZE)
30387c478bd9Sstevel@tonic-gate {
30397c478bd9Sstevel@tonic-gate errnum = ERR_WONT_FIT;
30407c478bd9Sstevel@tonic-gate return 1;
30417c478bd9Sstevel@tonic-gate }
30427c478bd9Sstevel@tonic-gate
30437c478bd9Sstevel@tonic-gate if (to == from)
30447c478bd9Sstevel@tonic-gate /* If TO is equal to FROM, delete the entry. */
30457c478bd9Sstevel@tonic-gate grub_memmove ((char *) &bios_drive_map[i], (char *) &bios_drive_map[i + 1],
30467c478bd9Sstevel@tonic-gate sizeof (unsigned short) * (DRIVE_MAP_SIZE - i));
30477c478bd9Sstevel@tonic-gate else
30487c478bd9Sstevel@tonic-gate bios_drive_map[i] = from | (to << 8);
30497c478bd9Sstevel@tonic-gate
30507c478bd9Sstevel@tonic-gate return 0;
30517c478bd9Sstevel@tonic-gate }
30527c478bd9Sstevel@tonic-gate
30537c478bd9Sstevel@tonic-gate static struct builtin builtin_map =
30547c478bd9Sstevel@tonic-gate {
30557c478bd9Sstevel@tonic-gate "map",
30567c478bd9Sstevel@tonic-gate map_func,
30577c478bd9Sstevel@tonic-gate BUILTIN_CMDLINE | BUILTIN_HELP_LIST,
30587c478bd9Sstevel@tonic-gate "map TO_DRIVE FROM_DRIVE",
30597c478bd9Sstevel@tonic-gate "Map the drive FROM_DRIVE to the drive TO_DRIVE. This is necessary"
30607c478bd9Sstevel@tonic-gate " when you chain-load some operating systems, such as DOS, if such an"
30617c478bd9Sstevel@tonic-gate " OS resides at a non-first drive."
30627c478bd9Sstevel@tonic-gate };
30637c478bd9Sstevel@tonic-gate
30647c478bd9Sstevel@tonic-gate
30657c478bd9Sstevel@tonic-gate #ifdef USE_MD5_PASSWORDS
30667c478bd9Sstevel@tonic-gate /* md5crypt */
30677c478bd9Sstevel@tonic-gate static int
md5crypt_func(char * arg,int flags)30687c478bd9Sstevel@tonic-gate md5crypt_func (char *arg, int flags)
30697c478bd9Sstevel@tonic-gate {
30707c478bd9Sstevel@tonic-gate char crypted[36];
30717c478bd9Sstevel@tonic-gate char key[32];
30727c478bd9Sstevel@tonic-gate unsigned int seed;
30737c478bd9Sstevel@tonic-gate int i;
30747c478bd9Sstevel@tonic-gate const char *const seedchars =
30757c478bd9Sstevel@tonic-gate "./0123456789ABCDEFGHIJKLMNOPQRST"
30767c478bd9Sstevel@tonic-gate "UVWXYZabcdefghijklmnopqrstuvwxyz";
30777c478bd9Sstevel@tonic-gate
30787c478bd9Sstevel@tonic-gate /* First create a salt. */
30797c478bd9Sstevel@tonic-gate
30807c478bd9Sstevel@tonic-gate /* The magical prefix. */
30817c478bd9Sstevel@tonic-gate grub_memset (crypted, 0, sizeof (crypted));
30827c478bd9Sstevel@tonic-gate grub_memmove (crypted, "$1$", 3);
30837c478bd9Sstevel@tonic-gate
30847c478bd9Sstevel@tonic-gate /* Create the length of a salt. */
30857c478bd9Sstevel@tonic-gate seed = currticks ();
30867c478bd9Sstevel@tonic-gate
30877c478bd9Sstevel@tonic-gate /* Generate a salt. */
30887c478bd9Sstevel@tonic-gate for (i = 0; i < 8 && seed; i++)
30897c478bd9Sstevel@tonic-gate {
30907c478bd9Sstevel@tonic-gate /* FIXME: This should be more random. */
30917c478bd9Sstevel@tonic-gate crypted[3 + i] = seedchars[seed & 0x3f];
30927c478bd9Sstevel@tonic-gate seed >>= 6;
30937c478bd9Sstevel@tonic-gate }
30947c478bd9Sstevel@tonic-gate
30957c478bd9Sstevel@tonic-gate /* A salt must be terminated with `$', if it is less than 8 chars. */
30967c478bd9Sstevel@tonic-gate crypted[3 + i] = '$';
30977c478bd9Sstevel@tonic-gate
30987c478bd9Sstevel@tonic-gate #ifdef DEBUG_MD5CRYPT
30997c478bd9Sstevel@tonic-gate grub_printf ("salt = %s\n", crypted);
31007c478bd9Sstevel@tonic-gate #endif
31017c478bd9Sstevel@tonic-gate
31027c478bd9Sstevel@tonic-gate /* Get a password. */
31037c478bd9Sstevel@tonic-gate grub_memset (key, 0, sizeof (key));
31047c478bd9Sstevel@tonic-gate get_cmdline ("Password: ", key, sizeof (key) - 1, '*', 0);
31057c478bd9Sstevel@tonic-gate
31067c478bd9Sstevel@tonic-gate /* Crypt the key. */
31077c478bd9Sstevel@tonic-gate make_md5_password (key, crypted);
31087c478bd9Sstevel@tonic-gate
31097c478bd9Sstevel@tonic-gate grub_printf ("Encrypted: %s\n", crypted);
31107c478bd9Sstevel@tonic-gate return 0;
31117c478bd9Sstevel@tonic-gate }
31127c478bd9Sstevel@tonic-gate
31137c478bd9Sstevel@tonic-gate static struct builtin builtin_md5crypt =
31147c478bd9Sstevel@tonic-gate {
31157c478bd9Sstevel@tonic-gate "md5crypt",
31167c478bd9Sstevel@tonic-gate md5crypt_func,
31177c478bd9Sstevel@tonic-gate BUILTIN_CMDLINE | BUILTIN_HELP_LIST,
31187c478bd9Sstevel@tonic-gate "md5crypt",
31197c478bd9Sstevel@tonic-gate "Generate a password in MD5 format."
31207c478bd9Sstevel@tonic-gate };
31217c478bd9Sstevel@tonic-gate #endif /* USE_MD5_PASSWORDS */
31227c478bd9Sstevel@tonic-gate
31237c478bd9Sstevel@tonic-gate
31247c478bd9Sstevel@tonic-gate /* module */
31257c478bd9Sstevel@tonic-gate static int
module_func(char * arg,int flags)31267c478bd9Sstevel@tonic-gate module_func (char *arg, int flags)
31277c478bd9Sstevel@tonic-gate {
31287c478bd9Sstevel@tonic-gate int len = grub_strlen (arg);
31297c478bd9Sstevel@tonic-gate
31307c478bd9Sstevel@tonic-gate switch (kernel_type)
31317c478bd9Sstevel@tonic-gate {
31327c478bd9Sstevel@tonic-gate case KERNEL_TYPE_MULTIBOOT:
31337c478bd9Sstevel@tonic-gate if (mb_cmdline + len + 1 > (char *) MB_CMDLINE_BUF + MB_CMDLINE_BUFLEN)
31347c478bd9Sstevel@tonic-gate {
31357c478bd9Sstevel@tonic-gate errnum = ERR_WONT_FIT;
31367c478bd9Sstevel@tonic-gate return 1;
31377c478bd9Sstevel@tonic-gate }
31387c478bd9Sstevel@tonic-gate grub_memmove (mb_cmdline, arg, len + 1);
31397c478bd9Sstevel@tonic-gate if (! load_module (arg, mb_cmdline))
31407c478bd9Sstevel@tonic-gate return 1;
3141b1b8ab34Slling
3142b1b8ab34Slling mb_cmdline += grub_strlen(mb_cmdline) + 1;
31437c478bd9Sstevel@tonic-gate break;
31447c478bd9Sstevel@tonic-gate
31457c478bd9Sstevel@tonic-gate case KERNEL_TYPE_LINUX:
31467c478bd9Sstevel@tonic-gate case KERNEL_TYPE_BIG_LINUX:
31477c478bd9Sstevel@tonic-gate if (! load_initrd (arg))
31487c478bd9Sstevel@tonic-gate return 1;
31497c478bd9Sstevel@tonic-gate break;
31507c478bd9Sstevel@tonic-gate
31517c478bd9Sstevel@tonic-gate default:
31527c478bd9Sstevel@tonic-gate errnum = ERR_NEED_MB_KERNEL;
31537c478bd9Sstevel@tonic-gate return 1;
31547c478bd9Sstevel@tonic-gate }
31557c478bd9Sstevel@tonic-gate
31567c478bd9Sstevel@tonic-gate return 0;
31577c478bd9Sstevel@tonic-gate }
31587c478bd9Sstevel@tonic-gate
31597c478bd9Sstevel@tonic-gate static struct builtin builtin_module =
31607c478bd9Sstevel@tonic-gate {
31617c478bd9Sstevel@tonic-gate "module",
31627c478bd9Sstevel@tonic-gate module_func,
31637c478bd9Sstevel@tonic-gate BUILTIN_CMDLINE | BUILTIN_HELP_LIST,
31647c478bd9Sstevel@tonic-gate "module FILE [ARG ...]",
31657c478bd9Sstevel@tonic-gate "Load a boot module FILE for a Multiboot format boot image (no"
31667c478bd9Sstevel@tonic-gate " interpretation of the file contents is made, so users of this"
31677c478bd9Sstevel@tonic-gate " command must know what the kernel in question expects). The"
31687c478bd9Sstevel@tonic-gate " rest of the line is passed as the \"module command line\", like"
31697c478bd9Sstevel@tonic-gate " the `kernel' command."
31707c478bd9Sstevel@tonic-gate };
31717c478bd9Sstevel@tonic-gate
3172ae115bc7Smrj /* module$ */
3173ae115bc7Smrj static int
module_dollar_func(char * arg,int flags)3174ae115bc7Smrj module_dollar_func (char *arg, int flags)
3175ae115bc7Smrj {
3176a5602e1bSKeith M Wesolowski char newarg[MAX_CMDLINE];
3177a5602e1bSKeith M Wesolowski char *cmdline_sav = mb_cmdline;
3178a5602e1bSKeith M Wesolowski int err;
3179b1b8ab34Slling
3180b1b8ab34Slling grub_printf("loading '%s' ...\n", arg);
3181a5602e1bSKeith M Wesolowski if ((err = expand_string(arg, newarg, MAX_CMDLINE)) != 0) {
3182a5602e1bSKeith M Wesolowski errnum = err;
3183a5602e1bSKeith M Wesolowski return (1);
3184a5602e1bSKeith M Wesolowski }
3185b1b8ab34Slling
3186a5602e1bSKeith M Wesolowski if ((err = module_func(newarg, flags)) != 0)
3187a5602e1bSKeith M Wesolowski return (err);
3188b1b8ab34Slling
3189a5602e1bSKeith M Wesolowski if ((err = expand_string(arg, cmdline_sav, MAX_CMDLINE)) != 0) {
3190a5602e1bSKeith M Wesolowski errnum = err;
3191a5602e1bSKeith M Wesolowski return (1);
3192ffb5616eSLin Ling }
3193b1b8ab34Slling
3194a5602e1bSKeith M Wesolowski grub_printf("loading '%s' ...\n", cmdline_sav);
3195b1b8ab34Slling mb_cmdline += grub_strlen(cmdline_sav) + 1;
3196b1b8ab34Slling return (0);
3197ae115bc7Smrj }
3198ae115bc7Smrj
3199ae115bc7Smrj static struct builtin builtin_module_dollar =
3200ae115bc7Smrj {
3201ae115bc7Smrj "module$",
3202ae115bc7Smrj module_dollar_func,
3203ae115bc7Smrj BUILTIN_CMDLINE | BUILTIN_HELP_LIST,
3204ae115bc7Smrj "module FILE [ARG ...]",
3205ae115bc7Smrj " Just like module, but with $ISADIR expansion."
3206ae115bc7Smrj };
3207ae115bc7Smrj
32087c478bd9Sstevel@tonic-gate
32097c478bd9Sstevel@tonic-gate /* modulenounzip */
32107c478bd9Sstevel@tonic-gate static int
modulenounzip_func(char * arg,int flags)32117c478bd9Sstevel@tonic-gate modulenounzip_func (char *arg, int flags)
32127c478bd9Sstevel@tonic-gate {
32137c478bd9Sstevel@tonic-gate int ret;
32147c478bd9Sstevel@tonic-gate
32157c478bd9Sstevel@tonic-gate #ifndef NO_DECOMPRESSION
32167c478bd9Sstevel@tonic-gate no_decompression = 1;
32177c478bd9Sstevel@tonic-gate #endif
32187c478bd9Sstevel@tonic-gate
32197c478bd9Sstevel@tonic-gate ret = module_func (arg, flags);
32207c478bd9Sstevel@tonic-gate
32217c478bd9Sstevel@tonic-gate #ifndef NO_DECOMPRESSION
32227c478bd9Sstevel@tonic-gate no_decompression = 0;
32237c478bd9Sstevel@tonic-gate #endif
32247c478bd9Sstevel@tonic-gate
32257c478bd9Sstevel@tonic-gate return ret;
32267c478bd9Sstevel@tonic-gate }
32277c478bd9Sstevel@tonic-gate
32287c478bd9Sstevel@tonic-gate static struct builtin builtin_modulenounzip =
32297c478bd9Sstevel@tonic-gate {
32307c478bd9Sstevel@tonic-gate "modulenounzip",
32317c478bd9Sstevel@tonic-gate modulenounzip_func,
32327c478bd9Sstevel@tonic-gate BUILTIN_CMDLINE | BUILTIN_HELP_LIST,
32337c478bd9Sstevel@tonic-gate "modulenounzip FILE [ARG ...]",
32347c478bd9Sstevel@tonic-gate "The same as `module', except that automatic decompression is"
32357c478bd9Sstevel@tonic-gate " disabled."
32367c478bd9Sstevel@tonic-gate };
32377c478bd9Sstevel@tonic-gate
32387c478bd9Sstevel@tonic-gate
32397c478bd9Sstevel@tonic-gate /* pager [on|off] */
32407c478bd9Sstevel@tonic-gate static int
pager_func(char * arg,int flags)32417c478bd9Sstevel@tonic-gate pager_func (char *arg, int flags)
32427c478bd9Sstevel@tonic-gate {
32437c478bd9Sstevel@tonic-gate /* If ARG is empty, toggle the flag. */
32447c478bd9Sstevel@tonic-gate if (! *arg)
32457c478bd9Sstevel@tonic-gate use_pager = ! use_pager;
32467c478bd9Sstevel@tonic-gate else if (grub_memcmp (arg, "on", 2) == 0)
32477c478bd9Sstevel@tonic-gate use_pager = 1;
32487c478bd9Sstevel@tonic-gate else if (grub_memcmp (arg, "off", 3) == 0)
32497c478bd9Sstevel@tonic-gate use_pager = 0;
32507c478bd9Sstevel@tonic-gate else
32517c478bd9Sstevel@tonic-gate {
32527c478bd9Sstevel@tonic-gate errnum = ERR_BAD_ARGUMENT;
32537c478bd9Sstevel@tonic-gate return 1;
32547c478bd9Sstevel@tonic-gate }
32557c478bd9Sstevel@tonic-gate
32567c478bd9Sstevel@tonic-gate grub_printf (" Internal pager is now %s\n", use_pager ? "on" : "off");
32577c478bd9Sstevel@tonic-gate return 0;
32587c478bd9Sstevel@tonic-gate }
32597c478bd9Sstevel@tonic-gate
32607c478bd9Sstevel@tonic-gate static struct builtin builtin_pager =
32617c478bd9Sstevel@tonic-gate {
32627c478bd9Sstevel@tonic-gate "pager",
32637c478bd9Sstevel@tonic-gate pager_func,
32647c478bd9Sstevel@tonic-gate BUILTIN_CMDLINE | BUILTIN_MENU | BUILTIN_HELP_LIST,
32657c478bd9Sstevel@tonic-gate "pager [FLAG]",
32667c478bd9Sstevel@tonic-gate "Toggle pager mode with no argument. If FLAG is given and its value"
32677c478bd9Sstevel@tonic-gate " is `on', turn on the mode. If FLAG is `off', turn off the mode."
32687c478bd9Sstevel@tonic-gate };
32697c478bd9Sstevel@tonic-gate
32707c478bd9Sstevel@tonic-gate
32717c478bd9Sstevel@tonic-gate /* partnew PART TYPE START LEN */
32727c478bd9Sstevel@tonic-gate static int
partnew_func(char * arg,int flags)32737c478bd9Sstevel@tonic-gate partnew_func (char *arg, int flags)
32747c478bd9Sstevel@tonic-gate {
32757c478bd9Sstevel@tonic-gate int new_type, new_start, new_len;
32767c478bd9Sstevel@tonic-gate int start_cl, start_ch, start_dh;
32777c478bd9Sstevel@tonic-gate int end_cl, end_ch, end_dh;
32787c478bd9Sstevel@tonic-gate int entry;
32797c478bd9Sstevel@tonic-gate char mbr[512];
32807c478bd9Sstevel@tonic-gate
32817c478bd9Sstevel@tonic-gate /* Convert a LBA address to a CHS address in the INT 13 format. */
32827c478bd9Sstevel@tonic-gate auto void lba_to_chs (int lba, int *cl, int *ch, int *dh);
32837c478bd9Sstevel@tonic-gate void lba_to_chs (int lba, int *cl, int *ch, int *dh)
32847c478bd9Sstevel@tonic-gate {
32857c478bd9Sstevel@tonic-gate int cylinder, head, sector;
32867c478bd9Sstevel@tonic-gate
32877c478bd9Sstevel@tonic-gate sector = lba % buf_geom.sectors + 1;
32887c478bd9Sstevel@tonic-gate head = (lba / buf_geom.sectors) % buf_geom.heads;
32897c478bd9Sstevel@tonic-gate cylinder = lba / (buf_geom.sectors * buf_geom.heads);
32907c478bd9Sstevel@tonic-gate
32917c478bd9Sstevel@tonic-gate if (cylinder >= buf_geom.cylinders)
32927c478bd9Sstevel@tonic-gate cylinder = buf_geom.cylinders - 1;
32937c478bd9Sstevel@tonic-gate
32947c478bd9Sstevel@tonic-gate *cl = sector | ((cylinder & 0x300) >> 2);
32957c478bd9Sstevel@tonic-gate *ch = cylinder & 0xFF;
32967c478bd9Sstevel@tonic-gate *dh = head;
32977c478bd9Sstevel@tonic-gate }
32987c478bd9Sstevel@tonic-gate
32997c478bd9Sstevel@tonic-gate /* Get the drive and the partition. */
33007c478bd9Sstevel@tonic-gate if (! set_device (arg))
33017c478bd9Sstevel@tonic-gate return 1;
33027c478bd9Sstevel@tonic-gate
33037c478bd9Sstevel@tonic-gate /* The drive must be a hard disk. */
33047c478bd9Sstevel@tonic-gate if (! (current_drive & 0x80))
33057c478bd9Sstevel@tonic-gate {
33067c478bd9Sstevel@tonic-gate errnum = ERR_BAD_ARGUMENT;
33077c478bd9Sstevel@tonic-gate return 1;
33087c478bd9Sstevel@tonic-gate }
33097c478bd9Sstevel@tonic-gate
33107c478bd9Sstevel@tonic-gate /* The partition must a primary partition. */
33117c478bd9Sstevel@tonic-gate if ((current_partition >> 16) > 3
33127c478bd9Sstevel@tonic-gate || (current_partition & 0xFFFF) != 0xFFFF)
33137c478bd9Sstevel@tonic-gate {
33147c478bd9Sstevel@tonic-gate errnum = ERR_BAD_ARGUMENT;
33157c478bd9Sstevel@tonic-gate return 1;
33167c478bd9Sstevel@tonic-gate }
33177c478bd9Sstevel@tonic-gate
33187c478bd9Sstevel@tonic-gate entry = current_partition >> 16;
33197c478bd9Sstevel@tonic-gate
33207c478bd9Sstevel@tonic-gate /* Get the new partition type. */
33217c478bd9Sstevel@tonic-gate arg = skip_to (0, arg);
33227c478bd9Sstevel@tonic-gate if (! safe_parse_maxint (&arg, &new_type))
33237c478bd9Sstevel@tonic-gate return 1;
33247c478bd9Sstevel@tonic-gate
33257c478bd9Sstevel@tonic-gate /* The partition type is unsigned char. */
33267c478bd9Sstevel@tonic-gate if (new_type > 0xFF)
33277c478bd9Sstevel@tonic-gate {
33287c478bd9Sstevel@tonic-gate errnum = ERR_BAD_ARGUMENT;
33297c478bd9Sstevel@tonic-gate return 1;
33307c478bd9Sstevel@tonic-gate }
33317c478bd9Sstevel@tonic-gate
33327c478bd9Sstevel@tonic-gate /* Get the new partition start. */
33337c478bd9Sstevel@tonic-gate arg = skip_to (0, arg);
33347c478bd9Sstevel@tonic-gate if (! safe_parse_maxint (&arg, &new_start))
33357c478bd9Sstevel@tonic-gate return 1;
33367c478bd9Sstevel@tonic-gate
33377c478bd9Sstevel@tonic-gate /* Get the new partition length. */
33387c478bd9Sstevel@tonic-gate arg = skip_to (0, arg);
33397c478bd9Sstevel@tonic-gate if (! safe_parse_maxint (&arg, &new_len))
33407c478bd9Sstevel@tonic-gate return 1;
33417c478bd9Sstevel@tonic-gate
33427c478bd9Sstevel@tonic-gate /* Read the MBR. */
33437c478bd9Sstevel@tonic-gate if (! rawread (current_drive, 0, 0, SECTOR_SIZE, mbr))
33447c478bd9Sstevel@tonic-gate return 1;
33457c478bd9Sstevel@tonic-gate
33467c478bd9Sstevel@tonic-gate /* Store the partition information in the MBR. */
33477c478bd9Sstevel@tonic-gate lba_to_chs (new_start, &start_cl, &start_ch, &start_dh);
33487c478bd9Sstevel@tonic-gate lba_to_chs (new_start + new_len - 1, &end_cl, &end_ch, &end_dh);
33497c478bd9Sstevel@tonic-gate
33507c478bd9Sstevel@tonic-gate PC_SLICE_FLAG (mbr, entry) = 0;
33517c478bd9Sstevel@tonic-gate PC_SLICE_HEAD (mbr, entry) = start_dh;
33527c478bd9Sstevel@tonic-gate PC_SLICE_SEC (mbr, entry) = start_cl;
33537c478bd9Sstevel@tonic-gate PC_SLICE_CYL (mbr, entry) = start_ch;
33547c478bd9Sstevel@tonic-gate PC_SLICE_TYPE (mbr, entry) = new_type;
33557c478bd9Sstevel@tonic-gate PC_SLICE_EHEAD (mbr, entry) = end_dh;
33567c478bd9Sstevel@tonic-gate PC_SLICE_ESEC (mbr, entry) = end_cl;
33577c478bd9Sstevel@tonic-gate PC_SLICE_ECYL (mbr, entry) = end_ch;
33587c478bd9Sstevel@tonic-gate PC_SLICE_START (mbr, entry) = new_start;
33597c478bd9Sstevel@tonic-gate PC_SLICE_LENGTH (mbr, entry) = new_len;
33607c478bd9Sstevel@tonic-gate
33617c478bd9Sstevel@tonic-gate /* Make sure that the MBR has a valid signature. */
33627c478bd9Sstevel@tonic-gate PC_MBR_SIG (mbr) = PC_MBR_SIGNATURE;
33637c478bd9Sstevel@tonic-gate
33647c478bd9Sstevel@tonic-gate /* Write back the MBR to the disk. */
3365342440ecSPrasad Singamsetty buf_track = BUF_CACHE_INVALID;
33667c478bd9Sstevel@tonic-gate if (! rawwrite (current_drive, 0, mbr))
33677c478bd9Sstevel@tonic-gate return 1;
33687c478bd9Sstevel@tonic-gate
33697c478bd9Sstevel@tonic-gate return 0;
33707c478bd9Sstevel@tonic-gate }
33717c478bd9Sstevel@tonic-gate
33727c478bd9Sstevel@tonic-gate static struct builtin builtin_partnew =
33737c478bd9Sstevel@tonic-gate {
33747c478bd9Sstevel@tonic-gate "partnew",
33757c478bd9Sstevel@tonic-gate partnew_func,
33767c478bd9Sstevel@tonic-gate BUILTIN_CMDLINE | BUILTIN_MENU | BUILTIN_HELP_LIST,
33777c478bd9Sstevel@tonic-gate "partnew PART TYPE START LEN",
33787c478bd9Sstevel@tonic-gate "Create a primary partition at the starting address START with the"
33797c478bd9Sstevel@tonic-gate " length LEN, with the type TYPE. START and LEN are in sector units."
33807c478bd9Sstevel@tonic-gate };
33817c478bd9Sstevel@tonic-gate
33827c478bd9Sstevel@tonic-gate
33837c478bd9Sstevel@tonic-gate /* parttype PART TYPE */
33847c478bd9Sstevel@tonic-gate static int
parttype_func(char * arg,int flags)33857c478bd9Sstevel@tonic-gate parttype_func (char *arg, int flags)
33867c478bd9Sstevel@tonic-gate {
33877c478bd9Sstevel@tonic-gate int new_type;
33887c478bd9Sstevel@tonic-gate unsigned long part = 0xFFFFFF;
33899890706eSHans Rosenfeld unsigned long long start, len, offset, ext_offset, gpt_offset;
339044bc9120SRichard Yao int entry, type, gpt_count, gpt_size;
33917c478bd9Sstevel@tonic-gate char mbr[512];
33927c478bd9Sstevel@tonic-gate
33937c478bd9Sstevel@tonic-gate /* Get the drive and the partition. */
33947c478bd9Sstevel@tonic-gate if (! set_device (arg))
33957c478bd9Sstevel@tonic-gate return 1;
33967c478bd9Sstevel@tonic-gate
33977c478bd9Sstevel@tonic-gate /* The drive must be a hard disk. */
33987c478bd9Sstevel@tonic-gate if (! (current_drive & 0x80))
33997c478bd9Sstevel@tonic-gate {
34007c478bd9Sstevel@tonic-gate errnum = ERR_BAD_ARGUMENT;
34017c478bd9Sstevel@tonic-gate return 1;
34027c478bd9Sstevel@tonic-gate }
34037c478bd9Sstevel@tonic-gate
34047c478bd9Sstevel@tonic-gate /* The partition must be a PC slice. */
34057c478bd9Sstevel@tonic-gate if ((current_partition >> 16) == 0xFF
34067c478bd9Sstevel@tonic-gate || (current_partition & 0xFFFF) != 0xFFFF)
34077c478bd9Sstevel@tonic-gate {
34087c478bd9Sstevel@tonic-gate errnum = ERR_BAD_ARGUMENT;
34097c478bd9Sstevel@tonic-gate return 1;
34107c478bd9Sstevel@tonic-gate }
34117c478bd9Sstevel@tonic-gate
34127c478bd9Sstevel@tonic-gate /* Get the new partition type. */
34137c478bd9Sstevel@tonic-gate arg = skip_to (0, arg);
34147c478bd9Sstevel@tonic-gate if (! safe_parse_maxint (&arg, &new_type))
34157c478bd9Sstevel@tonic-gate return 1;
34167c478bd9Sstevel@tonic-gate
34177c478bd9Sstevel@tonic-gate /* The partition type is unsigned char. */
34187c478bd9Sstevel@tonic-gate if (new_type > 0xFF)
34197c478bd9Sstevel@tonic-gate {
34207c478bd9Sstevel@tonic-gate errnum = ERR_BAD_ARGUMENT;
34217c478bd9Sstevel@tonic-gate return 1;
34227c478bd9Sstevel@tonic-gate }
34237c478bd9Sstevel@tonic-gate
34247c478bd9Sstevel@tonic-gate /* Look for the partition. */
34257c478bd9Sstevel@tonic-gate while (next_partition (current_drive, 0xFFFFFF, &part, &type,
34267c478bd9Sstevel@tonic-gate &start, &len, &offset, &entry,
342744bc9120SRichard Yao &ext_offset, &gpt_offset, &gpt_count, &gpt_size, mbr))
34287c478bd9Sstevel@tonic-gate {
342944bc9120SRichard Yao /* The partition may not be a GPT partition. */
343044bc9120SRichard Yao if (gpt_offset != 0)
343144bc9120SRichard Yao {
343244bc9120SRichard Yao errnum = ERR_BAD_ARGUMENT;
343344bc9120SRichard Yao return 1;
343444bc9120SRichard Yao }
343544bc9120SRichard Yao
34367c478bd9Sstevel@tonic-gate if (part == current_partition)
34377c478bd9Sstevel@tonic-gate {
34387c478bd9Sstevel@tonic-gate /* Found. */
34397c478bd9Sstevel@tonic-gate
34407c478bd9Sstevel@tonic-gate /* Set the type to NEW_TYPE. */
34417c478bd9Sstevel@tonic-gate PC_SLICE_TYPE (mbr, entry) = new_type;
34427c478bd9Sstevel@tonic-gate
34437c478bd9Sstevel@tonic-gate /* Write back the MBR to the disk. */
3444342440ecSPrasad Singamsetty buf_track = BUF_CACHE_INVALID;
34457c478bd9Sstevel@tonic-gate if (! rawwrite (current_drive, offset, mbr))
34467c478bd9Sstevel@tonic-gate return 1;
34477c478bd9Sstevel@tonic-gate
34487c478bd9Sstevel@tonic-gate /* Succeed. */
34497c478bd9Sstevel@tonic-gate return 0;
34507c478bd9Sstevel@tonic-gate }
34517c478bd9Sstevel@tonic-gate }
34527c478bd9Sstevel@tonic-gate
34537c478bd9Sstevel@tonic-gate /* The partition was not found. ERRNUM was set by next_partition. */
34547c478bd9Sstevel@tonic-gate return 1;
34557c478bd9Sstevel@tonic-gate }
34567c478bd9Sstevel@tonic-gate
34577c478bd9Sstevel@tonic-gate static struct builtin builtin_parttype =
34587c478bd9Sstevel@tonic-gate {
34597c478bd9Sstevel@tonic-gate "parttype",
34607c478bd9Sstevel@tonic-gate parttype_func,
34617c478bd9Sstevel@tonic-gate BUILTIN_CMDLINE | BUILTIN_MENU | BUILTIN_HELP_LIST,
34627c478bd9Sstevel@tonic-gate "parttype PART TYPE",
34637c478bd9Sstevel@tonic-gate "Change the type of the partition PART to TYPE."
34647c478bd9Sstevel@tonic-gate };
34657c478bd9Sstevel@tonic-gate
34667c478bd9Sstevel@tonic-gate
34677c478bd9Sstevel@tonic-gate /* password */
34687c478bd9Sstevel@tonic-gate static int
password_func(char * arg,int flags)34697c478bd9Sstevel@tonic-gate password_func (char *arg, int flags)
34707c478bd9Sstevel@tonic-gate {
34717c478bd9Sstevel@tonic-gate int len;
34727c478bd9Sstevel@tonic-gate password_t type = PASSWORD_PLAIN;
34737c478bd9Sstevel@tonic-gate
34747c478bd9Sstevel@tonic-gate #ifdef USE_MD5_PASSWORDS
34757c478bd9Sstevel@tonic-gate if (grub_memcmp (arg, "--md5", 5) == 0)
34767c478bd9Sstevel@tonic-gate {
34777c478bd9Sstevel@tonic-gate type = PASSWORD_MD5;
34787c478bd9Sstevel@tonic-gate arg = skip_to (0, arg);
34797c478bd9Sstevel@tonic-gate }
34807c478bd9Sstevel@tonic-gate #endif
34817c478bd9Sstevel@tonic-gate if (grub_memcmp (arg, "--", 2) == 0)
34827c478bd9Sstevel@tonic-gate {
34837c478bd9Sstevel@tonic-gate type = PASSWORD_UNSUPPORTED;
34847c478bd9Sstevel@tonic-gate arg = skip_to (0, arg);
34857c478bd9Sstevel@tonic-gate }
34867c478bd9Sstevel@tonic-gate
34877c478bd9Sstevel@tonic-gate if ((flags & (BUILTIN_CMDLINE | BUILTIN_SCRIPT)) != 0)
34887c478bd9Sstevel@tonic-gate {
34897c478bd9Sstevel@tonic-gate /* Do password check! */
34907c478bd9Sstevel@tonic-gate char entered[32];
34917c478bd9Sstevel@tonic-gate
34927c478bd9Sstevel@tonic-gate /* Wipe out any previously entered password */
34937c478bd9Sstevel@tonic-gate entered[0] = 0;
34947c478bd9Sstevel@tonic-gate get_cmdline ("Password: ", entered, 31, '*', 0);
34957c478bd9Sstevel@tonic-gate
34967c478bd9Sstevel@tonic-gate nul_terminate (arg);
34977c478bd9Sstevel@tonic-gate if (check_password (entered, arg, type) != 0)
34987c478bd9Sstevel@tonic-gate {
34997c478bd9Sstevel@tonic-gate errnum = ERR_PRIVILEGED;
35007c478bd9Sstevel@tonic-gate return 1;
35017c478bd9Sstevel@tonic-gate }
35027c478bd9Sstevel@tonic-gate }
35037c478bd9Sstevel@tonic-gate else
35047c478bd9Sstevel@tonic-gate {
35057c478bd9Sstevel@tonic-gate len = grub_strlen (arg);
35067c478bd9Sstevel@tonic-gate
35077c478bd9Sstevel@tonic-gate /* PASSWORD NUL NUL ... */
35087c478bd9Sstevel@tonic-gate if (len + 2 > PASSWORD_BUFLEN)
35097c478bd9Sstevel@tonic-gate {
35107c478bd9Sstevel@tonic-gate errnum = ERR_WONT_FIT;
35117c478bd9Sstevel@tonic-gate return 1;
35127c478bd9Sstevel@tonic-gate }
35137c478bd9Sstevel@tonic-gate
35147c478bd9Sstevel@tonic-gate /* Copy the password and clear the rest of the buffer. */
35157c478bd9Sstevel@tonic-gate password = (char *) PASSWORD_BUF;
35167c478bd9Sstevel@tonic-gate grub_memmove (password, arg, len);
35177c478bd9Sstevel@tonic-gate grub_memset (password + len, 0, PASSWORD_BUFLEN - len);
35187c478bd9Sstevel@tonic-gate password_type = type;
35197c478bd9Sstevel@tonic-gate }
35207c478bd9Sstevel@tonic-gate return 0;
35217c478bd9Sstevel@tonic-gate }
35227c478bd9Sstevel@tonic-gate
35237c478bd9Sstevel@tonic-gate static struct builtin builtin_password =
35247c478bd9Sstevel@tonic-gate {
35257c478bd9Sstevel@tonic-gate "password",
35267c478bd9Sstevel@tonic-gate password_func,
35277c478bd9Sstevel@tonic-gate BUILTIN_MENU | BUILTIN_CMDLINE | BUILTIN_NO_ECHO,
35287c478bd9Sstevel@tonic-gate "password [--md5] PASSWD [FILE]",
35297c478bd9Sstevel@tonic-gate "If used in the first section of a menu file, disable all"
35307c478bd9Sstevel@tonic-gate " interactive editing control (menu entry editor and"
35317c478bd9Sstevel@tonic-gate " command line). If the password PASSWD is entered, it loads the"
35327c478bd9Sstevel@tonic-gate " FILE as a new config file and restarts the GRUB Stage 2. If you"
35337c478bd9Sstevel@tonic-gate " omit the argument FILE, then GRUB just unlocks privileged"
35347c478bd9Sstevel@tonic-gate " instructions. You can also use it in the script section, in"
35357c478bd9Sstevel@tonic-gate " which case it will ask for the password, before continueing."
35367c478bd9Sstevel@tonic-gate " The option --md5 tells GRUB that PASSWD is encrypted with"
35377c478bd9Sstevel@tonic-gate " md5crypt."
35387c478bd9Sstevel@tonic-gate };
35397c478bd9Sstevel@tonic-gate
35407c478bd9Sstevel@tonic-gate
35417c478bd9Sstevel@tonic-gate /* pause */
35427c478bd9Sstevel@tonic-gate static int
pause_func(char * arg,int flags)35437c478bd9Sstevel@tonic-gate pause_func (char *arg, int flags)
35447c478bd9Sstevel@tonic-gate {
35457c478bd9Sstevel@tonic-gate printf("%s\n", arg);
35467c478bd9Sstevel@tonic-gate
35477c478bd9Sstevel@tonic-gate /* If ESC is returned, then abort this entry. */
35487c478bd9Sstevel@tonic-gate if (ASCII_CHAR (getkey ()) == 27)
35497c478bd9Sstevel@tonic-gate return 1;
35507c478bd9Sstevel@tonic-gate
35517c478bd9Sstevel@tonic-gate return 0;
35527c478bd9Sstevel@tonic-gate }
35537c478bd9Sstevel@tonic-gate
35547c478bd9Sstevel@tonic-gate static struct builtin builtin_pause =
35557c478bd9Sstevel@tonic-gate {
35567c478bd9Sstevel@tonic-gate "pause",
35577c478bd9Sstevel@tonic-gate pause_func,
35587c478bd9Sstevel@tonic-gate BUILTIN_CMDLINE | BUILTIN_NO_ECHO,
35597c478bd9Sstevel@tonic-gate "pause [MESSAGE ...]",
35607c478bd9Sstevel@tonic-gate "Print MESSAGE, then wait until a key is pressed."
35617c478bd9Sstevel@tonic-gate };
35627c478bd9Sstevel@tonic-gate
35637c478bd9Sstevel@tonic-gate
35647c478bd9Sstevel@tonic-gate #ifdef GRUB_UTIL
35657c478bd9Sstevel@tonic-gate /* quit */
35667c478bd9Sstevel@tonic-gate static int
quit_func(char * arg,int flags)35677c478bd9Sstevel@tonic-gate quit_func (char *arg, int flags)
35687c478bd9Sstevel@tonic-gate {
35697c478bd9Sstevel@tonic-gate stop ();
35707c478bd9Sstevel@tonic-gate
35717c478bd9Sstevel@tonic-gate /* Never reach here. */
35727c478bd9Sstevel@tonic-gate return 0;
35737c478bd9Sstevel@tonic-gate }
35747c478bd9Sstevel@tonic-gate
35757c478bd9Sstevel@tonic-gate static struct builtin builtin_quit =
35767c478bd9Sstevel@tonic-gate {
35777c478bd9Sstevel@tonic-gate "quit",
35787c478bd9Sstevel@tonic-gate quit_func,
35797c478bd9Sstevel@tonic-gate BUILTIN_CMDLINE | BUILTIN_HELP_LIST,
35807c478bd9Sstevel@tonic-gate "quit",
35817c478bd9Sstevel@tonic-gate "Exit from the GRUB shell."
35827c478bd9Sstevel@tonic-gate };
35837c478bd9Sstevel@tonic-gate #endif /* GRUB_UTIL */
35847c478bd9Sstevel@tonic-gate
35857c478bd9Sstevel@tonic-gate
35867c478bd9Sstevel@tonic-gate #ifdef SUPPORT_NETBOOT
35877c478bd9Sstevel@tonic-gate /* rarp */
35887c478bd9Sstevel@tonic-gate static int
rarp_func(char * arg,int flags)35897c478bd9Sstevel@tonic-gate rarp_func (char *arg, int flags)
35907c478bd9Sstevel@tonic-gate {
35917c478bd9Sstevel@tonic-gate if (! rarp ())
35927c478bd9Sstevel@tonic-gate {
35937c478bd9Sstevel@tonic-gate if (errnum == ERR_NONE)
35947c478bd9Sstevel@tonic-gate errnum = ERR_DEV_VALUES;
35957c478bd9Sstevel@tonic-gate
35967c478bd9Sstevel@tonic-gate return 1;
35977c478bd9Sstevel@tonic-gate }
35987c478bd9Sstevel@tonic-gate
35997c478bd9Sstevel@tonic-gate /* Notify the configuration. */
36007c478bd9Sstevel@tonic-gate print_network_configuration ();
36017c478bd9Sstevel@tonic-gate return 0;
36027c478bd9Sstevel@tonic-gate }
36037c478bd9Sstevel@tonic-gate
36047c478bd9Sstevel@tonic-gate static struct builtin builtin_rarp =
36057c478bd9Sstevel@tonic-gate {
36067c478bd9Sstevel@tonic-gate "rarp",
36077c478bd9Sstevel@tonic-gate rarp_func,
36087c478bd9Sstevel@tonic-gate BUILTIN_CMDLINE | BUILTIN_MENU | BUILTIN_HELP_LIST,
36097c478bd9Sstevel@tonic-gate "rarp",
36107c478bd9Sstevel@tonic-gate "Initialize a network device via RARP."
36117c478bd9Sstevel@tonic-gate };
36127c478bd9Sstevel@tonic-gate #endif /* SUPPORT_NETBOOT */
36137c478bd9Sstevel@tonic-gate
36147c478bd9Sstevel@tonic-gate
36157c478bd9Sstevel@tonic-gate static int
read_func(char * arg,int flags)36167c478bd9Sstevel@tonic-gate read_func (char *arg, int flags)
36177c478bd9Sstevel@tonic-gate {
36187c478bd9Sstevel@tonic-gate int addr;
36197c478bd9Sstevel@tonic-gate
36207c478bd9Sstevel@tonic-gate if (! safe_parse_maxint (&arg, &addr))
36217c478bd9Sstevel@tonic-gate return 1;
36227c478bd9Sstevel@tonic-gate
36237c478bd9Sstevel@tonic-gate grub_printf ("Address 0x%x: Value 0x%x\n",
36247c478bd9Sstevel@tonic-gate addr, *((unsigned *) RAW_ADDR (addr)));
36257c478bd9Sstevel@tonic-gate return 0;
36267c478bd9Sstevel@tonic-gate }
36277c478bd9Sstevel@tonic-gate
36287c478bd9Sstevel@tonic-gate static struct builtin builtin_read =
36297c478bd9Sstevel@tonic-gate {
36307c478bd9Sstevel@tonic-gate "read",
36317c478bd9Sstevel@tonic-gate read_func,
36327c478bd9Sstevel@tonic-gate BUILTIN_CMDLINE,
36337c478bd9Sstevel@tonic-gate "read ADDR",
36347c478bd9Sstevel@tonic-gate "Read a 32-bit value from memory at address ADDR and"
36357c478bd9Sstevel@tonic-gate " display it in hex format."
36367c478bd9Sstevel@tonic-gate };
36377c478bd9Sstevel@tonic-gate
36387c478bd9Sstevel@tonic-gate
36397c478bd9Sstevel@tonic-gate /* reboot */
36407c478bd9Sstevel@tonic-gate static int
reboot_func(char * arg,int flags)36417c478bd9Sstevel@tonic-gate reboot_func (char *arg, int flags)
36427c478bd9Sstevel@tonic-gate {
36437c478bd9Sstevel@tonic-gate grub_reboot ();
36447c478bd9Sstevel@tonic-gate
36457c478bd9Sstevel@tonic-gate /* Never reach here. */
36467c478bd9Sstevel@tonic-gate return 1;
36477c478bd9Sstevel@tonic-gate }
36487c478bd9Sstevel@tonic-gate
36497c478bd9Sstevel@tonic-gate static struct builtin builtin_reboot =
36507c478bd9Sstevel@tonic-gate {
36517c478bd9Sstevel@tonic-gate "reboot",
36527c478bd9Sstevel@tonic-gate reboot_func,
36537c478bd9Sstevel@tonic-gate BUILTIN_CMDLINE | BUILTIN_HELP_LIST,
36547c478bd9Sstevel@tonic-gate "reboot",
36557c478bd9Sstevel@tonic-gate "Reboot your system."
36567c478bd9Sstevel@tonic-gate };
36577c478bd9Sstevel@tonic-gate
36587c478bd9Sstevel@tonic-gate
36597c478bd9Sstevel@tonic-gate /* Print the root device information. */
36607c478bd9Sstevel@tonic-gate static void
print_root_device(void)36617c478bd9Sstevel@tonic-gate print_root_device (void)
36627c478bd9Sstevel@tonic-gate {
36637c478bd9Sstevel@tonic-gate if (saved_drive == NETWORK_DRIVE)
36647c478bd9Sstevel@tonic-gate {
36657c478bd9Sstevel@tonic-gate /* Network drive. */
36667c478bd9Sstevel@tonic-gate grub_printf (" (nd):");
36677c478bd9Sstevel@tonic-gate }
36687c478bd9Sstevel@tonic-gate else if (saved_drive & 0x80)
36697c478bd9Sstevel@tonic-gate {
36707c478bd9Sstevel@tonic-gate /* Hard disk drive. */
36717c478bd9Sstevel@tonic-gate grub_printf (" (hd%d", saved_drive - 0x80);
36727c478bd9Sstevel@tonic-gate
36737c478bd9Sstevel@tonic-gate if ((saved_partition & 0xFF0000) != 0xFF0000)
36747c478bd9Sstevel@tonic-gate grub_printf (",%d", saved_partition >> 16);
36757c478bd9Sstevel@tonic-gate
36767c478bd9Sstevel@tonic-gate if ((saved_partition & 0x00FF00) != 0x00FF00)
36777c478bd9Sstevel@tonic-gate grub_printf (",%c", ((saved_partition >> 8) & 0xFF) + 'a');
36787c478bd9Sstevel@tonic-gate
36797c478bd9Sstevel@tonic-gate grub_printf ("):");
36807c478bd9Sstevel@tonic-gate }
36817c478bd9Sstevel@tonic-gate else
36827c478bd9Sstevel@tonic-gate {
36837c478bd9Sstevel@tonic-gate /* Floppy disk drive. */
36847c478bd9Sstevel@tonic-gate grub_printf (" (fd%d):", saved_drive);
36857c478bd9Sstevel@tonic-gate }
36867c478bd9Sstevel@tonic-gate
36877c478bd9Sstevel@tonic-gate /* Print the filesystem information. */
36887c478bd9Sstevel@tonic-gate current_partition = saved_partition;
36897c478bd9Sstevel@tonic-gate current_drive = saved_drive;
36907c478bd9Sstevel@tonic-gate print_fsys_type ();
36917c478bd9Sstevel@tonic-gate }
36927c478bd9Sstevel@tonic-gate
36937c478bd9Sstevel@tonic-gate static int
real_root_func(char * arg,int attempt_mount)36947c478bd9Sstevel@tonic-gate real_root_func (char *arg, int attempt_mount)
36957c478bd9Sstevel@tonic-gate {
36967c478bd9Sstevel@tonic-gate int hdbias = 0;
36977c478bd9Sstevel@tonic-gate char *biasptr;
36987c478bd9Sstevel@tonic-gate char *next;
36997c478bd9Sstevel@tonic-gate
37007c478bd9Sstevel@tonic-gate /* If ARG is empty, just print the current root device. */
37017c478bd9Sstevel@tonic-gate if (! *arg)
37027c478bd9Sstevel@tonic-gate {
37037c478bd9Sstevel@tonic-gate print_root_device ();
37047c478bd9Sstevel@tonic-gate return 0;
37057c478bd9Sstevel@tonic-gate }
37067c478bd9Sstevel@tonic-gate
37077c478bd9Sstevel@tonic-gate /* Call set_device to get the drive and the partition in ARG. */
37087c478bd9Sstevel@tonic-gate next = set_device (arg);
37097c478bd9Sstevel@tonic-gate if (! next)
37107c478bd9Sstevel@tonic-gate return 1;
37117c478bd9Sstevel@tonic-gate
37127c478bd9Sstevel@tonic-gate /* Ignore ERR_FSYS_MOUNT. */
37137c478bd9Sstevel@tonic-gate if (attempt_mount)
37147c478bd9Sstevel@tonic-gate {
37157c478bd9Sstevel@tonic-gate if (! open_device () && errnum != ERR_FSYS_MOUNT)
37167c478bd9Sstevel@tonic-gate return 1;
37177c478bd9Sstevel@tonic-gate }
37187c478bd9Sstevel@tonic-gate else
37197c478bd9Sstevel@tonic-gate {
37207c478bd9Sstevel@tonic-gate /* This is necessary, because the location of a partition table
37217c478bd9Sstevel@tonic-gate must be set appropriately. */
37227c478bd9Sstevel@tonic-gate if (open_partition ())
37237c478bd9Sstevel@tonic-gate {
37247c478bd9Sstevel@tonic-gate set_bootdev (0);
37257c478bd9Sstevel@tonic-gate if (errnum)
37267c478bd9Sstevel@tonic-gate return 1;
37277c478bd9Sstevel@tonic-gate }
37287c478bd9Sstevel@tonic-gate }
37297c478bd9Sstevel@tonic-gate
37307c478bd9Sstevel@tonic-gate /* Clear ERRNUM. */
37317c478bd9Sstevel@tonic-gate errnum = 0;
37327c478bd9Sstevel@tonic-gate saved_partition = current_partition;
37337c478bd9Sstevel@tonic-gate saved_drive = current_drive;
37347c478bd9Sstevel@tonic-gate
37357c478bd9Sstevel@tonic-gate if (attempt_mount)
37367c478bd9Sstevel@tonic-gate {
37377c478bd9Sstevel@tonic-gate /* BSD and chainloading evil hacks !! */
37387c478bd9Sstevel@tonic-gate biasptr = skip_to (0, next);
37397c478bd9Sstevel@tonic-gate safe_parse_maxint (&biasptr, &hdbias);
37407c478bd9Sstevel@tonic-gate errnum = 0;
37417c478bd9Sstevel@tonic-gate bootdev = set_bootdev (hdbias);
37427c478bd9Sstevel@tonic-gate if (errnum)
37437c478bd9Sstevel@tonic-gate return 1;
37447c478bd9Sstevel@tonic-gate
37457c478bd9Sstevel@tonic-gate /* Print the type of the filesystem. */
37467c478bd9Sstevel@tonic-gate print_fsys_type ();
37477c478bd9Sstevel@tonic-gate }
37487c478bd9Sstevel@tonic-gate
37497c478bd9Sstevel@tonic-gate return 0;
37507c478bd9Sstevel@tonic-gate }
37517c478bd9Sstevel@tonic-gate
37527c478bd9Sstevel@tonic-gate static int
root_func(char * arg,int flags)37537c478bd9Sstevel@tonic-gate root_func (char *arg, int flags)
37547c478bd9Sstevel@tonic-gate {
3755b1b8ab34Slling is_zfs_mount = 0;
37567c478bd9Sstevel@tonic-gate return real_root_func (arg, 1);
37577c478bd9Sstevel@tonic-gate }
37587c478bd9Sstevel@tonic-gate
37597c478bd9Sstevel@tonic-gate static struct builtin builtin_root =
37607c478bd9Sstevel@tonic-gate {
37617c478bd9Sstevel@tonic-gate "root",
37627c478bd9Sstevel@tonic-gate root_func,
37637c478bd9Sstevel@tonic-gate BUILTIN_CMDLINE | BUILTIN_HELP_LIST,
37647c478bd9Sstevel@tonic-gate "root [DEVICE [HDBIAS]]",
37657c478bd9Sstevel@tonic-gate "Set the current \"root device\" to the device DEVICE, then"
37667c478bd9Sstevel@tonic-gate " attempt to mount it to get the partition size (for passing the"
37677c478bd9Sstevel@tonic-gate " partition descriptor in `ES:ESI', used by some chain-loaded"
37687c478bd9Sstevel@tonic-gate " bootloaders), the BSD drive-type (for booting BSD kernels using"
37697c478bd9Sstevel@tonic-gate " their native boot format), and correctly determine "
37707c478bd9Sstevel@tonic-gate " the PC partition where a BSD sub-partition is located. The"
37717c478bd9Sstevel@tonic-gate " optional HDBIAS parameter is a number to tell a BSD kernel"
37727c478bd9Sstevel@tonic-gate " how many BIOS drive numbers are on controllers before the current"
37737c478bd9Sstevel@tonic-gate " one. For example, if there is an IDE disk and a SCSI disk, and your"
37747c478bd9Sstevel@tonic-gate " FreeBSD root partition is on the SCSI disk, then use a `1' for HDBIAS."
37757c478bd9Sstevel@tonic-gate };
37767c478bd9Sstevel@tonic-gate
3777eb2bd662Svikram
3778eb2bd662Svikram /* findroot */
377917f1e64aSEric Taylor int
findroot_func(char * arg,int flags)3780eb2bd662Svikram findroot_func (char *arg, int flags)
3781eb2bd662Svikram {
3782eb2bd662Svikram int ret;
3783eb2bd662Svikram char root[32];
3784eb2bd662Svikram
3785eb2bd662Svikram if (grub_strlen(arg) >= BOOTSIGN_ARGLEN) {
3786eb2bd662Svikram errnum = ERR_BAD_ARGUMENT;
3787eb2bd662Svikram return 1;
3788eb2bd662Svikram }
3789eb2bd662Svikram
3790eb2bd662Svikram if (arg[0] == '\0') {
3791eb2bd662Svikram errnum = ERR_BAD_ARGUMENT;
3792eb2bd662Svikram return 1;
3793eb2bd662Svikram }
3794eb2bd662Svikram
3795051aabe6Staylor find_best_root = 1;
3796051aabe6Staylor best_drive = 0;
3797051aabe6Staylor best_part = 0;
3798eb2bd662Svikram ret = find_common(arg, root, 1, flags);
3799eb2bd662Svikram if (ret != 0)
3800eb2bd662Svikram return (ret);
3801051aabe6Staylor find_best_root = 0;
3802eb2bd662Svikram
3803eb2bd662Svikram return real_root_func (root, 1);
3804eb2bd662Svikram }
3805eb2bd662Svikram
3806eb2bd662Svikram static struct builtin builtin_findroot =
3807eb2bd662Svikram {
3808eb2bd662Svikram "findroot",
3809eb2bd662Svikram findroot_func,
3810eb2bd662Svikram BUILTIN_CMDLINE | BUILTIN_HELP_LIST,
3811963390b4Svikram "findroot <SIGNATURE | (SIGNATURE,partition[,slice])>",
3812963390b4Svikram "Searches across all partitions for the file name SIGNATURE."
3813963390b4Svikram " GRUB looks only in the directory /boot/grub/bootsign for the"
3814963390b4Svikram " filename and it stops as soon as it finds the first instance of"
3815963390b4Svikram " the file - so to be useful the name of the signature file must be"
3816963390b4Svikram " unique across all partitions. Once the signature file is found,"
3817963390b4Svikram " GRUB invokes the \"root\" command on that partition."
3818eb2bd662Svikram " An optional partition and slice may be specified to optimize the search."
3819eb2bd662Svikram };
3820eb2bd662Svikram
3821b1b8ab34Slling
3822b1b8ab34Slling /*
3823b1b8ab34Slling * COMMAND to override the default root filesystem for ZFS
3824b1b8ab34Slling * bootfs pool/fs
3825b1b8ab34Slling */
3826b1b8ab34Slling static int
bootfs_func(char * arg,int flags)3827b1b8ab34Slling bootfs_func (char *arg, int flags)
3828b1b8ab34Slling {
3829b1b8ab34Slling int hdbias = 0;
3830b1b8ab34Slling char *biasptr;
3831b1b8ab34Slling char *next;
3832b1b8ab34Slling
3833b1b8ab34Slling if (! *arg) {
3834b1b8ab34Slling if (current_bootfs[0] != '\0')
3835b1b8ab34Slling grub_printf ("The zfs boot filesystem is set to '%s'.\n",
3836b1b8ab34Slling current_bootfs);
3837b1b8ab34Slling else if (current_rootpool[0] != 0 && current_bootfs_obj != 0)
3838b1b8ab34Slling grub_printf("The zfs boot filesystem is <default: %s/%u>.",
3839b1b8ab34Slling current_rootpool, current_bootfs_obj);
3840b1b8ab34Slling else
384111a41203Slling grub_printf ("The zfs boot filesystem will be derived from "
384211a41203Slling "the default bootfs pool property.\n");
3843b1b8ab34Slling
3844b1b8ab34Slling return (1);
3845b1b8ab34Slling }
3846b1b8ab34Slling
3847b1b8ab34Slling /* Verify the zfs filesystem name */
3848b1b8ab34Slling if (arg[0] == '/' || arg[0] == '\0') {
3849b1b8ab34Slling errnum = ERR_BAD_ARGUMENT;
3850b1b8ab34Slling return 0;
3851b1b8ab34Slling }
3852b35c6776Staylor if (current_rootpool[0] != 0 && grub_strncmp(arg,
3853b35c6776Staylor current_rootpool, strlen(current_rootpool))) {
3854b35c6776Staylor errnum = ERR_BAD_ARGUMENT;
3855b35c6776Staylor return 0;
3856b35c6776Staylor }
3857b1b8ab34Slling
3858e23347b1SEric Taylor grub_memmove(current_bootfs, arg, MAXNAMELEN);
3859b1b8ab34Slling
3860b1b8ab34Slling return (1);
3861b1b8ab34Slling }
3862b1b8ab34Slling
3863b1b8ab34Slling static struct builtin builtin_bootfs =
3864b1b8ab34Slling {
3865b1b8ab34Slling "bootfs",
3866b1b8ab34Slling bootfs_func,
3867b1b8ab34Slling BUILTIN_CMDLINE | BUILTIN_HELP_LIST,
3868b1b8ab34Slling "bootfs [ZFSBOOTFS]",
3869b1b8ab34Slling "Set the current zfs boot filesystem to ZFSBOOTFS (rootpool/rootfs)."
3870b1b8ab34Slling };
3871b1b8ab34Slling
38727c478bd9Sstevel@tonic-gate
38737c478bd9Sstevel@tonic-gate /* rootnoverify */
38747c478bd9Sstevel@tonic-gate static int
rootnoverify_func(char * arg,int flags)38757c478bd9Sstevel@tonic-gate rootnoverify_func (char *arg, int flags)
38767c478bd9Sstevel@tonic-gate {
38777c478bd9Sstevel@tonic-gate return real_root_func (arg, 0);
38787c478bd9Sstevel@tonic-gate }
38797c478bd9Sstevel@tonic-gate
38807c478bd9Sstevel@tonic-gate static struct builtin builtin_rootnoverify =
38817c478bd9Sstevel@tonic-gate {
38827c478bd9Sstevel@tonic-gate "rootnoverify",
38837c478bd9Sstevel@tonic-gate rootnoverify_func,
38847c478bd9Sstevel@tonic-gate BUILTIN_CMDLINE | BUILTIN_HELP_LIST,
38857c478bd9Sstevel@tonic-gate "rootnoverify [DEVICE [HDBIAS]]",
38867c478bd9Sstevel@tonic-gate "Similar to `root', but don't attempt to mount the partition. This"
38877c478bd9Sstevel@tonic-gate " is useful for when an OS is outside of the area of the disk that"
38887c478bd9Sstevel@tonic-gate " GRUB can read, but setting the correct root device is still"
38897c478bd9Sstevel@tonic-gate " desired. Note that the items mentioned in `root' which"
38907c478bd9Sstevel@tonic-gate " derived from attempting the mount will NOT work correctly."
38917c478bd9Sstevel@tonic-gate };
38927c478bd9Sstevel@tonic-gate
38937c478bd9Sstevel@tonic-gate
38947c478bd9Sstevel@tonic-gate /* savedefault */
38957c478bd9Sstevel@tonic-gate static int
savedefault_func(char * arg,int flags)38967c478bd9Sstevel@tonic-gate savedefault_func (char *arg, int flags)
38977c478bd9Sstevel@tonic-gate {
38987c478bd9Sstevel@tonic-gate #if !defined(SUPPORT_DISKLESS) && !defined(GRUB_UTIL)
38997c478bd9Sstevel@tonic-gate unsigned long tmp_drive = saved_drive;
39007c478bd9Sstevel@tonic-gate unsigned long tmp_partition = saved_partition;
39017c478bd9Sstevel@tonic-gate char *default_file = (char *) DEFAULT_FILE_BUF;
39027c478bd9Sstevel@tonic-gate char buf[10];
39037c478bd9Sstevel@tonic-gate char sect[SECTOR_SIZE];
39047c478bd9Sstevel@tonic-gate int entryno;
39057c478bd9Sstevel@tonic-gate int sector_count = 0;
39069890706eSHans Rosenfeld unsigned long long saved_sectors[2];
39077c478bd9Sstevel@tonic-gate int saved_offsets[2];
39087c478bd9Sstevel@tonic-gate int saved_lengths[2];
39097c478bd9Sstevel@tonic-gate
3910b1b8ab34Slling /* not supported for zfs root */
3911b1b8ab34Slling if (is_zfs_mount == 1) {
3912b1b8ab34Slling return (0); /* no-op */
3913b1b8ab34Slling }
3914b1b8ab34Slling
39157c478bd9Sstevel@tonic-gate /* Save sector information about at most two sectors. */
39169890706eSHans Rosenfeld auto void disk_read_savesect_func (unsigned long long sector, int offset,
39171b8adde7SWilliam Kucharski int length);
39189890706eSHans Rosenfeld void disk_read_savesect_func (unsigned long long sector, int offset, int length)
39197c478bd9Sstevel@tonic-gate {
39207c478bd9Sstevel@tonic-gate if (sector_count < 2)
39217c478bd9Sstevel@tonic-gate {
39227c478bd9Sstevel@tonic-gate saved_sectors[sector_count] = sector;
39237c478bd9Sstevel@tonic-gate saved_offsets[sector_count] = offset;
39247c478bd9Sstevel@tonic-gate saved_lengths[sector_count] = length;
39257c478bd9Sstevel@tonic-gate }
39267c478bd9Sstevel@tonic-gate sector_count++;
39277c478bd9Sstevel@tonic-gate }
39287c478bd9Sstevel@tonic-gate
39297c478bd9Sstevel@tonic-gate /* This command is only useful when you boot an entry from the menu
39307c478bd9Sstevel@tonic-gate interface. */
39317c478bd9Sstevel@tonic-gate if (! (flags & BUILTIN_SCRIPT))
39327c478bd9Sstevel@tonic-gate {
39337c478bd9Sstevel@tonic-gate errnum = ERR_UNRECOGNIZED;
39347c478bd9Sstevel@tonic-gate return 1;
39357c478bd9Sstevel@tonic-gate }
39367c478bd9Sstevel@tonic-gate
39377c478bd9Sstevel@tonic-gate /* Determine a saved entry number. */
39387c478bd9Sstevel@tonic-gate if (*arg)
39397c478bd9Sstevel@tonic-gate {
39407c478bd9Sstevel@tonic-gate if (grub_memcmp (arg, "fallback", sizeof ("fallback") - 1) == 0)
39417c478bd9Sstevel@tonic-gate {
39427c478bd9Sstevel@tonic-gate int i;
39437c478bd9Sstevel@tonic-gate int index = 0;
39447c478bd9Sstevel@tonic-gate
39457c478bd9Sstevel@tonic-gate for (i = 0; i < MAX_FALLBACK_ENTRIES; i++)
39467c478bd9Sstevel@tonic-gate {
39477c478bd9Sstevel@tonic-gate if (fallback_entries[i] < 0)
39487c478bd9Sstevel@tonic-gate break;
39497c478bd9Sstevel@tonic-gate if (fallback_entries[i] == current_entryno)
39507c478bd9Sstevel@tonic-gate {
39517c478bd9Sstevel@tonic-gate index = i + 1;
39527c478bd9Sstevel@tonic-gate break;
39537c478bd9Sstevel@tonic-gate }
39547c478bd9Sstevel@tonic-gate }
39557c478bd9Sstevel@tonic-gate
39567c478bd9Sstevel@tonic-gate if (index >= MAX_FALLBACK_ENTRIES || fallback_entries[index] < 0)
39577c478bd9Sstevel@tonic-gate {
39587c478bd9Sstevel@tonic-gate /* This is the last. */
39597c478bd9Sstevel@tonic-gate errnum = ERR_BAD_ARGUMENT;
39607c478bd9Sstevel@tonic-gate return 1;
39617c478bd9Sstevel@tonic-gate }
39627c478bd9Sstevel@tonic-gate
39637c478bd9Sstevel@tonic-gate entryno = fallback_entries[index];
39647c478bd9Sstevel@tonic-gate }
39657c478bd9Sstevel@tonic-gate else if (! safe_parse_maxint (&arg, &entryno))
39667c478bd9Sstevel@tonic-gate return 1;
39677c478bd9Sstevel@tonic-gate }
39687c478bd9Sstevel@tonic-gate else
39697c478bd9Sstevel@tonic-gate entryno = current_entryno;
39707c478bd9Sstevel@tonic-gate
39717c478bd9Sstevel@tonic-gate /* Open the default file. */
39727c478bd9Sstevel@tonic-gate saved_drive = boot_drive;
39737c478bd9Sstevel@tonic-gate saved_partition = install_partition;
39747c478bd9Sstevel@tonic-gate if (grub_open (default_file))
39757c478bd9Sstevel@tonic-gate {
39767c478bd9Sstevel@tonic-gate int len;
39777c478bd9Sstevel@tonic-gate
39787c478bd9Sstevel@tonic-gate disk_read_hook = disk_read_savesect_func;
39797c478bd9Sstevel@tonic-gate len = grub_read (buf, sizeof (buf));
39807c478bd9Sstevel@tonic-gate disk_read_hook = 0;
39817c478bd9Sstevel@tonic-gate grub_close ();
39827c478bd9Sstevel@tonic-gate
39837c478bd9Sstevel@tonic-gate if (len != sizeof (buf))
39847c478bd9Sstevel@tonic-gate {
39857c478bd9Sstevel@tonic-gate /* This is too small. Do not modify the file manually, please! */
39867c478bd9Sstevel@tonic-gate errnum = ERR_READ;
39877c478bd9Sstevel@tonic-gate goto fail;
39887c478bd9Sstevel@tonic-gate }
39897c478bd9Sstevel@tonic-gate
39907c478bd9Sstevel@tonic-gate if (sector_count > 2)
39917c478bd9Sstevel@tonic-gate {
39927c478bd9Sstevel@tonic-gate /* Is this possible?! Too fragmented! */
39937c478bd9Sstevel@tonic-gate errnum = ERR_FSYS_CORRUPT;
39947c478bd9Sstevel@tonic-gate goto fail;
39957c478bd9Sstevel@tonic-gate }
39967c478bd9Sstevel@tonic-gate
39977c478bd9Sstevel@tonic-gate /* Set up a string to be written. */
39987c478bd9Sstevel@tonic-gate grub_memset (buf, '\n', sizeof (buf));
39997c478bd9Sstevel@tonic-gate grub_sprintf (buf, "%d", entryno);
40007c478bd9Sstevel@tonic-gate
40017c478bd9Sstevel@tonic-gate if (saved_lengths[0] < sizeof (buf))
40027c478bd9Sstevel@tonic-gate {
40037c478bd9Sstevel@tonic-gate /* The file is anchored to another file and the first few bytes
40047c478bd9Sstevel@tonic-gate are spanned in two sectors. Uggh... */
40057c478bd9Sstevel@tonic-gate if (! rawread (current_drive, saved_sectors[0], 0, SECTOR_SIZE,
40067c478bd9Sstevel@tonic-gate sect))
40077c478bd9Sstevel@tonic-gate goto fail;
40087c478bd9Sstevel@tonic-gate grub_memmove (sect + saved_offsets[0], buf, saved_lengths[0]);
40097c478bd9Sstevel@tonic-gate if (! rawwrite (current_drive, saved_sectors[0], sect))
40107c478bd9Sstevel@tonic-gate goto fail;
40117c478bd9Sstevel@tonic-gate
40127c478bd9Sstevel@tonic-gate if (! rawread (current_drive, saved_sectors[1], 0, SECTOR_SIZE,
40137c478bd9Sstevel@tonic-gate sect))
40147c478bd9Sstevel@tonic-gate goto fail;
40157c478bd9Sstevel@tonic-gate grub_memmove (sect + saved_offsets[1],
40167c478bd9Sstevel@tonic-gate buf + saved_lengths[0],
40177c478bd9Sstevel@tonic-gate sizeof (buf) - saved_lengths[0]);
40187c478bd9Sstevel@tonic-gate if (! rawwrite (current_drive, saved_sectors[1], sect))
40197c478bd9Sstevel@tonic-gate goto fail;
40207c478bd9Sstevel@tonic-gate }
40217c478bd9Sstevel@tonic-gate else
40227c478bd9Sstevel@tonic-gate {
40237c478bd9Sstevel@tonic-gate /* This is a simple case. It fits into a single sector. */
40247c478bd9Sstevel@tonic-gate if (! rawread (current_drive, saved_sectors[0], 0, SECTOR_SIZE,
40257c478bd9Sstevel@tonic-gate sect))
40267c478bd9Sstevel@tonic-gate goto fail;
40277c478bd9Sstevel@tonic-gate grub_memmove (sect + saved_offsets[0], buf, sizeof (buf));
40287c478bd9Sstevel@tonic-gate if (! rawwrite (current_drive, saved_sectors[0], sect))
40297c478bd9Sstevel@tonic-gate goto fail;
40307c478bd9Sstevel@tonic-gate }
40317c478bd9Sstevel@tonic-gate
40327c478bd9Sstevel@tonic-gate /* Clear the cache. */
4033342440ecSPrasad Singamsetty buf_track = BUF_CACHE_INVALID;
40347c478bd9Sstevel@tonic-gate }
40357c478bd9Sstevel@tonic-gate
40367c478bd9Sstevel@tonic-gate fail:
40377c478bd9Sstevel@tonic-gate saved_drive = tmp_drive;
40387c478bd9Sstevel@tonic-gate saved_partition = tmp_partition;
40397c478bd9Sstevel@tonic-gate return errnum;
40407c478bd9Sstevel@tonic-gate #else /* ! SUPPORT_DISKLESS && ! GRUB_UTIL */
40417c478bd9Sstevel@tonic-gate errnum = ERR_UNRECOGNIZED;
40427c478bd9Sstevel@tonic-gate return 1;
40437c478bd9Sstevel@tonic-gate #endif /* ! SUPPORT_DISKLESS && ! GRUB_UTIL */
40447c478bd9Sstevel@tonic-gate }
40457c478bd9Sstevel@tonic-gate
40467c478bd9Sstevel@tonic-gate static struct builtin builtin_savedefault =
40477c478bd9Sstevel@tonic-gate {
40487c478bd9Sstevel@tonic-gate "savedefault",
40497c478bd9Sstevel@tonic-gate savedefault_func,
40507c478bd9Sstevel@tonic-gate BUILTIN_CMDLINE,
40517c478bd9Sstevel@tonic-gate "savedefault [NUM | `fallback']",
40527c478bd9Sstevel@tonic-gate "Save the current entry as the default boot entry if no argument is"
40537c478bd9Sstevel@tonic-gate " specified. If a number is specified, this number is saved. If"
40547c478bd9Sstevel@tonic-gate " `fallback' is used, next fallback entry is saved."
40557c478bd9Sstevel@tonic-gate };
40567c478bd9Sstevel@tonic-gate
40577c478bd9Sstevel@tonic-gate
40587c478bd9Sstevel@tonic-gate #ifdef SUPPORT_SERIAL
40597c478bd9Sstevel@tonic-gate /* serial */
40607c478bd9Sstevel@tonic-gate static int
serial_func(char * arg,int flags)40617c478bd9Sstevel@tonic-gate serial_func (char *arg, int flags)
40627c478bd9Sstevel@tonic-gate {
40635626beecSKeith M Wesolowski int i;
40645626beecSKeith M Wesolowski int units[SERIAL_MAX_PORTS];
40655626beecSKeith M Wesolowski unsigned short ports[SERIAL_MAX_PORTS];
40667c478bd9Sstevel@tonic-gate unsigned int speed = 9600;
40677c478bd9Sstevel@tonic-gate int word_len = UART_8BITS_WORD;
40687c478bd9Sstevel@tonic-gate int parity = UART_NO_PARITY;
40697c478bd9Sstevel@tonic-gate int stop_bit_len = UART_1_STOP_BIT;
40707c478bd9Sstevel@tonic-gate
40715626beecSKeith M Wesolowski for (i = 0; i < SERIAL_MAX_PORTS; ++i)
40725626beecSKeith M Wesolowski {
40735626beecSKeith M Wesolowski units[i] = -1;
40745626beecSKeith M Wesolowski ports[i] = 0;
40755626beecSKeith M Wesolowski }
40765626beecSKeith M Wesolowski
40777c478bd9Sstevel@tonic-gate /* Process GNU-style long options.
40787c478bd9Sstevel@tonic-gate FIXME: We should implement a getopt-like function, to avoid
40797c478bd9Sstevel@tonic-gate duplications. */
40807c478bd9Sstevel@tonic-gate while (1)
40817c478bd9Sstevel@tonic-gate {
40827c478bd9Sstevel@tonic-gate if (grub_memcmp (arg, "--unit=", sizeof ("--unit=") - 1) == 0)
40837c478bd9Sstevel@tonic-gate {
40847c478bd9Sstevel@tonic-gate char *p = arg + sizeof ("--unit=") - 1;
40857c478bd9Sstevel@tonic-gate int unit;
40865626beecSKeith M Wesolowski
40875626beecSKeith M Wesolowski i = 0;
40885626beecSKeith M Wesolowski do
40897c478bd9Sstevel@tonic-gate {
40905626beecSKeith M Wesolowski if (i >= SERIAL_MAX_PORTS)
40915626beecSKeith M Wesolowski {
40925626beecSKeith M Wesolowski errnum = ERR_DEV_FORMAT;
40935626beecSKeith M Wesolowski return 1;
40945626beecSKeith M Wesolowski }
40955626beecSKeith M Wesolowski
40965626beecSKeith M Wesolowski if (! safe_parse_maxint (&p, &unit))
40975626beecSKeith M Wesolowski return 1;
40985626beecSKeith M Wesolowski
40995626beecSKeith M Wesolowski if (unit < 0 || unit > 3)
41005626beecSKeith M Wesolowski {
41015626beecSKeith M Wesolowski errnum = ERR_DEV_VALUES;
41025626beecSKeith M Wesolowski return 1;
41035626beecSKeith M Wesolowski }
41047c478bd9Sstevel@tonic-gate
41055626beecSKeith M Wesolowski units[i++] = unit;
41065626beecSKeith M Wesolowski }
41075626beecSKeith M Wesolowski while (*p++ == ',');
41087c478bd9Sstevel@tonic-gate }
41097c478bd9Sstevel@tonic-gate else if (grub_memcmp (arg, "--speed=", sizeof ("--speed=") - 1) == 0)
41107c478bd9Sstevel@tonic-gate {
41117c478bd9Sstevel@tonic-gate char *p = arg + sizeof ("--speed=") - 1;
41127c478bd9Sstevel@tonic-gate int num;
41137c478bd9Sstevel@tonic-gate
41147c478bd9Sstevel@tonic-gate if (! safe_parse_maxint (&p, &num))
41157c478bd9Sstevel@tonic-gate return 1;
41167c478bd9Sstevel@tonic-gate
41177c478bd9Sstevel@tonic-gate speed = (unsigned int) num;
41187c478bd9Sstevel@tonic-gate }
41197c478bd9Sstevel@tonic-gate else if (grub_memcmp (arg, "--port=", sizeof ("--port=") - 1) == 0)
41207c478bd9Sstevel@tonic-gate {
41217c478bd9Sstevel@tonic-gate char *p = arg + sizeof ("--port=") - 1;
41227c478bd9Sstevel@tonic-gate int num;
41237c478bd9Sstevel@tonic-gate
41245626beecSKeith M Wesolowski i = 0;
41255626beecSKeith M Wesolowski do
41265626beecSKeith M Wesolowski {
41275626beecSKeith M Wesolowski if (i >= SERIAL_MAX_PORTS)
41285626beecSKeith M Wesolowski {
41295626beecSKeith M Wesolowski errnum = ERR_DEV_FORMAT;
41305626beecSKeith M Wesolowski return 1;
41315626beecSKeith M Wesolowski }
41325626beecSKeith M Wesolowski
41335626beecSKeith M Wesolowski if (! safe_parse_maxint (&p, &num))
41345626beecSKeith M Wesolowski return 1;
41355626beecSKeith M Wesolowski
41365626beecSKeith M Wesolowski if (num > 0xffff || num <= 0)
41375626beecSKeith M Wesolowski {
41385626beecSKeith M Wesolowski errnum = ERR_DEV_VALUES;
41395626beecSKeith M Wesolowski return 1;
41405626beecSKeith M Wesolowski }
41415626beecSKeith M Wesolowski
41425626beecSKeith M Wesolowski ports[i++] = (unsigned short) num;
41435626beecSKeith M Wesolowski }
41445626beecSKeith M Wesolowski while (*p++ == ',');
41457c478bd9Sstevel@tonic-gate }
41467c478bd9Sstevel@tonic-gate else if (grub_memcmp (arg, "--word=", sizeof ("--word=") - 1) == 0)
41477c478bd9Sstevel@tonic-gate {
41487c478bd9Sstevel@tonic-gate char *p = arg + sizeof ("--word=") - 1;
41497c478bd9Sstevel@tonic-gate int len;
41507c478bd9Sstevel@tonic-gate
41517c478bd9Sstevel@tonic-gate if (! safe_parse_maxint (&p, &len))
41527c478bd9Sstevel@tonic-gate return 1;
41537c478bd9Sstevel@tonic-gate
41547c478bd9Sstevel@tonic-gate switch (len)
41557c478bd9Sstevel@tonic-gate {
41567c478bd9Sstevel@tonic-gate case 5: word_len = UART_5BITS_WORD; break;
41577c478bd9Sstevel@tonic-gate case 6: word_len = UART_6BITS_WORD; break;
41587c478bd9Sstevel@tonic-gate case 7: word_len = UART_7BITS_WORD; break;
41597c478bd9Sstevel@tonic-gate case 8: word_len = UART_8BITS_WORD; break;
41607c478bd9Sstevel@tonic-gate default:
41617c478bd9Sstevel@tonic-gate errnum = ERR_BAD_ARGUMENT;
41627c478bd9Sstevel@tonic-gate return 1;
41637c478bd9Sstevel@tonic-gate }
41647c478bd9Sstevel@tonic-gate }
41657c478bd9Sstevel@tonic-gate else if (grub_memcmp (arg, "--stop=", sizeof ("--stop=") - 1) == 0)
41667c478bd9Sstevel@tonic-gate {
41677c478bd9Sstevel@tonic-gate char *p = arg + sizeof ("--stop=") - 1;
41687c478bd9Sstevel@tonic-gate int len;
41697c478bd9Sstevel@tonic-gate
41707c478bd9Sstevel@tonic-gate if (! safe_parse_maxint (&p, &len))
41717c478bd9Sstevel@tonic-gate return 1;
41727c478bd9Sstevel@tonic-gate
41737c478bd9Sstevel@tonic-gate switch (len)
41747c478bd9Sstevel@tonic-gate {
41757c478bd9Sstevel@tonic-gate case 1: stop_bit_len = UART_1_STOP_BIT; break;
41767c478bd9Sstevel@tonic-gate case 2: stop_bit_len = UART_2_STOP_BITS; break;
41777c478bd9Sstevel@tonic-gate default:
41787c478bd9Sstevel@tonic-gate errnum = ERR_BAD_ARGUMENT;
41797c478bd9Sstevel@tonic-gate return 1;
41807c478bd9Sstevel@tonic-gate }
41817c478bd9Sstevel@tonic-gate }
41827c478bd9Sstevel@tonic-gate else if (grub_memcmp (arg, "--parity=", sizeof ("--parity=") - 1) == 0)
41837c478bd9Sstevel@tonic-gate {
41847c478bd9Sstevel@tonic-gate char *p = arg + sizeof ("--parity=") - 1;
41857c478bd9Sstevel@tonic-gate
41867c478bd9Sstevel@tonic-gate if (grub_memcmp (p, "no", sizeof ("no") - 1) == 0)
41877c478bd9Sstevel@tonic-gate parity = UART_NO_PARITY;
41887c478bd9Sstevel@tonic-gate else if (grub_memcmp (p, "odd", sizeof ("odd") - 1) == 0)
41897c478bd9Sstevel@tonic-gate parity = UART_ODD_PARITY;
41907c478bd9Sstevel@tonic-gate else if (grub_memcmp (p, "even", sizeof ("even") - 1) == 0)
41917c478bd9Sstevel@tonic-gate parity = UART_EVEN_PARITY;
41927c478bd9Sstevel@tonic-gate else
41937c478bd9Sstevel@tonic-gate {
41947c478bd9Sstevel@tonic-gate errnum = ERR_BAD_ARGUMENT;
41957c478bd9Sstevel@tonic-gate return 1;
41967c478bd9Sstevel@tonic-gate }
41977c478bd9Sstevel@tonic-gate }
41987c478bd9Sstevel@tonic-gate # ifdef GRUB_UTIL
41997c478bd9Sstevel@tonic-gate /* In the grub shell, don't use any port number but open a tty
42007c478bd9Sstevel@tonic-gate device instead. */
42017c478bd9Sstevel@tonic-gate else if (grub_memcmp (arg, "--device=", sizeof ("--device=") - 1) == 0)
42027c478bd9Sstevel@tonic-gate {
42037c478bd9Sstevel@tonic-gate char *p = arg + sizeof ("--device=") - 1;
42047c478bd9Sstevel@tonic-gate char dev[256]; /* XXX */
42057c478bd9Sstevel@tonic-gate char *q = dev;
42067c478bd9Sstevel@tonic-gate
42077c478bd9Sstevel@tonic-gate while (*p && ! grub_isspace (*p))
42087c478bd9Sstevel@tonic-gate *q++ = *p++;
42097c478bd9Sstevel@tonic-gate
42107c478bd9Sstevel@tonic-gate *q = 0;
42117c478bd9Sstevel@tonic-gate serial_set_device (dev);
42127c478bd9Sstevel@tonic-gate }
42137c478bd9Sstevel@tonic-gate # endif /* GRUB_UTIL */
42147c478bd9Sstevel@tonic-gate else
42157c478bd9Sstevel@tonic-gate break;
42167c478bd9Sstevel@tonic-gate
42177c478bd9Sstevel@tonic-gate arg = skip_to (0, arg);
42187c478bd9Sstevel@tonic-gate }
42197c478bd9Sstevel@tonic-gate
42205626beecSKeith M Wesolowski if (units[0] == -1 && ports[0] == 0)
42215626beecSKeith M Wesolowski units[0] = 0;
42225626beecSKeith M Wesolowski
42235626beecSKeith M Wesolowski for (i = 0; i < SERIAL_MAX_PORTS; ++i)
42245626beecSKeith M Wesolowski {
42255626beecSKeith M Wesolowski if (units[i] != -1)
42265626beecSKeith M Wesolowski ports[i] = serial_hw_get_port (units[i]);
42275626beecSKeith M Wesolowski if (ports[i] == 0)
42285626beecSKeith M Wesolowski continue;
42295626beecSKeith M Wesolowski
42305626beecSKeith M Wesolowski if (serial_hw_init (ports[i], speed, word_len, parity, stop_bit_len))
42315626beecSKeith M Wesolowski break;
42325626beecSKeith M Wesolowski }
42335626beecSKeith M Wesolowski
42345626beecSKeith M Wesolowski if (i >= SERIAL_MAX_PORTS)
42357c478bd9Sstevel@tonic-gate {
42367c478bd9Sstevel@tonic-gate errnum = ERR_BAD_ARGUMENT;
42377c478bd9Sstevel@tonic-gate return 1;
42387c478bd9Sstevel@tonic-gate }
42397c478bd9Sstevel@tonic-gate
42407c478bd9Sstevel@tonic-gate return 0;
42417c478bd9Sstevel@tonic-gate }
42427c478bd9Sstevel@tonic-gate
42437c478bd9Sstevel@tonic-gate static struct builtin builtin_serial =
42447c478bd9Sstevel@tonic-gate {
42457c478bd9Sstevel@tonic-gate "serial",
42467c478bd9Sstevel@tonic-gate serial_func,
42477c478bd9Sstevel@tonic-gate BUILTIN_MENU | BUILTIN_CMDLINE | BUILTIN_HELP_LIST,
42485626beecSKeith M Wesolowski "serial [[--unit=UNIT[,UNIT...]] | [--port=PORT[,PORT...]]] [--speed=SPEED] [--word=WORD] [--parity=PARITY] [--stop=STOP] [--device=DEV]",
42497c478bd9Sstevel@tonic-gate "Initialize a serial device. UNIT is a digit that specifies which serial"
42505626beecSKeith M Wesolowski " device is used (e.g. 0 == ttya (aka COM1)). If you need to specify the port"
42515626beecSKeith M Wesolowski " number, set it by --port. Either but not both of --unit and --port is"
42525626beecSKeith M Wesolowski " permitted; --unit takes precedence. Multiple devices may be specified,"
42535626beecSKeith M Wesolowski " separated by commas; the first working device in the list will be used"
42545626beecSKeith M Wesolowski " and the rest ignored. SPEED is the DTE-DTE speed. WORD is the word length,"
42557c478bd9Sstevel@tonic-gate " PARITY is the type of parity, which is one of `no', `odd' and `even'."
42567c478bd9Sstevel@tonic-gate " STOP is the length of stop bit(s). The option --device can be used only"
42577c478bd9Sstevel@tonic-gate " in the grub shell, which specifies the file name of a tty device. The"
42585626beecSKeith M Wesolowski " default values are ttya, 9600, 8N1."
42597c478bd9Sstevel@tonic-gate };
42607c478bd9Sstevel@tonic-gate #endif /* SUPPORT_SERIAL */
42617c478bd9Sstevel@tonic-gate
42627c478bd9Sstevel@tonic-gate
42637c478bd9Sstevel@tonic-gate /* setkey */
42647c478bd9Sstevel@tonic-gate struct keysym
42657c478bd9Sstevel@tonic-gate {
42667c478bd9Sstevel@tonic-gate char *unshifted_name; /* the name in unshifted state */
42677c478bd9Sstevel@tonic-gate char *shifted_name; /* the name in shifted state */
42687c478bd9Sstevel@tonic-gate unsigned char unshifted_ascii; /* the ascii code in unshifted state */
42697c478bd9Sstevel@tonic-gate unsigned char shifted_ascii; /* the ascii code in shifted state */
42707c478bd9Sstevel@tonic-gate unsigned char keycode; /* keyboard scancode */
42717c478bd9Sstevel@tonic-gate };
42727c478bd9Sstevel@tonic-gate
42737c478bd9Sstevel@tonic-gate /* The table for key symbols. If the "shifted" member of an entry is
42747c478bd9Sstevel@tonic-gate NULL, the entry does not have shifted state. */
42757c478bd9Sstevel@tonic-gate static struct keysym keysym_table[] =
42767c478bd9Sstevel@tonic-gate {
42777c478bd9Sstevel@tonic-gate {"escape", 0, 0x1b, 0, 0x01},
42787c478bd9Sstevel@tonic-gate {"1", "exclam", '1', '!', 0x02},
42797c478bd9Sstevel@tonic-gate {"2", "at", '2', '@', 0x03},
42807c478bd9Sstevel@tonic-gate {"3", "numbersign", '3', '#', 0x04},
42817c478bd9Sstevel@tonic-gate {"4", "dollar", '4', '$', 0x05},
42827c478bd9Sstevel@tonic-gate {"5", "percent", '5', '%', 0x06},
42837c478bd9Sstevel@tonic-gate {"6", "caret", '6', '^', 0x07},
42847c478bd9Sstevel@tonic-gate {"7", "ampersand", '7', '&', 0x08},
42857c478bd9Sstevel@tonic-gate {"8", "asterisk", '8', '*', 0x09},
42867c478bd9Sstevel@tonic-gate {"9", "parenleft", '9', '(', 0x0a},
42877c478bd9Sstevel@tonic-gate {"0", "parenright", '0', ')', 0x0b},
42887c478bd9Sstevel@tonic-gate {"minus", "underscore", '-', '_', 0x0c},
42897c478bd9Sstevel@tonic-gate {"equal", "plus", '=', '+', 0x0d},
42907c478bd9Sstevel@tonic-gate {"backspace", 0, '\b', 0, 0x0e},
42917c478bd9Sstevel@tonic-gate {"tab", 0, '\t', 0, 0x0f},
42927c478bd9Sstevel@tonic-gate {"q", "Q", 'q', 'Q', 0x10},
42937c478bd9Sstevel@tonic-gate {"w", "W", 'w', 'W', 0x11},
42947c478bd9Sstevel@tonic-gate {"e", "E", 'e', 'E', 0x12},
42957c478bd9Sstevel@tonic-gate {"r", "R", 'r', 'R', 0x13},
42967c478bd9Sstevel@tonic-gate {"t", "T", 't', 'T', 0x14},
42977c478bd9Sstevel@tonic-gate {"y", "Y", 'y', 'Y', 0x15},
42987c478bd9Sstevel@tonic-gate {"u", "U", 'u', 'U', 0x16},
42997c478bd9Sstevel@tonic-gate {"i", "I", 'i', 'I', 0x17},
43007c478bd9Sstevel@tonic-gate {"o", "O", 'o', 'O', 0x18},
43017c478bd9Sstevel@tonic-gate {"p", "P", 'p', 'P', 0x19},
43027c478bd9Sstevel@tonic-gate {"bracketleft", "braceleft", '[', '{', 0x1a},
43037c478bd9Sstevel@tonic-gate {"bracketright", "braceright", ']', '}', 0x1b},
43047c478bd9Sstevel@tonic-gate {"enter", 0, '\n', 0, 0x1c},
43057c478bd9Sstevel@tonic-gate {"control", 0, 0, 0, 0x1d},
43067c478bd9Sstevel@tonic-gate {"a", "A", 'a', 'A', 0x1e},
43077c478bd9Sstevel@tonic-gate {"s", "S", 's', 'S', 0x1f},
43087c478bd9Sstevel@tonic-gate {"d", "D", 'd', 'D', 0x20},
43097c478bd9Sstevel@tonic-gate {"f", "F", 'f', 'F', 0x21},
43107c478bd9Sstevel@tonic-gate {"g", "G", 'g', 'G', 0x22},
43117c478bd9Sstevel@tonic-gate {"h", "H", 'h', 'H', 0x23},
43127c478bd9Sstevel@tonic-gate {"j", "J", 'j', 'J', 0x24},
43137c478bd9Sstevel@tonic-gate {"k", "K", 'k', 'K', 0x25},
43147c478bd9Sstevel@tonic-gate {"l", "L", 'l', 'L', 0x26},
43157c478bd9Sstevel@tonic-gate {"semicolon", "colon", ';', ':', 0x27},
43167c478bd9Sstevel@tonic-gate {"quote", "doublequote", '\'', '"', 0x28},
43177c478bd9Sstevel@tonic-gate {"backquote", "tilde", '`', '~', 0x29},
43187c478bd9Sstevel@tonic-gate {"shift", 0, 0, 0, 0x2a},
43197c478bd9Sstevel@tonic-gate {"backslash", "bar", '\\', '|', 0x2b},
43207c478bd9Sstevel@tonic-gate {"z", "Z", 'z', 'Z', 0x2c},
43217c478bd9Sstevel@tonic-gate {"x", "X", 'x', 'X', 0x2d},
43227c478bd9Sstevel@tonic-gate {"c", "C", 'c', 'C', 0x2e},
43237c478bd9Sstevel@tonic-gate {"v", "V", 'v', 'V', 0x2f},
43247c478bd9Sstevel@tonic-gate {"b", "B", 'b', 'B', 0x30},
43257c478bd9Sstevel@tonic-gate {"n", "N", 'n', 'N', 0x31},
43267c478bd9Sstevel@tonic-gate {"m", "M", 'm', 'M', 0x32},
43277c478bd9Sstevel@tonic-gate {"comma", "less", ',', '<', 0x33},
43287c478bd9Sstevel@tonic-gate {"period", "greater", '.', '>', 0x34},
43297c478bd9Sstevel@tonic-gate {"slash", "question", '/', '?', 0x35},
43307c478bd9Sstevel@tonic-gate {"alt", 0, 0, 0, 0x38},
43317c478bd9Sstevel@tonic-gate {"space", 0, ' ', 0, 0x39},
43327c478bd9Sstevel@tonic-gate {"capslock", 0, 0, 0, 0x3a},
43337c478bd9Sstevel@tonic-gate {"F1", 0, 0, 0, 0x3b},
43347c478bd9Sstevel@tonic-gate {"F2", 0, 0, 0, 0x3c},
43357c478bd9Sstevel@tonic-gate {"F3", 0, 0, 0, 0x3d},
43367c478bd9Sstevel@tonic-gate {"F4", 0, 0, 0, 0x3e},
43377c478bd9Sstevel@tonic-gate {"F5", 0, 0, 0, 0x3f},
43387c478bd9Sstevel@tonic-gate {"F6", 0, 0, 0, 0x40},
43397c478bd9Sstevel@tonic-gate {"F7", 0, 0, 0, 0x41},
43407c478bd9Sstevel@tonic-gate {"F8", 0, 0, 0, 0x42},
43417c478bd9Sstevel@tonic-gate {"F9", 0, 0, 0, 0x43},
43427c478bd9Sstevel@tonic-gate {"F10", 0, 0, 0, 0x44},
43437c478bd9Sstevel@tonic-gate /* Caution: do not add NumLock here! we cannot deal with it properly. */
43447c478bd9Sstevel@tonic-gate {"delete", 0, 0x7f, 0, 0x53}
43457c478bd9Sstevel@tonic-gate };
43467c478bd9Sstevel@tonic-gate
43477c478bd9Sstevel@tonic-gate static int
setkey_func(char * arg,int flags)43487c478bd9Sstevel@tonic-gate setkey_func (char *arg, int flags)
43497c478bd9Sstevel@tonic-gate {
43507c478bd9Sstevel@tonic-gate char *to_key, *from_key;
43517c478bd9Sstevel@tonic-gate int to_code, from_code;
43527c478bd9Sstevel@tonic-gate int map_in_interrupt = 0;
43537c478bd9Sstevel@tonic-gate
43541b8adde7SWilliam Kucharski auto int find_key_code (char *key);
43551b8adde7SWilliam Kucharski auto int find_ascii_code (char *key);
43561b8adde7SWilliam Kucharski
43571b8adde7SWilliam Kucharski auto int find_key_code (char *key)
43587c478bd9Sstevel@tonic-gate {
43597c478bd9Sstevel@tonic-gate int i;
43607c478bd9Sstevel@tonic-gate
43617c478bd9Sstevel@tonic-gate for (i = 0; i < sizeof (keysym_table) / sizeof (keysym_table[0]); i++)
43627c478bd9Sstevel@tonic-gate {
43637c478bd9Sstevel@tonic-gate if (keysym_table[i].unshifted_name &&
43647c478bd9Sstevel@tonic-gate grub_strcmp (key, keysym_table[i].unshifted_name) == 0)
43657c478bd9Sstevel@tonic-gate return keysym_table[i].keycode;
43667c478bd9Sstevel@tonic-gate else if (keysym_table[i].shifted_name &&
43677c478bd9Sstevel@tonic-gate grub_strcmp (key, keysym_table[i].shifted_name) == 0)
43687c478bd9Sstevel@tonic-gate return keysym_table[i].keycode;
43697c478bd9Sstevel@tonic-gate }
43707c478bd9Sstevel@tonic-gate
43717c478bd9Sstevel@tonic-gate return 0;
43727c478bd9Sstevel@tonic-gate }
43737c478bd9Sstevel@tonic-gate
43741b8adde7SWilliam Kucharski auto int find_ascii_code (char *key)
43757c478bd9Sstevel@tonic-gate {
43767c478bd9Sstevel@tonic-gate int i;
43777c478bd9Sstevel@tonic-gate
43787c478bd9Sstevel@tonic-gate for (i = 0; i < sizeof (keysym_table) / sizeof (keysym_table[0]); i++)
43797c478bd9Sstevel@tonic-gate {
43807c478bd9Sstevel@tonic-gate if (keysym_table[i].unshifted_name &&
43817c478bd9Sstevel@tonic-gate grub_strcmp (key, keysym_table[i].unshifted_name) == 0)
43827c478bd9Sstevel@tonic-gate return keysym_table[i].unshifted_ascii;
43837c478bd9Sstevel@tonic-gate else if (keysym_table[i].shifted_name &&
43847c478bd9Sstevel@tonic-gate grub_strcmp (key, keysym_table[i].shifted_name) == 0)
43857c478bd9Sstevel@tonic-gate return keysym_table[i].shifted_ascii;
43867c478bd9Sstevel@tonic-gate }
43877c478bd9Sstevel@tonic-gate
43887c478bd9Sstevel@tonic-gate return 0;
43897c478bd9Sstevel@tonic-gate }
43907c478bd9Sstevel@tonic-gate
43917c478bd9Sstevel@tonic-gate to_key = arg;
43927c478bd9Sstevel@tonic-gate from_key = skip_to (0, to_key);
43937c478bd9Sstevel@tonic-gate
43947c478bd9Sstevel@tonic-gate if (! *to_key)
43957c478bd9Sstevel@tonic-gate {
43967c478bd9Sstevel@tonic-gate /* If the user specifies no argument, reset the key mappings. */
43977c478bd9Sstevel@tonic-gate grub_memset (bios_key_map, 0, KEY_MAP_SIZE * sizeof (unsigned short));
43987c478bd9Sstevel@tonic-gate grub_memset (ascii_key_map, 0, KEY_MAP_SIZE * sizeof (unsigned short));
43997c478bd9Sstevel@tonic-gate
44007c478bd9Sstevel@tonic-gate return 0;
44017c478bd9Sstevel@tonic-gate }
44027c478bd9Sstevel@tonic-gate else if (! *from_key)
44037c478bd9Sstevel@tonic-gate {
44047c478bd9Sstevel@tonic-gate /* The user must specify two arguments or zero argument. */
44057c478bd9Sstevel@tonic-gate errnum = ERR_BAD_ARGUMENT;
44067c478bd9Sstevel@tonic-gate return 1;
44077c478bd9Sstevel@tonic-gate }
44087c478bd9Sstevel@tonic-gate
44097c478bd9Sstevel@tonic-gate nul_terminate (to_key);
44107c478bd9Sstevel@tonic-gate nul_terminate (from_key);
44117c478bd9Sstevel@tonic-gate
44127c478bd9Sstevel@tonic-gate to_code = find_ascii_code (to_key);
44137c478bd9Sstevel@tonic-gate from_code = find_ascii_code (from_key);
44147c478bd9Sstevel@tonic-gate if (! to_code || ! from_code)
44157c478bd9Sstevel@tonic-gate {
44167c478bd9Sstevel@tonic-gate map_in_interrupt = 1;
44177c478bd9Sstevel@tonic-gate to_code = find_key_code (to_key);
44187c478bd9Sstevel@tonic-gate from_code = find_key_code (from_key);
44197c478bd9Sstevel@tonic-gate if (! to_code || ! from_code)
44207c478bd9Sstevel@tonic-gate {
44217c478bd9Sstevel@tonic-gate errnum = ERR_BAD_ARGUMENT;
44227c478bd9Sstevel@tonic-gate return 1;
44237c478bd9Sstevel@tonic-gate }
44247c478bd9Sstevel@tonic-gate }
44257c478bd9Sstevel@tonic-gate
44267c478bd9Sstevel@tonic-gate if (map_in_interrupt)
44277c478bd9Sstevel@tonic-gate {
44287c478bd9Sstevel@tonic-gate int i;
44297c478bd9Sstevel@tonic-gate
44307c478bd9Sstevel@tonic-gate /* Find an empty slot. */
44317c478bd9Sstevel@tonic-gate for (i = 0; i < KEY_MAP_SIZE; i++)
44327c478bd9Sstevel@tonic-gate {
44337c478bd9Sstevel@tonic-gate if ((bios_key_map[i] & 0xff) == from_code)
44347c478bd9Sstevel@tonic-gate /* Perhaps the user wants to overwrite the map. */
44357c478bd9Sstevel@tonic-gate break;
44367c478bd9Sstevel@tonic-gate
44377c478bd9Sstevel@tonic-gate if (! bios_key_map[i])
44387c478bd9Sstevel@tonic-gate break;
44397c478bd9Sstevel@tonic-gate }
44407c478bd9Sstevel@tonic-gate
44417c478bd9Sstevel@tonic-gate if (i == KEY_MAP_SIZE)
44427c478bd9Sstevel@tonic-gate {
44437c478bd9Sstevel@tonic-gate errnum = ERR_WONT_FIT;
44447c478bd9Sstevel@tonic-gate return 1;
44457c478bd9Sstevel@tonic-gate }
44467c478bd9Sstevel@tonic-gate
44477c478bd9Sstevel@tonic-gate if (to_code == from_code)
44487c478bd9Sstevel@tonic-gate /* If TO is equal to FROM, delete the entry. */
44497c478bd9Sstevel@tonic-gate grub_memmove ((char *) &bios_key_map[i],
44507c478bd9Sstevel@tonic-gate (char *) &bios_key_map[i + 1],
44517c478bd9Sstevel@tonic-gate sizeof (unsigned short) * (KEY_MAP_SIZE - i));
44527c478bd9Sstevel@tonic-gate else
44537c478bd9Sstevel@tonic-gate bios_key_map[i] = (to_code << 8) | from_code;
44547c478bd9Sstevel@tonic-gate
44557c478bd9Sstevel@tonic-gate /* Ugly but should work. */
44567c478bd9Sstevel@tonic-gate unset_int15_handler ();
44577c478bd9Sstevel@tonic-gate set_int15_handler ();
44587c478bd9Sstevel@tonic-gate }
44597c478bd9Sstevel@tonic-gate else
44607c478bd9Sstevel@tonic-gate {
44617c478bd9Sstevel@tonic-gate int i;
44627c478bd9Sstevel@tonic-gate
44637c478bd9Sstevel@tonic-gate /* Find an empty slot. */
44647c478bd9Sstevel@tonic-gate for (i = 0; i < KEY_MAP_SIZE; i++)
44657c478bd9Sstevel@tonic-gate {
44667c478bd9Sstevel@tonic-gate if ((ascii_key_map[i] & 0xff) == from_code)
44677c478bd9Sstevel@tonic-gate /* Perhaps the user wants to overwrite the map. */
44687c478bd9Sstevel@tonic-gate break;
44697c478bd9Sstevel@tonic-gate
44707c478bd9Sstevel@tonic-gate if (! ascii_key_map[i])
44717c478bd9Sstevel@tonic-gate break;
44727c478bd9Sstevel@tonic-gate }
44737c478bd9Sstevel@tonic-gate
44747c478bd9Sstevel@tonic-gate if (i == KEY_MAP_SIZE)
44757c478bd9Sstevel@tonic-gate {
44767c478bd9Sstevel@tonic-gate errnum = ERR_WONT_FIT;
44777c478bd9Sstevel@tonic-gate return 1;
44787c478bd9Sstevel@tonic-gate }
44797c478bd9Sstevel@tonic-gate
44807c478bd9Sstevel@tonic-gate if (to_code == from_code)
44817c478bd9Sstevel@tonic-gate /* If TO is equal to FROM, delete the entry. */
44827c478bd9Sstevel@tonic-gate grub_memmove ((char *) &ascii_key_map[i],
44837c478bd9Sstevel@tonic-gate (char *) &ascii_key_map[i + 1],
44847c478bd9Sstevel@tonic-gate sizeof (unsigned short) * (KEY_MAP_SIZE - i));
44857c478bd9Sstevel@tonic-gate else
44867c478bd9Sstevel@tonic-gate ascii_key_map[i] = (to_code << 8) | from_code;
44877c478bd9Sstevel@tonic-gate }
44887c478bd9Sstevel@tonic-gate
44897c478bd9Sstevel@tonic-gate return 0;
44907c478bd9Sstevel@tonic-gate }
44917c478bd9Sstevel@tonic-gate
44927c478bd9Sstevel@tonic-gate static struct builtin builtin_setkey =
44937c478bd9Sstevel@tonic-gate {
44947c478bd9Sstevel@tonic-gate "setkey",
44957c478bd9Sstevel@tonic-gate setkey_func,
44967c478bd9Sstevel@tonic-gate BUILTIN_CMDLINE | BUILTIN_MENU | BUILTIN_HELP_LIST,
44977c478bd9Sstevel@tonic-gate "setkey [TO_KEY FROM_KEY]",
44987c478bd9Sstevel@tonic-gate "Change the keyboard map. The key FROM_KEY is mapped to the key TO_KEY."
44997c478bd9Sstevel@tonic-gate " A key must be an alphabet, a digit, or one of these: escape, exclam,"
45007c478bd9Sstevel@tonic-gate " at, numbersign, dollar, percent, caret, ampersand, asterisk, parenleft,"
45017c478bd9Sstevel@tonic-gate " parenright, minus, underscore, equal, plus, backspace, tab, bracketleft,"
45027c478bd9Sstevel@tonic-gate " braceleft, bracketright, braceright, enter, control, semicolon, colon,"
45037c478bd9Sstevel@tonic-gate " quote, doublequote, backquote, tilde, shift, backslash, bar, comma,"
45047c478bd9Sstevel@tonic-gate " less, period, greater, slash, question, alt, space, capslock, FX (X"
45057c478bd9Sstevel@tonic-gate " is a digit), and delete. If no argument is specified, reset key"
45067c478bd9Sstevel@tonic-gate " mappings."
45077c478bd9Sstevel@tonic-gate };
45087c478bd9Sstevel@tonic-gate
45097c478bd9Sstevel@tonic-gate
45107c478bd9Sstevel@tonic-gate /* setup */
45117c478bd9Sstevel@tonic-gate static int
setup_func(char * arg,int flags)45127c478bd9Sstevel@tonic-gate setup_func (char *arg, int flags)
45137c478bd9Sstevel@tonic-gate {
45147c478bd9Sstevel@tonic-gate /* Point to the string of the installed drive/partition. */
45157c478bd9Sstevel@tonic-gate char *install_ptr;
45167c478bd9Sstevel@tonic-gate /* Point to the string of the drive/parition where the GRUB images
45177c478bd9Sstevel@tonic-gate reside. */
45187c478bd9Sstevel@tonic-gate char *image_ptr;
45197c478bd9Sstevel@tonic-gate unsigned long installed_drive, installed_partition;
45207c478bd9Sstevel@tonic-gate unsigned long image_drive, image_partition;
45217c478bd9Sstevel@tonic-gate unsigned long tmp_drive, tmp_partition;
45227c478bd9Sstevel@tonic-gate char stage1[64];
45237c478bd9Sstevel@tonic-gate char stage2[64];
45247c478bd9Sstevel@tonic-gate char config_filename[64];
45257c478bd9Sstevel@tonic-gate char real_config_filename[64];
45267c478bd9Sstevel@tonic-gate char cmd_arg[256];
45277c478bd9Sstevel@tonic-gate char device[16];
45287c478bd9Sstevel@tonic-gate char *buffer = (char *) RAW_ADDR (0x100000);
45297c478bd9Sstevel@tonic-gate int is_force_lba = 0;
45307c478bd9Sstevel@tonic-gate char *stage2_arg = 0;
45317c478bd9Sstevel@tonic-gate char *prefix = 0;
45327c478bd9Sstevel@tonic-gate
45337c478bd9Sstevel@tonic-gate auto int check_file (char *file);
45347c478bd9Sstevel@tonic-gate auto void sprint_device (int drive, int partition);
45357c478bd9Sstevel@tonic-gate auto int embed_stage1_5 (char * stage1_5, int drive, int partition);
45367c478bd9Sstevel@tonic-gate
45377c478bd9Sstevel@tonic-gate /* Check if the file FILE exists like Autoconf. */
45387c478bd9Sstevel@tonic-gate int check_file (char *file)
45397c478bd9Sstevel@tonic-gate {
45407c478bd9Sstevel@tonic-gate int ret;
45417c478bd9Sstevel@tonic-gate
45427c478bd9Sstevel@tonic-gate grub_printf (" Checking if \"%s\" exists... ", file);
45437c478bd9Sstevel@tonic-gate ret = grub_open (file);
45447c478bd9Sstevel@tonic-gate if (ret)
45457c478bd9Sstevel@tonic-gate {
45467c478bd9Sstevel@tonic-gate grub_close ();
45477c478bd9Sstevel@tonic-gate grub_printf ("yes\n");
45487c478bd9Sstevel@tonic-gate }
45497c478bd9Sstevel@tonic-gate else
45507c478bd9Sstevel@tonic-gate grub_printf ("no\n");
45517c478bd9Sstevel@tonic-gate
45527c478bd9Sstevel@tonic-gate return ret;
45537c478bd9Sstevel@tonic-gate }
45547c478bd9Sstevel@tonic-gate
45557c478bd9Sstevel@tonic-gate /* Construct a device name in DEVICE. */
45567c478bd9Sstevel@tonic-gate void sprint_device (int drive, int partition)
45577c478bd9Sstevel@tonic-gate {
45587c478bd9Sstevel@tonic-gate grub_sprintf (device, "(%cd%d",
45597c478bd9Sstevel@tonic-gate (drive & 0x80) ? 'h' : 'f',
45607c478bd9Sstevel@tonic-gate drive & ~0x80);
45617c478bd9Sstevel@tonic-gate if ((partition & 0xFF0000) != 0xFF0000)
45627c478bd9Sstevel@tonic-gate {
45637c478bd9Sstevel@tonic-gate char tmp[16];
45647c478bd9Sstevel@tonic-gate grub_sprintf (tmp, ",%d", (partition >> 16) & 0xFF);
456509fadd94SJerry Jelinek grub_strncat (device, tmp, sizeof (device));
45667c478bd9Sstevel@tonic-gate }
45677c478bd9Sstevel@tonic-gate if ((partition & 0x00FF00) != 0x00FF00)
45687c478bd9Sstevel@tonic-gate {
45697c478bd9Sstevel@tonic-gate char tmp[16];
45707c478bd9Sstevel@tonic-gate grub_sprintf (tmp, ",%c", 'a' + ((partition >> 8) & 0xFF));
457109fadd94SJerry Jelinek grub_strncat (device, tmp, sizeof (device));
45727c478bd9Sstevel@tonic-gate }
457309fadd94SJerry Jelinek grub_strncat (device, ")", sizeof (device));
45747c478bd9Sstevel@tonic-gate }
45757c478bd9Sstevel@tonic-gate
45767c478bd9Sstevel@tonic-gate int embed_stage1_5 (char *stage1_5, int drive, int partition)
45777c478bd9Sstevel@tonic-gate {
45787c478bd9Sstevel@tonic-gate /* We install GRUB into the MBR, so try to embed the
45797c478bd9Sstevel@tonic-gate Stage 1.5 in the sectors right after the MBR. */
45807c478bd9Sstevel@tonic-gate sprint_device (drive, partition);
45817c478bd9Sstevel@tonic-gate grub_sprintf (cmd_arg, "%s %s", stage1_5, device);
45827c478bd9Sstevel@tonic-gate
45837c478bd9Sstevel@tonic-gate /* Notify what will be run. */
45847c478bd9Sstevel@tonic-gate grub_printf (" Running \"embed %s\"... ", cmd_arg);
45857c478bd9Sstevel@tonic-gate
45867c478bd9Sstevel@tonic-gate embed_func (cmd_arg, flags);
45877c478bd9Sstevel@tonic-gate if (! errnum)
45887c478bd9Sstevel@tonic-gate {
45897c478bd9Sstevel@tonic-gate /* Construct the blocklist representation. */
45907c478bd9Sstevel@tonic-gate grub_sprintf (buffer, "%s%s", device, embed_info);
45917c478bd9Sstevel@tonic-gate grub_printf ("succeeded\n");
45927c478bd9Sstevel@tonic-gate return 1;
45937c478bd9Sstevel@tonic-gate }
45947c478bd9Sstevel@tonic-gate else
45957c478bd9Sstevel@tonic-gate {
45967c478bd9Sstevel@tonic-gate grub_printf ("failed (this is not fatal)\n");
45977c478bd9Sstevel@tonic-gate return 0;
45987c478bd9Sstevel@tonic-gate }
45997c478bd9Sstevel@tonic-gate }
46007c478bd9Sstevel@tonic-gate
46017c478bd9Sstevel@tonic-gate struct stage1_5_map {
46027c478bd9Sstevel@tonic-gate char *fsys;
46037c478bd9Sstevel@tonic-gate char *name;
46047c478bd9Sstevel@tonic-gate };
46057c478bd9Sstevel@tonic-gate struct stage1_5_map stage1_5_map[] =
46067c478bd9Sstevel@tonic-gate {
46077c478bd9Sstevel@tonic-gate {"ext2fs", "/e2fs_stage1_5"},
46087c478bd9Sstevel@tonic-gate {"fat", "/fat_stage1_5"},
46097c478bd9Sstevel@tonic-gate {"ufs2", "/ufs2_stage1_5"},
46107c478bd9Sstevel@tonic-gate {"ffs", "/ffs_stage1_5"},
46117c478bd9Sstevel@tonic-gate {"iso9660", "/iso9660_stage1_5"},
46127c478bd9Sstevel@tonic-gate {"jfs", "/jfs_stage1_5"},
46137c478bd9Sstevel@tonic-gate {"minix", "/minix_stage1_5"},
46147c478bd9Sstevel@tonic-gate {"reiserfs", "/reiserfs_stage1_5"},
46157c478bd9Sstevel@tonic-gate {"vstafs", "/vstafs_stage1_5"},
46167c478bd9Sstevel@tonic-gate {"xfs", "/xfs_stage1_5"},
46177c478bd9Sstevel@tonic-gate {"ufs", "/ufs_stage1_5"}
46187c478bd9Sstevel@tonic-gate };
46197c478bd9Sstevel@tonic-gate
46207c478bd9Sstevel@tonic-gate tmp_drive = saved_drive;
46217c478bd9Sstevel@tonic-gate tmp_partition = saved_partition;
46227c478bd9Sstevel@tonic-gate
46237c478bd9Sstevel@tonic-gate /* Check if the user specifies --force-lba. */
46247c478bd9Sstevel@tonic-gate while (1)
46257c478bd9Sstevel@tonic-gate {
46267c478bd9Sstevel@tonic-gate if (grub_memcmp ("--force-lba", arg, sizeof ("--force-lba") - 1) == 0)
46277c478bd9Sstevel@tonic-gate {
46287c478bd9Sstevel@tonic-gate is_force_lba = 1;
46297c478bd9Sstevel@tonic-gate arg = skip_to (0, arg);
46307c478bd9Sstevel@tonic-gate }
46317c478bd9Sstevel@tonic-gate else if (grub_memcmp ("--prefix=", arg, sizeof ("--prefix=") - 1) == 0)
46327c478bd9Sstevel@tonic-gate {
46337c478bd9Sstevel@tonic-gate prefix = arg + sizeof ("--prefix=") - 1;
46347c478bd9Sstevel@tonic-gate arg = skip_to (0, arg);
46357c478bd9Sstevel@tonic-gate nul_terminate (prefix);
46367c478bd9Sstevel@tonic-gate }
46377c478bd9Sstevel@tonic-gate #ifdef GRUB_UTIL
46387c478bd9Sstevel@tonic-gate else if (grub_memcmp ("--stage2=", arg, sizeof ("--stage2=") - 1) == 0)
46397c478bd9Sstevel@tonic-gate {
46407c478bd9Sstevel@tonic-gate stage2_arg = arg;
46417c478bd9Sstevel@tonic-gate arg = skip_to (0, arg);
46427c478bd9Sstevel@tonic-gate nul_terminate (stage2_arg);
46437c478bd9Sstevel@tonic-gate }
46447c478bd9Sstevel@tonic-gate #endif /* GRUB_UTIL */
46457c478bd9Sstevel@tonic-gate else
46467c478bd9Sstevel@tonic-gate break;
46477c478bd9Sstevel@tonic-gate }
46487c478bd9Sstevel@tonic-gate
46497c478bd9Sstevel@tonic-gate install_ptr = arg;
46507c478bd9Sstevel@tonic-gate image_ptr = skip_to (0, install_ptr);
46517c478bd9Sstevel@tonic-gate
46527c478bd9Sstevel@tonic-gate /* Make sure that INSTALL_PTR is valid. */
46537c478bd9Sstevel@tonic-gate set_device (install_ptr);
46547c478bd9Sstevel@tonic-gate if (errnum)
46557c478bd9Sstevel@tonic-gate return 1;
46567c478bd9Sstevel@tonic-gate
46577c478bd9Sstevel@tonic-gate installed_drive = current_drive;
46587c478bd9Sstevel@tonic-gate installed_partition = current_partition;
46597c478bd9Sstevel@tonic-gate
46607c478bd9Sstevel@tonic-gate /* Mount the drive pointed by IMAGE_PTR. */
46617c478bd9Sstevel@tonic-gate if (*image_ptr)
46627c478bd9Sstevel@tonic-gate {
46637c478bd9Sstevel@tonic-gate /* If the drive/partition where the images reside is specified,
46647c478bd9Sstevel@tonic-gate get the drive and the partition. */
46657c478bd9Sstevel@tonic-gate set_device (image_ptr);
46667c478bd9Sstevel@tonic-gate if (errnum)
46677c478bd9Sstevel@tonic-gate return 1;
46687c478bd9Sstevel@tonic-gate }
46697c478bd9Sstevel@tonic-gate else
46707c478bd9Sstevel@tonic-gate {
46717c478bd9Sstevel@tonic-gate /* If omitted, use SAVED_PARTITION and SAVED_DRIVE. */
46727c478bd9Sstevel@tonic-gate current_drive = saved_drive;
46737c478bd9Sstevel@tonic-gate current_partition = saved_partition;
46747c478bd9Sstevel@tonic-gate }
46757c478bd9Sstevel@tonic-gate
46767c478bd9Sstevel@tonic-gate image_drive = saved_drive = current_drive;
46777c478bd9Sstevel@tonic-gate image_partition = saved_partition = current_partition;
46787c478bd9Sstevel@tonic-gate
46797c478bd9Sstevel@tonic-gate /* Open it. */
46807c478bd9Sstevel@tonic-gate if (! open_device ())
46817c478bd9Sstevel@tonic-gate goto fail;
46827c478bd9Sstevel@tonic-gate
46837c478bd9Sstevel@tonic-gate /* Check if stage1 exists. If the user doesn't specify the option
46847c478bd9Sstevel@tonic-gate `--prefix', attempt /boot/grub and /grub. */
46857c478bd9Sstevel@tonic-gate /* NOTE: It is dangerous to run this command without `--prefix' in the
46867c478bd9Sstevel@tonic-gate grub shell, since that affects `--stage2'. */
46877c478bd9Sstevel@tonic-gate if (! prefix)
46887c478bd9Sstevel@tonic-gate {
46897c478bd9Sstevel@tonic-gate prefix = "/boot/grub";
46907c478bd9Sstevel@tonic-gate grub_sprintf (stage1, "%s%s", prefix, "/stage1");
46917c478bd9Sstevel@tonic-gate if (! check_file (stage1))
46927c478bd9Sstevel@tonic-gate {
46937c478bd9Sstevel@tonic-gate errnum = ERR_NONE;
46947c478bd9Sstevel@tonic-gate prefix = "/grub";
46957c478bd9Sstevel@tonic-gate grub_sprintf (stage1, "%s%s", prefix, "/stage1");
46967c478bd9Sstevel@tonic-gate if (! check_file (stage1))
46977c478bd9Sstevel@tonic-gate goto fail;
46987c478bd9Sstevel@tonic-gate }
46997c478bd9Sstevel@tonic-gate }
47007c478bd9Sstevel@tonic-gate else
47017c478bd9Sstevel@tonic-gate {
47027c478bd9Sstevel@tonic-gate grub_sprintf (stage1, "%s%s", prefix, "/stage1");
47037c478bd9Sstevel@tonic-gate if (! check_file (stage1))
47047c478bd9Sstevel@tonic-gate goto fail;
47057c478bd9Sstevel@tonic-gate }
47067c478bd9Sstevel@tonic-gate
47077c478bd9Sstevel@tonic-gate /* The prefix was determined. */
47087c478bd9Sstevel@tonic-gate grub_sprintf (stage2, "%s%s", prefix, "/stage2");
47097c478bd9Sstevel@tonic-gate grub_sprintf (config_filename, "%s%s", prefix, "/menu.lst");
47107c478bd9Sstevel@tonic-gate *real_config_filename = 0;
47117c478bd9Sstevel@tonic-gate
47127c478bd9Sstevel@tonic-gate /* Check if stage2 exists. */
47137c478bd9Sstevel@tonic-gate if (! check_file (stage2))
47147c478bd9Sstevel@tonic-gate goto fail;
47157c478bd9Sstevel@tonic-gate
47167c478bd9Sstevel@tonic-gate {
47177c478bd9Sstevel@tonic-gate char *fsys = fsys_table[fsys_type].name;
47187c478bd9Sstevel@tonic-gate int i;
47197c478bd9Sstevel@tonic-gate int size = sizeof (stage1_5_map) / sizeof (stage1_5_map[0]);
47207c478bd9Sstevel@tonic-gate
47217c478bd9Sstevel@tonic-gate /* Iterate finding the same filesystem name as FSYS. */
47227c478bd9Sstevel@tonic-gate for (i = 0; i < size; i++)
47237c478bd9Sstevel@tonic-gate if (grub_strcmp (fsys, stage1_5_map[i].fsys) == 0)
47247c478bd9Sstevel@tonic-gate {
47257c478bd9Sstevel@tonic-gate /* OK, check if the Stage 1.5 exists. */
47267c478bd9Sstevel@tonic-gate char stage1_5[64];
47277c478bd9Sstevel@tonic-gate
47287c478bd9Sstevel@tonic-gate grub_sprintf (stage1_5, "%s%s", prefix, stage1_5_map[i].name);
47297c478bd9Sstevel@tonic-gate if (check_file (stage1_5))
47307c478bd9Sstevel@tonic-gate {
47317c478bd9Sstevel@tonic-gate if (embed_stage1_5 (stage1_5,
47327c478bd9Sstevel@tonic-gate installed_drive, installed_partition)
47337c478bd9Sstevel@tonic-gate || embed_stage1_5 (stage1_5,
47347c478bd9Sstevel@tonic-gate image_drive, image_partition))
47357c478bd9Sstevel@tonic-gate {
47367c478bd9Sstevel@tonic-gate grub_strcpy (real_config_filename, config_filename);
47377c478bd9Sstevel@tonic-gate sprint_device (image_drive, image_partition);
47387c478bd9Sstevel@tonic-gate grub_sprintf (config_filename, "%s%s", device, stage2);
47397c478bd9Sstevel@tonic-gate grub_strcpy (stage2, buffer);
47407c478bd9Sstevel@tonic-gate }
47417c478bd9Sstevel@tonic-gate }
47427c478bd9Sstevel@tonic-gate errnum = 0;
47437c478bd9Sstevel@tonic-gate break;
47447c478bd9Sstevel@tonic-gate }
47457c478bd9Sstevel@tonic-gate }
47467c478bd9Sstevel@tonic-gate
47477c478bd9Sstevel@tonic-gate /* Construct a string that is used by the command "install" as its
47487c478bd9Sstevel@tonic-gate arguments. */
47497c478bd9Sstevel@tonic-gate sprint_device (installed_drive, installed_partition);
47507c478bd9Sstevel@tonic-gate
47517c478bd9Sstevel@tonic-gate #if 1
47527c478bd9Sstevel@tonic-gate /* Don't embed a drive number unnecessarily. */
47537c478bd9Sstevel@tonic-gate grub_sprintf (cmd_arg, "%s%s%s%s %s%s %s p %s %s",
47547c478bd9Sstevel@tonic-gate is_force_lba? "--force-lba " : "",
47557c478bd9Sstevel@tonic-gate stage2_arg? stage2_arg : "",
47567c478bd9Sstevel@tonic-gate stage2_arg? " " : "",
47577c478bd9Sstevel@tonic-gate stage1,
47587c478bd9Sstevel@tonic-gate (installed_drive != image_drive) ? "d " : "",
47597c478bd9Sstevel@tonic-gate device,
47607c478bd9Sstevel@tonic-gate stage2,
47617c478bd9Sstevel@tonic-gate config_filename,
47627c478bd9Sstevel@tonic-gate real_config_filename);
47637c478bd9Sstevel@tonic-gate #else /* NOT USED */
47647c478bd9Sstevel@tonic-gate /* This code was used, because we belived some BIOSes had a problem
47657c478bd9Sstevel@tonic-gate that they didn't pass a booting drive correctly. It turned out,
47667c478bd9Sstevel@tonic-gate however, stage1 could trash a booting drive when checking LBA support,
47677c478bd9Sstevel@tonic-gate because some BIOSes modified the register %dx in INT 13H, AH=48H.
47687c478bd9Sstevel@tonic-gate So it becamed unclear whether GRUB should use a pre-defined booting
47697c478bd9Sstevel@tonic-gate drive or not. If the problem still exists, it would be necessary to
47707c478bd9Sstevel@tonic-gate switch back to this code. */
47717c478bd9Sstevel@tonic-gate grub_sprintf (cmd_arg, "%s%s%s%s d %s %s p %s %s",
47727c478bd9Sstevel@tonic-gate is_force_lba? "--force-lba " : "",
47737c478bd9Sstevel@tonic-gate stage2_arg? stage2_arg : "",
47747c478bd9Sstevel@tonic-gate stage2_arg? " " : "",
47757c478bd9Sstevel@tonic-gate stage1,
47767c478bd9Sstevel@tonic-gate device,
47777c478bd9Sstevel@tonic-gate stage2,
47787c478bd9Sstevel@tonic-gate config_filename,
47797c478bd9Sstevel@tonic-gate real_config_filename);
47807c478bd9Sstevel@tonic-gate #endif /* NOT USED */
47817c478bd9Sstevel@tonic-gate
47827c478bd9Sstevel@tonic-gate /* Notify what will be run. */
47837c478bd9Sstevel@tonic-gate grub_printf (" Running \"install %s\"... ", cmd_arg);
47847c478bd9Sstevel@tonic-gate
47857c478bd9Sstevel@tonic-gate /* Make sure that SAVED_DRIVE and SAVED_PARTITION are identical
47867c478bd9Sstevel@tonic-gate with IMAGE_DRIVE and IMAGE_PARTITION, respectively. */
47877c478bd9Sstevel@tonic-gate saved_drive = image_drive;
47887c478bd9Sstevel@tonic-gate saved_partition = image_partition;
47897c478bd9Sstevel@tonic-gate
47907c478bd9Sstevel@tonic-gate /* Run the command. */
47917c478bd9Sstevel@tonic-gate if (! install_func (cmd_arg, flags))
47927c478bd9Sstevel@tonic-gate grub_printf ("succeeded\nDone.\n");
47937c478bd9Sstevel@tonic-gate else
47947c478bd9Sstevel@tonic-gate grub_printf ("failed\n");
47957c478bd9Sstevel@tonic-gate
47967c478bd9Sstevel@tonic-gate fail:
47977c478bd9Sstevel@tonic-gate saved_drive = tmp_drive;
47987c478bd9Sstevel@tonic-gate saved_partition = tmp_partition;
47997c478bd9Sstevel@tonic-gate return errnum;
48007c478bd9Sstevel@tonic-gate }
48017c478bd9Sstevel@tonic-gate
48027c478bd9Sstevel@tonic-gate static struct builtin builtin_setup =
48037c478bd9Sstevel@tonic-gate {
48047c478bd9Sstevel@tonic-gate "setup",
48057c478bd9Sstevel@tonic-gate setup_func,
48067c478bd9Sstevel@tonic-gate BUILTIN_CMDLINE | BUILTIN_HELP_LIST,
48077c478bd9Sstevel@tonic-gate "setup [--prefix=DIR] [--stage2=STAGE2_FILE] [--force-lba] INSTALL_DEVICE [IMAGE_DEVICE]",
48087c478bd9Sstevel@tonic-gate "Set up the installation of GRUB automatically. This command uses"
48097c478bd9Sstevel@tonic-gate " the more flexible command \"install\" in the backend and installs"
48107c478bd9Sstevel@tonic-gate " GRUB into the device INSTALL_DEVICE. If IMAGE_DEVICE is specified,"
48117c478bd9Sstevel@tonic-gate " then find the GRUB images in the device IMAGE_DEVICE, otherwise"
48127c478bd9Sstevel@tonic-gate " use the current \"root device\", which can be set by the command"
48137c478bd9Sstevel@tonic-gate " \"root\". If you know that your BIOS should support LBA but GRUB"
48147c478bd9Sstevel@tonic-gate " doesn't work in LBA mode, specify the option `--force-lba'."
48157c478bd9Sstevel@tonic-gate " If you install GRUB under the grub shell and you cannot unmount the"
48167c478bd9Sstevel@tonic-gate " partition where GRUB images reside, specify the option `--stage2'"
48177c478bd9Sstevel@tonic-gate " to tell GRUB the file name under your OS."
48187c478bd9Sstevel@tonic-gate };
48197c478bd9Sstevel@tonic-gate
48207c478bd9Sstevel@tonic-gate
48217c478bd9Sstevel@tonic-gate #if defined(SUPPORT_SERIAL) || defined(SUPPORT_HERCULES) || defined(SUPPORT_GRAPHICS)
48227c478bd9Sstevel@tonic-gate /* terminal */
48237c478bd9Sstevel@tonic-gate static int
terminal_func(char * arg,int flags)48247c478bd9Sstevel@tonic-gate terminal_func (char *arg, int flags)
48257c478bd9Sstevel@tonic-gate {
48267c478bd9Sstevel@tonic-gate /* The index of the default terminal in TERM_TABLE. */
48277c478bd9Sstevel@tonic-gate int default_term = -1;
48287c478bd9Sstevel@tonic-gate struct term_entry *prev_term = current_term;
48297c478bd9Sstevel@tonic-gate int to = -1;
48307c478bd9Sstevel@tonic-gate int lines = 0;
48317c478bd9Sstevel@tonic-gate int no_message = 0;
48327c478bd9Sstevel@tonic-gate unsigned long term_flags = 0;
48337c478bd9Sstevel@tonic-gate /* XXX: Assume less than 32 terminals. */
48347c478bd9Sstevel@tonic-gate unsigned long term_bitmap = 0;
48357c478bd9Sstevel@tonic-gate
48367c478bd9Sstevel@tonic-gate /* Get GNU-style long options. */
48377c478bd9Sstevel@tonic-gate while (1)
48387c478bd9Sstevel@tonic-gate {
48397c478bd9Sstevel@tonic-gate if (grub_memcmp (arg, "--dumb", sizeof ("--dumb") - 1) == 0)
48407c478bd9Sstevel@tonic-gate term_flags |= TERM_DUMB;
48417c478bd9Sstevel@tonic-gate else if (grub_memcmp (arg, "--no-echo", sizeof ("--no-echo") - 1) == 0)
48427c478bd9Sstevel@tonic-gate /* ``--no-echo'' implies ``--no-edit''. */
48437c478bd9Sstevel@tonic-gate term_flags |= (TERM_NO_ECHO | TERM_NO_EDIT);
48447c478bd9Sstevel@tonic-gate else if (grub_memcmp (arg, "--no-edit", sizeof ("--no-edit") - 1) == 0)
48457c478bd9Sstevel@tonic-gate term_flags |= TERM_NO_EDIT;
48467c478bd9Sstevel@tonic-gate else if (grub_memcmp (arg, "--timeout=", sizeof ("--timeout=") - 1) == 0)
48477c478bd9Sstevel@tonic-gate {
48487c478bd9Sstevel@tonic-gate char *val = arg + sizeof ("--timeout=") - 1;
48497c478bd9Sstevel@tonic-gate
48507c478bd9Sstevel@tonic-gate if (! safe_parse_maxint (&val, &to))
48517c478bd9Sstevel@tonic-gate return 1;
48527c478bd9Sstevel@tonic-gate }
48537c478bd9Sstevel@tonic-gate else if (grub_memcmp (arg, "--lines=", sizeof ("--lines=") - 1) == 0)
48547c478bd9Sstevel@tonic-gate {
48557c478bd9Sstevel@tonic-gate char *val = arg + sizeof ("--lines=") - 1;
48567c478bd9Sstevel@tonic-gate
48577c478bd9Sstevel@tonic-gate if (! safe_parse_maxint (&val, &lines))
48587c478bd9Sstevel@tonic-gate return 1;
48597c478bd9Sstevel@tonic-gate
48607c478bd9Sstevel@tonic-gate /* Probably less than four is meaningless.... */
48617c478bd9Sstevel@tonic-gate if (lines < 4)
48627c478bd9Sstevel@tonic-gate {
48637c478bd9Sstevel@tonic-gate errnum = ERR_BAD_ARGUMENT;
48647c478bd9Sstevel@tonic-gate return 1;
48657c478bd9Sstevel@tonic-gate }
48667c478bd9Sstevel@tonic-gate }
48677c478bd9Sstevel@tonic-gate else if (grub_memcmp (arg, "--silent", sizeof ("--silent") - 1) == 0)
48687c478bd9Sstevel@tonic-gate no_message = 1;
48697c478bd9Sstevel@tonic-gate else
48707c478bd9Sstevel@tonic-gate break;
48717c478bd9Sstevel@tonic-gate
48727c478bd9Sstevel@tonic-gate arg = skip_to (0, arg);
48737c478bd9Sstevel@tonic-gate }
48747c478bd9Sstevel@tonic-gate
48757c478bd9Sstevel@tonic-gate /* If no argument is specified, show current setting. */
48767c478bd9Sstevel@tonic-gate if (! *arg)
48777c478bd9Sstevel@tonic-gate {
48787c478bd9Sstevel@tonic-gate grub_printf ("%s%s%s%s\n",
48797c478bd9Sstevel@tonic-gate current_term->name,
48807c478bd9Sstevel@tonic-gate current_term->flags & TERM_DUMB ? " (dumb)" : "",
48817c478bd9Sstevel@tonic-gate current_term->flags & TERM_NO_EDIT ? " (no edit)" : "",
48827c478bd9Sstevel@tonic-gate current_term->flags & TERM_NO_ECHO ? " (no echo)" : "");
48837c478bd9Sstevel@tonic-gate return 0;
48847c478bd9Sstevel@tonic-gate }
48857c478bd9Sstevel@tonic-gate
48867c478bd9Sstevel@tonic-gate while (*arg)
48877c478bd9Sstevel@tonic-gate {
48887c478bd9Sstevel@tonic-gate int i;
48897c478bd9Sstevel@tonic-gate char *next = skip_to (0, arg);
48907c478bd9Sstevel@tonic-gate
48917c478bd9Sstevel@tonic-gate nul_terminate (arg);
48927c478bd9Sstevel@tonic-gate
48937c478bd9Sstevel@tonic-gate for (i = 0; term_table[i].name; i++)
48947c478bd9Sstevel@tonic-gate {
48957c478bd9Sstevel@tonic-gate if (grub_strcmp (arg, term_table[i].name) == 0)
48967c478bd9Sstevel@tonic-gate {
48977c478bd9Sstevel@tonic-gate if (term_table[i].flags & TERM_NEED_INIT)
48987c478bd9Sstevel@tonic-gate {
48997c478bd9Sstevel@tonic-gate errnum = ERR_DEV_NEED_INIT;
49007c478bd9Sstevel@tonic-gate return 1;
49017c478bd9Sstevel@tonic-gate }
49027c478bd9Sstevel@tonic-gate
49037c478bd9Sstevel@tonic-gate if (default_term < 0)
49047c478bd9Sstevel@tonic-gate default_term = i;
49057c478bd9Sstevel@tonic-gate
49067c478bd9Sstevel@tonic-gate term_bitmap |= (1 << i);
49077c478bd9Sstevel@tonic-gate break;
49087c478bd9Sstevel@tonic-gate }
49097c478bd9Sstevel@tonic-gate }
49107c478bd9Sstevel@tonic-gate
49117c478bd9Sstevel@tonic-gate if (! term_table[i].name)
49127c478bd9Sstevel@tonic-gate {
49137c478bd9Sstevel@tonic-gate errnum = ERR_BAD_ARGUMENT;
49147c478bd9Sstevel@tonic-gate return 1;
49157c478bd9Sstevel@tonic-gate }
49167c478bd9Sstevel@tonic-gate
49177c478bd9Sstevel@tonic-gate arg = next;
49187c478bd9Sstevel@tonic-gate }
49197c478bd9Sstevel@tonic-gate
49207c478bd9Sstevel@tonic-gate /* If multiple terminals are specified, wait until the user pushes any
49217c478bd9Sstevel@tonic-gate key on one of the terminals. */
49227c478bd9Sstevel@tonic-gate if (term_bitmap & ~(1 << default_term))
49237c478bd9Sstevel@tonic-gate {
49247c478bd9Sstevel@tonic-gate int time1, time2 = -1;
49257c478bd9Sstevel@tonic-gate
49267c478bd9Sstevel@tonic-gate /* XXX: Disable the pager. */
49277c478bd9Sstevel@tonic-gate count_lines = -1;
49287c478bd9Sstevel@tonic-gate
49297c478bd9Sstevel@tonic-gate /* Get current time. */
49307c478bd9Sstevel@tonic-gate while ((time1 = getrtsecs ()) == 0xFF)
49317c478bd9Sstevel@tonic-gate ;
49327c478bd9Sstevel@tonic-gate
49337c478bd9Sstevel@tonic-gate /* Wait for a key input. */
49347c478bd9Sstevel@tonic-gate while (to)
49357c478bd9Sstevel@tonic-gate {
49367c478bd9Sstevel@tonic-gate int i;
49377c478bd9Sstevel@tonic-gate
49387c478bd9Sstevel@tonic-gate for (i = 0; term_table[i].name; i++)
49397c478bd9Sstevel@tonic-gate {
49407c478bd9Sstevel@tonic-gate if (term_bitmap & (1 << i))
49417c478bd9Sstevel@tonic-gate {
49427c478bd9Sstevel@tonic-gate if (term_table[i].checkkey () >= 0)
49437c478bd9Sstevel@tonic-gate {
49447c478bd9Sstevel@tonic-gate (void) term_table[i].getkey ();
49457c478bd9Sstevel@tonic-gate default_term = i;
49467c478bd9Sstevel@tonic-gate
49477c478bd9Sstevel@tonic-gate goto end;
49487c478bd9Sstevel@tonic-gate }
49497c478bd9Sstevel@tonic-gate }
49507c478bd9Sstevel@tonic-gate }
49517c478bd9Sstevel@tonic-gate
49527c478bd9Sstevel@tonic-gate /* Prompt the user, once per sec. */
49537c478bd9Sstevel@tonic-gate if ((time1 = getrtsecs ()) != time2 && time1 != 0xFF)
49547c478bd9Sstevel@tonic-gate {
49557c478bd9Sstevel@tonic-gate if (! no_message)
49567c478bd9Sstevel@tonic-gate {
49577c478bd9Sstevel@tonic-gate /* Need to set CURRENT_TERM to each of selected
49587c478bd9Sstevel@tonic-gate terminals. */
49597c478bd9Sstevel@tonic-gate for (i = 0; term_table[i].name; i++)
49607c478bd9Sstevel@tonic-gate if (term_bitmap & (1 << i))
49617c478bd9Sstevel@tonic-gate {
49627c478bd9Sstevel@tonic-gate current_term = term_table + i;
49637c478bd9Sstevel@tonic-gate grub_printf ("\rPress any key to continue.\n");
49647c478bd9Sstevel@tonic-gate }
49657c478bd9Sstevel@tonic-gate
49667c478bd9Sstevel@tonic-gate /* Restore CURRENT_TERM. */
49677c478bd9Sstevel@tonic-gate current_term = prev_term;
49687c478bd9Sstevel@tonic-gate }
49697c478bd9Sstevel@tonic-gate
49707c478bd9Sstevel@tonic-gate time2 = time1;
49717c478bd9Sstevel@tonic-gate if (to > 0)
49727c478bd9Sstevel@tonic-gate to--;
49737c478bd9Sstevel@tonic-gate }
49747c478bd9Sstevel@tonic-gate }
49757c478bd9Sstevel@tonic-gate }
49767c478bd9Sstevel@tonic-gate
49777c478bd9Sstevel@tonic-gate end:
49787c478bd9Sstevel@tonic-gate current_term = term_table + default_term;
49797c478bd9Sstevel@tonic-gate current_term->flags = term_flags;
49809b4e3ac2SWilliam Kucharski
49817c478bd9Sstevel@tonic-gate if (lines)
49827c478bd9Sstevel@tonic-gate max_lines = lines;
49837c478bd9Sstevel@tonic-gate else
49847c478bd9Sstevel@tonic-gate max_lines = current_term->max_lines;
49857c478bd9Sstevel@tonic-gate
49867c478bd9Sstevel@tonic-gate /* If the interface is currently the command-line,
49877c478bd9Sstevel@tonic-gate restart it to repaint the screen. */
49887c478bd9Sstevel@tonic-gate if ((current_term != prev_term) && (flags & BUILTIN_CMDLINE)){
49897c478bd9Sstevel@tonic-gate if (prev_term->shutdown)
49907c478bd9Sstevel@tonic-gate prev_term->shutdown();
49917c478bd9Sstevel@tonic-gate if (current_term->startup)
49927c478bd9Sstevel@tonic-gate current_term->startup();
49937c478bd9Sstevel@tonic-gate grub_longjmp (restart_cmdline_env, 0);
49947c478bd9Sstevel@tonic-gate }
49957c478bd9Sstevel@tonic-gate
49967c478bd9Sstevel@tonic-gate return 0;
49977c478bd9Sstevel@tonic-gate }
49987c478bd9Sstevel@tonic-gate
49997c478bd9Sstevel@tonic-gate static struct builtin builtin_terminal =
50007c478bd9Sstevel@tonic-gate {
50017c478bd9Sstevel@tonic-gate "terminal",
50027c478bd9Sstevel@tonic-gate terminal_func,
50037c478bd9Sstevel@tonic-gate BUILTIN_MENU | BUILTIN_CMDLINE | BUILTIN_HELP_LIST,
5004a5602e1bSKeith M Wesolowski "terminal [--dumb] [--no-echo] [--no-edit] [--timeout=SECS] [--lines=LINES] [--silent] [console] [serial] [hercules] [graphics] [composite]",
50057c478bd9Sstevel@tonic-gate "Select a terminal. When multiple terminals are specified, wait until"
50067c478bd9Sstevel@tonic-gate " you push any key to continue. If both console and serial are specified,"
50077c478bd9Sstevel@tonic-gate " the terminal to which you input a key first will be selected. If no"
5008a5602e1bSKeith M Wesolowski " argument is specified, print current setting. To accomodate systems"
5009a5602e1bSKeith M Wesolowski " where console redirection may or may not be present, the composite"
5010a5602e1bSKeith M Wesolowski " console will direct output to the serial and BIOS consoles, and accept"
5011a5602e1bSKeith M Wesolowski " input from either one, without requiring selection. The option --dumb"
50127c478bd9Sstevel@tonic-gate " specifies that your terminal is dumb, otherwise, vt100-compatibility"
50137c478bd9Sstevel@tonic-gate " is assumed. If you specify --no-echo, input characters won't be echoed."
50147c478bd9Sstevel@tonic-gate " If you specify --no-edit, the BASH-like editing feature will be disabled."
50157c478bd9Sstevel@tonic-gate " If --timeout is present, this command will wait at most for SECS"
50167c478bd9Sstevel@tonic-gate " seconds. The option --lines specifies the maximum number of lines."
50177c478bd9Sstevel@tonic-gate " The option --silent is used to suppress messages."
50187c478bd9Sstevel@tonic-gate };
50197c478bd9Sstevel@tonic-gate #endif /* SUPPORT_SERIAL || SUPPORT_HERCULES || SUPPORT_GRAPHICS */
50207c478bd9Sstevel@tonic-gate
50217c478bd9Sstevel@tonic-gate
50227c478bd9Sstevel@tonic-gate #ifdef SUPPORT_SERIAL
50237c478bd9Sstevel@tonic-gate static int
terminfo_func(char * arg,int flags)50247c478bd9Sstevel@tonic-gate terminfo_func (char *arg, int flags)
50257c478bd9Sstevel@tonic-gate {
50267c478bd9Sstevel@tonic-gate struct terminfo term;
50277c478bd9Sstevel@tonic-gate
50287c478bd9Sstevel@tonic-gate if (*arg)
50297c478bd9Sstevel@tonic-gate {
50307c478bd9Sstevel@tonic-gate struct
50317c478bd9Sstevel@tonic-gate {
50327c478bd9Sstevel@tonic-gate const char *name;
50337c478bd9Sstevel@tonic-gate char *var;
50347c478bd9Sstevel@tonic-gate }
50357c478bd9Sstevel@tonic-gate options[] =
50367c478bd9Sstevel@tonic-gate {
50377c478bd9Sstevel@tonic-gate {"--name=", term.name},
50387c478bd9Sstevel@tonic-gate {"--cursor-address=", term.cursor_address},
50397c478bd9Sstevel@tonic-gate {"--clear-screen=", term.clear_screen},
50407c478bd9Sstevel@tonic-gate {"--enter-standout-mode=", term.enter_standout_mode},
50417c478bd9Sstevel@tonic-gate {"--exit-standout-mode=", term.exit_standout_mode}
50427c478bd9Sstevel@tonic-gate };
50437c478bd9Sstevel@tonic-gate
50447c478bd9Sstevel@tonic-gate grub_memset (&term, 0, sizeof (term));
50457c478bd9Sstevel@tonic-gate
50467c478bd9Sstevel@tonic-gate while (*arg)
50477c478bd9Sstevel@tonic-gate {
50487c478bd9Sstevel@tonic-gate int i;
50497c478bd9Sstevel@tonic-gate char *next = skip_to (0, arg);
50507c478bd9Sstevel@tonic-gate
50517c478bd9Sstevel@tonic-gate nul_terminate (arg);
50527c478bd9Sstevel@tonic-gate
50537c478bd9Sstevel@tonic-gate for (i = 0; i < sizeof (options) / sizeof (options[0]); i++)
50547c478bd9Sstevel@tonic-gate {
50557c478bd9Sstevel@tonic-gate const char *name = options[i].name;
50567c478bd9Sstevel@tonic-gate int len = grub_strlen (name);
50577c478bd9Sstevel@tonic-gate
50587c478bd9Sstevel@tonic-gate if (! grub_memcmp (arg, name, len))
50597c478bd9Sstevel@tonic-gate {
50607c478bd9Sstevel@tonic-gate grub_strcpy (options[i].var, ti_unescape_string (arg + len));
50617c478bd9Sstevel@tonic-gate break;
50627c478bd9Sstevel@tonic-gate }
50637c478bd9Sstevel@tonic-gate }
50647c478bd9Sstevel@tonic-gate
50657c478bd9Sstevel@tonic-gate if (i == sizeof (options) / sizeof (options[0]))
50667c478bd9Sstevel@tonic-gate {
50677c478bd9Sstevel@tonic-gate errnum = ERR_BAD_ARGUMENT;
50687c478bd9Sstevel@tonic-gate return errnum;
50697c478bd9Sstevel@tonic-gate }
50707c478bd9Sstevel@tonic-gate
50717c478bd9Sstevel@tonic-gate arg = next;
50727c478bd9Sstevel@tonic-gate }
50737c478bd9Sstevel@tonic-gate
50747c478bd9Sstevel@tonic-gate if (term.name[0] == 0 || term.cursor_address[0] == 0)
50757c478bd9Sstevel@tonic-gate {
50767c478bd9Sstevel@tonic-gate errnum = ERR_BAD_ARGUMENT;
50777c478bd9Sstevel@tonic-gate return errnum;
50787c478bd9Sstevel@tonic-gate }
50797c478bd9Sstevel@tonic-gate
50807c478bd9Sstevel@tonic-gate ti_set_term (&term);
50817c478bd9Sstevel@tonic-gate }
50827c478bd9Sstevel@tonic-gate else
50837c478bd9Sstevel@tonic-gate {
50847c478bd9Sstevel@tonic-gate /* No option specifies printing out current settings. */
50857c478bd9Sstevel@tonic-gate ti_get_term (&term);
50867c478bd9Sstevel@tonic-gate
50877c478bd9Sstevel@tonic-gate grub_printf ("name=%s\n",
50887c478bd9Sstevel@tonic-gate ti_escape_string (term.name));
50897c478bd9Sstevel@tonic-gate grub_printf ("cursor_address=%s\n",
50907c478bd9Sstevel@tonic-gate ti_escape_string (term.cursor_address));
50917c478bd9Sstevel@tonic-gate grub_printf ("clear_screen=%s\n",
50927c478bd9Sstevel@tonic-gate ti_escape_string (term.clear_screen));
50937c478bd9Sstevel@tonic-gate grub_printf ("enter_standout_mode=%s\n",
50947c478bd9Sstevel@tonic-gate ti_escape_string (term.enter_standout_mode));
50957c478bd9Sstevel@tonic-gate grub_printf ("exit_standout_mode=%s\n",
50967c478bd9Sstevel@tonic-gate ti_escape_string (term.exit_standout_mode));
50977c478bd9Sstevel@tonic-gate }
50987c478bd9Sstevel@tonic-gate
50997c478bd9Sstevel@tonic-gate return 0;
51007c478bd9Sstevel@tonic-gate }
51017c478bd9Sstevel@tonic-gate
51027c478bd9Sstevel@tonic-gate static struct builtin builtin_terminfo =
51037c478bd9Sstevel@tonic-gate {
51047c478bd9Sstevel@tonic-gate "terminfo",
51057c478bd9Sstevel@tonic-gate terminfo_func,
51067c478bd9Sstevel@tonic-gate BUILTIN_MENU | BUILTIN_CMDLINE | BUILTIN_HELP_LIST,
51077c478bd9Sstevel@tonic-gate "terminfo [--name=NAME --cursor-address=SEQ [--clear-screen=SEQ]"
51087c478bd9Sstevel@tonic-gate " [--enter-standout-mode=SEQ] [--exit-standout-mode=SEQ]]",
51097c478bd9Sstevel@tonic-gate
51107c478bd9Sstevel@tonic-gate "Define the capabilities of your terminal. Use this command to"
51117c478bd9Sstevel@tonic-gate " define escape sequences, if it is not vt100-compatible."
51127c478bd9Sstevel@tonic-gate " You may use \\e for ESC and ^X for a control character."
51137c478bd9Sstevel@tonic-gate " If no option is specified, the current settings are printed."
51147c478bd9Sstevel@tonic-gate };
51157c478bd9Sstevel@tonic-gate #endif /* SUPPORT_SERIAL */
51167c478bd9Sstevel@tonic-gate
51177c478bd9Sstevel@tonic-gate
51187c478bd9Sstevel@tonic-gate /* testload */
51197c478bd9Sstevel@tonic-gate static int
testload_func(char * arg,int flags)51207c478bd9Sstevel@tonic-gate testload_func (char *arg, int flags)
51217c478bd9Sstevel@tonic-gate {
51227c478bd9Sstevel@tonic-gate int i;
51237c478bd9Sstevel@tonic-gate
51247c478bd9Sstevel@tonic-gate kernel_type = KERNEL_TYPE_NONE;
51257c478bd9Sstevel@tonic-gate
51267c478bd9Sstevel@tonic-gate if (! grub_open (arg))
51277c478bd9Sstevel@tonic-gate return 1;
51287c478bd9Sstevel@tonic-gate
51297c478bd9Sstevel@tonic-gate disk_read_hook = disk_read_print_func;
51307c478bd9Sstevel@tonic-gate
51317c478bd9Sstevel@tonic-gate /* Perform filesystem test on the specified file. */
51327c478bd9Sstevel@tonic-gate /* Read whole file first. */
51337c478bd9Sstevel@tonic-gate grub_printf ("Whole file: ");
51347c478bd9Sstevel@tonic-gate
51357c478bd9Sstevel@tonic-gate grub_read ((char *) RAW_ADDR (0x100000), -1);
51367c478bd9Sstevel@tonic-gate
51377c478bd9Sstevel@tonic-gate /* Now compare two sections of the file read differently. */
51387c478bd9Sstevel@tonic-gate
51397c478bd9Sstevel@tonic-gate for (i = 0; i < 0x10ac0; i++)
51407c478bd9Sstevel@tonic-gate {
51417c478bd9Sstevel@tonic-gate *((unsigned char *) RAW_ADDR (0x200000 + i)) = 0;
51427c478bd9Sstevel@tonic-gate *((unsigned char *) RAW_ADDR (0x300000 + i)) = 1;
51437c478bd9Sstevel@tonic-gate }
51447c478bd9Sstevel@tonic-gate
51457c478bd9Sstevel@tonic-gate /* First partial read. */
51467c478bd9Sstevel@tonic-gate grub_printf ("\nPartial read 1: ");
51477c478bd9Sstevel@tonic-gate
51487c478bd9Sstevel@tonic-gate grub_seek (0);
51497c478bd9Sstevel@tonic-gate grub_read ((char *) RAW_ADDR (0x200000), 0x7);
51507c478bd9Sstevel@tonic-gate grub_read ((char *) RAW_ADDR (0x200007), 0x100);
51517c478bd9Sstevel@tonic-gate grub_read ((char *) RAW_ADDR (0x200107), 0x10);
51527c478bd9Sstevel@tonic-gate grub_read ((char *) RAW_ADDR (0x200117), 0x999);
51537c478bd9Sstevel@tonic-gate grub_read ((char *) RAW_ADDR (0x200ab0), 0x10);
51547c478bd9Sstevel@tonic-gate grub_read ((char *) RAW_ADDR (0x200ac0), 0x10000);
51557c478bd9Sstevel@tonic-gate
51567c478bd9Sstevel@tonic-gate /* Second partial read. */
51577c478bd9Sstevel@tonic-gate grub_printf ("\nPartial read 2: ");
51587c478bd9Sstevel@tonic-gate
51597c478bd9Sstevel@tonic-gate grub_seek (0);
51607c478bd9Sstevel@tonic-gate grub_read ((char *) RAW_ADDR (0x300000), 0x10000);
51617c478bd9Sstevel@tonic-gate grub_read ((char *) RAW_ADDR (0x310000), 0x10);
51627c478bd9Sstevel@tonic-gate grub_read ((char *) RAW_ADDR (0x310010), 0x7);
51637c478bd9Sstevel@tonic-gate grub_read ((char *) RAW_ADDR (0x310017), 0x10);
51647c478bd9Sstevel@tonic-gate grub_read ((char *) RAW_ADDR (0x310027), 0x999);
51657c478bd9Sstevel@tonic-gate grub_read ((char *) RAW_ADDR (0x3109c0), 0x100);
51667c478bd9Sstevel@tonic-gate
51677c478bd9Sstevel@tonic-gate grub_printf ("\nHeader1 = 0x%x, next = 0x%x, next = 0x%x, next = 0x%x\n",
51687c478bd9Sstevel@tonic-gate *((int *) RAW_ADDR (0x200000)),
51697c478bd9Sstevel@tonic-gate *((int *) RAW_ADDR (0x200004)),
51707c478bd9Sstevel@tonic-gate *((int *) RAW_ADDR (0x200008)),
51717c478bd9Sstevel@tonic-gate *((int *) RAW_ADDR (0x20000c)));
51727c478bd9Sstevel@tonic-gate
51737c478bd9Sstevel@tonic-gate grub_printf ("Header2 = 0x%x, next = 0x%x, next = 0x%x, next = 0x%x\n",
51747c478bd9Sstevel@tonic-gate *((int *) RAW_ADDR (0x300000)),
51757c478bd9Sstevel@tonic-gate *((int *) RAW_ADDR (0x300004)),
51767c478bd9Sstevel@tonic-gate *((int *) RAW_ADDR (0x300008)),
51777c478bd9Sstevel@tonic-gate *((int *) RAW_ADDR (0x30000c)));
51787c478bd9Sstevel@tonic-gate
51797c478bd9Sstevel@tonic-gate for (i = 0; i < 0x10ac0; i++)
51807c478bd9Sstevel@tonic-gate if (*((unsigned char *) RAW_ADDR (0x200000 + i))
51817c478bd9Sstevel@tonic-gate != *((unsigned char *) RAW_ADDR (0x300000 + i)))
51827c478bd9Sstevel@tonic-gate break;
51837c478bd9Sstevel@tonic-gate
51847c478bd9Sstevel@tonic-gate grub_printf ("Max is 0x10ac0: i=0x%x, filepos=0x%x\n", i, filepos);
51857c478bd9Sstevel@tonic-gate disk_read_hook = 0;
51867c478bd9Sstevel@tonic-gate grub_close ();
51877c478bd9Sstevel@tonic-gate return 0;
51887c478bd9Sstevel@tonic-gate }
51897c478bd9Sstevel@tonic-gate
51907c478bd9Sstevel@tonic-gate static struct builtin builtin_testload =
51917c478bd9Sstevel@tonic-gate {
51927c478bd9Sstevel@tonic-gate "testload",
51937c478bd9Sstevel@tonic-gate testload_func,
51947c478bd9Sstevel@tonic-gate BUILTIN_CMDLINE,
51957c478bd9Sstevel@tonic-gate "testload FILE",
51967c478bd9Sstevel@tonic-gate "Read the entire contents of FILE in several different ways and"
51977c478bd9Sstevel@tonic-gate " compares them, to test the filesystem code. The output is somewhat"
51987c478bd9Sstevel@tonic-gate " cryptic, but if no errors are reported and the final `i=X,"
51997c478bd9Sstevel@tonic-gate " filepos=Y' reading has X and Y equal, then it is definitely"
52007c478bd9Sstevel@tonic-gate " consistent, and very likely works correctly subject to a"
52017c478bd9Sstevel@tonic-gate " consistent offset error. If this test succeeds, then a good next"
52027c478bd9Sstevel@tonic-gate " step is to try loading a kernel."
52037c478bd9Sstevel@tonic-gate };
52047c478bd9Sstevel@tonic-gate
52057c478bd9Sstevel@tonic-gate
52067c478bd9Sstevel@tonic-gate /* testvbe MODE */
52077c478bd9Sstevel@tonic-gate static int
testvbe_func(char * arg,int flags)52087c478bd9Sstevel@tonic-gate testvbe_func (char *arg, int flags)
52097c478bd9Sstevel@tonic-gate {
52107c478bd9Sstevel@tonic-gate int mode_number;
52117c478bd9Sstevel@tonic-gate struct vbe_controller controller;
52127c478bd9Sstevel@tonic-gate struct vbe_mode mode;
52137c478bd9Sstevel@tonic-gate
52147c478bd9Sstevel@tonic-gate if (! *arg)
52157c478bd9Sstevel@tonic-gate {
52167c478bd9Sstevel@tonic-gate errnum = ERR_BAD_ARGUMENT;
52177c478bd9Sstevel@tonic-gate return 1;
52187c478bd9Sstevel@tonic-gate }
52197c478bd9Sstevel@tonic-gate
52207c478bd9Sstevel@tonic-gate if (! safe_parse_maxint (&arg, &mode_number))
52217c478bd9Sstevel@tonic-gate return 1;
52227c478bd9Sstevel@tonic-gate
52237c478bd9Sstevel@tonic-gate /* Preset `VBE2'. */
52247c478bd9Sstevel@tonic-gate grub_memmove (controller.signature, "VBE2", 4);
52257c478bd9Sstevel@tonic-gate
52267c478bd9Sstevel@tonic-gate /* Detect VBE BIOS. */
52277c478bd9Sstevel@tonic-gate if (get_vbe_controller_info (&controller) != 0x004F)
52287c478bd9Sstevel@tonic-gate {
52297c478bd9Sstevel@tonic-gate grub_printf (" VBE BIOS is not present.\n");
52307c478bd9Sstevel@tonic-gate return 0;
52317c478bd9Sstevel@tonic-gate }
52327c478bd9Sstevel@tonic-gate
52337c478bd9Sstevel@tonic-gate if (controller.version < 0x0200)
52347c478bd9Sstevel@tonic-gate {
52357c478bd9Sstevel@tonic-gate grub_printf (" VBE version %d.%d is not supported.\n",
52367c478bd9Sstevel@tonic-gate (int) (controller.version >> 8),
52377c478bd9Sstevel@tonic-gate (int) (controller.version & 0xFF));
52387c478bd9Sstevel@tonic-gate return 0;
52397c478bd9Sstevel@tonic-gate }
52407c478bd9Sstevel@tonic-gate
52417c478bd9Sstevel@tonic-gate if (get_vbe_mode_info (mode_number, &mode) != 0x004F
52427c478bd9Sstevel@tonic-gate || (mode.mode_attributes & 0x0091) != 0x0091)
52437c478bd9Sstevel@tonic-gate {
52447c478bd9Sstevel@tonic-gate grub_printf (" Mode 0x%x is not supported.\n", mode_number);
52457c478bd9Sstevel@tonic-gate return 0;
52467c478bd9Sstevel@tonic-gate }
52477c478bd9Sstevel@tonic-gate
52487c478bd9Sstevel@tonic-gate /* Now trip to the graphics mode. */
52497c478bd9Sstevel@tonic-gate if (set_vbe_mode (mode_number | (1 << 14)) != 0x004F)
52507c478bd9Sstevel@tonic-gate {
52517c478bd9Sstevel@tonic-gate grub_printf (" Switching to Mode 0x%x failed.\n", mode_number);
52527c478bd9Sstevel@tonic-gate return 0;
52537c478bd9Sstevel@tonic-gate }
52547c478bd9Sstevel@tonic-gate
52557c478bd9Sstevel@tonic-gate /* Draw something on the screen... */
52567c478bd9Sstevel@tonic-gate {
52577c478bd9Sstevel@tonic-gate unsigned char *base_buf = (unsigned char *) mode.phys_base;
52587c478bd9Sstevel@tonic-gate int scanline = controller.version >= 0x0300
52597c478bd9Sstevel@tonic-gate ? mode.linear_bytes_per_scanline : mode.bytes_per_scanline;
52607c478bd9Sstevel@tonic-gate /* FIXME: this assumes that any depth is a modulo of 8. */
52617c478bd9Sstevel@tonic-gate int bpp = mode.bits_per_pixel / 8;
52627c478bd9Sstevel@tonic-gate int width = mode.x_resolution;
52637c478bd9Sstevel@tonic-gate int height = mode.y_resolution;
52647c478bd9Sstevel@tonic-gate int x, y;
52657c478bd9Sstevel@tonic-gate unsigned color = 0;
52667c478bd9Sstevel@tonic-gate
52677c478bd9Sstevel@tonic-gate /* Iterate drawing on the screen, until the user hits any key. */
52687c478bd9Sstevel@tonic-gate while (checkkey () == -1)
52697c478bd9Sstevel@tonic-gate {
52707c478bd9Sstevel@tonic-gate for (y = 0; y < height; y++)
52717c478bd9Sstevel@tonic-gate {
52727c478bd9Sstevel@tonic-gate unsigned char *line_buf = base_buf + scanline * y;
52737c478bd9Sstevel@tonic-gate
52747c478bd9Sstevel@tonic-gate for (x = 0; x < width; x++)
52757c478bd9Sstevel@tonic-gate {
52767c478bd9Sstevel@tonic-gate unsigned char *buf = line_buf + bpp * x;
52777c478bd9Sstevel@tonic-gate int i;
52787c478bd9Sstevel@tonic-gate
52797c478bd9Sstevel@tonic-gate for (i = 0; i < bpp; i++, buf++)
52807c478bd9Sstevel@tonic-gate *buf = (color >> (i * 8)) & 0xff;
52817c478bd9Sstevel@tonic-gate }
52827c478bd9Sstevel@tonic-gate
52837c478bd9Sstevel@tonic-gate color++;
52847c478bd9Sstevel@tonic-gate }
52857c478bd9Sstevel@tonic-gate }
52867c478bd9Sstevel@tonic-gate
52877c478bd9Sstevel@tonic-gate /* Discard the input. */
52887c478bd9Sstevel@tonic-gate getkey ();
52897c478bd9Sstevel@tonic-gate }
52907c478bd9Sstevel@tonic-gate
52917c478bd9Sstevel@tonic-gate /* Back to the default text mode. */
52927c478bd9Sstevel@tonic-gate if (set_vbe_mode (0x03) != 0x004F)
52937c478bd9Sstevel@tonic-gate {
52947c478bd9Sstevel@tonic-gate /* Why?! */
52957c478bd9Sstevel@tonic-gate grub_reboot ();
52967c478bd9Sstevel@tonic-gate }
52977c478bd9Sstevel@tonic-gate
52987c478bd9Sstevel@tonic-gate return 0;
52997c478bd9Sstevel@tonic-gate }
53007c478bd9Sstevel@tonic-gate
53017c478bd9Sstevel@tonic-gate static struct builtin builtin_testvbe =
53027c478bd9Sstevel@tonic-gate {
53037c478bd9Sstevel@tonic-gate "testvbe",
53047c478bd9Sstevel@tonic-gate testvbe_func,
53057c478bd9Sstevel@tonic-gate BUILTIN_CMDLINE | BUILTIN_HELP_LIST,
53067c478bd9Sstevel@tonic-gate "testvbe MODE",
53077c478bd9Sstevel@tonic-gate "Test the VBE mode MODE. Hit any key to return."
53087c478bd9Sstevel@tonic-gate };
53097c478bd9Sstevel@tonic-gate
53107c478bd9Sstevel@tonic-gate
53117c478bd9Sstevel@tonic-gate #ifdef SUPPORT_NETBOOT
53127c478bd9Sstevel@tonic-gate /* tftpserver */
53137c478bd9Sstevel@tonic-gate static int
tftpserver_func(char * arg,int flags)53147c478bd9Sstevel@tonic-gate tftpserver_func (char *arg, int flags)
53157c478bd9Sstevel@tonic-gate {
53167c478bd9Sstevel@tonic-gate if (! *arg || ! ifconfig (0, 0, 0, arg))
53177c478bd9Sstevel@tonic-gate {
53187c478bd9Sstevel@tonic-gate errnum = ERR_BAD_ARGUMENT;
53197c478bd9Sstevel@tonic-gate return 1;
53207c478bd9Sstevel@tonic-gate }
53217c478bd9Sstevel@tonic-gate
53227c478bd9Sstevel@tonic-gate print_network_configuration ();
53237c478bd9Sstevel@tonic-gate return 0;
53247c478bd9Sstevel@tonic-gate }
53257c478bd9Sstevel@tonic-gate
53267c478bd9Sstevel@tonic-gate static struct builtin builtin_tftpserver =
53277c478bd9Sstevel@tonic-gate {
53287c478bd9Sstevel@tonic-gate "tftpserver",
53297c478bd9Sstevel@tonic-gate tftpserver_func,
53307c478bd9Sstevel@tonic-gate BUILTIN_CMDLINE | BUILTIN_MENU | BUILTIN_HELP_LIST,
53317c478bd9Sstevel@tonic-gate "tftpserver IPADDR",
53327c478bd9Sstevel@tonic-gate "Override the TFTP server address."
53337c478bd9Sstevel@tonic-gate };
53347c478bd9Sstevel@tonic-gate #endif /* SUPPORT_NETBOOT */
53357c478bd9Sstevel@tonic-gate
53367c478bd9Sstevel@tonic-gate
53377c478bd9Sstevel@tonic-gate /* timeout */
53387c478bd9Sstevel@tonic-gate static int
timeout_func(char * arg,int flags)53397c478bd9Sstevel@tonic-gate timeout_func (char *arg, int flags)
53407c478bd9Sstevel@tonic-gate {
53417c478bd9Sstevel@tonic-gate if (! safe_parse_maxint (&arg, &grub_timeout))
53427c478bd9Sstevel@tonic-gate return 1;
53437c478bd9Sstevel@tonic-gate
53447c478bd9Sstevel@tonic-gate return 0;
53457c478bd9Sstevel@tonic-gate }
53467c478bd9Sstevel@tonic-gate
53477c478bd9Sstevel@tonic-gate static struct builtin builtin_timeout =
53487c478bd9Sstevel@tonic-gate {
53497c478bd9Sstevel@tonic-gate "timeout",
53507c478bd9Sstevel@tonic-gate timeout_func,
53517c478bd9Sstevel@tonic-gate BUILTIN_MENU,
53527c478bd9Sstevel@tonic-gate #if 0
53537c478bd9Sstevel@tonic-gate "timeout SEC",
53547c478bd9Sstevel@tonic-gate "Set a timeout, in SEC seconds, before automatically booting the"
53557c478bd9Sstevel@tonic-gate " default entry (normally the first entry defined)."
53567c478bd9Sstevel@tonic-gate #endif
53577c478bd9Sstevel@tonic-gate };
53587c478bd9Sstevel@tonic-gate
53597c478bd9Sstevel@tonic-gate
53607c478bd9Sstevel@tonic-gate /* title */
53617c478bd9Sstevel@tonic-gate static int
title_func(char * arg,int flags)53627c478bd9Sstevel@tonic-gate title_func (char *arg, int flags)
53637c478bd9Sstevel@tonic-gate {
53647c478bd9Sstevel@tonic-gate /* This function is not actually used at least currently. */
53657c478bd9Sstevel@tonic-gate return 0;
53667c478bd9Sstevel@tonic-gate }
53677c478bd9Sstevel@tonic-gate
53687c478bd9Sstevel@tonic-gate static struct builtin builtin_title =
53697c478bd9Sstevel@tonic-gate {
53707c478bd9Sstevel@tonic-gate "title",
53717c478bd9Sstevel@tonic-gate title_func,
53727c478bd9Sstevel@tonic-gate BUILTIN_TITLE,
53737c478bd9Sstevel@tonic-gate #if 0
53747c478bd9Sstevel@tonic-gate "title [NAME ...]",
53757c478bd9Sstevel@tonic-gate "Start a new boot entry, and set its name to the contents of the"
53767c478bd9Sstevel@tonic-gate " rest of the line, starting with the first non-space character."
53777c478bd9Sstevel@tonic-gate #endif
53787c478bd9Sstevel@tonic-gate };
53797c478bd9Sstevel@tonic-gate
53807c478bd9Sstevel@tonic-gate
53817c478bd9Sstevel@tonic-gate /* unhide */
53827c478bd9Sstevel@tonic-gate static int
unhide_func(char * arg,int flags)53837c478bd9Sstevel@tonic-gate unhide_func (char *arg, int flags)
53847c478bd9Sstevel@tonic-gate {
53857c478bd9Sstevel@tonic-gate if (! set_device (arg))
53867c478bd9Sstevel@tonic-gate return 1;
53877c478bd9Sstevel@tonic-gate
53887c478bd9Sstevel@tonic-gate if (! set_partition_hidden_flag (0))
53897c478bd9Sstevel@tonic-gate return 1;
53907c478bd9Sstevel@tonic-gate
53917c478bd9Sstevel@tonic-gate return 0;
53927c478bd9Sstevel@tonic-gate }
53937c478bd9Sstevel@tonic-gate
53947c478bd9Sstevel@tonic-gate static struct builtin builtin_unhide =
53957c478bd9Sstevel@tonic-gate {
53967c478bd9Sstevel@tonic-gate "unhide",
53977c478bd9Sstevel@tonic-gate unhide_func,
53987c478bd9Sstevel@tonic-gate BUILTIN_CMDLINE | BUILTIN_MENU | BUILTIN_HELP_LIST,
53997c478bd9Sstevel@tonic-gate "unhide PARTITION",
54007c478bd9Sstevel@tonic-gate "Unhide PARTITION by clearing the \"hidden\" bit in its"
54017c478bd9Sstevel@tonic-gate " partition type code."
54027c478bd9Sstevel@tonic-gate };
54037c478bd9Sstevel@tonic-gate
54047c478bd9Sstevel@tonic-gate
54057c478bd9Sstevel@tonic-gate /* uppermem */
54067c478bd9Sstevel@tonic-gate static int
uppermem_func(char * arg,int flags)54077c478bd9Sstevel@tonic-gate uppermem_func (char *arg, int flags)
54087c478bd9Sstevel@tonic-gate {
54097c478bd9Sstevel@tonic-gate if (! safe_parse_maxint (&arg, (int *) &mbi.mem_upper))
54107c478bd9Sstevel@tonic-gate return 1;
54117c478bd9Sstevel@tonic-gate
54127c478bd9Sstevel@tonic-gate mbi.flags &= ~MB_INFO_MEM_MAP;
54137c478bd9Sstevel@tonic-gate return 0;
54147c478bd9Sstevel@tonic-gate }
54157c478bd9Sstevel@tonic-gate
54167c478bd9Sstevel@tonic-gate static struct builtin builtin_uppermem =
54177c478bd9Sstevel@tonic-gate {
54187c478bd9Sstevel@tonic-gate "uppermem",
54197c478bd9Sstevel@tonic-gate uppermem_func,
54207c478bd9Sstevel@tonic-gate BUILTIN_CMDLINE | BUILTIN_HELP_LIST,
54217c478bd9Sstevel@tonic-gate "uppermem KBYTES",
54227c478bd9Sstevel@tonic-gate "Force GRUB to assume that only KBYTES kilobytes of upper memory are"
54237c478bd9Sstevel@tonic-gate " installed. Any system address range maps are discarded."
54247c478bd9Sstevel@tonic-gate };
54257c478bd9Sstevel@tonic-gate
54267c478bd9Sstevel@tonic-gate
54277c478bd9Sstevel@tonic-gate /* vbeprobe */
54287c478bd9Sstevel@tonic-gate static int
vbeprobe_func(char * arg,int flags)54297c478bd9Sstevel@tonic-gate vbeprobe_func (char *arg, int flags)
54307c478bd9Sstevel@tonic-gate {
54317c478bd9Sstevel@tonic-gate struct vbe_controller controller;
54327c478bd9Sstevel@tonic-gate unsigned short *mode_list;
54337c478bd9Sstevel@tonic-gate int mode_number = -1;
54347c478bd9Sstevel@tonic-gate
54357c478bd9Sstevel@tonic-gate auto unsigned long vbe_far_ptr_to_linear (unsigned long);
54367c478bd9Sstevel@tonic-gate
54377c478bd9Sstevel@tonic-gate unsigned long vbe_far_ptr_to_linear (unsigned long ptr)
54387c478bd9Sstevel@tonic-gate {
54397c478bd9Sstevel@tonic-gate unsigned short seg = (ptr >> 16);
54407c478bd9Sstevel@tonic-gate unsigned short off = (ptr & 0xFFFF);
54417c478bd9Sstevel@tonic-gate
54427c478bd9Sstevel@tonic-gate return (seg << 4) + off;
54437c478bd9Sstevel@tonic-gate }
54447c478bd9Sstevel@tonic-gate
54457c478bd9Sstevel@tonic-gate if (*arg)
54467c478bd9Sstevel@tonic-gate {
54477c478bd9Sstevel@tonic-gate if (! safe_parse_maxint (&arg, &mode_number))
54487c478bd9Sstevel@tonic-gate return 1;
54497c478bd9Sstevel@tonic-gate }
54507c478bd9Sstevel@tonic-gate
54517c478bd9Sstevel@tonic-gate /* Set the signature to `VBE2', to obtain VBE 3.0 information. */
54527c478bd9Sstevel@tonic-gate grub_memmove (controller.signature, "VBE2", 4);
54537c478bd9Sstevel@tonic-gate
54547c478bd9Sstevel@tonic-gate if (get_vbe_controller_info (&controller) != 0x004F)
54557c478bd9Sstevel@tonic-gate {
54567c478bd9Sstevel@tonic-gate grub_printf (" VBE BIOS is not present.\n");
54577c478bd9Sstevel@tonic-gate return 0;
54587c478bd9Sstevel@tonic-gate }
54597c478bd9Sstevel@tonic-gate
54607c478bd9Sstevel@tonic-gate /* Check the version. */
54617c478bd9Sstevel@tonic-gate if (controller.version < 0x0200)
54627c478bd9Sstevel@tonic-gate {
54637c478bd9Sstevel@tonic-gate grub_printf (" VBE version %d.%d is not supported.\n",
54647c478bd9Sstevel@tonic-gate (int) (controller.version >> 8),
54657c478bd9Sstevel@tonic-gate (int) (controller.version & 0xFF));
54667c478bd9Sstevel@tonic-gate return 0;
54677c478bd9Sstevel@tonic-gate }
54687c478bd9Sstevel@tonic-gate
54697c478bd9Sstevel@tonic-gate /* Print some information. */
54707c478bd9Sstevel@tonic-gate grub_printf (" VBE version %d.%d\n",
54717c478bd9Sstevel@tonic-gate (int) (controller.version >> 8),
54727c478bd9Sstevel@tonic-gate (int) (controller.version & 0xFF));
54737c478bd9Sstevel@tonic-gate
54747c478bd9Sstevel@tonic-gate /* Iterate probing modes. */
54757c478bd9Sstevel@tonic-gate for (mode_list
54767c478bd9Sstevel@tonic-gate = (unsigned short *) vbe_far_ptr_to_linear (controller.video_mode);
54777c478bd9Sstevel@tonic-gate *mode_list != 0xFFFF;
54787c478bd9Sstevel@tonic-gate mode_list++)
54797c478bd9Sstevel@tonic-gate {
54807c478bd9Sstevel@tonic-gate struct vbe_mode mode;
54817c478bd9Sstevel@tonic-gate
54827c478bd9Sstevel@tonic-gate if (get_vbe_mode_info (*mode_list, &mode) != 0x004F)
54837c478bd9Sstevel@tonic-gate continue;
54847c478bd9Sstevel@tonic-gate
54857c478bd9Sstevel@tonic-gate /* Skip this, if this is not supported or linear frame buffer
54867c478bd9Sstevel@tonic-gate mode is not support. */
54877c478bd9Sstevel@tonic-gate if ((mode.mode_attributes & 0x0081) != 0x0081)
54887c478bd9Sstevel@tonic-gate continue;
54897c478bd9Sstevel@tonic-gate
54907c478bd9Sstevel@tonic-gate if (mode_number == -1 || mode_number == *mode_list)
54917c478bd9Sstevel@tonic-gate {
54927c478bd9Sstevel@tonic-gate char *model;
54937c478bd9Sstevel@tonic-gate switch (mode.memory_model)
54947c478bd9Sstevel@tonic-gate {
54957c478bd9Sstevel@tonic-gate case 0x00: model = "Text"; break;
54967c478bd9Sstevel@tonic-gate case 0x01: model = "CGA graphics"; break;
54977c478bd9Sstevel@tonic-gate case 0x02: model = "Hercules graphics"; break;
54987c478bd9Sstevel@tonic-gate case 0x03: model = "Planar"; break;
54997c478bd9Sstevel@tonic-gate case 0x04: model = "Packed pixel"; break;
55007c478bd9Sstevel@tonic-gate case 0x05: model = "Non-chain 4, 256 color"; break;
55017c478bd9Sstevel@tonic-gate case 0x06: model = "Direct Color"; break;
55027c478bd9Sstevel@tonic-gate case 0x07: model = "YUV"; break;
55037c478bd9Sstevel@tonic-gate default: model = "Unknown"; break;
55047c478bd9Sstevel@tonic-gate }
55057c478bd9Sstevel@tonic-gate
55067c478bd9Sstevel@tonic-gate grub_printf (" 0x%x: %s, %ux%ux%u\n",
55077c478bd9Sstevel@tonic-gate (unsigned) *mode_list,
55087c478bd9Sstevel@tonic-gate model,
55097c478bd9Sstevel@tonic-gate (unsigned) mode.x_resolution,
55107c478bd9Sstevel@tonic-gate (unsigned) mode.y_resolution,
55117c478bd9Sstevel@tonic-gate (unsigned) mode.bits_per_pixel);
55127c478bd9Sstevel@tonic-gate
55137c478bd9Sstevel@tonic-gate if (mode_number != -1)
55147c478bd9Sstevel@tonic-gate break;
55157c478bd9Sstevel@tonic-gate }
55167c478bd9Sstevel@tonic-gate }
55177c478bd9Sstevel@tonic-gate
55187c478bd9Sstevel@tonic-gate if (mode_number != -1 && mode_number != *mode_list)
55197c478bd9Sstevel@tonic-gate grub_printf (" Mode 0x%x is not found or supported.\n", mode_number);
55207c478bd9Sstevel@tonic-gate
55217c478bd9Sstevel@tonic-gate return 0;
55227c478bd9Sstevel@tonic-gate }
55237c478bd9Sstevel@tonic-gate
55247c478bd9Sstevel@tonic-gate static struct builtin builtin_vbeprobe =
55257c478bd9Sstevel@tonic-gate {
55267c478bd9Sstevel@tonic-gate "vbeprobe",
55277c478bd9Sstevel@tonic-gate vbeprobe_func,
55287c478bd9Sstevel@tonic-gate BUILTIN_CMDLINE | BUILTIN_HELP_LIST,
55297c478bd9Sstevel@tonic-gate "vbeprobe [MODE]",
55307c478bd9Sstevel@tonic-gate "Probe VBE information. If the mode number MODE is specified, show only"
55317c478bd9Sstevel@tonic-gate " the information about only the mode."
55327c478bd9Sstevel@tonic-gate };
5533a5602e1bSKeith M Wesolowski
5534a5602e1bSKeith M Wesolowski static int
variable_func(char * arg,int flags)5535a5602e1bSKeith M Wesolowski variable_func(char *arg, int flags)
5536a5602e1bSKeith M Wesolowski {
5537a5602e1bSKeith M Wesolowski char name[EV_NAMELEN];
5538a5602e1bSKeith M Wesolowski char *val;
5539a5602e1bSKeith M Wesolowski int err;
5540a5602e1bSKeith M Wesolowski
5541a5602e1bSKeith M Wesolowski if (*arg == '\0') {
5542a5602e1bSKeith M Wesolowski dump_variables();
5543a5602e1bSKeith M Wesolowski return (0);
5544a5602e1bSKeith M Wesolowski }
5545a5602e1bSKeith M Wesolowski
5546a5602e1bSKeith M Wesolowski if ((val = grub_strchr(arg, ' ')) != NULL) {
5547a5602e1bSKeith M Wesolowski if (val - arg >= sizeof (name)) {
5548a5602e1bSKeith M Wesolowski errnum = ERR_WONT_FIT;
5549a5602e1bSKeith M Wesolowski return (1);
5550a5602e1bSKeith M Wesolowski }
5551a5602e1bSKeith M Wesolowski (void) grub_memcpy(name, arg, (val - arg));
5552a5602e1bSKeith M Wesolowski name[val - arg] = '\0';
5553a5602e1bSKeith M Wesolowski val = skip_to(0, arg);
5554a5602e1bSKeith M Wesolowski } else {
5555a5602e1bSKeith M Wesolowski if (grub_strlen(arg) >= sizeof (name)) {
5556a5602e1bSKeith M Wesolowski errnum = ERR_WONT_FIT;
5557a5602e1bSKeith M Wesolowski return (1);
5558a5602e1bSKeith M Wesolowski }
5559a5602e1bSKeith M Wesolowski (void) grub_strcpy(name, arg);
5560a5602e1bSKeith M Wesolowski }
5561a5602e1bSKeith M Wesolowski
5562a5602e1bSKeith M Wesolowski if ((err = set_variable(name, val)) != 0) {
5563a5602e1bSKeith M Wesolowski errnum = err;
5564a5602e1bSKeith M Wesolowski return (1);
5565a5602e1bSKeith M Wesolowski }
5566a5602e1bSKeith M Wesolowski
5567a5602e1bSKeith M Wesolowski return (0);
5568a5602e1bSKeith M Wesolowski }
5569a5602e1bSKeith M Wesolowski
5570a5602e1bSKeith M Wesolowski static struct builtin builtin_variable =
5571a5602e1bSKeith M Wesolowski {
5572a5602e1bSKeith M Wesolowski "variable",
5573a5602e1bSKeith M Wesolowski variable_func,
5574a5602e1bSKeith M Wesolowski BUILTIN_CMDLINE | BUILTIN_MENU | BUILTIN_SCRIPT | BUILTIN_HELP_LIST,
5575a5602e1bSKeith M Wesolowski "variable NAME [VALUE]",
5576a5602e1bSKeith M Wesolowski "Set the variable NAME to VALUE, or to the empty string if no value is"
5577a5602e1bSKeith M Wesolowski " given. NAME must contain no spaces. There is no quoting mechanism"
5578a5602e1bSKeith M Wesolowski " and nested variable references are not allowed. Variable values may"
5579a5602e1bSKeith M Wesolowski " be substituted into the kernel$ and module$ commands using ${NAME}."
5580a5602e1bSKeith M Wesolowski };
55817c478bd9Sstevel@tonic-gate
55827c478bd9Sstevel@tonic-gate
55837c478bd9Sstevel@tonic-gate /* The table of builtin commands. Sorted in dictionary order. */
55847c478bd9Sstevel@tonic-gate struct builtin *builtin_table[] =
55857c478bd9Sstevel@tonic-gate {
55867c478bd9Sstevel@tonic-gate #ifdef SUPPORT_GRAPHICS
55877c478bd9Sstevel@tonic-gate &builtin_background,
55887c478bd9Sstevel@tonic-gate #endif
55897c478bd9Sstevel@tonic-gate &builtin_blocklist,
55907c478bd9Sstevel@tonic-gate &builtin_boot,
5591b1b8ab34Slling &builtin_bootfs,
55927c478bd9Sstevel@tonic-gate #ifdef SUPPORT_NETBOOT
55937c478bd9Sstevel@tonic-gate &builtin_bootp,
55947c478bd9Sstevel@tonic-gate #endif /* SUPPORT_NETBOOT */
55957c478bd9Sstevel@tonic-gate &builtin_cat,
55967c478bd9Sstevel@tonic-gate &builtin_chainloader,
55977c478bd9Sstevel@tonic-gate &builtin_clear,
55987c478bd9Sstevel@tonic-gate &builtin_cmp,
55997c478bd9Sstevel@tonic-gate &builtin_color,
56007c478bd9Sstevel@tonic-gate &builtin_configfile,
56017c478bd9Sstevel@tonic-gate &builtin_debug,
56027c478bd9Sstevel@tonic-gate &builtin_default,
56037c478bd9Sstevel@tonic-gate #ifdef GRUB_UTIL
56047c478bd9Sstevel@tonic-gate &builtin_device,
56057c478bd9Sstevel@tonic-gate #endif /* GRUB_UTIL */
56067c478bd9Sstevel@tonic-gate #ifdef SUPPORT_NETBOOT
56077c478bd9Sstevel@tonic-gate &builtin_dhcp,
56087c478bd9Sstevel@tonic-gate #endif /* SUPPORT_NETBOOT */
56097c478bd9Sstevel@tonic-gate &builtin_displayapm,
56107c478bd9Sstevel@tonic-gate &builtin_displaymem,
56117c478bd9Sstevel@tonic-gate #ifdef GRUB_UTIL
56127c478bd9Sstevel@tonic-gate &builtin_dump,
56137c478bd9Sstevel@tonic-gate #endif /* GRUB_UTIL */
56147c478bd9Sstevel@tonic-gate &builtin_embed,
56157c478bd9Sstevel@tonic-gate &builtin_fallback,
56167c478bd9Sstevel@tonic-gate &builtin_find,
5617eb2bd662Svikram &builtin_findroot,
56187c478bd9Sstevel@tonic-gate #ifdef SUPPORT_GRAPHICS
56197c478bd9Sstevel@tonic-gate &builtin_foreground,
56207c478bd9Sstevel@tonic-gate #endif
56217c478bd9Sstevel@tonic-gate &builtin_fstest,
56227c478bd9Sstevel@tonic-gate &builtin_geometry,
56237c478bd9Sstevel@tonic-gate &builtin_halt,
56247c478bd9Sstevel@tonic-gate &builtin_help,
56257c478bd9Sstevel@tonic-gate &builtin_hiddenmenu,
56267c478bd9Sstevel@tonic-gate &builtin_hide,
56277c478bd9Sstevel@tonic-gate #ifdef SUPPORT_NETBOOT
56287c478bd9Sstevel@tonic-gate &builtin_ifconfig,
56297c478bd9Sstevel@tonic-gate #endif /* SUPPORT_NETBOOT */
56307c478bd9Sstevel@tonic-gate &builtin_impsprobe,
56317c478bd9Sstevel@tonic-gate &builtin_initrd,
56327c478bd9Sstevel@tonic-gate &builtin_install,
56337c478bd9Sstevel@tonic-gate &builtin_ioprobe,
56347c478bd9Sstevel@tonic-gate &builtin_kernel,
5635ae115bc7Smrj &builtin_kernel_dollar,
56367c478bd9Sstevel@tonic-gate &builtin_lock,
56377c478bd9Sstevel@tonic-gate &builtin_makeactive,
56387c478bd9Sstevel@tonic-gate &builtin_map,
56397c478bd9Sstevel@tonic-gate #ifdef USE_MD5_PASSWORDS
56407c478bd9Sstevel@tonic-gate &builtin_md5crypt,
56417c478bd9Sstevel@tonic-gate #endif /* USE_MD5_PASSWORDS */
5642342440ecSPrasad Singamsetty &builtin_min_mem64,
56437c478bd9Sstevel@tonic-gate &builtin_module,
5644ae115bc7Smrj &builtin_module_dollar,
56457c478bd9Sstevel@tonic-gate &builtin_modulenounzip,
56467c478bd9Sstevel@tonic-gate &builtin_pager,
56477c478bd9Sstevel@tonic-gate &builtin_partnew,
56487c478bd9Sstevel@tonic-gate &builtin_parttype,
56497c478bd9Sstevel@tonic-gate &builtin_password,
56507c478bd9Sstevel@tonic-gate &builtin_pause,
56517c478bd9Sstevel@tonic-gate #if defined(RPC_DEBUG) && defined(SUPPORT_NETBOOT)
56527c478bd9Sstevel@tonic-gate &builtin_portmap,
56537c478bd9Sstevel@tonic-gate #endif /* RPC_DEBUG && SUPPORT_NETBOOT */
56547c478bd9Sstevel@tonic-gate #ifdef GRUB_UTIL
56557c478bd9Sstevel@tonic-gate &builtin_quit,
56567c478bd9Sstevel@tonic-gate #endif /* GRUB_UTIL */
56577c478bd9Sstevel@tonic-gate #ifdef SUPPORT_NETBOOT
56587c478bd9Sstevel@tonic-gate &builtin_rarp,
56597c478bd9Sstevel@tonic-gate #endif /* SUPPORT_NETBOOT */
56607c478bd9Sstevel@tonic-gate &builtin_read,
56617c478bd9Sstevel@tonic-gate &builtin_reboot,
56627c478bd9Sstevel@tonic-gate &builtin_root,
56637c478bd9Sstevel@tonic-gate &builtin_rootnoverify,
56647c478bd9Sstevel@tonic-gate &builtin_savedefault,
56657c478bd9Sstevel@tonic-gate #ifdef SUPPORT_SERIAL
56667c478bd9Sstevel@tonic-gate &builtin_serial,
56677c478bd9Sstevel@tonic-gate #endif /* SUPPORT_SERIAL */
56687c478bd9Sstevel@tonic-gate &builtin_setkey,
56697c478bd9Sstevel@tonic-gate &builtin_setup,
56707c478bd9Sstevel@tonic-gate #ifdef SUPPORT_GRAPHICS
56717c478bd9Sstevel@tonic-gate &builtin_splashimage,
56727c478bd9Sstevel@tonic-gate #endif /* SUPPORT_GRAPHICS */
56737c478bd9Sstevel@tonic-gate #if defined(SUPPORT_SERIAL) || defined(SUPPORT_HERCULES) || defined(SUPPORT_GRAPHICS)
56747c478bd9Sstevel@tonic-gate &builtin_terminal,
56757c478bd9Sstevel@tonic-gate #endif /* SUPPORT_SERIAL || SUPPORT_HERCULES || SUPPORT_GRAPHICS */
56767c478bd9Sstevel@tonic-gate #ifdef SUPPORT_SERIAL
56777c478bd9Sstevel@tonic-gate &builtin_terminfo,
56787c478bd9Sstevel@tonic-gate #endif /* SUPPORT_SERIAL */
56797c478bd9Sstevel@tonic-gate &builtin_testload,
56807c478bd9Sstevel@tonic-gate &builtin_testvbe,
56817c478bd9Sstevel@tonic-gate #ifdef SUPPORT_NETBOOT
56827c478bd9Sstevel@tonic-gate &builtin_tftpserver,
56837c478bd9Sstevel@tonic-gate #endif /* SUPPORT_NETBOOT */
56847c478bd9Sstevel@tonic-gate &builtin_timeout,
56857c478bd9Sstevel@tonic-gate &builtin_title,
56867c478bd9Sstevel@tonic-gate &builtin_unhide,
56877c478bd9Sstevel@tonic-gate &builtin_uppermem,
5688a5602e1bSKeith M Wesolowski &builtin_variable,
56897c478bd9Sstevel@tonic-gate &builtin_vbeprobe,
56901fac5a60Ssetje &builtin_verbose,
56917c478bd9Sstevel@tonic-gate 0
56927c478bd9Sstevel@tonic-gate };
5693