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. 57c478bd9Sstevel@tonic-gate * 67c478bd9Sstevel@tonic-gate * This program is free software; you can redistribute it and/or modify 77c478bd9Sstevel@tonic-gate * it under the terms of the GNU General Public License as published by 87c478bd9Sstevel@tonic-gate * the Free Software Foundation; either version 2 of the License, or 97c478bd9Sstevel@tonic-gate * (at your option) any later version. 107c478bd9Sstevel@tonic-gate * 117c478bd9Sstevel@tonic-gate * This program is distributed in the hope that it will be useful, 127c478bd9Sstevel@tonic-gate * but WITHOUT ANY WARRANTY; without even the implied warranty of 137c478bd9Sstevel@tonic-gate * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 147c478bd9Sstevel@tonic-gate * GNU General Public License for more details. 157c478bd9Sstevel@tonic-gate * 167c478bd9Sstevel@tonic-gate * You should have received a copy of the GNU General Public License 177c478bd9Sstevel@tonic-gate * along with this program; if not, write to the Free Software 187c478bd9Sstevel@tonic-gate * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 197c478bd9Sstevel@tonic-gate */ 20342440ecSPrasad Singamsetty 21eb2bd662Svikram /* 22eb2bd662Svikram * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 23eb2bd662Svikram * Use is subject to license terms. 24eb2bd662Svikram */ 257c478bd9Sstevel@tonic-gate 267c478bd9Sstevel@tonic-gate /* Include stdio.h before shared.h, because we can't define 277c478bd9Sstevel@tonic-gate WITHOUT_LIBC_STUBS here. */ 287c478bd9Sstevel@tonic-gate #ifdef GRUB_UTIL 297c478bd9Sstevel@tonic-gate # include <stdio.h> 307c478bd9Sstevel@tonic-gate #endif 317c478bd9Sstevel@tonic-gate 327c478bd9Sstevel@tonic-gate #include <shared.h> 337c478bd9Sstevel@tonic-gate #include <filesys.h> 347c478bd9Sstevel@tonic-gate #include <term.h> 357c478bd9Sstevel@tonic-gate 367c478bd9Sstevel@tonic-gate #ifdef SUPPORT_NETBOOT 377c478bd9Sstevel@tonic-gate # include <grub.h> 387c478bd9Sstevel@tonic-gate #endif 397c478bd9Sstevel@tonic-gate 407c478bd9Sstevel@tonic-gate #ifdef SUPPORT_SERIAL 417c478bd9Sstevel@tonic-gate # include <serial.h> 427c478bd9Sstevel@tonic-gate # include <terminfo.h> 437c478bd9Sstevel@tonic-gate #endif 447c478bd9Sstevel@tonic-gate 457c478bd9Sstevel@tonic-gate #ifdef GRUB_UTIL 467c478bd9Sstevel@tonic-gate # include <device.h> 477c478bd9Sstevel@tonic-gate #else /* ! GRUB_UTIL */ 487c478bd9Sstevel@tonic-gate # include <apic.h> 497c478bd9Sstevel@tonic-gate # include <smp-imps.h> 507c478bd9Sstevel@tonic-gate #endif /* ! GRUB_UTIL */ 517c478bd9Sstevel@tonic-gate 527c478bd9Sstevel@tonic-gate #ifdef USE_MD5_PASSWORDS 537c478bd9Sstevel@tonic-gate # include <md5.h> 547c478bd9Sstevel@tonic-gate #endif 557c478bd9Sstevel@tonic-gate 56ae115bc7Smrj #include <cpu.h> 57ae115bc7Smrj 587c478bd9Sstevel@tonic-gate /* The type of kernel loaded. */ 597c478bd9Sstevel@tonic-gate kernel_t kernel_type; 607c478bd9Sstevel@tonic-gate /* The boot device. */ 617c478bd9Sstevel@tonic-gate static int bootdev; 627c478bd9Sstevel@tonic-gate /* True when the debug mode is turned on, and false 637c478bd9Sstevel@tonic-gate when it is turned off. */ 647c478bd9Sstevel@tonic-gate int debug = 0; 657c478bd9Sstevel@tonic-gate /* The default entry. */ 667c478bd9Sstevel@tonic-gate int default_entry = 0; 677c478bd9Sstevel@tonic-gate /* The fallback entry. */ 687c478bd9Sstevel@tonic-gate int fallback_entryno; 697c478bd9Sstevel@tonic-gate int fallback_entries[MAX_FALLBACK_ENTRIES]; 707c478bd9Sstevel@tonic-gate /* The number of current entry. */ 717c478bd9Sstevel@tonic-gate int current_entryno; 727c478bd9Sstevel@tonic-gate /* The address for Multiboot command-line buffer. */ 737c478bd9Sstevel@tonic-gate static char *mb_cmdline; 747c478bd9Sstevel@tonic-gate /* The password. */ 757c478bd9Sstevel@tonic-gate char *password; 767c478bd9Sstevel@tonic-gate /* The password type. */ 777c478bd9Sstevel@tonic-gate password_t password_type; 787c478bd9Sstevel@tonic-gate /* The flag for indicating that the user is authoritative. */ 797c478bd9Sstevel@tonic-gate int auth = 0; 807c478bd9Sstevel@tonic-gate /* The timeout. */ 817c478bd9Sstevel@tonic-gate int grub_timeout = -1; 827c478bd9Sstevel@tonic-gate /* Whether to show the menu or not. */ 837c478bd9Sstevel@tonic-gate int show_menu = 1; 847c478bd9Sstevel@tonic-gate /* The BIOS drive map. */ 857c478bd9Sstevel@tonic-gate static unsigned short bios_drive_map[DRIVE_MAP_SIZE + 1]; 867c478bd9Sstevel@tonic-gate 877c478bd9Sstevel@tonic-gate /* Prototypes for allowing straightfoward calling of builtins functions 887c478bd9Sstevel@tonic-gate inside other functions. */ 897c478bd9Sstevel@tonic-gate static int configfile_func (char *arg, int flags); 907c478bd9Sstevel@tonic-gate #ifdef SUPPORT_NETBOOT 917c478bd9Sstevel@tonic-gate static void solaris_config_file (void); 927c478bd9Sstevel@tonic-gate #endif 937c478bd9Sstevel@tonic-gate 94342440ecSPrasad Singamsetty static unsigned int min_mem64 = 0; 95342440ecSPrasad Singamsetty 967c478bd9Sstevel@tonic-gate #if defined(__sun) && !defined(GRUB_UTIL) 977c478bd9Sstevel@tonic-gate extern void __enable_execute_stack (void *); 987c478bd9Sstevel@tonic-gate void 997c478bd9Sstevel@tonic-gate __enable_execute_stack (void *addr) 1007c478bd9Sstevel@tonic-gate { 1017c478bd9Sstevel@tonic-gate } 1027c478bd9Sstevel@tonic-gate #endif /* __sun && !GRUB_UTIL */ 1037c478bd9Sstevel@tonic-gate 1047c478bd9Sstevel@tonic-gate /* Initialize the data for builtins. */ 1057c478bd9Sstevel@tonic-gate void 1067c478bd9Sstevel@tonic-gate init_builtins (void) 1077c478bd9Sstevel@tonic-gate { 1087c478bd9Sstevel@tonic-gate kernel_type = KERNEL_TYPE_NONE; 1097c478bd9Sstevel@tonic-gate /* BSD and chainloading evil hacks! */ 1107c478bd9Sstevel@tonic-gate bootdev = set_bootdev (0); 1117c478bd9Sstevel@tonic-gate mb_cmdline = (char *) MB_CMDLINE_BUF; 1127c478bd9Sstevel@tonic-gate } 1137c478bd9Sstevel@tonic-gate 1147c478bd9Sstevel@tonic-gate /* Initialize the data for the configuration file. */ 1157c478bd9Sstevel@tonic-gate void 1167c478bd9Sstevel@tonic-gate init_config (void) 1177c478bd9Sstevel@tonic-gate { 1187c478bd9Sstevel@tonic-gate default_entry = 0; 1197c478bd9Sstevel@tonic-gate password = 0; 1207c478bd9Sstevel@tonic-gate fallback_entryno = -1; 1217c478bd9Sstevel@tonic-gate fallback_entries[0] = -1; 1227c478bd9Sstevel@tonic-gate grub_timeout = -1; 123b1b8ab34Slling current_rootpool[0] = '\0'; 124b1b8ab34Slling current_bootfs[0] = '\0'; 125e7cbe64fSgw current_bootpath[0] = '\0'; 126b1b8ab34Slling current_bootfs_obj = 0; 127051aabe6Staylor current_devid[0] = '\0'; 128b1b8ab34Slling is_zfs_mount = 0; 1297c478bd9Sstevel@tonic-gate } 1307c478bd9Sstevel@tonic-gate 1317c478bd9Sstevel@tonic-gate /* Check a password for correctness. Returns 0 if password was 1327c478bd9Sstevel@tonic-gate correct, and a value != 0 for error, similarly to strcmp. */ 1337c478bd9Sstevel@tonic-gate int 1347c478bd9Sstevel@tonic-gate check_password (char *entered, char* expected, password_t type) 1357c478bd9Sstevel@tonic-gate { 1367c478bd9Sstevel@tonic-gate switch (type) 1377c478bd9Sstevel@tonic-gate { 1387c478bd9Sstevel@tonic-gate case PASSWORD_PLAIN: 1397c478bd9Sstevel@tonic-gate return strcmp (entered, expected); 1407c478bd9Sstevel@tonic-gate 1417c478bd9Sstevel@tonic-gate #ifdef USE_MD5_PASSWORDS 1427c478bd9Sstevel@tonic-gate case PASSWORD_MD5: 1437c478bd9Sstevel@tonic-gate return check_md5_password (entered, expected); 1447c478bd9Sstevel@tonic-gate #endif 1457c478bd9Sstevel@tonic-gate default: 1467c478bd9Sstevel@tonic-gate /* unsupported password type: be secure */ 1477c478bd9Sstevel@tonic-gate return 1; 1487c478bd9Sstevel@tonic-gate } 1497c478bd9Sstevel@tonic-gate } 1507c478bd9Sstevel@tonic-gate 1517c478bd9Sstevel@tonic-gate /* Print which sector is read when loading a file. */ 1527c478bd9Sstevel@tonic-gate static void 153342440ecSPrasad Singamsetty disk_read_print_func(unsigned int sector, int offset, int length) 1547c478bd9Sstevel@tonic-gate { 155342440ecSPrasad Singamsetty grub_printf ("[%u,%d,%d]", sector, offset, length); 1567c478bd9Sstevel@tonic-gate } 1577c478bd9Sstevel@tonic-gate 1587c478bd9Sstevel@tonic-gate 1597c478bd9Sstevel@tonic-gate /* blocklist */ 1607c478bd9Sstevel@tonic-gate static int 1617c478bd9Sstevel@tonic-gate blocklist_func (char *arg, int flags) 1627c478bd9Sstevel@tonic-gate { 1637c478bd9Sstevel@tonic-gate char *dummy = (char *) RAW_ADDR (0x100000); 1641b8adde7SWilliam Kucharski unsigned int start_sector = 0; 1657c478bd9Sstevel@tonic-gate int num_sectors = 0; 1667c478bd9Sstevel@tonic-gate int num_entries = 0; 1677c478bd9Sstevel@tonic-gate int last_length = 0; 1687c478bd9Sstevel@tonic-gate 1691b8adde7SWilliam Kucharski auto void disk_read_blocklist_func (unsigned int sector, int offset, 1701b8adde7SWilliam Kucharski int length); 1711b8adde7SWilliam Kucharski 1727c478bd9Sstevel@tonic-gate /* Collect contiguous blocks into one entry as many as possible, 1737c478bd9Sstevel@tonic-gate and print the blocklist notation on the screen. */ 1741b8adde7SWilliam Kucharski auto void disk_read_blocklist_func (unsigned int sector, int offset, 1751b8adde7SWilliam Kucharski int length) 1767c478bd9Sstevel@tonic-gate { 1777c478bd9Sstevel@tonic-gate if (num_sectors > 0) 1787c478bd9Sstevel@tonic-gate { 1797c478bd9Sstevel@tonic-gate if (start_sector + num_sectors == sector 1807c478bd9Sstevel@tonic-gate && offset == 0 && last_length == SECTOR_SIZE) 1817c478bd9Sstevel@tonic-gate { 1827c478bd9Sstevel@tonic-gate num_sectors++; 1837c478bd9Sstevel@tonic-gate last_length = length; 1847c478bd9Sstevel@tonic-gate return; 1857c478bd9Sstevel@tonic-gate } 1867c478bd9Sstevel@tonic-gate else 1877c478bd9Sstevel@tonic-gate { 1887c478bd9Sstevel@tonic-gate if (last_length == SECTOR_SIZE) 1897c478bd9Sstevel@tonic-gate grub_printf ("%s%d+%d", num_entries ? "," : "", 1907c478bd9Sstevel@tonic-gate start_sector - part_start, num_sectors); 1917c478bd9Sstevel@tonic-gate else if (num_sectors > 1) 1927c478bd9Sstevel@tonic-gate grub_printf ("%s%d+%d,%d[0-%d]", num_entries ? "," : "", 1937c478bd9Sstevel@tonic-gate start_sector - part_start, num_sectors-1, 1947c478bd9Sstevel@tonic-gate start_sector + num_sectors-1 - part_start, 1957c478bd9Sstevel@tonic-gate last_length); 1967c478bd9Sstevel@tonic-gate else 1977c478bd9Sstevel@tonic-gate grub_printf ("%s%d[0-%d]", num_entries ? "," : "", 1987c478bd9Sstevel@tonic-gate start_sector - part_start, last_length); 1997c478bd9Sstevel@tonic-gate num_entries++; 2007c478bd9Sstevel@tonic-gate num_sectors = 0; 2017c478bd9Sstevel@tonic-gate } 2027c478bd9Sstevel@tonic-gate } 2037c478bd9Sstevel@tonic-gate 2047c478bd9Sstevel@tonic-gate if (offset > 0) 2057c478bd9Sstevel@tonic-gate { 2061b8adde7SWilliam Kucharski grub_printf("%s%u[%d-%d]", num_entries ? "," : "", 2077c478bd9Sstevel@tonic-gate sector-part_start, offset, offset+length); 2087c478bd9Sstevel@tonic-gate num_entries++; 2097c478bd9Sstevel@tonic-gate } 2107c478bd9Sstevel@tonic-gate else 2117c478bd9Sstevel@tonic-gate { 2127c478bd9Sstevel@tonic-gate start_sector = sector; 2137c478bd9Sstevel@tonic-gate num_sectors = 1; 2147c478bd9Sstevel@tonic-gate last_length = length; 2157c478bd9Sstevel@tonic-gate } 2167c478bd9Sstevel@tonic-gate } 2177c478bd9Sstevel@tonic-gate 2187c478bd9Sstevel@tonic-gate /* Open the file. */ 2197c478bd9Sstevel@tonic-gate if (! grub_open (arg)) 2207c478bd9Sstevel@tonic-gate return 1; 2217c478bd9Sstevel@tonic-gate 2227c478bd9Sstevel@tonic-gate /* Print the device name. */ 2237c478bd9Sstevel@tonic-gate grub_printf ("(%cd%d", 2247c478bd9Sstevel@tonic-gate (current_drive & 0x80) ? 'h' : 'f', 2257c478bd9Sstevel@tonic-gate current_drive & ~0x80); 2267c478bd9Sstevel@tonic-gate 2277c478bd9Sstevel@tonic-gate if ((current_partition & 0xFF0000) != 0xFF0000) 2287c478bd9Sstevel@tonic-gate grub_printf (",%d", (current_partition >> 16) & 0xFF); 2297c478bd9Sstevel@tonic-gate 2307c478bd9Sstevel@tonic-gate if ((current_partition & 0x00FF00) != 0x00FF00) 2317c478bd9Sstevel@tonic-gate grub_printf (",%c", 'a' + ((current_partition >> 8) & 0xFF)); 2327c478bd9Sstevel@tonic-gate 2337c478bd9Sstevel@tonic-gate grub_printf (")"); 2347c478bd9Sstevel@tonic-gate 2357c478bd9Sstevel@tonic-gate /* Read in the whole file to DUMMY. */ 2367c478bd9Sstevel@tonic-gate disk_read_hook = disk_read_blocklist_func; 2377c478bd9Sstevel@tonic-gate if (! grub_read (dummy, -1)) 2387c478bd9Sstevel@tonic-gate goto fail; 2397c478bd9Sstevel@tonic-gate 2407c478bd9Sstevel@tonic-gate /* The last entry may not be printed yet. Don't check if it is a 2417c478bd9Sstevel@tonic-gate * full sector, since it doesn't matter if we read too much. */ 2427c478bd9Sstevel@tonic-gate if (num_sectors > 0) 2437c478bd9Sstevel@tonic-gate grub_printf ("%s%d+%d", num_entries ? "," : "", 2447c478bd9Sstevel@tonic-gate start_sector - part_start, num_sectors); 2457c478bd9Sstevel@tonic-gate 2467c478bd9Sstevel@tonic-gate grub_printf ("\n"); 2477c478bd9Sstevel@tonic-gate 2487c478bd9Sstevel@tonic-gate fail: 2497c478bd9Sstevel@tonic-gate disk_read_hook = 0; 2507c478bd9Sstevel@tonic-gate grub_close (); 2517c478bd9Sstevel@tonic-gate return errnum; 2527c478bd9Sstevel@tonic-gate } 2537c478bd9Sstevel@tonic-gate 2547c478bd9Sstevel@tonic-gate static struct builtin builtin_blocklist = 2557c478bd9Sstevel@tonic-gate { 2567c478bd9Sstevel@tonic-gate "blocklist", 2577c478bd9Sstevel@tonic-gate blocklist_func, 2587c478bd9Sstevel@tonic-gate BUILTIN_CMDLINE | BUILTIN_HELP_LIST, 2597c478bd9Sstevel@tonic-gate "blocklist FILE", 2607c478bd9Sstevel@tonic-gate "Print the blocklist notation of the file FILE." 2617c478bd9Sstevel@tonic-gate }; 2627c478bd9Sstevel@tonic-gate 2637c478bd9Sstevel@tonic-gate /* boot */ 2647c478bd9Sstevel@tonic-gate static int 2657c478bd9Sstevel@tonic-gate boot_func (char *arg, int flags) 2667c478bd9Sstevel@tonic-gate { 2677c478bd9Sstevel@tonic-gate /* Clear the int15 handler if we can boot the kernel successfully. 2687c478bd9Sstevel@tonic-gate This assumes that the boot code never fails only if KERNEL_TYPE is 2697c478bd9Sstevel@tonic-gate not KERNEL_TYPE_NONE. Is this assumption is bad? */ 2707c478bd9Sstevel@tonic-gate if (kernel_type != KERNEL_TYPE_NONE) 2717c478bd9Sstevel@tonic-gate unset_int15_handler (); 2727c478bd9Sstevel@tonic-gate 2737c478bd9Sstevel@tonic-gate #ifdef SUPPORT_NETBOOT 2747c478bd9Sstevel@tonic-gate /* Shut down the networking. */ 2757c478bd9Sstevel@tonic-gate cleanup_net (); 2767c478bd9Sstevel@tonic-gate #endif 2777c478bd9Sstevel@tonic-gate 2787c478bd9Sstevel@tonic-gate switch (kernel_type) 2797c478bd9Sstevel@tonic-gate { 2807c478bd9Sstevel@tonic-gate case KERNEL_TYPE_FREEBSD: 2817c478bd9Sstevel@tonic-gate case KERNEL_TYPE_NETBSD: 2827c478bd9Sstevel@tonic-gate /* *BSD */ 2837c478bd9Sstevel@tonic-gate bsd_boot (kernel_type, bootdev, (char *) mbi.cmdline); 2847c478bd9Sstevel@tonic-gate break; 2857c478bd9Sstevel@tonic-gate 2867c478bd9Sstevel@tonic-gate case KERNEL_TYPE_LINUX: 2877c478bd9Sstevel@tonic-gate /* Linux */ 2887c478bd9Sstevel@tonic-gate linux_boot (); 2897c478bd9Sstevel@tonic-gate break; 2907c478bd9Sstevel@tonic-gate 2917c478bd9Sstevel@tonic-gate case KERNEL_TYPE_BIG_LINUX: 2927c478bd9Sstevel@tonic-gate /* Big Linux */ 2937c478bd9Sstevel@tonic-gate big_linux_boot (); 2947c478bd9Sstevel@tonic-gate break; 2957c478bd9Sstevel@tonic-gate 2967c478bd9Sstevel@tonic-gate case KERNEL_TYPE_CHAINLOADER: 2977c478bd9Sstevel@tonic-gate /* Chainloader */ 2987c478bd9Sstevel@tonic-gate 2997c478bd9Sstevel@tonic-gate /* Check if we should set the int13 handler. */ 3007c478bd9Sstevel@tonic-gate if (bios_drive_map[0] != 0) 3017c478bd9Sstevel@tonic-gate { 3027c478bd9Sstevel@tonic-gate int i; 3037c478bd9Sstevel@tonic-gate 3047c478bd9Sstevel@tonic-gate /* Search for SAVED_DRIVE. */ 3057c478bd9Sstevel@tonic-gate for (i = 0; i < DRIVE_MAP_SIZE; i++) 3067c478bd9Sstevel@tonic-gate { 3077c478bd9Sstevel@tonic-gate if (! bios_drive_map[i]) 3087c478bd9Sstevel@tonic-gate break; 3097c478bd9Sstevel@tonic-gate else if ((bios_drive_map[i] & 0xFF) == saved_drive) 3107c478bd9Sstevel@tonic-gate { 3117c478bd9Sstevel@tonic-gate /* Exchage SAVED_DRIVE with the mapped drive. */ 3127c478bd9Sstevel@tonic-gate saved_drive = (bios_drive_map[i] >> 8) & 0xFF; 3137c478bd9Sstevel@tonic-gate break; 3147c478bd9Sstevel@tonic-gate } 3157c478bd9Sstevel@tonic-gate } 3167c478bd9Sstevel@tonic-gate 3177c478bd9Sstevel@tonic-gate /* Set the handler. This is somewhat dangerous. */ 3187c478bd9Sstevel@tonic-gate set_int13_handler (bios_drive_map); 3197c478bd9Sstevel@tonic-gate } 3207c478bd9Sstevel@tonic-gate 3217c478bd9Sstevel@tonic-gate gateA20 (0); 3227c478bd9Sstevel@tonic-gate boot_drive = saved_drive; 3237c478bd9Sstevel@tonic-gate chain_stage1 (0, BOOTSEC_LOCATION, boot_part_addr); 3247c478bd9Sstevel@tonic-gate break; 3257c478bd9Sstevel@tonic-gate 3267c478bd9Sstevel@tonic-gate case KERNEL_TYPE_MULTIBOOT: 3277c478bd9Sstevel@tonic-gate /* Multiboot */ 3287c478bd9Sstevel@tonic-gate #ifdef SUPPORT_NETBOOT 3297c478bd9Sstevel@tonic-gate #ifdef SOLARIS_NETBOOT 3307c478bd9Sstevel@tonic-gate if (current_drive == NETWORK_DRIVE) { 3317c478bd9Sstevel@tonic-gate /* 3327c478bd9Sstevel@tonic-gate * XXX Solaris hack: use drive_info to pass network information 3337c478bd9Sstevel@tonic-gate * Turn off the flag bit to the loader is technically 3347c478bd9Sstevel@tonic-gate * multiboot compliant. 3357c478bd9Sstevel@tonic-gate */ 3367c478bd9Sstevel@tonic-gate mbi.flags &= ~MB_INFO_DRIVE_INFO; 3377c478bd9Sstevel@tonic-gate mbi.drives_length = dhcpack_length; 3387c478bd9Sstevel@tonic-gate mbi.drives_addr = dhcpack_buf; 3397c478bd9Sstevel@tonic-gate } 3407c478bd9Sstevel@tonic-gate #endif /* SOLARIS_NETBOOT */ 3417c478bd9Sstevel@tonic-gate #endif 3427c478bd9Sstevel@tonic-gate multi_boot ((int) entry_addr, (int) &mbi); 3437c478bd9Sstevel@tonic-gate break; 3447c478bd9Sstevel@tonic-gate 3457c478bd9Sstevel@tonic-gate default: 3467c478bd9Sstevel@tonic-gate errnum = ERR_BOOT_COMMAND; 3477c478bd9Sstevel@tonic-gate return 1; 3487c478bd9Sstevel@tonic-gate } 3497c478bd9Sstevel@tonic-gate 3507c478bd9Sstevel@tonic-gate return 0; 3517c478bd9Sstevel@tonic-gate } 3527c478bd9Sstevel@tonic-gate 3537c478bd9Sstevel@tonic-gate static struct builtin builtin_boot = 3547c478bd9Sstevel@tonic-gate { 3557c478bd9Sstevel@tonic-gate "boot", 3567c478bd9Sstevel@tonic-gate boot_func, 3577c478bd9Sstevel@tonic-gate BUILTIN_CMDLINE | BUILTIN_HELP_LIST, 3587c478bd9Sstevel@tonic-gate "boot", 3597c478bd9Sstevel@tonic-gate "Boot the OS/chain-loader which has been loaded." 3607c478bd9Sstevel@tonic-gate }; 3617c478bd9Sstevel@tonic-gate 3627c478bd9Sstevel@tonic-gate 3637c478bd9Sstevel@tonic-gate #ifdef SUPPORT_NETBOOT 3647c478bd9Sstevel@tonic-gate /* bootp */ 3657c478bd9Sstevel@tonic-gate static int 3667c478bd9Sstevel@tonic-gate bootp_func (char *arg, int flags) 3677c478bd9Sstevel@tonic-gate { 3687c478bd9Sstevel@tonic-gate int with_configfile = 0; 3697c478bd9Sstevel@tonic-gate 3707c478bd9Sstevel@tonic-gate if (grub_memcmp (arg, "--with-configfile", sizeof ("--with-configfile") - 1) 3717c478bd9Sstevel@tonic-gate == 0) 3727c478bd9Sstevel@tonic-gate { 3737c478bd9Sstevel@tonic-gate with_configfile = 1; 3747c478bd9Sstevel@tonic-gate arg = skip_to (0, arg); 3757c478bd9Sstevel@tonic-gate } 3767c478bd9Sstevel@tonic-gate 3777c478bd9Sstevel@tonic-gate if (! bootp ()) 3787c478bd9Sstevel@tonic-gate { 3797c478bd9Sstevel@tonic-gate if (errnum == ERR_NONE) 3807c478bd9Sstevel@tonic-gate errnum = ERR_DEV_VALUES; 3817c478bd9Sstevel@tonic-gate 3827c478bd9Sstevel@tonic-gate return 1; 3837c478bd9Sstevel@tonic-gate } 3847c478bd9Sstevel@tonic-gate 3857c478bd9Sstevel@tonic-gate /* Notify the configuration. */ 3867c478bd9Sstevel@tonic-gate print_network_configuration (); 3877c478bd9Sstevel@tonic-gate 3887c478bd9Sstevel@tonic-gate /* XXX: this can cause an endless loop, but there is no easy way to 3897c478bd9Sstevel@tonic-gate detect such a loop unfortunately. */ 3907c478bd9Sstevel@tonic-gate if (with_configfile) 3917c478bd9Sstevel@tonic-gate configfile_func (config_file, flags); 3927c478bd9Sstevel@tonic-gate 3937c478bd9Sstevel@tonic-gate return 0; 3947c478bd9Sstevel@tonic-gate } 3957c478bd9Sstevel@tonic-gate 3967c478bd9Sstevel@tonic-gate static struct builtin builtin_bootp = 3977c478bd9Sstevel@tonic-gate { 3987c478bd9Sstevel@tonic-gate "bootp", 3997c478bd9Sstevel@tonic-gate bootp_func, 4007c478bd9Sstevel@tonic-gate BUILTIN_CMDLINE | BUILTIN_MENU | BUILTIN_HELP_LIST, 4017c478bd9Sstevel@tonic-gate "bootp [--with-configfile]", 4027c478bd9Sstevel@tonic-gate "Initialize a network device via BOOTP. If the option `--with-configfile'" 4037c478bd9Sstevel@tonic-gate " is given, try to load a configuration file specified by the 150 vendor" 4047c478bd9Sstevel@tonic-gate " tag." 4057c478bd9Sstevel@tonic-gate }; 4067c478bd9Sstevel@tonic-gate #endif /* SUPPORT_NETBOOT */ 4077c478bd9Sstevel@tonic-gate 4087c478bd9Sstevel@tonic-gate 4097c478bd9Sstevel@tonic-gate /* cat */ 4107c478bd9Sstevel@tonic-gate static int 4117c478bd9Sstevel@tonic-gate cat_func (char *arg, int flags) 4127c478bd9Sstevel@tonic-gate { 4137c478bd9Sstevel@tonic-gate char c; 4147c478bd9Sstevel@tonic-gate 4157c478bd9Sstevel@tonic-gate if (! grub_open (arg)) 4167c478bd9Sstevel@tonic-gate return 1; 4177c478bd9Sstevel@tonic-gate 4187c478bd9Sstevel@tonic-gate while (grub_read (&c, 1)) 4197c478bd9Sstevel@tonic-gate { 4207c478bd9Sstevel@tonic-gate /* Because running "cat" with a binary file can confuse the terminal, 4217c478bd9Sstevel@tonic-gate print only some characters as they are. */ 4227c478bd9Sstevel@tonic-gate if (grub_isspace (c) || (c >= ' ' && c <= '~')) 4237c478bd9Sstevel@tonic-gate grub_putchar (c); 4247c478bd9Sstevel@tonic-gate else 4257c478bd9Sstevel@tonic-gate grub_putchar ('?'); 4267c478bd9Sstevel@tonic-gate } 4277c478bd9Sstevel@tonic-gate 4287c478bd9Sstevel@tonic-gate grub_close (); 4297c478bd9Sstevel@tonic-gate return 0; 4307c478bd9Sstevel@tonic-gate } 4317c478bd9Sstevel@tonic-gate 4327c478bd9Sstevel@tonic-gate static struct builtin builtin_cat = 4337c478bd9Sstevel@tonic-gate { 4347c478bd9Sstevel@tonic-gate "cat", 4357c478bd9Sstevel@tonic-gate cat_func, 4367c478bd9Sstevel@tonic-gate BUILTIN_CMDLINE | BUILTIN_HELP_LIST, 4377c478bd9Sstevel@tonic-gate "cat FILE", 4387c478bd9Sstevel@tonic-gate "Print the contents of the file FILE." 4397c478bd9Sstevel@tonic-gate }; 4407c478bd9Sstevel@tonic-gate 4417c478bd9Sstevel@tonic-gate 4427c478bd9Sstevel@tonic-gate /* chainloader */ 4437c478bd9Sstevel@tonic-gate static int 4447c478bd9Sstevel@tonic-gate chainloader_func (char *arg, int flags) 4457c478bd9Sstevel@tonic-gate { 4467c478bd9Sstevel@tonic-gate int force = 0; 4477c478bd9Sstevel@tonic-gate char *file = arg; 4487c478bd9Sstevel@tonic-gate 4497c478bd9Sstevel@tonic-gate /* If the option `--force' is specified? */ 4507c478bd9Sstevel@tonic-gate if (substring ("--force", arg) <= 0) 4517c478bd9Sstevel@tonic-gate { 4527c478bd9Sstevel@tonic-gate force = 1; 4537c478bd9Sstevel@tonic-gate file = skip_to (0, arg); 4547c478bd9Sstevel@tonic-gate } 4557c478bd9Sstevel@tonic-gate 4567c478bd9Sstevel@tonic-gate /* Open the file. */ 4577c478bd9Sstevel@tonic-gate if (! grub_open (file)) 4587c478bd9Sstevel@tonic-gate { 4597c478bd9Sstevel@tonic-gate kernel_type = KERNEL_TYPE_NONE; 4607c478bd9Sstevel@tonic-gate return 1; 4617c478bd9Sstevel@tonic-gate } 4627c478bd9Sstevel@tonic-gate 4637c478bd9Sstevel@tonic-gate /* Read the first block. */ 4647c478bd9Sstevel@tonic-gate if (grub_read ((char *) BOOTSEC_LOCATION, SECTOR_SIZE) != SECTOR_SIZE) 4657c478bd9Sstevel@tonic-gate { 4667c478bd9Sstevel@tonic-gate grub_close (); 4677c478bd9Sstevel@tonic-gate kernel_type = KERNEL_TYPE_NONE; 4687c478bd9Sstevel@tonic-gate 4697c478bd9Sstevel@tonic-gate /* This below happens, if a file whose size is less than 512 bytes 4707c478bd9Sstevel@tonic-gate is loaded. */ 4717c478bd9Sstevel@tonic-gate if (errnum == ERR_NONE) 4727c478bd9Sstevel@tonic-gate errnum = ERR_EXEC_FORMAT; 4737c478bd9Sstevel@tonic-gate 4747c478bd9Sstevel@tonic-gate return 1; 4757c478bd9Sstevel@tonic-gate } 4767c478bd9Sstevel@tonic-gate 4777c478bd9Sstevel@tonic-gate /* If not loading it forcibly, check for the signature. */ 4787c478bd9Sstevel@tonic-gate if (! force 4797c478bd9Sstevel@tonic-gate && (*((unsigned short *) (BOOTSEC_LOCATION + BOOTSEC_SIG_OFFSET)) 4807c478bd9Sstevel@tonic-gate != BOOTSEC_SIGNATURE)) 4817c478bd9Sstevel@tonic-gate { 4827c478bd9Sstevel@tonic-gate grub_close (); 4837c478bd9Sstevel@tonic-gate errnum = ERR_EXEC_FORMAT; 4847c478bd9Sstevel@tonic-gate kernel_type = KERNEL_TYPE_NONE; 4857c478bd9Sstevel@tonic-gate return 1; 4867c478bd9Sstevel@tonic-gate } 4877c478bd9Sstevel@tonic-gate 4887c478bd9Sstevel@tonic-gate grub_close (); 4897c478bd9Sstevel@tonic-gate kernel_type = KERNEL_TYPE_CHAINLOADER; 4907c478bd9Sstevel@tonic-gate 4917c478bd9Sstevel@tonic-gate /* XXX: Windows evil hack. For now, only the first five letters are 4927c478bd9Sstevel@tonic-gate checked. */ 4937c478bd9Sstevel@tonic-gate if (IS_PC_SLICE_TYPE_FAT (current_slice) 4947c478bd9Sstevel@tonic-gate && ! grub_memcmp ((char *) BOOTSEC_LOCATION + BOOTSEC_BPB_SYSTEM_ID, 4957c478bd9Sstevel@tonic-gate "MSWIN", 5)) 4967c478bd9Sstevel@tonic-gate *((unsigned long *) (BOOTSEC_LOCATION + BOOTSEC_BPB_HIDDEN_SECTORS)) 4977c478bd9Sstevel@tonic-gate = part_start; 4987c478bd9Sstevel@tonic-gate 4997c478bd9Sstevel@tonic-gate errnum = ERR_NONE; 5007c478bd9Sstevel@tonic-gate 5017c478bd9Sstevel@tonic-gate return 0; 5027c478bd9Sstevel@tonic-gate } 5037c478bd9Sstevel@tonic-gate 5047c478bd9Sstevel@tonic-gate static struct builtin builtin_chainloader = 5057c478bd9Sstevel@tonic-gate { 5067c478bd9Sstevel@tonic-gate "chainloader", 5077c478bd9Sstevel@tonic-gate chainloader_func, 5087c478bd9Sstevel@tonic-gate BUILTIN_CMDLINE | BUILTIN_HELP_LIST, 5097c478bd9Sstevel@tonic-gate "chainloader [--force] FILE", 5107c478bd9Sstevel@tonic-gate "Load the chain-loader FILE. If --force is specified, then load it" 5117c478bd9Sstevel@tonic-gate " forcibly, whether the boot loader signature is present or not." 5127c478bd9Sstevel@tonic-gate }; 5137c478bd9Sstevel@tonic-gate 5147c478bd9Sstevel@tonic-gate 5157c478bd9Sstevel@tonic-gate /* This function could be used to debug new filesystem code. Put a file 5167c478bd9Sstevel@tonic-gate in the new filesystem and the same file in a well-tested filesystem. 5177c478bd9Sstevel@tonic-gate Then, run "cmp" with the files. If no output is obtained, probably 5187c478bd9Sstevel@tonic-gate the code is good, otherwise investigate what's wrong... */ 5197c478bd9Sstevel@tonic-gate /* cmp FILE1 FILE2 */ 5207c478bd9Sstevel@tonic-gate static int 5217c478bd9Sstevel@tonic-gate cmp_func (char *arg, int flags) 5227c478bd9Sstevel@tonic-gate { 5237c478bd9Sstevel@tonic-gate /* The filenames. */ 5247c478bd9Sstevel@tonic-gate char *file1, *file2; 5257c478bd9Sstevel@tonic-gate /* The addresses. */ 5267c478bd9Sstevel@tonic-gate char *addr1, *addr2; 5277c478bd9Sstevel@tonic-gate int i; 5287c478bd9Sstevel@tonic-gate /* The size of the file. */ 5297c478bd9Sstevel@tonic-gate int size; 5307c478bd9Sstevel@tonic-gate 5317c478bd9Sstevel@tonic-gate /* Get the filenames from ARG. */ 5327c478bd9Sstevel@tonic-gate file1 = arg; 5337c478bd9Sstevel@tonic-gate file2 = skip_to (0, arg); 5347c478bd9Sstevel@tonic-gate if (! *file1 || ! *file2) 5357c478bd9Sstevel@tonic-gate { 5367c478bd9Sstevel@tonic-gate errnum = ERR_BAD_ARGUMENT; 5377c478bd9Sstevel@tonic-gate return 1; 5387c478bd9Sstevel@tonic-gate } 5397c478bd9Sstevel@tonic-gate 5407c478bd9Sstevel@tonic-gate /* Terminate the filenames for convenience. */ 5417c478bd9Sstevel@tonic-gate nul_terminate (file1); 5427c478bd9Sstevel@tonic-gate nul_terminate (file2); 5437c478bd9Sstevel@tonic-gate 5447c478bd9Sstevel@tonic-gate /* Read the whole data from FILE1. */ 5457c478bd9Sstevel@tonic-gate addr1 = (char *) RAW_ADDR (0x100000); 5467c478bd9Sstevel@tonic-gate if (! grub_open (file1)) 5477c478bd9Sstevel@tonic-gate return 1; 5487c478bd9Sstevel@tonic-gate 5497c478bd9Sstevel@tonic-gate /* Get the size. */ 5507c478bd9Sstevel@tonic-gate size = filemax; 5517c478bd9Sstevel@tonic-gate if (grub_read (addr1, -1) != size) 5527c478bd9Sstevel@tonic-gate { 5537c478bd9Sstevel@tonic-gate grub_close (); 5547c478bd9Sstevel@tonic-gate return 1; 5557c478bd9Sstevel@tonic-gate } 5567c478bd9Sstevel@tonic-gate 5577c478bd9Sstevel@tonic-gate grub_close (); 5587c478bd9Sstevel@tonic-gate 5597c478bd9Sstevel@tonic-gate /* Read the whole data from FILE2. */ 5607c478bd9Sstevel@tonic-gate addr2 = addr1 + size; 5617c478bd9Sstevel@tonic-gate if (! grub_open (file2)) 5627c478bd9Sstevel@tonic-gate return 1; 5637c478bd9Sstevel@tonic-gate 5647c478bd9Sstevel@tonic-gate /* Check if the size of FILE2 is equal to the one of FILE2. */ 5657c478bd9Sstevel@tonic-gate if (size != filemax) 5667c478bd9Sstevel@tonic-gate { 5677c478bd9Sstevel@tonic-gate grub_printf ("Differ in size: 0x%x [%s], 0x%x [%s]\n", 5687c478bd9Sstevel@tonic-gate size, file1, filemax, file2); 5697c478bd9Sstevel@tonic-gate grub_close (); 5707c478bd9Sstevel@tonic-gate return 0; 5717c478bd9Sstevel@tonic-gate } 5727c478bd9Sstevel@tonic-gate 5737c478bd9Sstevel@tonic-gate if (! grub_read (addr2, -1)) 5747c478bd9Sstevel@tonic-gate { 5757c478bd9Sstevel@tonic-gate grub_close (); 5767c478bd9Sstevel@tonic-gate return 1; 5777c478bd9Sstevel@tonic-gate } 5787c478bd9Sstevel@tonic-gate 5797c478bd9Sstevel@tonic-gate grub_close (); 5807c478bd9Sstevel@tonic-gate 5817c478bd9Sstevel@tonic-gate /* Now compare ADDR1 with ADDR2. */ 5827c478bd9Sstevel@tonic-gate for (i = 0; i < size; i++) 5837c478bd9Sstevel@tonic-gate { 5847c478bd9Sstevel@tonic-gate if (addr1[i] != addr2[i]) 5857c478bd9Sstevel@tonic-gate grub_printf ("Differ at the offset %d: 0x%x [%s], 0x%x [%s]\n", 5867c478bd9Sstevel@tonic-gate i, (unsigned) addr1[i], file1, 5877c478bd9Sstevel@tonic-gate (unsigned) addr2[i], file2); 5887c478bd9Sstevel@tonic-gate } 5897c478bd9Sstevel@tonic-gate 5907c478bd9Sstevel@tonic-gate return 0; 5917c478bd9Sstevel@tonic-gate } 5927c478bd9Sstevel@tonic-gate 5937c478bd9Sstevel@tonic-gate static struct builtin builtin_cmp = 5947c478bd9Sstevel@tonic-gate { 5957c478bd9Sstevel@tonic-gate "cmp", 5967c478bd9Sstevel@tonic-gate cmp_func, 5977c478bd9Sstevel@tonic-gate BUILTIN_CMDLINE, 5987c478bd9Sstevel@tonic-gate "cmp FILE1 FILE2", 5997c478bd9Sstevel@tonic-gate "Compare the file FILE1 with the FILE2 and inform the different values" 6007c478bd9Sstevel@tonic-gate " if any." 6017c478bd9Sstevel@tonic-gate }; 6027c478bd9Sstevel@tonic-gate 6037c478bd9Sstevel@tonic-gate 6047c478bd9Sstevel@tonic-gate /* color */ 6057c478bd9Sstevel@tonic-gate /* Set new colors used for the menu interface. Support two methods to 6067c478bd9Sstevel@tonic-gate specify a color name: a direct integer representation and a symbolic 6077c478bd9Sstevel@tonic-gate color name. An example of the latter is "blink-light-gray/blue". */ 6087c478bd9Sstevel@tonic-gate static int 6097c478bd9Sstevel@tonic-gate color_func (char *arg, int flags) 6107c478bd9Sstevel@tonic-gate { 6117c478bd9Sstevel@tonic-gate char *normal; 6127c478bd9Sstevel@tonic-gate char *highlight; 6137c478bd9Sstevel@tonic-gate int new_normal_color; 6147c478bd9Sstevel@tonic-gate int new_highlight_color; 6157c478bd9Sstevel@tonic-gate static char *color_list[16] = 6167c478bd9Sstevel@tonic-gate { 6177c478bd9Sstevel@tonic-gate "black", 6187c478bd9Sstevel@tonic-gate "blue", 6197c478bd9Sstevel@tonic-gate "green", 6207c478bd9Sstevel@tonic-gate "cyan", 6217c478bd9Sstevel@tonic-gate "red", 6227c478bd9Sstevel@tonic-gate "magenta", 6237c478bd9Sstevel@tonic-gate "brown", 6247c478bd9Sstevel@tonic-gate "light-gray", 6257c478bd9Sstevel@tonic-gate "dark-gray", 6267c478bd9Sstevel@tonic-gate "light-blue", 6277c478bd9Sstevel@tonic-gate "light-green", 6287c478bd9Sstevel@tonic-gate "light-cyan", 6297c478bd9Sstevel@tonic-gate "light-red", 6307c478bd9Sstevel@tonic-gate "light-magenta", 6317c478bd9Sstevel@tonic-gate "yellow", 6327c478bd9Sstevel@tonic-gate "white" 6337c478bd9Sstevel@tonic-gate }; 6347c478bd9Sstevel@tonic-gate 6351b8adde7SWilliam Kucharski auto int color_number (char *str); 6361b8adde7SWilliam Kucharski 6377c478bd9Sstevel@tonic-gate /* Convert the color name STR into the magical number. */ 6381b8adde7SWilliam Kucharski auto int color_number (char *str) 6397c478bd9Sstevel@tonic-gate { 6407c478bd9Sstevel@tonic-gate char *ptr; 6417c478bd9Sstevel@tonic-gate int i; 6427c478bd9Sstevel@tonic-gate int color = 0; 6437c478bd9Sstevel@tonic-gate 6447c478bd9Sstevel@tonic-gate /* Find the separator. */ 6457c478bd9Sstevel@tonic-gate for (ptr = str; *ptr && *ptr != '/'; ptr++) 6467c478bd9Sstevel@tonic-gate ; 6477c478bd9Sstevel@tonic-gate 6487c478bd9Sstevel@tonic-gate /* If not found, return -1. */ 6497c478bd9Sstevel@tonic-gate if (! *ptr) 6507c478bd9Sstevel@tonic-gate return -1; 6517c478bd9Sstevel@tonic-gate 6527c478bd9Sstevel@tonic-gate /* Terminate the string STR. */ 6537c478bd9Sstevel@tonic-gate *ptr++ = 0; 6547c478bd9Sstevel@tonic-gate 6557c478bd9Sstevel@tonic-gate /* If STR contains the prefix "blink-", then set the `blink' bit 6567c478bd9Sstevel@tonic-gate in COLOR. */ 6577c478bd9Sstevel@tonic-gate if (substring ("blink-", str) <= 0) 6587c478bd9Sstevel@tonic-gate { 6597c478bd9Sstevel@tonic-gate color = 0x80; 6607c478bd9Sstevel@tonic-gate str += 6; 6617c478bd9Sstevel@tonic-gate } 6627c478bd9Sstevel@tonic-gate 6637c478bd9Sstevel@tonic-gate /* Search for the color name. */ 6647c478bd9Sstevel@tonic-gate for (i = 0; i < 16; i++) 6657c478bd9Sstevel@tonic-gate if (grub_strcmp (color_list[i], str) == 0) 6667c478bd9Sstevel@tonic-gate { 6677c478bd9Sstevel@tonic-gate color |= i; 6687c478bd9Sstevel@tonic-gate break; 6697c478bd9Sstevel@tonic-gate } 6707c478bd9Sstevel@tonic-gate 6717c478bd9Sstevel@tonic-gate if (i == 16) 6727c478bd9Sstevel@tonic-gate return -1; 6737c478bd9Sstevel@tonic-gate 6747c478bd9Sstevel@tonic-gate str = ptr; 6757c478bd9Sstevel@tonic-gate nul_terminate (str); 6767c478bd9Sstevel@tonic-gate 6777c478bd9Sstevel@tonic-gate /* Search for the color name. */ 6787c478bd9Sstevel@tonic-gate for (i = 0; i < 8; i++) 6797c478bd9Sstevel@tonic-gate if (grub_strcmp (color_list[i], str) == 0) 6807c478bd9Sstevel@tonic-gate { 6817c478bd9Sstevel@tonic-gate color |= i << 4; 6827c478bd9Sstevel@tonic-gate break; 6837c478bd9Sstevel@tonic-gate } 6847c478bd9Sstevel@tonic-gate 6857c478bd9Sstevel@tonic-gate if (i == 8) 6867c478bd9Sstevel@tonic-gate return -1; 6877c478bd9Sstevel@tonic-gate 6887c478bd9Sstevel@tonic-gate return color; 6897c478bd9Sstevel@tonic-gate } 6907c478bd9Sstevel@tonic-gate 6917c478bd9Sstevel@tonic-gate normal = arg; 6927c478bd9Sstevel@tonic-gate highlight = skip_to (0, arg); 6937c478bd9Sstevel@tonic-gate 6947c478bd9Sstevel@tonic-gate new_normal_color = color_number (normal); 6957c478bd9Sstevel@tonic-gate if (new_normal_color < 0 && ! safe_parse_maxint (&normal, &new_normal_color)) 6967c478bd9Sstevel@tonic-gate return 1; 6977c478bd9Sstevel@tonic-gate 6987c478bd9Sstevel@tonic-gate /* The second argument is optional, so set highlight_color 6997c478bd9Sstevel@tonic-gate to inverted NORMAL_COLOR. */ 7007c478bd9Sstevel@tonic-gate if (! *highlight) 7017c478bd9Sstevel@tonic-gate new_highlight_color = ((new_normal_color >> 4) 7027c478bd9Sstevel@tonic-gate | ((new_normal_color & 0xf) << 4)); 7037c478bd9Sstevel@tonic-gate else 7047c478bd9Sstevel@tonic-gate { 7057c478bd9Sstevel@tonic-gate new_highlight_color = color_number (highlight); 7067c478bd9Sstevel@tonic-gate if (new_highlight_color < 0 7077c478bd9Sstevel@tonic-gate && ! safe_parse_maxint (&highlight, &new_highlight_color)) 7087c478bd9Sstevel@tonic-gate return 1; 7097c478bd9Sstevel@tonic-gate } 7107c478bd9Sstevel@tonic-gate 7117c478bd9Sstevel@tonic-gate if (current_term->setcolor) 7127c478bd9Sstevel@tonic-gate current_term->setcolor (new_normal_color, new_highlight_color); 7137c478bd9Sstevel@tonic-gate 7147c478bd9Sstevel@tonic-gate return 0; 7157c478bd9Sstevel@tonic-gate } 7167c478bd9Sstevel@tonic-gate 7177c478bd9Sstevel@tonic-gate static struct builtin builtin_color = 7187c478bd9Sstevel@tonic-gate { 7197c478bd9Sstevel@tonic-gate "color", 7207c478bd9Sstevel@tonic-gate color_func, 7217c478bd9Sstevel@tonic-gate BUILTIN_CMDLINE | BUILTIN_MENU | BUILTIN_HELP_LIST, 7227c478bd9Sstevel@tonic-gate "color NORMAL [HIGHLIGHT]", 7237c478bd9Sstevel@tonic-gate "Change the menu colors. The color NORMAL is used for most" 7247c478bd9Sstevel@tonic-gate " lines in the menu, and the color HIGHLIGHT is used to highlight the" 7257c478bd9Sstevel@tonic-gate " line where the cursor points. If you omit HIGHLIGHT, then the" 7267c478bd9Sstevel@tonic-gate " inverted color of NORMAL is used for the highlighted line." 7277c478bd9Sstevel@tonic-gate " The format of a color is \"FG/BG\". FG and BG are symbolic color names." 7287c478bd9Sstevel@tonic-gate " A symbolic color name must be one of these: black, blue, green," 7297c478bd9Sstevel@tonic-gate " cyan, red, magenta, brown, light-gray, dark-gray, light-blue," 7307c478bd9Sstevel@tonic-gate " light-green, light-cyan, light-red, light-magenta, yellow and white." 7317c478bd9Sstevel@tonic-gate " But only the first eight names can be used for BG. You can prefix" 7327c478bd9Sstevel@tonic-gate " \"blink-\" to FG if you want a blinking foreground color." 7337c478bd9Sstevel@tonic-gate }; 7347c478bd9Sstevel@tonic-gate 7357c478bd9Sstevel@tonic-gate 7367c478bd9Sstevel@tonic-gate /* configfile */ 7377c478bd9Sstevel@tonic-gate static int 7387c478bd9Sstevel@tonic-gate configfile_func (char *arg, int flags) 7397c478bd9Sstevel@tonic-gate { 7407c478bd9Sstevel@tonic-gate char *new_config = config_file; 7417c478bd9Sstevel@tonic-gate 7427c478bd9Sstevel@tonic-gate /* Check if the file ARG is present. */ 7437c478bd9Sstevel@tonic-gate if (! grub_open (arg)) 7447c478bd9Sstevel@tonic-gate return 1; 7457c478bd9Sstevel@tonic-gate 7467c478bd9Sstevel@tonic-gate grub_close (); 7477c478bd9Sstevel@tonic-gate 7487c478bd9Sstevel@tonic-gate /* Copy ARG to CONFIG_FILE. */ 7497c478bd9Sstevel@tonic-gate while ((*new_config++ = *arg++) != 0) 7507c478bd9Sstevel@tonic-gate ; 7517c478bd9Sstevel@tonic-gate 7527c478bd9Sstevel@tonic-gate #ifdef GRUB_UTIL 7537c478bd9Sstevel@tonic-gate /* Force to load the configuration file. */ 7547c478bd9Sstevel@tonic-gate use_config_file = 1; 7557c478bd9Sstevel@tonic-gate #endif 7567c478bd9Sstevel@tonic-gate 7577c478bd9Sstevel@tonic-gate /* Make sure that the user will not be authoritative. */ 7587c478bd9Sstevel@tonic-gate auth = 0; 7597c478bd9Sstevel@tonic-gate 7607c478bd9Sstevel@tonic-gate /* Restart cmain. */ 7617c478bd9Sstevel@tonic-gate grub_longjmp (restart_env, 0); 7627c478bd9Sstevel@tonic-gate 7637c478bd9Sstevel@tonic-gate /* Never reach here. */ 7647c478bd9Sstevel@tonic-gate return 0; 7657c478bd9Sstevel@tonic-gate } 7667c478bd9Sstevel@tonic-gate 7677c478bd9Sstevel@tonic-gate static struct builtin builtin_configfile = 7687c478bd9Sstevel@tonic-gate { 7697c478bd9Sstevel@tonic-gate "configfile", 7707c478bd9Sstevel@tonic-gate configfile_func, 7717c478bd9Sstevel@tonic-gate BUILTIN_CMDLINE | BUILTIN_HELP_LIST, 7727c478bd9Sstevel@tonic-gate "configfile FILE", 7737c478bd9Sstevel@tonic-gate "Load FILE as the configuration file." 7747c478bd9Sstevel@tonic-gate }; 7757c478bd9Sstevel@tonic-gate 7767c478bd9Sstevel@tonic-gate 7777c478bd9Sstevel@tonic-gate /* debug */ 7787c478bd9Sstevel@tonic-gate static int 7797c478bd9Sstevel@tonic-gate debug_func (char *arg, int flags) 7807c478bd9Sstevel@tonic-gate { 7817c478bd9Sstevel@tonic-gate if (debug) 7827c478bd9Sstevel@tonic-gate { 7837c478bd9Sstevel@tonic-gate debug = 0; 7847c478bd9Sstevel@tonic-gate grub_printf (" Debug mode is turned off\n"); 7857c478bd9Sstevel@tonic-gate } 7867c478bd9Sstevel@tonic-gate else 7877c478bd9Sstevel@tonic-gate { 7887c478bd9Sstevel@tonic-gate debug = 1; 7897c478bd9Sstevel@tonic-gate grub_printf (" Debug mode is turned on\n"); 7907c478bd9Sstevel@tonic-gate } 7917c478bd9Sstevel@tonic-gate 7927c478bd9Sstevel@tonic-gate return 0; 7937c478bd9Sstevel@tonic-gate } 7947c478bd9Sstevel@tonic-gate 7957c478bd9Sstevel@tonic-gate static struct builtin builtin_debug = 7967c478bd9Sstevel@tonic-gate { 7977c478bd9Sstevel@tonic-gate "debug", 7987c478bd9Sstevel@tonic-gate debug_func, 7997c478bd9Sstevel@tonic-gate BUILTIN_CMDLINE, 8007c478bd9Sstevel@tonic-gate "debug", 8017c478bd9Sstevel@tonic-gate "Turn on/off the debug mode." 8027c478bd9Sstevel@tonic-gate }; 8037c478bd9Sstevel@tonic-gate 8047c478bd9Sstevel@tonic-gate 8057c478bd9Sstevel@tonic-gate /* default */ 8067c478bd9Sstevel@tonic-gate static int 8077c478bd9Sstevel@tonic-gate default_func (char *arg, int flags) 8087c478bd9Sstevel@tonic-gate { 8097c478bd9Sstevel@tonic-gate #ifndef SUPPORT_DISKLESS 8107c478bd9Sstevel@tonic-gate if (grub_strcmp (arg, "saved") == 0) 8117c478bd9Sstevel@tonic-gate { 8127c478bd9Sstevel@tonic-gate default_entry = saved_entryno; 8137c478bd9Sstevel@tonic-gate return 0; 8147c478bd9Sstevel@tonic-gate } 8157c478bd9Sstevel@tonic-gate #endif /* SUPPORT_DISKLESS */ 8167c478bd9Sstevel@tonic-gate 8177c478bd9Sstevel@tonic-gate if (! safe_parse_maxint (&arg, &default_entry)) 8187c478bd9Sstevel@tonic-gate return 1; 8197c478bd9Sstevel@tonic-gate 8207c478bd9Sstevel@tonic-gate return 0; 8217c478bd9Sstevel@tonic-gate } 8227c478bd9Sstevel@tonic-gate 8237c478bd9Sstevel@tonic-gate static struct builtin builtin_default = 8247c478bd9Sstevel@tonic-gate { 8257c478bd9Sstevel@tonic-gate "default", 8267c478bd9Sstevel@tonic-gate default_func, 8277c478bd9Sstevel@tonic-gate BUILTIN_MENU, 8287c478bd9Sstevel@tonic-gate #if 0 8297c478bd9Sstevel@tonic-gate "default [NUM | `saved']", 8307c478bd9Sstevel@tonic-gate "Set the default entry to entry number NUM (if not specified, it is" 8317c478bd9Sstevel@tonic-gate " 0, the first entry) or the entry number saved by savedefault." 8327c478bd9Sstevel@tonic-gate #endif 8337c478bd9Sstevel@tonic-gate }; 8347c478bd9Sstevel@tonic-gate 8357c478bd9Sstevel@tonic-gate 8367c478bd9Sstevel@tonic-gate #ifdef GRUB_UTIL 8377c478bd9Sstevel@tonic-gate /* device */ 8387c478bd9Sstevel@tonic-gate static int 8397c478bd9Sstevel@tonic-gate device_func (char *arg, int flags) 8407c478bd9Sstevel@tonic-gate { 8417c478bd9Sstevel@tonic-gate char *drive = arg; 8427c478bd9Sstevel@tonic-gate char *device; 8437c478bd9Sstevel@tonic-gate 8447c478bd9Sstevel@tonic-gate /* Get the drive number from DRIVE. */ 8457c478bd9Sstevel@tonic-gate if (! set_device (drive)) 8467c478bd9Sstevel@tonic-gate return 1; 8477c478bd9Sstevel@tonic-gate 8487c478bd9Sstevel@tonic-gate /* Get the device argument. */ 8497c478bd9Sstevel@tonic-gate device = skip_to (0, drive); 8507c478bd9Sstevel@tonic-gate 8517c478bd9Sstevel@tonic-gate /* Terminate DEVICE. */ 8527c478bd9Sstevel@tonic-gate nul_terminate (device); 8537c478bd9Sstevel@tonic-gate 8547c478bd9Sstevel@tonic-gate if (! *device || ! check_device (device)) 8557c478bd9Sstevel@tonic-gate { 8567c478bd9Sstevel@tonic-gate errnum = ERR_FILE_NOT_FOUND; 8577c478bd9Sstevel@tonic-gate return 1; 8587c478bd9Sstevel@tonic-gate } 8597c478bd9Sstevel@tonic-gate 8607c478bd9Sstevel@tonic-gate assign_device_name (current_drive, device); 8617c478bd9Sstevel@tonic-gate 8627c478bd9Sstevel@tonic-gate return 0; 8637c478bd9Sstevel@tonic-gate } 8647c478bd9Sstevel@tonic-gate 8657c478bd9Sstevel@tonic-gate static struct builtin builtin_device = 8667c478bd9Sstevel@tonic-gate { 8677c478bd9Sstevel@tonic-gate "device", 8687c478bd9Sstevel@tonic-gate device_func, 8697c478bd9Sstevel@tonic-gate BUILTIN_MENU | BUILTIN_CMDLINE | BUILTIN_HELP_LIST, 8707c478bd9Sstevel@tonic-gate "device DRIVE DEVICE", 8717c478bd9Sstevel@tonic-gate "Specify DEVICE as the actual drive for a BIOS drive DRIVE. This command" 8727c478bd9Sstevel@tonic-gate " can be used only in the grub shell." 8737c478bd9Sstevel@tonic-gate }; 8747c478bd9Sstevel@tonic-gate #endif /* GRUB_UTIL */ 8757c478bd9Sstevel@tonic-gate 8767c478bd9Sstevel@tonic-gate #ifdef SUPPORT_NETBOOT 8777c478bd9Sstevel@tonic-gate /* Debug Function for RPC */ 8787c478bd9Sstevel@tonic-gate #ifdef RPC_DEBUG 8797c478bd9Sstevel@tonic-gate /* portmap */ 8807c478bd9Sstevel@tonic-gate static int 8817c478bd9Sstevel@tonic-gate portmap_func (char *arg, int flags) 8827c478bd9Sstevel@tonic-gate { 8837c478bd9Sstevel@tonic-gate int port, prog, ver; 8847c478bd9Sstevel@tonic-gate if (! grub_eth_probe ()){ 8857c478bd9Sstevel@tonic-gate grub_printf ("No ethernet card found.\n"); 8867c478bd9Sstevel@tonic-gate errnum = ERR_DEV_VALUES; 8877c478bd9Sstevel@tonic-gate return 1; 8887c478bd9Sstevel@tonic-gate } 8897c478bd9Sstevel@tonic-gate if ((prog = getdec(&arg)) == -1){ 8907c478bd9Sstevel@tonic-gate grub_printf("Error prog number\n"); 8917c478bd9Sstevel@tonic-gate return 1; 8927c478bd9Sstevel@tonic-gate } 8937c478bd9Sstevel@tonic-gate arg = skip_to (0, arg); 8947c478bd9Sstevel@tonic-gate if ((ver = getdec(&arg)) == -1){ 8957c478bd9Sstevel@tonic-gate grub_printf("Error ver number\n"); 8967c478bd9Sstevel@tonic-gate return 1; 8977c478bd9Sstevel@tonic-gate } 8987c478bd9Sstevel@tonic-gate port = __pmapudp_getport(ARP_SERVER, prog, ver); 8997c478bd9Sstevel@tonic-gate printf("portmap getport %d", port); 9007c478bd9Sstevel@tonic-gate return 0; 9017c478bd9Sstevel@tonic-gate } 9027c478bd9Sstevel@tonic-gate 9037c478bd9Sstevel@tonic-gate static struct builtin builtin_portmap = 9047c478bd9Sstevel@tonic-gate { 9057c478bd9Sstevel@tonic-gate "portmap", 9067c478bd9Sstevel@tonic-gate portmap_func, 9077c478bd9Sstevel@tonic-gate BUILTIN_CMDLINE | BUILTIN_HELP_LIST, 9087c478bd9Sstevel@tonic-gate "portmap prog_number vers_number", 9097c478bd9Sstevel@tonic-gate "Do portmap with the prog_number and vers_number" 9107c478bd9Sstevel@tonic-gate }; 9117c478bd9Sstevel@tonic-gate #endif /* RPC_DEBUG */ 9127c478bd9Sstevel@tonic-gate 9137c478bd9Sstevel@tonic-gate /* dhcp */ 9147c478bd9Sstevel@tonic-gate static int 9157c478bd9Sstevel@tonic-gate dhcp_func (char *arg, int flags) 9167c478bd9Sstevel@tonic-gate { 9177c478bd9Sstevel@tonic-gate int with_configfile = 0; 9187c478bd9Sstevel@tonic-gate 9197c478bd9Sstevel@tonic-gate if (grub_memcmp (arg, "--with-configfile", sizeof ("--with-configfile") - 1) 9207c478bd9Sstevel@tonic-gate == 0) 9217c478bd9Sstevel@tonic-gate { 9227c478bd9Sstevel@tonic-gate with_configfile = 1; 9237c478bd9Sstevel@tonic-gate arg = skip_to (0, arg); 9247c478bd9Sstevel@tonic-gate } 9257c478bd9Sstevel@tonic-gate 9267c478bd9Sstevel@tonic-gate if (! dhcp ()) 9277c478bd9Sstevel@tonic-gate { 9287c478bd9Sstevel@tonic-gate if (errnum == ERR_NONE) 9297c478bd9Sstevel@tonic-gate errnum = ERR_DEV_VALUES; 9307c478bd9Sstevel@tonic-gate 9317c478bd9Sstevel@tonic-gate return 1; 9327c478bd9Sstevel@tonic-gate } 9337c478bd9Sstevel@tonic-gate 9347c478bd9Sstevel@tonic-gate /* Notify the configuration. */ 9357c478bd9Sstevel@tonic-gate print_network_configuration (); 9367c478bd9Sstevel@tonic-gate 9377c478bd9Sstevel@tonic-gate /* XXX: this can cause an endless loop, but there is no easy way to 9387c478bd9Sstevel@tonic-gate detect such a loop unfortunately. */ 9397c478bd9Sstevel@tonic-gate if (with_configfile) 9407c478bd9Sstevel@tonic-gate configfile_func (config_file, flags); 9417c478bd9Sstevel@tonic-gate else 9427c478bd9Sstevel@tonic-gate solaris_config_file(); 9437c478bd9Sstevel@tonic-gate 9447c478bd9Sstevel@tonic-gate return 0; 9457c478bd9Sstevel@tonic-gate } 9467c478bd9Sstevel@tonic-gate 947*2506833eSJan Setje-Eilers static int 948*2506833eSJan Setje-Eilers test_config_file(char *menufile) 949*2506833eSJan Setje-Eilers { 950*2506833eSJan Setje-Eilers int err; 951*2506833eSJan Setje-Eilers 952*2506833eSJan Setje-Eilers /* 953*2506833eSJan Setje-Eilers * If the file exists, make it the default. Else, fallback 954*2506833eSJan Setje-Eilers * to what it was. Make sure we don't change errnum in the 955*2506833eSJan Setje-Eilers * process. 956*2506833eSJan Setje-Eilers */ 957*2506833eSJan Setje-Eilers err = errnum; 958*2506833eSJan Setje-Eilers if (grub_open(menufile)) { 959*2506833eSJan Setje-Eilers grub_strcpy(config_file, menufile); 960*2506833eSJan Setje-Eilers grub_close(); 961*2506833eSJan Setje-Eilers errnum = err; 962*2506833eSJan Setje-Eilers return (1); 963*2506833eSJan Setje-Eilers } 964*2506833eSJan Setje-Eilers errnum = err; 965*2506833eSJan Setje-Eilers return (0); 966*2506833eSJan Setje-Eilers } 967*2506833eSJan Setje-Eilers 9687c478bd9Sstevel@tonic-gate static void solaris_config_file (void) 9697c478bd9Sstevel@tonic-gate { 9707c478bd9Sstevel@tonic-gate static char menufile[64]; 9717c478bd9Sstevel@tonic-gate static char hexdigit[] = "0123456789ABCDEF"; 9727c478bd9Sstevel@tonic-gate char *c = menufile; 9737c478bd9Sstevel@tonic-gate int i; 9747c478bd9Sstevel@tonic-gate 975*2506833eSJan Setje-Eilers /* 976*2506833eSJan Setje-Eilers * if DHCP option 150 has been provided, config_file will 977*2506833eSJan Setje-Eilers * already contain the string, try it. 978*2506833eSJan Setje-Eilers */ 979*2506833eSJan Setje-Eilers if (configfile_origin == CFG_150) { 980*2506833eSJan Setje-Eilers if (test_config_file(config_file)) 981*2506833eSJan Setje-Eilers return; 982*2506833eSJan Setje-Eilers } 9837c478bd9Sstevel@tonic-gate 984*2506833eSJan Setje-Eilers /* 985*2506833eSJan Setje-Eilers * try to find host (MAC address) specific configfile: 986*2506833eSJan Setje-Eilers * menu.lst.01<ether_addr> 987*2506833eSJan Setje-Eilers */ 9882269adc8Sszhou grub_strcpy(c, "menu.lst.01"); 9897c478bd9Sstevel@tonic-gate c += grub_strlen(c); 9907c478bd9Sstevel@tonic-gate for (i = 0; i < ETH_ALEN; i++) { 9917c478bd9Sstevel@tonic-gate unsigned char b = arptable[ARP_CLIENT].node[i]; 9927c478bd9Sstevel@tonic-gate *c++ = hexdigit[b >> 4]; 9937c478bd9Sstevel@tonic-gate *c++ = hexdigit[b & 0xf]; 9947c478bd9Sstevel@tonic-gate } 9957c478bd9Sstevel@tonic-gate *c = 0; 996*2506833eSJan Setje-Eilers configfile_origin = CFG_MAC; 997*2506833eSJan Setje-Eilers if (test_config_file(menufile)) 998*2506833eSJan Setje-Eilers return; 9997c478bd9Sstevel@tonic-gate 10006759d08fScasper /* 1001*2506833eSJan Setje-Eilers * try to find a configfile derived from the DHCP/bootp 1002*2506833eSJan Setje-Eilers * BootFile string: menu.lst.<BootFile> 10037c478bd9Sstevel@tonic-gate */ 1004*2506833eSJan Setje-Eilers if (bootfile != NULL && bootfile[0] != 0) { 1005*2506833eSJan Setje-Eilers c = menufile; 1006*2506833eSJan Setje-Eilers grub_strcpy(c, "menu.lst."); 1007*2506833eSJan Setje-Eilers c += grub_strlen("menu.lst."); 1008*2506833eSJan Setje-Eilers i = grub_strlen("pxegrub."); 1009*2506833eSJan Setje-Eilers if (grub_memcmp(bootfile, "pxegrub.", i) == 0) 1010*2506833eSJan Setje-Eilers grub_strcpy(c, bootfile + i); 1011*2506833eSJan Setje-Eilers else 1012*2506833eSJan Setje-Eilers grub_strcpy(c, bootfile); 1013*2506833eSJan Setje-Eilers configfile_origin = CFG_BOOTFILE; 1014*2506833eSJan Setje-Eilers if (test_config_file(menufile)) 1015*2506833eSJan Setje-Eilers return; 10167c478bd9Sstevel@tonic-gate } 1017*2506833eSJan Setje-Eilers 1018*2506833eSJan Setje-Eilers /* 1019*2506833eSJan Setje-Eilers * Default to hard coded "/boot/grub/menu.lst" config file. 1020*2506833eSJan Setje-Eilers * This is the last resort, so there's no need to test it, 1021*2506833eSJan Setje-Eilers * as there's nothing else to try. 1022*2506833eSJan Setje-Eilers */ 1023*2506833eSJan Setje-Eilers char *cp = config_file; 1024*2506833eSJan Setje-Eilers /* skip leading slashes for tftp */ 1025*2506833eSJan Setje-Eilers while (*cp == '/') 1026*2506833eSJan Setje-Eilers ++cp; 1027*2506833eSJan Setje-Eilers grub_memmove (config_file, cp, strlen(cp) + 1); 1028*2506833eSJan Setje-Eilers configfile_origin = CFG_HARDCODED; 10297c478bd9Sstevel@tonic-gate } 10307c478bd9Sstevel@tonic-gate 10317c478bd9Sstevel@tonic-gate static struct builtin builtin_dhcp = 10327c478bd9Sstevel@tonic-gate { 10337c478bd9Sstevel@tonic-gate "dhcp", 10347c478bd9Sstevel@tonic-gate dhcp_func, 10357c478bd9Sstevel@tonic-gate BUILTIN_CMDLINE | BUILTIN_MENU | BUILTIN_HELP_LIST, 10367c478bd9Sstevel@tonic-gate "dhcp", 10377c478bd9Sstevel@tonic-gate "Initialize a network device via DHCP." 10387c478bd9Sstevel@tonic-gate }; 10397c478bd9Sstevel@tonic-gate #endif /* SUPPORT_NETBOOT */ 10407c478bd9Sstevel@tonic-gate 10417c478bd9Sstevel@tonic-gate static int terminal_func (char *arg, int flags); 10427c478bd9Sstevel@tonic-gate 10431fac5a60Ssetje static int verbose_func(char *arg, int flags) { 10441fac5a60Ssetje 10451fac5a60Ssetje if (grub_strcmp(arg, "off") == 0) { 10461fac5a60Ssetje silent.status = DEFER_SILENT; 10471fac5a60Ssetje return; 10481fac5a60Ssetje } else 10491fac5a60Ssetje if (flags == BUILTIN_CMDLINE) { 10501fac5a60Ssetje silent.status = DEFER_VERBOSE; 10511fac5a60Ssetje return; 10521fac5a60Ssetje } 10531fac5a60Ssetje 10541fac5a60Ssetje silent.status = VERBOSE; 10551fac5a60Ssetje 1056ae115bc7Smrj /* get back to text console */ 10571fac5a60Ssetje if (current_term->shutdown) { 10581fac5a60Ssetje (*current_term->shutdown)(); 10591fac5a60Ssetje current_term = term_table; /* assumption: console is first */ 10601fac5a60Ssetje } 10611fac5a60Ssetje 10621fac5a60Ssetje /* dump the buffer */ 10631fac5a60Ssetje if (!silent.looped) { 10641fac5a60Ssetje /* if the buffer hasn't looped, just print it */ 10651fac5a60Ssetje printf("%s", silent.buffer); 10661fac5a60Ssetje } else { 10671fac5a60Ssetje /* 10681fac5a60Ssetje * If the buffer has looped, first print the oldest part of the buffer, 10691fac5a60Ssetje * which is one past the current null. Then print the newer part which 10701fac5a60Ssetje * starts at the beginning of the buffer. 10711fac5a60Ssetje */ 10721fac5a60Ssetje printf("%s", silent.buffer_start + 1); 10731fac5a60Ssetje printf("%s", silent.buffer); 10741fac5a60Ssetje } 10751fac5a60Ssetje 10761fac5a60Ssetje return 0; 10771fac5a60Ssetje } 10781fac5a60Ssetje 10791fac5a60Ssetje static struct builtin builtin_verbose = 10801fac5a60Ssetje { 10811fac5a60Ssetje "verbose", 10821fac5a60Ssetje verbose_func, 10831fac5a60Ssetje BUILTIN_CMDLINE | BUILTIN_MENU | BUILTIN_SCRIPT | BUILTIN_HELP_LIST, 10841fac5a60Ssetje "verbose", 10851fac5a60Ssetje "Verbose output during menu entry (script) execution." 10861fac5a60Ssetje }; 10871fac5a60Ssetje 10887c478bd9Sstevel@tonic-gate #ifdef SUPPORT_GRAPHICS 10897c478bd9Sstevel@tonic-gate 10907c478bd9Sstevel@tonic-gate static int splashimage_func(char *arg, int flags) { 10917c478bd9Sstevel@tonic-gate char splashimage[64]; 10927c478bd9Sstevel@tonic-gate int i; 10931fac5a60Ssetje 10947c478bd9Sstevel@tonic-gate /* filename can only be 64 characters due to our buffer size */ 10957c478bd9Sstevel@tonic-gate if (strlen(arg) > 63) 10967c478bd9Sstevel@tonic-gate return 1; 10977c478bd9Sstevel@tonic-gate 10981fac5a60Ssetje if (flags == BUILTIN_SCRIPT) 10991fac5a60Ssetje flags = BUILTIN_CMDLINE; 11001fac5a60Ssetje 1101a6e28364SSuhasini Peddada if (flags == BUILTIN_CMDLINE) { 1102a6e28364SSuhasini Peddada if (!grub_open(arg)) 1103a6e28364SSuhasini Peddada return 1; 1104a6e28364SSuhasini Peddada grub_close(); 1105a6e28364SSuhasini Peddada } 11067c478bd9Sstevel@tonic-gate 1107a6e28364SSuhasini Peddada strcpy(splashimage, arg); 110841c4174fSWilliam Kucharski 11097c478bd9Sstevel@tonic-gate /* get rid of TERM_NEED_INIT from the graphics terminal. */ 11107c478bd9Sstevel@tonic-gate for (i = 0; term_table[i].name; i++) { 11117c478bd9Sstevel@tonic-gate if (grub_strcmp (term_table[i].name, "graphics") == 0) { 11127c478bd9Sstevel@tonic-gate term_table[i].flags &= ~TERM_NEED_INIT; 11137c478bd9Sstevel@tonic-gate break; 11147c478bd9Sstevel@tonic-gate } 11157c478bd9Sstevel@tonic-gate } 11169b4e3ac2SWilliam Kucharski 1117a6e28364SSuhasini Peddada graphics_set_splash(splashimage); 1118a6e28364SSuhasini Peddada 11197c478bd9Sstevel@tonic-gate if (flags == BUILTIN_CMDLINE && graphics_inited) { 11201fac5a60Ssetje /* 11211fac5a60Ssetje * calling graphics_end() here flickers the screen black. OTOH not 11221fac5a60Ssetje * calling it gets us odd plane interlacing / early palette switching ? 11231fac5a60Ssetje * ideally one should figure out how to double buffer and switch... 11241fac5a60Ssetje */ 11257c478bd9Sstevel@tonic-gate graphics_end(); 11267c478bd9Sstevel@tonic-gate graphics_init(); 11277c478bd9Sstevel@tonic-gate graphics_cls(); 11287c478bd9Sstevel@tonic-gate } 11297c478bd9Sstevel@tonic-gate 11309b4e3ac2SWilliam Kucharski /* 11319b4e3ac2SWilliam Kucharski * This call does not explicitly initialize graphics mode, but rather 11329b4e3ac2SWilliam Kucharski * simply sets the terminal type unless we're in command line mode and 11339b4e3ac2SWilliam Kucharski * call this function while in terminal mode. 11349b4e3ac2SWilliam Kucharski */ 11357c478bd9Sstevel@tonic-gate terminal_func("graphics", flags); 11367c478bd9Sstevel@tonic-gate 11371fac5a60Ssetje reset_term = 0; 11381fac5a60Ssetje 11397c478bd9Sstevel@tonic-gate return 0; 11407c478bd9Sstevel@tonic-gate } 11417c478bd9Sstevel@tonic-gate 11427c478bd9Sstevel@tonic-gate static struct builtin builtin_splashimage = 11437c478bd9Sstevel@tonic-gate { 11447c478bd9Sstevel@tonic-gate "splashimage", 11457c478bd9Sstevel@tonic-gate splashimage_func, 11461fac5a60Ssetje BUILTIN_CMDLINE | BUILTIN_MENU | BUILTIN_SCRIPT | BUILTIN_HELP_LIST, 11477c478bd9Sstevel@tonic-gate "splashimage FILE", 11487c478bd9Sstevel@tonic-gate "Load FILE as the background image when in graphics mode." 11497c478bd9Sstevel@tonic-gate }; 11507c478bd9Sstevel@tonic-gate 11517c478bd9Sstevel@tonic-gate 11527c478bd9Sstevel@tonic-gate /* foreground */ 11537c478bd9Sstevel@tonic-gate static int 11547c478bd9Sstevel@tonic-gate foreground_func(char *arg, int flags) 11557c478bd9Sstevel@tonic-gate { 11567c478bd9Sstevel@tonic-gate if (grub_strlen(arg) == 6) { 11577c478bd9Sstevel@tonic-gate int r = ((hex(arg[0]) << 4) | hex(arg[1])) >> 2; 11587c478bd9Sstevel@tonic-gate int g = ((hex(arg[2]) << 4) | hex(arg[3])) >> 2; 11597c478bd9Sstevel@tonic-gate int b = ((hex(arg[4]) << 4) | hex(arg[5])) >> 2; 11607c478bd9Sstevel@tonic-gate 11617c478bd9Sstevel@tonic-gate foreground = (r << 16) | (g << 8) | b; 11627c478bd9Sstevel@tonic-gate if (graphics_inited) 11637c478bd9Sstevel@tonic-gate graphics_set_palette(15, r, g, b); 11647c478bd9Sstevel@tonic-gate 11657c478bd9Sstevel@tonic-gate return (0); 11667c478bd9Sstevel@tonic-gate } 11677c478bd9Sstevel@tonic-gate 11687c478bd9Sstevel@tonic-gate return (1); 11697c478bd9Sstevel@tonic-gate } 11707c478bd9Sstevel@tonic-gate 11717c478bd9Sstevel@tonic-gate static struct builtin builtin_foreground = 11727c478bd9Sstevel@tonic-gate { 11737c478bd9Sstevel@tonic-gate "foreground", 11747c478bd9Sstevel@tonic-gate foreground_func, 117567ce1dadSJan Setje-Eilers BUILTIN_CMDLINE | BUILTIN_MENU | BUILTIN_HELP_LIST | BUILTIN_SCRIPT, 11767c478bd9Sstevel@tonic-gate "foreground RRGGBB", 11777c478bd9Sstevel@tonic-gate "Sets the foreground color when in graphics mode." 11787c478bd9Sstevel@tonic-gate "RR is red, GG is green, and BB blue. Numbers must be in hexadecimal." 11797c478bd9Sstevel@tonic-gate }; 11807c478bd9Sstevel@tonic-gate 11817c478bd9Sstevel@tonic-gate 11827c478bd9Sstevel@tonic-gate /* background */ 11837c478bd9Sstevel@tonic-gate static int 11847c478bd9Sstevel@tonic-gate background_func(char *arg, int flags) 11857c478bd9Sstevel@tonic-gate { 11867c478bd9Sstevel@tonic-gate if (grub_strlen(arg) == 6) { 11877c478bd9Sstevel@tonic-gate int r = ((hex(arg[0]) << 4) | hex(arg[1])) >> 2; 11887c478bd9Sstevel@tonic-gate int g = ((hex(arg[2]) << 4) | hex(arg[3])) >> 2; 11897c478bd9Sstevel@tonic-gate int b = ((hex(arg[4]) << 4) | hex(arg[5])) >> 2; 11907c478bd9Sstevel@tonic-gate 11917c478bd9Sstevel@tonic-gate background = (r << 16) | (g << 8) | b; 11927c478bd9Sstevel@tonic-gate if (graphics_inited) 11937c478bd9Sstevel@tonic-gate graphics_set_palette(0, r, g, b); 11947c478bd9Sstevel@tonic-gate return (0); 11957c478bd9Sstevel@tonic-gate } 11967c478bd9Sstevel@tonic-gate 11977c478bd9Sstevel@tonic-gate return (1); 11987c478bd9Sstevel@tonic-gate } 11997c478bd9Sstevel@tonic-gate 12007c478bd9Sstevel@tonic-gate static struct builtin builtin_background = 12017c478bd9Sstevel@tonic-gate { 12027c478bd9Sstevel@tonic-gate "background", 12037c478bd9Sstevel@tonic-gate background_func, 120467ce1dadSJan Setje-Eilers BUILTIN_CMDLINE | BUILTIN_MENU | BUILTIN_HELP_LIST | BUILTIN_SCRIPT, 12057c478bd9Sstevel@tonic-gate "background RRGGBB", 12067c478bd9Sstevel@tonic-gate "Sets the background color when in graphics mode." 12077c478bd9Sstevel@tonic-gate "RR is red, GG is green, and BB blue. Numbers must be in hexadecimal." 12087c478bd9Sstevel@tonic-gate }; 12097c478bd9Sstevel@tonic-gate 12107c478bd9Sstevel@tonic-gate #endif /* SUPPORT_GRAPHICS */ 12117c478bd9Sstevel@tonic-gate 12127c478bd9Sstevel@tonic-gate 12137c478bd9Sstevel@tonic-gate /* clear */ 12147c478bd9Sstevel@tonic-gate static int 12157c478bd9Sstevel@tonic-gate clear_func() 12167c478bd9Sstevel@tonic-gate { 12177c478bd9Sstevel@tonic-gate if (current_term->cls) 12187c478bd9Sstevel@tonic-gate current_term->cls(); 12197c478bd9Sstevel@tonic-gate 12207c478bd9Sstevel@tonic-gate return 0; 12217c478bd9Sstevel@tonic-gate } 12227c478bd9Sstevel@tonic-gate 12237c478bd9Sstevel@tonic-gate static struct builtin builtin_clear = 12247c478bd9Sstevel@tonic-gate { 12257c478bd9Sstevel@tonic-gate "clear", 12267c478bd9Sstevel@tonic-gate clear_func, 12277c478bd9Sstevel@tonic-gate BUILTIN_CMDLINE | BUILTIN_HELP_LIST, 12287c478bd9Sstevel@tonic-gate "clear", 12297c478bd9Sstevel@tonic-gate "Clear the screen" 12307c478bd9Sstevel@tonic-gate }; 12317c478bd9Sstevel@tonic-gate 12327c478bd9Sstevel@tonic-gate /* displayapm */ 12337c478bd9Sstevel@tonic-gate static int 12347c478bd9Sstevel@tonic-gate displayapm_func (char *arg, int flags) 12357c478bd9Sstevel@tonic-gate { 12367c478bd9Sstevel@tonic-gate if (mbi.flags & MB_INFO_APM_TABLE) 12377c478bd9Sstevel@tonic-gate { 12387c478bd9Sstevel@tonic-gate grub_printf ("APM BIOS information:\n" 12397c478bd9Sstevel@tonic-gate " Version: 0x%x\n" 12407c478bd9Sstevel@tonic-gate " 32-bit CS: 0x%x\n" 12417c478bd9Sstevel@tonic-gate " Offset: 0x%x\n" 12427c478bd9Sstevel@tonic-gate " 16-bit CS: 0x%x\n" 12437c478bd9Sstevel@tonic-gate " 16-bit DS: 0x%x\n" 12447c478bd9Sstevel@tonic-gate " 32-bit CS length: 0x%x\n" 12457c478bd9Sstevel@tonic-gate " 16-bit CS length: 0x%x\n" 12467c478bd9Sstevel@tonic-gate " 16-bit DS length: 0x%x\n", 12477c478bd9Sstevel@tonic-gate (unsigned) apm_bios_info.version, 12487c478bd9Sstevel@tonic-gate (unsigned) apm_bios_info.cseg, 12497c478bd9Sstevel@tonic-gate apm_bios_info.offset, 12507c478bd9Sstevel@tonic-gate (unsigned) apm_bios_info.cseg_16, 12517c478bd9Sstevel@tonic-gate (unsigned) apm_bios_info.dseg_16, 12527c478bd9Sstevel@tonic-gate (unsigned) apm_bios_info.cseg_len, 12537c478bd9Sstevel@tonic-gate (unsigned) apm_bios_info.cseg_16_len, 12547c478bd9Sstevel@tonic-gate (unsigned) apm_bios_info.dseg_16_len); 12557c478bd9Sstevel@tonic-gate } 12567c478bd9Sstevel@tonic-gate else 12577c478bd9Sstevel@tonic-gate { 12587c478bd9Sstevel@tonic-gate grub_printf ("No APM BIOS found or probe failed\n"); 12597c478bd9Sstevel@tonic-gate } 12607c478bd9Sstevel@tonic-gate 12617c478bd9Sstevel@tonic-gate return 0; 12627c478bd9Sstevel@tonic-gate } 12637c478bd9Sstevel@tonic-gate 12647c478bd9Sstevel@tonic-gate static struct builtin builtin_displayapm = 12657c478bd9Sstevel@tonic-gate { 12667c478bd9Sstevel@tonic-gate "displayapm", 12677c478bd9Sstevel@tonic-gate displayapm_func, 12687c478bd9Sstevel@tonic-gate BUILTIN_CMDLINE | BUILTIN_HELP_LIST, 12697c478bd9Sstevel@tonic-gate "displayapm", 12707c478bd9Sstevel@tonic-gate "Display APM BIOS information." 12717c478bd9Sstevel@tonic-gate }; 12727c478bd9Sstevel@tonic-gate 12737c478bd9Sstevel@tonic-gate 12747c478bd9Sstevel@tonic-gate /* displaymem */ 12757c478bd9Sstevel@tonic-gate static int 12767c478bd9Sstevel@tonic-gate displaymem_func (char *arg, int flags) 12777c478bd9Sstevel@tonic-gate { 12787c478bd9Sstevel@tonic-gate if (get_eisamemsize () != -1) 12797c478bd9Sstevel@tonic-gate grub_printf (" EISA Memory BIOS Interface is present\n"); 12807c478bd9Sstevel@tonic-gate if (get_mmap_entry ((void *) SCRATCHADDR, 0) != 0 12817c478bd9Sstevel@tonic-gate || *((int *) SCRATCHADDR) != 0) 12827c478bd9Sstevel@tonic-gate grub_printf (" Address Map BIOS Interface is present\n"); 12837c478bd9Sstevel@tonic-gate 12847c478bd9Sstevel@tonic-gate grub_printf (" Lower memory: %uK, " 12857c478bd9Sstevel@tonic-gate "Upper memory (to first chipset hole): %uK\n", 12867c478bd9Sstevel@tonic-gate mbi.mem_lower, mbi.mem_upper); 12877c478bd9Sstevel@tonic-gate 1288342440ecSPrasad Singamsetty if (min_mem64 != 0) 1289342440ecSPrasad Singamsetty grub_printf (" Memory limit for 64-bit ISADIR expansion: %uMB\n", 1290342440ecSPrasad Singamsetty min_mem64); 1291342440ecSPrasad Singamsetty 12927c478bd9Sstevel@tonic-gate if (mbi.flags & MB_INFO_MEM_MAP) 12937c478bd9Sstevel@tonic-gate { 12947c478bd9Sstevel@tonic-gate struct AddrRangeDesc *map = (struct AddrRangeDesc *) mbi.mmap_addr; 12957c478bd9Sstevel@tonic-gate int end_addr = mbi.mmap_addr + mbi.mmap_length; 12967c478bd9Sstevel@tonic-gate 12977c478bd9Sstevel@tonic-gate grub_printf (" [Address Range Descriptor entries " 12987c478bd9Sstevel@tonic-gate "immediately follow (values are 64-bit)]\n"); 12997c478bd9Sstevel@tonic-gate while (end_addr > (int) map) 13007c478bd9Sstevel@tonic-gate { 13017c478bd9Sstevel@tonic-gate char *str; 13027c478bd9Sstevel@tonic-gate 13037c478bd9Sstevel@tonic-gate if (map->Type == MB_ARD_MEMORY) 13047c478bd9Sstevel@tonic-gate str = "Usable RAM"; 13057c478bd9Sstevel@tonic-gate else 13067c478bd9Sstevel@tonic-gate str = "Reserved"; 13077c478bd9Sstevel@tonic-gate grub_printf (" %s: Base Address: 0x%x X 4GB + 0x%x,\n" 1308342440ecSPrasad Singamsetty " Length: 0x%x X 4GB + 0x%x bytes\n", 1309342440ecSPrasad Singamsetty str, 1310342440ecSPrasad Singamsetty (unsigned long) (map->BaseAddr >> 32), 1311342440ecSPrasad Singamsetty (unsigned long) (map->BaseAddr & 0xFFFFFFFF), 1312342440ecSPrasad Singamsetty (unsigned long) (map->Length >> 32), 1313342440ecSPrasad Singamsetty (unsigned long) (map->Length & 0xFFFFFFFF)); 13147c478bd9Sstevel@tonic-gate 13157c478bd9Sstevel@tonic-gate map = ((struct AddrRangeDesc *) (((int) map) + 4 + map->size)); 13167c478bd9Sstevel@tonic-gate } 13177c478bd9Sstevel@tonic-gate } 13187c478bd9Sstevel@tonic-gate 13197c478bd9Sstevel@tonic-gate return 0; 13207c478bd9Sstevel@tonic-gate } 13217c478bd9Sstevel@tonic-gate 13227c478bd9Sstevel@tonic-gate static struct builtin builtin_displaymem = 13237c478bd9Sstevel@tonic-gate { 13247c478bd9Sstevel@tonic-gate "displaymem", 13257c478bd9Sstevel@tonic-gate displaymem_func, 13267c478bd9Sstevel@tonic-gate BUILTIN_CMDLINE | BUILTIN_HELP_LIST, 13277c478bd9Sstevel@tonic-gate "displaymem", 13287c478bd9Sstevel@tonic-gate "Display what GRUB thinks the system address space map of the" 13297c478bd9Sstevel@tonic-gate " machine is, including all regions of physical RAM installed." 13307c478bd9Sstevel@tonic-gate }; 13317c478bd9Sstevel@tonic-gate 13327c478bd9Sstevel@tonic-gate 13337c478bd9Sstevel@tonic-gate /* dump FROM TO */ 13347c478bd9Sstevel@tonic-gate #ifdef GRUB_UTIL 13357c478bd9Sstevel@tonic-gate static int 13367c478bd9Sstevel@tonic-gate dump_func (char *arg, int flags) 13377c478bd9Sstevel@tonic-gate { 13387c478bd9Sstevel@tonic-gate char *from, *to; 13397c478bd9Sstevel@tonic-gate FILE *fp; 13407c478bd9Sstevel@tonic-gate char c; 13417c478bd9Sstevel@tonic-gate 13427c478bd9Sstevel@tonic-gate from = arg; 13437c478bd9Sstevel@tonic-gate to = skip_to (0, arg); 13447c478bd9Sstevel@tonic-gate if (! *from || ! *to) 13457c478bd9Sstevel@tonic-gate { 13467c478bd9Sstevel@tonic-gate errnum = ERR_BAD_ARGUMENT; 13477c478bd9Sstevel@tonic-gate return 1; 13487c478bd9Sstevel@tonic-gate } 13497c478bd9Sstevel@tonic-gate 13507c478bd9Sstevel@tonic-gate nul_terminate (from); 13517c478bd9Sstevel@tonic-gate nul_terminate (to); 13527c478bd9Sstevel@tonic-gate 13537c478bd9Sstevel@tonic-gate if (! grub_open (from)) 13547c478bd9Sstevel@tonic-gate return 1; 13557c478bd9Sstevel@tonic-gate 13567c478bd9Sstevel@tonic-gate fp = fopen (to, "w"); 13577c478bd9Sstevel@tonic-gate if (! fp) 13587c478bd9Sstevel@tonic-gate { 13597c478bd9Sstevel@tonic-gate errnum = ERR_WRITE; 13607c478bd9Sstevel@tonic-gate return 1; 13617c478bd9Sstevel@tonic-gate } 13627c478bd9Sstevel@tonic-gate 13637c478bd9Sstevel@tonic-gate while (grub_read (&c, 1)) 13647c478bd9Sstevel@tonic-gate if (fputc (c, fp) == EOF) 13657c478bd9Sstevel@tonic-gate { 13667c478bd9Sstevel@tonic-gate errnum = ERR_WRITE; 13677c478bd9Sstevel@tonic-gate fclose (fp); 13687c478bd9Sstevel@tonic-gate return 1; 13697c478bd9Sstevel@tonic-gate } 13707c478bd9Sstevel@tonic-gate 13717c478bd9Sstevel@tonic-gate if (fclose (fp) == EOF) 13727c478bd9Sstevel@tonic-gate { 13737c478bd9Sstevel@tonic-gate errnum = ERR_WRITE; 13747c478bd9Sstevel@tonic-gate return 1; 13757c478bd9Sstevel@tonic-gate } 13767c478bd9Sstevel@tonic-gate 13777c478bd9Sstevel@tonic-gate grub_close (); 13787c478bd9Sstevel@tonic-gate return 0; 13797c478bd9Sstevel@tonic-gate } 13807c478bd9Sstevel@tonic-gate 13817c478bd9Sstevel@tonic-gate static struct builtin builtin_dump = 13827c478bd9Sstevel@tonic-gate { 13837c478bd9Sstevel@tonic-gate "dump", 13847c478bd9Sstevel@tonic-gate dump_func, 13857c478bd9Sstevel@tonic-gate BUILTIN_CMDLINE, 13867c478bd9Sstevel@tonic-gate "dump FROM TO", 13877c478bd9Sstevel@tonic-gate "Dump the contents of the file FROM to the file TO. FROM must be" 13887c478bd9Sstevel@tonic-gate " a GRUB file and TO must be an OS file." 13897c478bd9Sstevel@tonic-gate }; 13907c478bd9Sstevel@tonic-gate #endif /* GRUB_UTIL */ 13917c478bd9Sstevel@tonic-gate 13927c478bd9Sstevel@tonic-gate 13937c478bd9Sstevel@tonic-gate static char embed_info[32]; 13947c478bd9Sstevel@tonic-gate /* embed */ 13957c478bd9Sstevel@tonic-gate /* Embed a Stage 1.5 in the first cylinder after MBR or in the 13967c478bd9Sstevel@tonic-gate bootloader block in a FFS. */ 13977c478bd9Sstevel@tonic-gate static int 13987c478bd9Sstevel@tonic-gate embed_func (char *arg, int flags) 13997c478bd9Sstevel@tonic-gate { 14007c478bd9Sstevel@tonic-gate char *stage1_5; 14017c478bd9Sstevel@tonic-gate char *device; 14027c478bd9Sstevel@tonic-gate char *stage1_5_buffer = (char *) RAW_ADDR (0x100000); 14037c478bd9Sstevel@tonic-gate int len, size; 14047c478bd9Sstevel@tonic-gate int sector; 14057c478bd9Sstevel@tonic-gate 14067c478bd9Sstevel@tonic-gate stage1_5 = arg; 14077c478bd9Sstevel@tonic-gate device = skip_to (0, stage1_5); 14087c478bd9Sstevel@tonic-gate 14097c478bd9Sstevel@tonic-gate /* Open a Stage 1.5. */ 14107c478bd9Sstevel@tonic-gate if (! grub_open (stage1_5)) 14117c478bd9Sstevel@tonic-gate return 1; 14127c478bd9Sstevel@tonic-gate 14137c478bd9Sstevel@tonic-gate /* Read the whole of the Stage 1.5. */ 14147c478bd9Sstevel@tonic-gate len = grub_read (stage1_5_buffer, -1); 14157c478bd9Sstevel@tonic-gate grub_close (); 14167c478bd9Sstevel@tonic-gate 14177c478bd9Sstevel@tonic-gate if (errnum) 14187c478bd9Sstevel@tonic-gate return 1; 14197c478bd9Sstevel@tonic-gate 14207c478bd9Sstevel@tonic-gate size = (len + SECTOR_SIZE - 1) / SECTOR_SIZE; 14217c478bd9Sstevel@tonic-gate 14227c478bd9Sstevel@tonic-gate /* Get the device where the Stage 1.5 will be embedded. */ 14237c478bd9Sstevel@tonic-gate set_device (device); 14247c478bd9Sstevel@tonic-gate if (errnum) 14257c478bd9Sstevel@tonic-gate return 1; 14267c478bd9Sstevel@tonic-gate 14277c478bd9Sstevel@tonic-gate if (current_partition == 0xFFFFFF) 14287c478bd9Sstevel@tonic-gate { 14297c478bd9Sstevel@tonic-gate /* Embed it after the MBR. */ 14307c478bd9Sstevel@tonic-gate 14317c478bd9Sstevel@tonic-gate char mbr[SECTOR_SIZE]; 14327c478bd9Sstevel@tonic-gate char ezbios_check[2*SECTOR_SIZE]; 14337c478bd9Sstevel@tonic-gate int i; 14347c478bd9Sstevel@tonic-gate 14357c478bd9Sstevel@tonic-gate /* Open the partition. */ 14367c478bd9Sstevel@tonic-gate if (! open_partition ()) 14377c478bd9Sstevel@tonic-gate return 1; 14387c478bd9Sstevel@tonic-gate 14397c478bd9Sstevel@tonic-gate /* No floppy has MBR. */ 14407c478bd9Sstevel@tonic-gate if (! (current_drive & 0x80)) 14417c478bd9Sstevel@tonic-gate { 14427c478bd9Sstevel@tonic-gate errnum = ERR_DEV_VALUES; 14437c478bd9Sstevel@tonic-gate return 1; 14447c478bd9Sstevel@tonic-gate } 14457c478bd9Sstevel@tonic-gate 14467c478bd9Sstevel@tonic-gate /* Read the MBR of CURRENT_DRIVE. */ 14477c478bd9Sstevel@tonic-gate if (! rawread (current_drive, PC_MBR_SECTOR, 0, SECTOR_SIZE, mbr)) 14487c478bd9Sstevel@tonic-gate return 1; 14497c478bd9Sstevel@tonic-gate 14507c478bd9Sstevel@tonic-gate /* Sanity check. */ 14517c478bd9Sstevel@tonic-gate if (! PC_MBR_CHECK_SIG (mbr)) 14527c478bd9Sstevel@tonic-gate { 14537c478bd9Sstevel@tonic-gate errnum = ERR_BAD_PART_TABLE; 14547c478bd9Sstevel@tonic-gate return 1; 14557c478bd9Sstevel@tonic-gate } 14567c478bd9Sstevel@tonic-gate 14577c478bd9Sstevel@tonic-gate /* Check if the disk can store the Stage 1.5. */ 14587c478bd9Sstevel@tonic-gate for (i = 0; i < 4; i++) 14597c478bd9Sstevel@tonic-gate if (PC_SLICE_TYPE (mbr, i) && PC_SLICE_START (mbr, i) - 1 < size) 14607c478bd9Sstevel@tonic-gate { 14617c478bd9Sstevel@tonic-gate errnum = ERR_NO_DISK_SPACE; 14627c478bd9Sstevel@tonic-gate return 1; 14637c478bd9Sstevel@tonic-gate } 14647c478bd9Sstevel@tonic-gate 14657c478bd9Sstevel@tonic-gate /* Check for EZ-BIOS signature. It should be in the third 14667c478bd9Sstevel@tonic-gate * sector, but due to remapping it can appear in the second, so 14677c478bd9Sstevel@tonic-gate * load and check both. 14687c478bd9Sstevel@tonic-gate */ 14697c478bd9Sstevel@tonic-gate if (! rawread (current_drive, 1, 0, 2 * SECTOR_SIZE, ezbios_check)) 14707c478bd9Sstevel@tonic-gate return 1; 14717c478bd9Sstevel@tonic-gate 14727c478bd9Sstevel@tonic-gate if (! memcmp (ezbios_check + 3, "AERMH", 5) 14737c478bd9Sstevel@tonic-gate || ! memcmp (ezbios_check + 512 + 3, "AERMH", 5)) 14747c478bd9Sstevel@tonic-gate { 14757c478bd9Sstevel@tonic-gate /* The space after the MBR is used by EZ-BIOS which we must 14767c478bd9Sstevel@tonic-gate * not overwrite. 14777c478bd9Sstevel@tonic-gate */ 14787c478bd9Sstevel@tonic-gate errnum = ERR_NO_DISK_SPACE; 14797c478bd9Sstevel@tonic-gate return 1; 14807c478bd9Sstevel@tonic-gate } 14817c478bd9Sstevel@tonic-gate 14827c478bd9Sstevel@tonic-gate sector = 1; 14837c478bd9Sstevel@tonic-gate } 14847c478bd9Sstevel@tonic-gate else 14857c478bd9Sstevel@tonic-gate { 14867c478bd9Sstevel@tonic-gate /* Embed it in the bootloader block in the filesystem. */ 14877c478bd9Sstevel@tonic-gate int start_sector; 14887c478bd9Sstevel@tonic-gate 14897c478bd9Sstevel@tonic-gate /* Open the partition. */ 14907c478bd9Sstevel@tonic-gate if (! open_device ()) 14917c478bd9Sstevel@tonic-gate return 1; 14927c478bd9Sstevel@tonic-gate 14937c478bd9Sstevel@tonic-gate /* Check if the current slice supports embedding. */ 14947c478bd9Sstevel@tonic-gate if (fsys_table[fsys_type].embed_func == 0 14957c478bd9Sstevel@tonic-gate || ! fsys_table[fsys_type].embed_func (&start_sector, size)) 14967c478bd9Sstevel@tonic-gate { 14977c478bd9Sstevel@tonic-gate errnum = ERR_DEV_VALUES; 14987c478bd9Sstevel@tonic-gate return 1; 14997c478bd9Sstevel@tonic-gate } 15007c478bd9Sstevel@tonic-gate 15017c478bd9Sstevel@tonic-gate sector = part_start + start_sector; 15027c478bd9Sstevel@tonic-gate } 15037c478bd9Sstevel@tonic-gate 15047c478bd9Sstevel@tonic-gate /* Clear the cache. */ 1505342440ecSPrasad Singamsetty buf_track = BUF_CACHE_INVALID; 15067c478bd9Sstevel@tonic-gate 15077c478bd9Sstevel@tonic-gate /* Now perform the embedding. */ 15087c478bd9Sstevel@tonic-gate if (! devwrite (sector - part_start, size, stage1_5_buffer)) 15097c478bd9Sstevel@tonic-gate return 1; 15107c478bd9Sstevel@tonic-gate 15117c478bd9Sstevel@tonic-gate grub_printf (" %d sectors are embedded.\n", size); 15127c478bd9Sstevel@tonic-gate grub_sprintf (embed_info, "%d+%d", sector - part_start, size); 15137c478bd9Sstevel@tonic-gate return 0; 15147c478bd9Sstevel@tonic-gate } 15157c478bd9Sstevel@tonic-gate 15167c478bd9Sstevel@tonic-gate static struct builtin builtin_embed = 15177c478bd9Sstevel@tonic-gate { 15187c478bd9Sstevel@tonic-gate "embed", 15197c478bd9Sstevel@tonic-gate embed_func, 15207c478bd9Sstevel@tonic-gate BUILTIN_CMDLINE, 15217c478bd9Sstevel@tonic-gate "embed STAGE1_5 DEVICE", 15227c478bd9Sstevel@tonic-gate "Embed the Stage 1.5 STAGE1_5 in the sectors after MBR if DEVICE" 15237c478bd9Sstevel@tonic-gate " is a drive, or in the \"bootloader\" area if DEVICE is a FFS partition." 15247c478bd9Sstevel@tonic-gate " Print the number of sectors which STAGE1_5 occupies if successful." 15257c478bd9Sstevel@tonic-gate }; 15267c478bd9Sstevel@tonic-gate 15277c478bd9Sstevel@tonic-gate 15287c478bd9Sstevel@tonic-gate /* fallback */ 15297c478bd9Sstevel@tonic-gate static int 15307c478bd9Sstevel@tonic-gate fallback_func (char *arg, int flags) 15317c478bd9Sstevel@tonic-gate { 15327c478bd9Sstevel@tonic-gate int i = 0; 15337c478bd9Sstevel@tonic-gate 15347c478bd9Sstevel@tonic-gate while (*arg) 15357c478bd9Sstevel@tonic-gate { 15367c478bd9Sstevel@tonic-gate int entry; 15377c478bd9Sstevel@tonic-gate int j; 15387c478bd9Sstevel@tonic-gate 15397c478bd9Sstevel@tonic-gate if (! safe_parse_maxint (&arg, &entry)) 15407c478bd9Sstevel@tonic-gate return 1; 15417c478bd9Sstevel@tonic-gate 15427c478bd9Sstevel@tonic-gate /* Remove duplications to prevent infinite looping. */ 15437c478bd9Sstevel@tonic-gate for (j = 0; j < i; j++) 15447c478bd9Sstevel@tonic-gate if (entry == fallback_entries[j]) 15457c478bd9Sstevel@tonic-gate break; 15467c478bd9Sstevel@tonic-gate if (j != i) 15477c478bd9Sstevel@tonic-gate continue; 15487c478bd9Sstevel@tonic-gate 15497c478bd9Sstevel@tonic-gate fallback_entries[i++] = entry; 15507c478bd9Sstevel@tonic-gate if (i == MAX_FALLBACK_ENTRIES) 15517c478bd9Sstevel@tonic-gate break; 15527c478bd9Sstevel@tonic-gate 15537c478bd9Sstevel@tonic-gate arg = skip_to (0, arg); 15547c478bd9Sstevel@tonic-gate } 15557c478bd9Sstevel@tonic-gate 15567c478bd9Sstevel@tonic-gate if (i < MAX_FALLBACK_ENTRIES) 15577c478bd9Sstevel@tonic-gate fallback_entries[i] = -1; 15587c478bd9Sstevel@tonic-gate 15597c478bd9Sstevel@tonic-gate fallback_entryno = (i == 0) ? -1 : 0; 15607c478bd9Sstevel@tonic-gate 15617c478bd9Sstevel@tonic-gate return 0; 15627c478bd9Sstevel@tonic-gate } 15637c478bd9Sstevel@tonic-gate 15647c478bd9Sstevel@tonic-gate static struct builtin builtin_fallback = 15657c478bd9Sstevel@tonic-gate { 15667c478bd9Sstevel@tonic-gate "fallback", 15677c478bd9Sstevel@tonic-gate fallback_func, 15687c478bd9Sstevel@tonic-gate BUILTIN_MENU, 15697c478bd9Sstevel@tonic-gate #if 0 15707c478bd9Sstevel@tonic-gate "fallback NUM...", 15717c478bd9Sstevel@tonic-gate "Go into unattended boot mode: if the default boot entry has any" 15727c478bd9Sstevel@tonic-gate " errors, instead of waiting for the user to do anything, it" 15737c478bd9Sstevel@tonic-gate " immediately starts over using the NUM entry (same numbering as the" 15747c478bd9Sstevel@tonic-gate " `default' command). This obviously won't help if the machine" 15757c478bd9Sstevel@tonic-gate " was rebooted by a kernel that GRUB loaded." 15767c478bd9Sstevel@tonic-gate #endif 15777c478bd9Sstevel@tonic-gate }; 15787c478bd9Sstevel@tonic-gate 15797c478bd9Sstevel@tonic-gate 1580051aabe6Staylor 1581051aabe6Staylor void 1582051aabe6Staylor set_root (char *root, unsigned long drive, unsigned long part) 1583051aabe6Staylor { 1584051aabe6Staylor int bsd_part = (part >> 8) & 0xFF; 1585051aabe6Staylor int pc_slice = part >> 16; 1586051aabe6Staylor 1587051aabe6Staylor if (bsd_part == 0xFF) { 1588051aabe6Staylor grub_sprintf (root, "(hd%d,%d)\n", drive - 0x80, pc_slice); 1589051aabe6Staylor } else { 1590051aabe6Staylor grub_sprintf (root, "(hd%d,%d,%c)\n", 1591051aabe6Staylor drive - 0x80, pc_slice, bsd_part + 'a'); 1592051aabe6Staylor } 1593051aabe6Staylor } 1594051aabe6Staylor 15957c478bd9Sstevel@tonic-gate static int 1596eb2bd662Svikram find_common (char *arg, char *root, int for_root, int flags) 15977c478bd9Sstevel@tonic-gate { 1598eb2bd662Svikram char *filename = NULL; 1599eb2bd662Svikram static char argpart[32]; 1600eb2bd662Svikram static char device[32]; 1601eb2bd662Svikram char *tmp_argpart = NULL; 16027c478bd9Sstevel@tonic-gate unsigned long drive; 16037c478bd9Sstevel@tonic-gate unsigned long tmp_drive = saved_drive; 16047c478bd9Sstevel@tonic-gate unsigned long tmp_partition = saved_partition; 16057c478bd9Sstevel@tonic-gate int got_file = 0; 1606eb2bd662Svikram static char bootsign[BOOTSIGN_LEN]; 1607eb2bd662Svikram 1608eb2bd662Svikram /* 1609eb2bd662Svikram * If argument has partition information (findroot command only), then 1610eb2bd662Svikram * it can't be a floppy 1611eb2bd662Svikram */ 1612eb2bd662Svikram if (for_root && arg[0] == '(') { 1613eb2bd662Svikram tmp_argpart = grub_strchr(arg + 1, ','); 1614eb2bd662Svikram if (tmp_argpart == NULL) 1615eb2bd662Svikram goto out; 1616eb2bd662Svikram grub_strcpy(argpart, tmp_argpart); 1617eb2bd662Svikram *tmp_argpart = '\0'; 1618eb2bd662Svikram arg++; 1619eb2bd662Svikram grub_sprintf(bootsign, "%s/%s", BOOTSIGN_DIR, arg); 1620eb2bd662Svikram filename = bootsign; 1621eb2bd662Svikram goto harddisk; 1622eb2bd662Svikram } else if (for_root) { 1623eb2bd662Svikram /* Boot signature without partition/slice information */ 1624eb2bd662Svikram grub_sprintf(bootsign, "%s/%s", BOOTSIGN_DIR, arg); 1625eb2bd662Svikram filename = bootsign; 1626eb2bd662Svikram } else { 1627eb2bd662Svikram /* plain vanilla find cmd */ 1628eb2bd662Svikram filename = arg; 1629eb2bd662Svikram } 16307c478bd9Sstevel@tonic-gate 16317c478bd9Sstevel@tonic-gate /* Floppies. */ 16327c478bd9Sstevel@tonic-gate for (drive = 0; drive < 8; drive++) 16337c478bd9Sstevel@tonic-gate { 16347c478bd9Sstevel@tonic-gate current_drive = drive; 16357c478bd9Sstevel@tonic-gate current_partition = 0xFFFFFF; 16367c478bd9Sstevel@tonic-gate 16377c478bd9Sstevel@tonic-gate if (open_device ()) 16387c478bd9Sstevel@tonic-gate { 16397c478bd9Sstevel@tonic-gate saved_drive = current_drive; 16407c478bd9Sstevel@tonic-gate saved_partition = current_partition; 16417c478bd9Sstevel@tonic-gate if (grub_open (filename)) 16427c478bd9Sstevel@tonic-gate { 16437c478bd9Sstevel@tonic-gate grub_close (); 16447c478bd9Sstevel@tonic-gate got_file = 1; 1645eb2bd662Svikram if (for_root) { 1646eb2bd662Svikram grub_sprintf(root, "(fd%d)", drive); 1647eb2bd662Svikram goto out; 1648eb2bd662Svikram } else 1649eb2bd662Svikram grub_printf (" (fd%d)\n", drive); 16507c478bd9Sstevel@tonic-gate } 16517c478bd9Sstevel@tonic-gate } 16527c478bd9Sstevel@tonic-gate 16537c478bd9Sstevel@tonic-gate errnum = ERR_NONE; 16547c478bd9Sstevel@tonic-gate } 16557c478bd9Sstevel@tonic-gate 1656eb2bd662Svikram harddisk: 16577c478bd9Sstevel@tonic-gate /* Hard disks. */ 16587c478bd9Sstevel@tonic-gate for (drive = 0x80; drive < 0x88; drive++) 16597c478bd9Sstevel@tonic-gate { 16607c478bd9Sstevel@tonic-gate unsigned long part = 0xFFFFFF; 16617c478bd9Sstevel@tonic-gate unsigned long start, len, offset, ext_offset; 16627c478bd9Sstevel@tonic-gate int type, entry; 16637c478bd9Sstevel@tonic-gate char buf[SECTOR_SIZE]; 16647c478bd9Sstevel@tonic-gate 1665eb2bd662Svikram if (for_root && tmp_argpart) { 1666051aabe6Staylor grub_sprintf(device, "(hd%d%s", drive - 0x80, argpart); 1667eb2bd662Svikram set_device(device); 1668eb2bd662Svikram errnum = ERR_NONE; 1669eb2bd662Svikram part = current_partition; 1670eb2bd662Svikram if (open_device ()) { 1671eb2bd662Svikram saved_drive = current_drive; 1672eb2bd662Svikram saved_partition = current_partition; 1673eb2bd662Svikram errnum = ERR_NONE; 1674eb2bd662Svikram if (grub_open (filename)) { 1675eb2bd662Svikram grub_close (); 1676eb2bd662Svikram got_file = 1; 1677051aabe6Staylor if (is_zfs_mount == 0) { 1678051aabe6Staylor set_root(root, current_drive, current_partition); 1679051aabe6Staylor goto out; 1680051aabe6Staylor } else { 1681051aabe6Staylor best_drive = current_drive; 1682051aabe6Staylor best_part = current_partition; 1683051aabe6Staylor } 1684eb2bd662Svikram } 1685eb2bd662Svikram } 1686eb2bd662Svikram errnum = ERR_NONE; 1687eb2bd662Svikram continue; 1688eb2bd662Svikram } 16897c478bd9Sstevel@tonic-gate current_drive = drive; 16907c478bd9Sstevel@tonic-gate while (next_partition (drive, 0xFFFFFF, &part, &type, 16917c478bd9Sstevel@tonic-gate &start, &len, &offset, &entry, 16927c478bd9Sstevel@tonic-gate &ext_offset, 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 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 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 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, " 1876342440ecSPrasad Singamsetty "The number of sectors = %u, %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 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 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 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 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 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 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 21787ce76caaSEnrico Perla - Sun Microsystems /* extended info */ 21797ce76caaSEnrico Perla - Sun Microsystems static int 21807ce76caaSEnrico Perla - Sun Microsystems info_func (char *arg, int flags) 21817ce76caaSEnrico Perla - Sun Microsystems { 21827ce76caaSEnrico Perla - Sun Microsystems int i; 21837ce76caaSEnrico Perla - Sun Microsystems 21847ce76caaSEnrico Perla - Sun Microsystems grub_printf("Extended version information : %s\n", pkg_version); 21857ce76caaSEnrico Perla - Sun Microsystems grub_printf("stage2 (MD5) signature : "); 21867ce76caaSEnrico Perla - Sun Microsystems 21877ce76caaSEnrico Perla - Sun Microsystems for (i = 0; i < 0x10; i++) 21887ce76caaSEnrico Perla - Sun Microsystems grub_printf("%x", md5hash[i]); 21897ce76caaSEnrico Perla - Sun Microsystems 21907ce76caaSEnrico Perla - Sun Microsystems grub_printf("\n"); 21917ce76caaSEnrico Perla - Sun Microsystems } 21927ce76caaSEnrico Perla - Sun Microsystems 21937ce76caaSEnrico Perla - Sun Microsystems static struct builtin builtin_info = 21947ce76caaSEnrico Perla - Sun Microsystems { 21957ce76caaSEnrico Perla - Sun Microsystems "info", 21967ce76caaSEnrico Perla - Sun Microsystems info_func, 21977ce76caaSEnrico Perla - Sun Microsystems BUILTIN_CMDLINE | BUILTIN_HELP_LIST | BUILTIN_SCRIPT, 21987ce76caaSEnrico Perla - Sun Microsystems "info", 21997ce76caaSEnrico Perla - Sun Microsystems "Read Grub extended version and stage2 MD5 hash" 22007ce76caaSEnrico Perla - Sun Microsystems }; 22017ce76caaSEnrico Perla - Sun Microsystems 22027ce76caaSEnrico Perla - Sun Microsystems 22037c478bd9Sstevel@tonic-gate 22047c478bd9Sstevel@tonic-gate /* initrd */ 22057c478bd9Sstevel@tonic-gate static int 22067c478bd9Sstevel@tonic-gate initrd_func (char *arg, int flags) 22077c478bd9Sstevel@tonic-gate { 22087c478bd9Sstevel@tonic-gate switch (kernel_type) 22097c478bd9Sstevel@tonic-gate { 22107c478bd9Sstevel@tonic-gate case KERNEL_TYPE_LINUX: 22117c478bd9Sstevel@tonic-gate case KERNEL_TYPE_BIG_LINUX: 22127c478bd9Sstevel@tonic-gate if (! load_initrd (arg)) 22137c478bd9Sstevel@tonic-gate return 1; 22147c478bd9Sstevel@tonic-gate break; 22157c478bd9Sstevel@tonic-gate 22167c478bd9Sstevel@tonic-gate default: 22177c478bd9Sstevel@tonic-gate errnum = ERR_NEED_LX_KERNEL; 22187c478bd9Sstevel@tonic-gate return 1; 22197c478bd9Sstevel@tonic-gate } 22207c478bd9Sstevel@tonic-gate 22217c478bd9Sstevel@tonic-gate return 0; 22227c478bd9Sstevel@tonic-gate } 22237c478bd9Sstevel@tonic-gate 22247c478bd9Sstevel@tonic-gate static struct builtin builtin_initrd = 22257c478bd9Sstevel@tonic-gate { 22267c478bd9Sstevel@tonic-gate "initrd", 22277c478bd9Sstevel@tonic-gate initrd_func, 22287c478bd9Sstevel@tonic-gate BUILTIN_CMDLINE | BUILTIN_HELP_LIST, 22297c478bd9Sstevel@tonic-gate "initrd FILE [ARG ...]", 22307c478bd9Sstevel@tonic-gate "Load an initial ramdisk FILE for a Linux format boot image and set the" 22317c478bd9Sstevel@tonic-gate " appropriate parameters in the Linux setup area in memory." 22327c478bd9Sstevel@tonic-gate }; 22337c478bd9Sstevel@tonic-gate 22347c478bd9Sstevel@tonic-gate 22357c478bd9Sstevel@tonic-gate /* install */ 22367c478bd9Sstevel@tonic-gate static int 22377c478bd9Sstevel@tonic-gate install_func (char *arg, int flags) 22387c478bd9Sstevel@tonic-gate { 22397c478bd9Sstevel@tonic-gate char *stage1_file, *dest_dev, *file, *addr; 22407c478bd9Sstevel@tonic-gate char *stage1_buffer = (char *) RAW_ADDR (0x100000); 22417c478bd9Sstevel@tonic-gate char *stage2_buffer = stage1_buffer + SECTOR_SIZE; 22427c478bd9Sstevel@tonic-gate char *old_sect = stage2_buffer + SECTOR_SIZE; 22437c478bd9Sstevel@tonic-gate char *stage2_first_buffer = old_sect + SECTOR_SIZE; 22447c478bd9Sstevel@tonic-gate char *stage2_second_buffer = stage2_first_buffer + SECTOR_SIZE; 22457c478bd9Sstevel@tonic-gate /* XXX: Probably SECTOR_SIZE is reasonable. */ 22467c478bd9Sstevel@tonic-gate char *config_filename = stage2_second_buffer + SECTOR_SIZE; 22477c478bd9Sstevel@tonic-gate char *dummy = config_filename + SECTOR_SIZE; 22487c478bd9Sstevel@tonic-gate int new_drive = GRUB_INVALID_DRIVE; 2249342440ecSPrasad Singamsetty int dest_drive, dest_partition; 2250342440ecSPrasad Singamsetty unsigned int dest_sector; 22517c478bd9Sstevel@tonic-gate int src_drive, src_partition, src_part_start; 22527c478bd9Sstevel@tonic-gate int i; 22537c478bd9Sstevel@tonic-gate struct geometry dest_geom, src_geom; 2254342440ecSPrasad Singamsetty unsigned int saved_sector; 2255342440ecSPrasad Singamsetty unsigned int stage2_first_sector, stage2_second_sector; 22567c478bd9Sstevel@tonic-gate char *ptr; 22577c478bd9Sstevel@tonic-gate int installaddr, installlist; 22587c478bd9Sstevel@tonic-gate /* Point to the location of the name of a configuration file in Stage 2. */ 22597c478bd9Sstevel@tonic-gate char *config_file_location; 22607c478bd9Sstevel@tonic-gate /* If FILE is a Stage 1.5? */ 22617c478bd9Sstevel@tonic-gate int is_stage1_5 = 0; 22627c478bd9Sstevel@tonic-gate /* Must call grub_close? */ 22637c478bd9Sstevel@tonic-gate int is_open = 0; 22647c478bd9Sstevel@tonic-gate /* If LBA is forced? */ 22657c478bd9Sstevel@tonic-gate int is_force_lba = 0; 22667c478bd9Sstevel@tonic-gate /* Was the last sector full? */ 22677c478bd9Sstevel@tonic-gate int last_length = SECTOR_SIZE; 22687c478bd9Sstevel@tonic-gate 22697c478bd9Sstevel@tonic-gate #ifdef GRUB_UTIL 22707c478bd9Sstevel@tonic-gate /* If the Stage 2 is in a partition mounted by an OS, this will store 22717c478bd9Sstevel@tonic-gate the filename under the OS. */ 22727c478bd9Sstevel@tonic-gate char *stage2_os_file = 0; 22737c478bd9Sstevel@tonic-gate #endif /* GRUB_UTIL */ 22747c478bd9Sstevel@tonic-gate 22751b8adde7SWilliam Kucharski auto void disk_read_savesect_func (unsigned int sector, int offset, 22761b8adde7SWilliam Kucharski int length); 22771b8adde7SWilliam Kucharski auto void disk_read_blocklist_func (unsigned int sector, int offset, 22781b8adde7SWilliam Kucharski int length); 22791b8adde7SWilliam Kucharski 22807c478bd9Sstevel@tonic-gate /* Save the first sector of Stage2 in STAGE2_SECT. */ 22811b8adde7SWilliam Kucharski auto void disk_read_savesect_func (unsigned int sector, int offset, 22821b8adde7SWilliam Kucharski int length) 22837c478bd9Sstevel@tonic-gate { 22847c478bd9Sstevel@tonic-gate if (debug) 2285342440ecSPrasad Singamsetty printf ("[%u]", sector); 22867c478bd9Sstevel@tonic-gate 22877c478bd9Sstevel@tonic-gate /* ReiserFS has files which sometimes contain data not aligned 22887c478bd9Sstevel@tonic-gate on sector boundaries. Returning an error is better than 22897c478bd9Sstevel@tonic-gate silently failing. */ 22907c478bd9Sstevel@tonic-gate if (offset != 0 || length != SECTOR_SIZE) 22917c478bd9Sstevel@tonic-gate errnum = ERR_UNALIGNED; 22927c478bd9Sstevel@tonic-gate 22937c478bd9Sstevel@tonic-gate saved_sector = sector; 22947c478bd9Sstevel@tonic-gate } 22957c478bd9Sstevel@tonic-gate 22967c478bd9Sstevel@tonic-gate /* Write SECTOR to INSTALLLIST, and update INSTALLADDR and 22977c478bd9Sstevel@tonic-gate INSTALLSECT. */ 22981b8adde7SWilliam Kucharski auto void disk_read_blocklist_func (unsigned int sector, int offset, 22991b8adde7SWilliam Kucharski int length) 23007c478bd9Sstevel@tonic-gate { 23017c478bd9Sstevel@tonic-gate if (debug) 2302342440ecSPrasad Singamsetty printf("[%u]", sector); 23037c478bd9Sstevel@tonic-gate 23047c478bd9Sstevel@tonic-gate if (offset != 0 || last_length != SECTOR_SIZE) 23057c478bd9Sstevel@tonic-gate { 23067c478bd9Sstevel@tonic-gate /* We found a non-sector-aligned data block. */ 23077c478bd9Sstevel@tonic-gate errnum = ERR_UNALIGNED; 23087c478bd9Sstevel@tonic-gate return; 23097c478bd9Sstevel@tonic-gate } 23107c478bd9Sstevel@tonic-gate 23117c478bd9Sstevel@tonic-gate last_length = length; 23127c478bd9Sstevel@tonic-gate 23137c478bd9Sstevel@tonic-gate if (*((unsigned long *) (installlist - 4)) 23147c478bd9Sstevel@tonic-gate + *((unsigned short *) installlist) != sector 23157c478bd9Sstevel@tonic-gate || installlist == (int) stage2_first_buffer + SECTOR_SIZE + 4) 23167c478bd9Sstevel@tonic-gate { 23177c478bd9Sstevel@tonic-gate installlist -= 8; 23187c478bd9Sstevel@tonic-gate 23197c478bd9Sstevel@tonic-gate if (*((unsigned long *) (installlist - 8))) 23207c478bd9Sstevel@tonic-gate errnum = ERR_WONT_FIT; 23217c478bd9Sstevel@tonic-gate else 23227c478bd9Sstevel@tonic-gate { 23237c478bd9Sstevel@tonic-gate *((unsigned short *) (installlist + 2)) = (installaddr >> 4); 23247c478bd9Sstevel@tonic-gate *((unsigned long *) (installlist - 4)) = sector; 23257c478bd9Sstevel@tonic-gate } 23267c478bd9Sstevel@tonic-gate } 23277c478bd9Sstevel@tonic-gate 23287c478bd9Sstevel@tonic-gate *((unsigned short *) installlist) += 1; 23297c478bd9Sstevel@tonic-gate installaddr += 512; 23307c478bd9Sstevel@tonic-gate } 23317c478bd9Sstevel@tonic-gate 23327c478bd9Sstevel@tonic-gate /* First, check the GNU-style long option. */ 23337c478bd9Sstevel@tonic-gate while (1) 23347c478bd9Sstevel@tonic-gate { 23357c478bd9Sstevel@tonic-gate if (grub_memcmp ("--force-lba", arg, sizeof ("--force-lba") - 1) == 0) 23367c478bd9Sstevel@tonic-gate { 23377c478bd9Sstevel@tonic-gate is_force_lba = 1; 23387c478bd9Sstevel@tonic-gate arg = skip_to (0, arg); 23397c478bd9Sstevel@tonic-gate } 23407c478bd9Sstevel@tonic-gate #ifdef GRUB_UTIL 23417c478bd9Sstevel@tonic-gate else if (grub_memcmp ("--stage2=", arg, sizeof ("--stage2=") - 1) == 0) 23427c478bd9Sstevel@tonic-gate { 23437c478bd9Sstevel@tonic-gate stage2_os_file = arg + sizeof ("--stage2=") - 1; 23447c478bd9Sstevel@tonic-gate arg = skip_to (0, arg); 23457c478bd9Sstevel@tonic-gate nul_terminate (stage2_os_file); 23467c478bd9Sstevel@tonic-gate } 23477c478bd9Sstevel@tonic-gate #endif /* GRUB_UTIL */ 23487c478bd9Sstevel@tonic-gate else 23497c478bd9Sstevel@tonic-gate break; 23507c478bd9Sstevel@tonic-gate } 23517c478bd9Sstevel@tonic-gate 23527c478bd9Sstevel@tonic-gate stage1_file = arg; 23537c478bd9Sstevel@tonic-gate dest_dev = skip_to (0, stage1_file); 23547c478bd9Sstevel@tonic-gate if (*dest_dev == 'd') 23557c478bd9Sstevel@tonic-gate { 23567c478bd9Sstevel@tonic-gate new_drive = 0; 23577c478bd9Sstevel@tonic-gate dest_dev = skip_to (0, dest_dev); 23587c478bd9Sstevel@tonic-gate } 23597c478bd9Sstevel@tonic-gate file = skip_to (0, dest_dev); 23607c478bd9Sstevel@tonic-gate addr = skip_to (0, file); 23617c478bd9Sstevel@tonic-gate 23627c478bd9Sstevel@tonic-gate /* Get the installation address. */ 23637c478bd9Sstevel@tonic-gate if (! safe_parse_maxint (&addr, &installaddr)) 23647c478bd9Sstevel@tonic-gate { 23657c478bd9Sstevel@tonic-gate /* ADDR is not specified. */ 23667c478bd9Sstevel@tonic-gate installaddr = 0; 23677c478bd9Sstevel@tonic-gate ptr = addr; 23687c478bd9Sstevel@tonic-gate errnum = 0; 23697c478bd9Sstevel@tonic-gate } 23707c478bd9Sstevel@tonic-gate else 23717c478bd9Sstevel@tonic-gate ptr = skip_to (0, addr); 23727c478bd9Sstevel@tonic-gate 23737c478bd9Sstevel@tonic-gate #ifndef NO_DECOMPRESSION 23747c478bd9Sstevel@tonic-gate /* Do not decompress Stage 1 or Stage 2. */ 23757c478bd9Sstevel@tonic-gate no_decompression = 1; 23767c478bd9Sstevel@tonic-gate #endif 23777c478bd9Sstevel@tonic-gate 23787c478bd9Sstevel@tonic-gate /* Read Stage 1. */ 23797c478bd9Sstevel@tonic-gate is_open = grub_open (stage1_file); 23807c478bd9Sstevel@tonic-gate if (! is_open 23817c478bd9Sstevel@tonic-gate || ! grub_read (stage1_buffer, SECTOR_SIZE) == SECTOR_SIZE) 23827c478bd9Sstevel@tonic-gate goto fail; 23837c478bd9Sstevel@tonic-gate 23847c478bd9Sstevel@tonic-gate /* Read the old sector from DEST_DEV. */ 23857c478bd9Sstevel@tonic-gate if (! set_device (dest_dev) 23867c478bd9Sstevel@tonic-gate || ! open_partition () 23877c478bd9Sstevel@tonic-gate || ! devread (0, 0, SECTOR_SIZE, old_sect)) 23887c478bd9Sstevel@tonic-gate goto fail; 23897c478bd9Sstevel@tonic-gate 23907c478bd9Sstevel@tonic-gate /* Store the information for the destination device. */ 23917c478bd9Sstevel@tonic-gate dest_drive = current_drive; 23927c478bd9Sstevel@tonic-gate dest_partition = current_partition; 23937c478bd9Sstevel@tonic-gate dest_geom = buf_geom; 23947c478bd9Sstevel@tonic-gate dest_sector = part_start; 23957c478bd9Sstevel@tonic-gate 23967c478bd9Sstevel@tonic-gate /* Copy the possible DOS BPB, 59 bytes at byte offset 3. */ 23977c478bd9Sstevel@tonic-gate grub_memmove (stage1_buffer + BOOTSEC_BPB_OFFSET, 23987c478bd9Sstevel@tonic-gate old_sect + BOOTSEC_BPB_OFFSET, 23997c478bd9Sstevel@tonic-gate BOOTSEC_BPB_LENGTH); 24007c478bd9Sstevel@tonic-gate 24017c478bd9Sstevel@tonic-gate /* If for a hard disk, copy the possible MBR/extended part table. */ 24027c478bd9Sstevel@tonic-gate if (dest_drive & 0x80) 24037c478bd9Sstevel@tonic-gate grub_memmove (stage1_buffer + STAGE1_WINDOWS_NT_MAGIC, 24047c478bd9Sstevel@tonic-gate old_sect + STAGE1_WINDOWS_NT_MAGIC, 24057c478bd9Sstevel@tonic-gate STAGE1_PARTEND - STAGE1_WINDOWS_NT_MAGIC); 24067c478bd9Sstevel@tonic-gate 24077c478bd9Sstevel@tonic-gate /* Check for the version and the signature of Stage 1. */ 24087c478bd9Sstevel@tonic-gate if (*((short *)(stage1_buffer + STAGE1_VER_MAJ_OFFS)) != COMPAT_VERSION 24097c478bd9Sstevel@tonic-gate || (*((unsigned short *) (stage1_buffer + BOOTSEC_SIG_OFFSET)) 24107c478bd9Sstevel@tonic-gate != BOOTSEC_SIGNATURE)) 24117c478bd9Sstevel@tonic-gate { 24127c478bd9Sstevel@tonic-gate errnum = ERR_BAD_VERSION; 24137c478bd9Sstevel@tonic-gate goto fail; 24147c478bd9Sstevel@tonic-gate } 24157c478bd9Sstevel@tonic-gate 24167c478bd9Sstevel@tonic-gate /* This below is not true any longer. But should we leave this alone? */ 24177c478bd9Sstevel@tonic-gate 24187c478bd9Sstevel@tonic-gate /* If DEST_DRIVE is a floppy, Stage 2 must have the iteration probe 24197c478bd9Sstevel@tonic-gate routine. */ 24207c478bd9Sstevel@tonic-gate if (! (dest_drive & 0x80) 24217c478bd9Sstevel@tonic-gate && (*((unsigned char *) (stage1_buffer + BOOTSEC_PART_OFFSET)) == 0x80 24227c478bd9Sstevel@tonic-gate || stage1_buffer[BOOTSEC_PART_OFFSET] == 0)) 24237c478bd9Sstevel@tonic-gate { 24247c478bd9Sstevel@tonic-gate errnum = ERR_BAD_VERSION; 24257c478bd9Sstevel@tonic-gate goto fail; 24267c478bd9Sstevel@tonic-gate } 24277c478bd9Sstevel@tonic-gate 24287c478bd9Sstevel@tonic-gate grub_close (); 24297c478bd9Sstevel@tonic-gate 24307c478bd9Sstevel@tonic-gate /* Open Stage 2. */ 24317c478bd9Sstevel@tonic-gate is_open = grub_open (file); 24327c478bd9Sstevel@tonic-gate if (! is_open) 24337c478bd9Sstevel@tonic-gate goto fail; 24347c478bd9Sstevel@tonic-gate 24357c478bd9Sstevel@tonic-gate src_drive = current_drive; 24367c478bd9Sstevel@tonic-gate src_partition = current_partition; 24377c478bd9Sstevel@tonic-gate src_part_start = part_start; 24387c478bd9Sstevel@tonic-gate src_geom = buf_geom; 24397c478bd9Sstevel@tonic-gate 24407c478bd9Sstevel@tonic-gate if (! new_drive) 24417c478bd9Sstevel@tonic-gate new_drive = src_drive; 24427c478bd9Sstevel@tonic-gate else if (src_drive != dest_drive) 24437c478bd9Sstevel@tonic-gate grub_printf ("Warning: the option `d' was not used, but the Stage 1 will" 24447c478bd9Sstevel@tonic-gate " be installed on a\ndifferent drive than the drive where" 24457c478bd9Sstevel@tonic-gate " the Stage 2 resides.\n"); 24467c478bd9Sstevel@tonic-gate 24477c478bd9Sstevel@tonic-gate /* Set the boot drive. */ 24487c478bd9Sstevel@tonic-gate *((unsigned char *) (stage1_buffer + STAGE1_BOOT_DRIVE)) = new_drive; 24497c478bd9Sstevel@tonic-gate 24507c478bd9Sstevel@tonic-gate /* Set the "force LBA" flag. */ 24517c478bd9Sstevel@tonic-gate *((unsigned char *) (stage1_buffer + STAGE1_FORCE_LBA)) = is_force_lba; 24527c478bd9Sstevel@tonic-gate 24531b8adde7SWilliam Kucharski /* If DEST_DRIVE is a hard disk, enable the workaround, which is 24541b8adde7SWilliam Kucharski for buggy BIOSes which don't pass boot drive correctly. Instead, 24551b8adde7SWilliam Kucharski they pass 0x00 or 0x01 even when booted from 0x80. */ 24561b8adde7SWilliam Kucharski if (dest_drive & BIOS_FLAG_FIXED_DISK) 24571b8adde7SWilliam Kucharski /* Replace the jmp (2 bytes) with double nop's. */ 24581b8adde7SWilliam Kucharski *((unsigned short *) (stage1_buffer + STAGE1_BOOT_DRIVE_CHECK)) 24591b8adde7SWilliam Kucharski = 0x9090; 24601b8adde7SWilliam Kucharski 24617c478bd9Sstevel@tonic-gate /* Read the first sector of Stage 2. */ 24627c478bd9Sstevel@tonic-gate disk_read_hook = disk_read_savesect_func; 24637c478bd9Sstevel@tonic-gate if (grub_read (stage2_first_buffer, SECTOR_SIZE) != SECTOR_SIZE) 24647c478bd9Sstevel@tonic-gate goto fail; 24657c478bd9Sstevel@tonic-gate 24667c478bd9Sstevel@tonic-gate stage2_first_sector = saved_sector; 24677c478bd9Sstevel@tonic-gate 24687c478bd9Sstevel@tonic-gate /* Read the second sector of Stage 2. */ 24697c478bd9Sstevel@tonic-gate if (grub_read (stage2_second_buffer, SECTOR_SIZE) != SECTOR_SIZE) 24707c478bd9Sstevel@tonic-gate goto fail; 24717c478bd9Sstevel@tonic-gate 24727c478bd9Sstevel@tonic-gate stage2_second_sector = saved_sector; 24737c478bd9Sstevel@tonic-gate 24747c478bd9Sstevel@tonic-gate /* Check for the version of Stage 2. */ 24757c478bd9Sstevel@tonic-gate if (*((short *) (stage2_second_buffer + STAGE2_VER_MAJ_OFFS)) 24767c478bd9Sstevel@tonic-gate != COMPAT_VERSION) 24777c478bd9Sstevel@tonic-gate { 24787c478bd9Sstevel@tonic-gate errnum = ERR_BAD_VERSION; 24797c478bd9Sstevel@tonic-gate goto fail; 24807c478bd9Sstevel@tonic-gate } 24817c478bd9Sstevel@tonic-gate 24827c478bd9Sstevel@tonic-gate /* Check for the Stage 2 id. */ 24837c478bd9Sstevel@tonic-gate if (stage2_second_buffer[STAGE2_STAGE2_ID] != STAGE2_ID_STAGE2) 24847c478bd9Sstevel@tonic-gate is_stage1_5 = 1; 24857c478bd9Sstevel@tonic-gate 24867c478bd9Sstevel@tonic-gate /* If INSTALLADDR is not specified explicitly in the command-line, 24877c478bd9Sstevel@tonic-gate determine it by the Stage 2 id. */ 24887c478bd9Sstevel@tonic-gate if (! installaddr) 24897c478bd9Sstevel@tonic-gate { 24907c478bd9Sstevel@tonic-gate if (! is_stage1_5) 24917c478bd9Sstevel@tonic-gate /* Stage 2. */ 24927c478bd9Sstevel@tonic-gate installaddr = 0x8000; 24937c478bd9Sstevel@tonic-gate else 24947c478bd9Sstevel@tonic-gate /* Stage 1.5. */ 24957c478bd9Sstevel@tonic-gate installaddr = 0x2000; 24967c478bd9Sstevel@tonic-gate } 24977c478bd9Sstevel@tonic-gate 24987c478bd9Sstevel@tonic-gate *((unsigned long *) (stage1_buffer + STAGE1_STAGE2_SECTOR)) 24997c478bd9Sstevel@tonic-gate = stage2_first_sector; 25007c478bd9Sstevel@tonic-gate *((unsigned short *) (stage1_buffer + STAGE1_STAGE2_ADDRESS)) 25017c478bd9Sstevel@tonic-gate = installaddr; 25027c478bd9Sstevel@tonic-gate *((unsigned short *) (stage1_buffer + STAGE1_STAGE2_SEGMENT)) 25037c478bd9Sstevel@tonic-gate = installaddr >> 4; 25047c478bd9Sstevel@tonic-gate 25057c478bd9Sstevel@tonic-gate i = (int) stage2_first_buffer + SECTOR_SIZE - 4; 25067c478bd9Sstevel@tonic-gate while (*((unsigned long *) i)) 25077c478bd9Sstevel@tonic-gate { 25087c478bd9Sstevel@tonic-gate if (i < (int) stage2_first_buffer 25097c478bd9Sstevel@tonic-gate || (*((int *) (i - 4)) & 0x80000000) 25107c478bd9Sstevel@tonic-gate || *((unsigned short *) i) >= 0xA00 25117c478bd9Sstevel@tonic-gate || *((short *) (i + 2)) == 0) 25127c478bd9Sstevel@tonic-gate { 25137c478bd9Sstevel@tonic-gate errnum = ERR_BAD_VERSION; 25147c478bd9Sstevel@tonic-gate goto fail; 25157c478bd9Sstevel@tonic-gate } 25167c478bd9Sstevel@tonic-gate 25177c478bd9Sstevel@tonic-gate *((int *) i) = 0; 25187c478bd9Sstevel@tonic-gate *((int *) (i - 4)) = 0; 25197c478bd9Sstevel@tonic-gate i -= 8; 25207c478bd9Sstevel@tonic-gate } 25217c478bd9Sstevel@tonic-gate 25227c478bd9Sstevel@tonic-gate installlist = (int) stage2_first_buffer + SECTOR_SIZE + 4; 25237c478bd9Sstevel@tonic-gate installaddr += SECTOR_SIZE; 25247c478bd9Sstevel@tonic-gate 25257c478bd9Sstevel@tonic-gate /* Read the whole of Stage2 except for the first sector. */ 25267c478bd9Sstevel@tonic-gate grub_seek (SECTOR_SIZE); 25277c478bd9Sstevel@tonic-gate 25287c478bd9Sstevel@tonic-gate disk_read_hook = disk_read_blocklist_func; 25297c478bd9Sstevel@tonic-gate if (! grub_read (dummy, -1)) 25307c478bd9Sstevel@tonic-gate goto fail; 25317c478bd9Sstevel@tonic-gate 25327c478bd9Sstevel@tonic-gate disk_read_hook = 0; 25337c478bd9Sstevel@tonic-gate 25347c478bd9Sstevel@tonic-gate /* Find a string for the configuration filename. */ 25357c478bd9Sstevel@tonic-gate config_file_location = stage2_second_buffer + STAGE2_VER_STR_OFFS; 25367c478bd9Sstevel@tonic-gate while (*(config_file_location++)) 25377c478bd9Sstevel@tonic-gate ; 25387c478bd9Sstevel@tonic-gate 25397c478bd9Sstevel@tonic-gate /* Set the "force LBA" flag for Stage2. */ 25407c478bd9Sstevel@tonic-gate *((unsigned char *) (stage2_second_buffer + STAGE2_FORCE_LBA)) 25417c478bd9Sstevel@tonic-gate = is_force_lba; 25427c478bd9Sstevel@tonic-gate 25437c478bd9Sstevel@tonic-gate if (*ptr == 'p') 25447c478bd9Sstevel@tonic-gate { 25457c478bd9Sstevel@tonic-gate *((long *) (stage2_second_buffer + STAGE2_INSTALLPART)) 25467c478bd9Sstevel@tonic-gate = src_partition; 25477c478bd9Sstevel@tonic-gate if (is_stage1_5) 25487c478bd9Sstevel@tonic-gate { 25497c478bd9Sstevel@tonic-gate /* Reset the device information in FILE if it is a Stage 1.5. */ 25507c478bd9Sstevel@tonic-gate unsigned long device = 0xFFFFFFFF; 25517c478bd9Sstevel@tonic-gate 25527c478bd9Sstevel@tonic-gate grub_memmove (config_file_location, (char *) &device, 25537c478bd9Sstevel@tonic-gate sizeof (device)); 25547c478bd9Sstevel@tonic-gate } 25557c478bd9Sstevel@tonic-gate 25567c478bd9Sstevel@tonic-gate ptr = skip_to (0, ptr); 25577c478bd9Sstevel@tonic-gate } 25587c478bd9Sstevel@tonic-gate 25597c478bd9Sstevel@tonic-gate if (*ptr) 25607c478bd9Sstevel@tonic-gate { 25617c478bd9Sstevel@tonic-gate grub_strcpy (config_filename, ptr); 25627c478bd9Sstevel@tonic-gate nul_terminate (config_filename); 25637c478bd9Sstevel@tonic-gate 25647c478bd9Sstevel@tonic-gate if (! is_stage1_5) 25657c478bd9Sstevel@tonic-gate /* If it is a Stage 2, just copy PTR to CONFIG_FILE_LOCATION. */ 25667c478bd9Sstevel@tonic-gate grub_strcpy (config_file_location, ptr); 25677c478bd9Sstevel@tonic-gate else 25687c478bd9Sstevel@tonic-gate { 25697c478bd9Sstevel@tonic-gate char *real_config; 25707c478bd9Sstevel@tonic-gate unsigned long device; 25717c478bd9Sstevel@tonic-gate 25727c478bd9Sstevel@tonic-gate /* Translate the external device syntax to the internal device 25737c478bd9Sstevel@tonic-gate syntax. */ 25747c478bd9Sstevel@tonic-gate if (! (real_config = set_device (ptr))) 25757c478bd9Sstevel@tonic-gate { 25767c478bd9Sstevel@tonic-gate /* The Stage 2 PTR does not contain the device name, so 25777c478bd9Sstevel@tonic-gate use the root device instead. */ 25787c478bd9Sstevel@tonic-gate errnum = ERR_NONE; 25797c478bd9Sstevel@tonic-gate current_drive = saved_drive; 25807c478bd9Sstevel@tonic-gate current_partition = saved_partition; 25817c478bd9Sstevel@tonic-gate real_config = ptr; 25827c478bd9Sstevel@tonic-gate } 25837c478bd9Sstevel@tonic-gate 25847c478bd9Sstevel@tonic-gate if (current_drive == src_drive) 25857c478bd9Sstevel@tonic-gate { 25867c478bd9Sstevel@tonic-gate /* If the drive where the Stage 2 resides is the same as 25877c478bd9Sstevel@tonic-gate the one where the Stage 1.5 resides, do not embed the 25887c478bd9Sstevel@tonic-gate drive number. */ 25897c478bd9Sstevel@tonic-gate current_drive = GRUB_INVALID_DRIVE; 25907c478bd9Sstevel@tonic-gate } 25917c478bd9Sstevel@tonic-gate 25927c478bd9Sstevel@tonic-gate device = (current_drive << 24) | current_partition; 25937c478bd9Sstevel@tonic-gate grub_memmove (config_file_location, (char *) &device, 25947c478bd9Sstevel@tonic-gate sizeof (device)); 25957c478bd9Sstevel@tonic-gate grub_strcpy (config_file_location + sizeof (device), 25967c478bd9Sstevel@tonic-gate real_config); 25977c478bd9Sstevel@tonic-gate } 25987c478bd9Sstevel@tonic-gate 25997c478bd9Sstevel@tonic-gate /* If a Stage 1.5 is used, then we need to modify the Stage2. */ 26007c478bd9Sstevel@tonic-gate if (is_stage1_5) 26017c478bd9Sstevel@tonic-gate { 26027c478bd9Sstevel@tonic-gate char *real_config_filename = skip_to (0, ptr); 26037c478bd9Sstevel@tonic-gate 26047c478bd9Sstevel@tonic-gate is_open = grub_open (config_filename); 26057c478bd9Sstevel@tonic-gate if (! is_open) 26067c478bd9Sstevel@tonic-gate goto fail; 26077c478bd9Sstevel@tonic-gate 26087c478bd9Sstevel@tonic-gate /* Skip the first sector. */ 26097c478bd9Sstevel@tonic-gate grub_seek (SECTOR_SIZE); 26107c478bd9Sstevel@tonic-gate 26117c478bd9Sstevel@tonic-gate disk_read_hook = disk_read_savesect_func; 26127c478bd9Sstevel@tonic-gate if (grub_read (stage2_buffer, SECTOR_SIZE) != SECTOR_SIZE) 26137c478bd9Sstevel@tonic-gate goto fail; 26147c478bd9Sstevel@tonic-gate 26157c478bd9Sstevel@tonic-gate disk_read_hook = 0; 26167c478bd9Sstevel@tonic-gate grub_close (); 26177c478bd9Sstevel@tonic-gate is_open = 0; 26187c478bd9Sstevel@tonic-gate 26197c478bd9Sstevel@tonic-gate /* Sanity check. */ 26207c478bd9Sstevel@tonic-gate if (*(stage2_buffer + STAGE2_STAGE2_ID) != STAGE2_ID_STAGE2) 26217c478bd9Sstevel@tonic-gate { 26227c478bd9Sstevel@tonic-gate errnum = ERR_BAD_VERSION; 26237c478bd9Sstevel@tonic-gate goto fail; 26247c478bd9Sstevel@tonic-gate } 26257c478bd9Sstevel@tonic-gate 26267c478bd9Sstevel@tonic-gate /* Set the "force LBA" flag for Stage2. */ 26277c478bd9Sstevel@tonic-gate *(stage2_buffer + STAGE2_FORCE_LBA) = is_force_lba; 26287c478bd9Sstevel@tonic-gate 26297c478bd9Sstevel@tonic-gate /* If REAL_CONFIG_FILENAME is specified, copy it to the Stage2. */ 26307c478bd9Sstevel@tonic-gate if (*real_config_filename) 26317c478bd9Sstevel@tonic-gate { 26327c478bd9Sstevel@tonic-gate /* Specified */ 26337c478bd9Sstevel@tonic-gate char *location; 26347c478bd9Sstevel@tonic-gate 26357c478bd9Sstevel@tonic-gate /* Find a string for the configuration filename. */ 26367c478bd9Sstevel@tonic-gate location = stage2_buffer + STAGE2_VER_STR_OFFS; 26377c478bd9Sstevel@tonic-gate while (*(location++)) 26387c478bd9Sstevel@tonic-gate ; 26397c478bd9Sstevel@tonic-gate 26407c478bd9Sstevel@tonic-gate /* Copy the name. */ 26417c478bd9Sstevel@tonic-gate grub_strcpy (location, real_config_filename); 26427c478bd9Sstevel@tonic-gate } 26437c478bd9Sstevel@tonic-gate 26447c478bd9Sstevel@tonic-gate /* Write it to the disk. */ 2645342440ecSPrasad Singamsetty buf_track = BUF_CACHE_INVALID; 26467c478bd9Sstevel@tonic-gate 26477c478bd9Sstevel@tonic-gate #ifdef GRUB_UTIL 26487c478bd9Sstevel@tonic-gate /* In the grub shell, access the Stage 2 via the OS filesystem 26497c478bd9Sstevel@tonic-gate service, if possible. */ 26507c478bd9Sstevel@tonic-gate if (stage2_os_file) 26517c478bd9Sstevel@tonic-gate { 26527c478bd9Sstevel@tonic-gate FILE *fp; 26537c478bd9Sstevel@tonic-gate 26547c478bd9Sstevel@tonic-gate fp = fopen (stage2_os_file, "r+"); 26557c478bd9Sstevel@tonic-gate if (! fp) 26567c478bd9Sstevel@tonic-gate { 26577c478bd9Sstevel@tonic-gate errnum = ERR_FILE_NOT_FOUND; 26587c478bd9Sstevel@tonic-gate goto fail; 26597c478bd9Sstevel@tonic-gate } 26607c478bd9Sstevel@tonic-gate 26617c478bd9Sstevel@tonic-gate if (fseek (fp, SECTOR_SIZE, SEEK_SET) != 0) 26627c478bd9Sstevel@tonic-gate { 26637c478bd9Sstevel@tonic-gate fclose (fp); 26647c478bd9Sstevel@tonic-gate errnum = ERR_BAD_VERSION; 26657c478bd9Sstevel@tonic-gate goto fail; 26667c478bd9Sstevel@tonic-gate } 26677c478bd9Sstevel@tonic-gate 26687c478bd9Sstevel@tonic-gate if (fwrite (stage2_buffer, 1, SECTOR_SIZE, fp) 26697c478bd9Sstevel@tonic-gate != SECTOR_SIZE) 26707c478bd9Sstevel@tonic-gate { 26717c478bd9Sstevel@tonic-gate fclose (fp); 26727c478bd9Sstevel@tonic-gate errnum = ERR_WRITE; 26737c478bd9Sstevel@tonic-gate goto fail; 26747c478bd9Sstevel@tonic-gate } 26757c478bd9Sstevel@tonic-gate 26767c478bd9Sstevel@tonic-gate fclose (fp); 26777c478bd9Sstevel@tonic-gate } 26787c478bd9Sstevel@tonic-gate else 26797c478bd9Sstevel@tonic-gate #endif /* GRUB_UTIL */ 26807c478bd9Sstevel@tonic-gate { 26817c478bd9Sstevel@tonic-gate if (! devwrite (saved_sector - part_start, 1, stage2_buffer)) 26827c478bd9Sstevel@tonic-gate goto fail; 26837c478bd9Sstevel@tonic-gate } 26847c478bd9Sstevel@tonic-gate } 26857c478bd9Sstevel@tonic-gate } 26867c478bd9Sstevel@tonic-gate 26877c478bd9Sstevel@tonic-gate /* Clear the cache. */ 2688342440ecSPrasad Singamsetty buf_track = BUF_CACHE_INVALID; 26897c478bd9Sstevel@tonic-gate 26907c478bd9Sstevel@tonic-gate /* Write the modified sectors of Stage2 to the disk. */ 26917c478bd9Sstevel@tonic-gate #ifdef GRUB_UTIL 26927c478bd9Sstevel@tonic-gate if (! is_stage1_5 && stage2_os_file) 26937c478bd9Sstevel@tonic-gate { 26947c478bd9Sstevel@tonic-gate FILE *fp; 26957c478bd9Sstevel@tonic-gate 26967c478bd9Sstevel@tonic-gate fp = fopen (stage2_os_file, "r+"); 26977c478bd9Sstevel@tonic-gate if (! fp) 26987c478bd9Sstevel@tonic-gate { 26997c478bd9Sstevel@tonic-gate errnum = ERR_FILE_NOT_FOUND; 27007c478bd9Sstevel@tonic-gate goto fail; 27017c478bd9Sstevel@tonic-gate } 27027c478bd9Sstevel@tonic-gate 27037c478bd9Sstevel@tonic-gate if (fwrite (stage2_first_buffer, 1, SECTOR_SIZE, fp) != SECTOR_SIZE) 27047c478bd9Sstevel@tonic-gate { 27057c478bd9Sstevel@tonic-gate fclose (fp); 27067c478bd9Sstevel@tonic-gate errnum = ERR_WRITE; 27077c478bd9Sstevel@tonic-gate goto fail; 27087c478bd9Sstevel@tonic-gate } 27097c478bd9Sstevel@tonic-gate 27107c478bd9Sstevel@tonic-gate if (fwrite (stage2_second_buffer, 1, SECTOR_SIZE, fp) != SECTOR_SIZE) 27117c478bd9Sstevel@tonic-gate { 27127c478bd9Sstevel@tonic-gate fclose (fp); 27137c478bd9Sstevel@tonic-gate errnum = ERR_WRITE; 27147c478bd9Sstevel@tonic-gate goto fail; 27157c478bd9Sstevel@tonic-gate } 27167c478bd9Sstevel@tonic-gate 27177c478bd9Sstevel@tonic-gate fclose (fp); 27187c478bd9Sstevel@tonic-gate } 27197c478bd9Sstevel@tonic-gate else 27207c478bd9Sstevel@tonic-gate #endif /* GRUB_UTIL */ 27217c478bd9Sstevel@tonic-gate { 27227c478bd9Sstevel@tonic-gate /* The first. */ 27237c478bd9Sstevel@tonic-gate current_drive = src_drive; 27247c478bd9Sstevel@tonic-gate current_partition = src_partition; 27257c478bd9Sstevel@tonic-gate 27267c478bd9Sstevel@tonic-gate if (! open_partition ()) 27277c478bd9Sstevel@tonic-gate goto fail; 27287c478bd9Sstevel@tonic-gate 27297c478bd9Sstevel@tonic-gate if (! devwrite (stage2_first_sector - src_part_start, 1, 27307c478bd9Sstevel@tonic-gate stage2_first_buffer)) 27317c478bd9Sstevel@tonic-gate goto fail; 27327c478bd9Sstevel@tonic-gate 27337c478bd9Sstevel@tonic-gate if (! devwrite (stage2_second_sector - src_part_start, 1, 27347c478bd9Sstevel@tonic-gate stage2_second_buffer)) 27357c478bd9Sstevel@tonic-gate goto fail; 27367c478bd9Sstevel@tonic-gate } 27377c478bd9Sstevel@tonic-gate 27387c478bd9Sstevel@tonic-gate /* Write the modified sector of Stage 1 to the disk. */ 27397c478bd9Sstevel@tonic-gate current_drive = dest_drive; 27407c478bd9Sstevel@tonic-gate current_partition = dest_partition; 27417c478bd9Sstevel@tonic-gate if (! open_partition ()) 27427c478bd9Sstevel@tonic-gate goto fail; 27437c478bd9Sstevel@tonic-gate 27447c478bd9Sstevel@tonic-gate devwrite (0, 1, stage1_buffer); 27457c478bd9Sstevel@tonic-gate 27467c478bd9Sstevel@tonic-gate fail: 27477c478bd9Sstevel@tonic-gate if (is_open) 27487c478bd9Sstevel@tonic-gate grub_close (); 27497c478bd9Sstevel@tonic-gate 27507c478bd9Sstevel@tonic-gate disk_read_hook = 0; 27517c478bd9Sstevel@tonic-gate 27527c478bd9Sstevel@tonic-gate #ifndef NO_DECOMPRESSION 27537c478bd9Sstevel@tonic-gate no_decompression = 0; 27547c478bd9Sstevel@tonic-gate #endif 27557c478bd9Sstevel@tonic-gate 27567c478bd9Sstevel@tonic-gate return errnum; 27577c478bd9Sstevel@tonic-gate } 27587c478bd9Sstevel@tonic-gate 27597c478bd9Sstevel@tonic-gate static struct builtin builtin_install = 27607c478bd9Sstevel@tonic-gate { 27617c478bd9Sstevel@tonic-gate "install", 27627c478bd9Sstevel@tonic-gate install_func, 27637c478bd9Sstevel@tonic-gate BUILTIN_CMDLINE, 27647c478bd9Sstevel@tonic-gate "install [--stage2=STAGE2_FILE] [--force-lba] STAGE1 [d] DEVICE STAGE2 [ADDR] [p] [CONFIG_FILE] [REAL_CONFIG_FILE]", 27657c478bd9Sstevel@tonic-gate "Install STAGE1 on DEVICE, and install a blocklist for loading STAGE2" 27667c478bd9Sstevel@tonic-gate " as a Stage 2. If the option `d' is present, the Stage 1 will always" 27677c478bd9Sstevel@tonic-gate " look for the disk where STAGE2 was installed, rather than using" 27687c478bd9Sstevel@tonic-gate " the booting drive. The Stage 2 will be loaded at address ADDR, which" 27697c478bd9Sstevel@tonic-gate " will be determined automatically if you don't specify it. If" 27707c478bd9Sstevel@tonic-gate " the option `p' or CONFIG_FILE is present, then the first block" 27717c478bd9Sstevel@tonic-gate " of Stage 2 is patched with new values of the partition and name" 27727c478bd9Sstevel@tonic-gate " of the configuration file used by the true Stage 2 (for a Stage 1.5," 27737c478bd9Sstevel@tonic-gate " this is the name of the true Stage 2) at boot time. If STAGE2 is a Stage" 27747c478bd9Sstevel@tonic-gate " 1.5 and REAL_CONFIG_FILE is present, then the Stage 2 CONFIG_FILE is" 27757c478bd9Sstevel@tonic-gate " patched with the configuration filename REAL_CONFIG_FILE." 27767c478bd9Sstevel@tonic-gate " If the option `--force-lba' is specified, disable some sanity checks" 27777c478bd9Sstevel@tonic-gate " for LBA mode. If the option `--stage2' is specified, rewrite the Stage" 27787c478bd9Sstevel@tonic-gate " 2 via your OS's filesystem instead of the raw device." 27797c478bd9Sstevel@tonic-gate }; 27807c478bd9Sstevel@tonic-gate 27817c478bd9Sstevel@tonic-gate 27827c478bd9Sstevel@tonic-gate /* ioprobe */ 27837c478bd9Sstevel@tonic-gate static int 27847c478bd9Sstevel@tonic-gate ioprobe_func (char *arg, int flags) 27857c478bd9Sstevel@tonic-gate { 27867c478bd9Sstevel@tonic-gate #ifdef GRUB_UTIL 27877c478bd9Sstevel@tonic-gate 27887c478bd9Sstevel@tonic-gate errnum = ERR_UNRECOGNIZED; 27897c478bd9Sstevel@tonic-gate return 1; 27907c478bd9Sstevel@tonic-gate 27917c478bd9Sstevel@tonic-gate #else /* ! GRUB_UTIL */ 27927c478bd9Sstevel@tonic-gate 27937c478bd9Sstevel@tonic-gate unsigned short *port; 27947c478bd9Sstevel@tonic-gate 27957c478bd9Sstevel@tonic-gate /* Get the drive number. */ 27967c478bd9Sstevel@tonic-gate set_device (arg); 27977c478bd9Sstevel@tonic-gate if (errnum) 27987c478bd9Sstevel@tonic-gate return 1; 27997c478bd9Sstevel@tonic-gate 28007c478bd9Sstevel@tonic-gate /* Clean out IO_MAP. */ 28017c478bd9Sstevel@tonic-gate grub_memset ((char *) io_map, 0, IO_MAP_SIZE * sizeof (unsigned short)); 28027c478bd9Sstevel@tonic-gate 28037c478bd9Sstevel@tonic-gate /* Track the int13 handler. */ 28047c478bd9Sstevel@tonic-gate track_int13 (current_drive); 28057c478bd9Sstevel@tonic-gate 28067c478bd9Sstevel@tonic-gate /* Print out the result. */ 28077c478bd9Sstevel@tonic-gate for (port = io_map; *port != 0; port++) 28087c478bd9Sstevel@tonic-gate grub_printf (" 0x%x", (unsigned int) *port); 28097c478bd9Sstevel@tonic-gate 28107c478bd9Sstevel@tonic-gate return 0; 28117c478bd9Sstevel@tonic-gate 28127c478bd9Sstevel@tonic-gate #endif /* ! GRUB_UTIL */ 28137c478bd9Sstevel@tonic-gate } 28147c478bd9Sstevel@tonic-gate 28157c478bd9Sstevel@tonic-gate static struct builtin builtin_ioprobe = 28167c478bd9Sstevel@tonic-gate { 28177c478bd9Sstevel@tonic-gate "ioprobe", 28187c478bd9Sstevel@tonic-gate ioprobe_func, 28197c478bd9Sstevel@tonic-gate BUILTIN_CMDLINE, 28207c478bd9Sstevel@tonic-gate "ioprobe DRIVE", 28217c478bd9Sstevel@tonic-gate "Probe I/O ports used for the drive DRIVE." 28227c478bd9Sstevel@tonic-gate }; 28237c478bd9Sstevel@tonic-gate 28247c478bd9Sstevel@tonic-gate 2825b1b8ab34Slling /* 2826b1b8ab34Slling * To boot from a ZFS root filesystem, the kernel$ or module$ commands 2827ffb5616eSLin Ling * must include "-B $ZFS-BOOTFS" to expand to the zfs-bootfs, bootpath, 2828ffb5616eSLin Ling * and diskdevid boot property values for passing to the kernel: 2829b1b8ab34Slling * 2830b1b8ab34Slling * e.g. 2831b1b8ab34Slling * kernel$ /platform/i86pc/kernel/$ISADIR/unix -B $ZFS-BOOTFS,console=ttya 2832b1b8ab34Slling * 2833ffb5616eSLin Ling * $ZFS-BOOTFS is expanded to 2834ffb5616eSLin Ling * 2835ffb5616eSLin Ling * zfs-bootfs=<rootpool-name/zfs-rootfilesystem-object-num>, 2836ffb5616eSLin Ling * bootpath=<device phys path>, 2837ffb5616eSLin Ling * diskdevid=<device id> 2838ffb5616eSLin Ling * 2839ffb5616eSLin Ling * if both bootpath and diskdevid can be found. 2840ffb5616eSLin Ling * e.g 2841ffb5616eSLin Ling * zfs-bootfs=rpool/85, 2842ffb5616eSLin Ling * bootpath="/pci@0,0/pci1022,7450@a/pci17c2,10@4/sd@0,0:a", 2843ffb5616eSLin Ling * diskdevid="id1,sd@SSEAGATE_ST336607LC______3JA0LNHE0000741326W6/a" 2844b1b8ab34Slling */ 2845b1b8ab34Slling static int 2846b1b8ab34Slling expand_dollar_bootfs(char *in, char *out) 2847b1b8ab34Slling { 2848b1b8ab34Slling char *token, *tmpout = out; 2849b1b8ab34Slling int outlen, blen; 2850bf82a41bSeschrock int postcomma = 0; 2851b1b8ab34Slling 285238614cc7SLin Ling /* no op if this is not zfs */ 285338614cc7SLin Ling if (is_zfs_mount == 0) 285438614cc7SLin Ling return (0); 285538614cc7SLin Ling 2856ffb5616eSLin Ling if (current_bootpath[0] == '\0' && current_devid[0] == '\0') { 2857ffb5616eSLin Ling errnum = ERR_NO_BOOTPATH; 2858ffb5616eSLin Ling return (1); 2859ffb5616eSLin Ling } 2860ffb5616eSLin Ling 2861b1b8ab34Slling outlen = strlen(in); 2862b1b8ab34Slling blen = current_bootfs_obj == 0 ? strlen(current_rootpool) : 2863b1b8ab34Slling strlen(current_rootpool) + 11; 2864b1b8ab34Slling 2865b1b8ab34Slling out[0] = '\0'; 2866b1b8ab34Slling while (token = strstr(in, "$ZFS-BOOTFS")) { 2867b1b8ab34Slling 2868ffb5616eSLin Ling if ((outlen += blen) >= MAX_CMDLINE) { 2869b1b8ab34Slling errnum = ERR_WONT_FIT; 2870b1b8ab34Slling return (1); 2871b1b8ab34Slling } 2872b1b8ab34Slling 2873b1b8ab34Slling token[0] = '\0'; 2874b1b8ab34Slling grub_sprintf(tmpout, "%s", in); 2875b1b8ab34Slling token[0] = '$'; 2876051aabe6Staylor in = token + 11; /* skip over $ZFS-BOOTFS */ 2877b1b8ab34Slling tmpout = out + strlen(out); 2878b1b8ab34Slling 2879b1b8ab34Slling /* Note: %u only fits 32 bit integer; */ 2880b1b8ab34Slling if (current_bootfs_obj > 0) 2881b1b8ab34Slling grub_sprintf(tmpout, "zfs-bootfs=%s/%u", 2882b1b8ab34Slling current_rootpool, current_bootfs_obj); 2883b1b8ab34Slling else 2884b1b8ab34Slling grub_sprintf(tmpout, "zfs-bootfs=%s", 2885b1b8ab34Slling current_rootpool); 2886b1b8ab34Slling tmpout = out + strlen(out); 2887b1b8ab34Slling } 2888b1b8ab34Slling 2889e7cbe64fSgw /* 2890bf82a41bSeschrock * Check to see if 'zfs-bootfs' was explicitly specified on the command 2891bf82a41bSeschrock * line so that we can insert the 'bootpath' property. 2892bf82a41bSeschrock */ 2893bf82a41bSeschrock if ((tmpout == out) && (token = strstr(in, "zfs-bootfs")) != NULL) { 2894bf82a41bSeschrock token[0] = '\0'; 2895bf82a41bSeschrock grub_strcpy(tmpout, in); 2896bf82a41bSeschrock token[0] = 'z'; 2897bf82a41bSeschrock in = token; 2898bf82a41bSeschrock 2899bf82a41bSeschrock tmpout = out + strlen(out); 2900bf82a41bSeschrock postcomma = 1; 2901bf82a41bSeschrock } 2902bf82a41bSeschrock 2903bf82a41bSeschrock /* 2904bf82a41bSeschrock * Set the 'bootpath' property if a ZFS dataset was specified, either 2905bf82a41bSeschrock * through '$ZFS-BOOTFS' or an explicit 'zfs-bootfs' setting. 2906e7cbe64fSgw */ 2907e7cbe64fSgw if (tmpout != out) { 2908ffb5616eSLin Ling if (current_bootpath[0] != '\0') { 2909ffb5616eSLin Ling if ((outlen += 12 + strlen(current_bootpath)) 2910ffb5616eSLin Ling >= MAX_CMDLINE) { 2911ffb5616eSLin Ling errnum = ERR_WONT_FIT; 2912ffb5616eSLin Ling return (1); 2913ffb5616eSLin Ling } 2914ffb5616eSLin Ling grub_sprintf(tmpout, 2915ffb5616eSLin Ling postcomma ? "bootpath=\"%s\"," : ",bootpath=\"%s\"", 2916ffb5616eSLin Ling current_bootpath); 2917ffb5616eSLin Ling tmpout = out + strlen(out); 2918e7cbe64fSgw } 2919ffb5616eSLin Ling 2920ffb5616eSLin Ling if (current_devid[0] != '\0') { 2921ffb5616eSLin Ling if ((outlen += 13 + strlen(current_devid)) 2922ffb5616eSLin Ling >= MAX_CMDLINE) { 2923ffb5616eSLin Ling errnum = ERR_WONT_FIT; 2924ffb5616eSLin Ling return (1); 2925ffb5616eSLin Ling } 2926ffb5616eSLin Ling grub_sprintf(tmpout, 2927ffb5616eSLin Ling postcomma ? "diskdevid=\"%s\"," : ",diskdevid=\"%s\"", 2928ffb5616eSLin Ling current_devid); 2929051aabe6Staylor } 2930e7cbe64fSgw } 2931e7cbe64fSgw 2932b1b8ab34Slling strncat(out, in, MAX_CMDLINE); 2933b1b8ab34Slling return (0); 2934b1b8ab34Slling } 2935b1b8ab34Slling 29367c478bd9Sstevel@tonic-gate /* kernel */ 29377c478bd9Sstevel@tonic-gate static int 29387c478bd9Sstevel@tonic-gate kernel_func (char *arg, int flags) 29397c478bd9Sstevel@tonic-gate { 29407c478bd9Sstevel@tonic-gate int len; 29417c478bd9Sstevel@tonic-gate kernel_t suggested_type = KERNEL_TYPE_NONE; 29427c478bd9Sstevel@tonic-gate unsigned long load_flags = 0; 29437c478bd9Sstevel@tonic-gate 29447c478bd9Sstevel@tonic-gate #ifndef AUTO_LINUX_MEM_OPT 29457c478bd9Sstevel@tonic-gate load_flags |= KERNEL_LOAD_NO_MEM_OPTION; 29467c478bd9Sstevel@tonic-gate #endif 29477c478bd9Sstevel@tonic-gate 29487c478bd9Sstevel@tonic-gate /* Deal with GNU-style long options. */ 29497c478bd9Sstevel@tonic-gate while (1) 29507c478bd9Sstevel@tonic-gate { 29517c478bd9Sstevel@tonic-gate /* If the option `--type=TYPE' is specified, convert the string to 29527c478bd9Sstevel@tonic-gate a kernel type. */ 29537c478bd9Sstevel@tonic-gate if (grub_memcmp (arg, "--type=", 7) == 0) 29547c478bd9Sstevel@tonic-gate { 29557c478bd9Sstevel@tonic-gate arg += 7; 29567c478bd9Sstevel@tonic-gate 29577c478bd9Sstevel@tonic-gate if (grub_memcmp (arg, "netbsd", 6) == 0) 29587c478bd9Sstevel@tonic-gate suggested_type = KERNEL_TYPE_NETBSD; 29597c478bd9Sstevel@tonic-gate else if (grub_memcmp (arg, "freebsd", 7) == 0) 29607c478bd9Sstevel@tonic-gate suggested_type = KERNEL_TYPE_FREEBSD; 29617c478bd9Sstevel@tonic-gate else if (grub_memcmp (arg, "openbsd", 7) == 0) 29627c478bd9Sstevel@tonic-gate /* XXX: For now, OpenBSD is identical to NetBSD, from GRUB's 29637c478bd9Sstevel@tonic-gate point of view. */ 29647c478bd9Sstevel@tonic-gate suggested_type = KERNEL_TYPE_NETBSD; 29657c478bd9Sstevel@tonic-gate else if (grub_memcmp (arg, "linux", 5) == 0) 29667c478bd9Sstevel@tonic-gate suggested_type = KERNEL_TYPE_LINUX; 29677c478bd9Sstevel@tonic-gate else if (grub_memcmp (arg, "biglinux", 8) == 0) 29687c478bd9Sstevel@tonic-gate suggested_type = KERNEL_TYPE_BIG_LINUX; 29697c478bd9Sstevel@tonic-gate else if (grub_memcmp (arg, "multiboot", 9) == 0) 29707c478bd9Sstevel@tonic-gate suggested_type = KERNEL_TYPE_MULTIBOOT; 29717c478bd9Sstevel@tonic-gate else 29727c478bd9Sstevel@tonic-gate { 29737c478bd9Sstevel@tonic-gate errnum = ERR_BAD_ARGUMENT; 29747c478bd9Sstevel@tonic-gate return 1; 29757c478bd9Sstevel@tonic-gate } 29767c478bd9Sstevel@tonic-gate } 29777c478bd9Sstevel@tonic-gate /* If the `--no-mem-option' is specified, don't pass a Linux's mem 29787c478bd9Sstevel@tonic-gate option automatically. If the kernel is another type, this flag 29797c478bd9Sstevel@tonic-gate has no effect. */ 29807c478bd9Sstevel@tonic-gate else if (grub_memcmp (arg, "--no-mem-option", 15) == 0) 29817c478bd9Sstevel@tonic-gate load_flags |= KERNEL_LOAD_NO_MEM_OPTION; 29827c478bd9Sstevel@tonic-gate else 29837c478bd9Sstevel@tonic-gate break; 29847c478bd9Sstevel@tonic-gate 29857c478bd9Sstevel@tonic-gate /* Try the next. */ 29867c478bd9Sstevel@tonic-gate arg = skip_to (0, arg); 29877c478bd9Sstevel@tonic-gate } 29887c478bd9Sstevel@tonic-gate 29897c478bd9Sstevel@tonic-gate len = grub_strlen (arg); 29907c478bd9Sstevel@tonic-gate 29917c478bd9Sstevel@tonic-gate /* Reset MB_CMDLINE. */ 29927c478bd9Sstevel@tonic-gate mb_cmdline = (char *) MB_CMDLINE_BUF; 29937c478bd9Sstevel@tonic-gate if (len + 1 > MB_CMDLINE_BUFLEN) 29947c478bd9Sstevel@tonic-gate { 29957c478bd9Sstevel@tonic-gate errnum = ERR_WONT_FIT; 29967c478bd9Sstevel@tonic-gate return 1; 29977c478bd9Sstevel@tonic-gate } 29987c478bd9Sstevel@tonic-gate 29997c478bd9Sstevel@tonic-gate /* Copy the command-line to MB_CMDLINE. */ 30007c478bd9Sstevel@tonic-gate grub_memmove (mb_cmdline, arg, len + 1); 30017c478bd9Sstevel@tonic-gate kernel_type = load_image (arg, mb_cmdline, suggested_type, load_flags); 30027c478bd9Sstevel@tonic-gate if (kernel_type == KERNEL_TYPE_NONE) 30037c478bd9Sstevel@tonic-gate return 1; 30047c478bd9Sstevel@tonic-gate 3005b1b8ab34Slling mb_cmdline += grub_strlen(mb_cmdline) + 1; 30067c478bd9Sstevel@tonic-gate return 0; 30077c478bd9Sstevel@tonic-gate } 30087c478bd9Sstevel@tonic-gate 30097c478bd9Sstevel@tonic-gate static struct builtin builtin_kernel = 30107c478bd9Sstevel@tonic-gate { 30117c478bd9Sstevel@tonic-gate "kernel", 30127c478bd9Sstevel@tonic-gate kernel_func, 30137c478bd9Sstevel@tonic-gate BUILTIN_CMDLINE | BUILTIN_HELP_LIST, 30147c478bd9Sstevel@tonic-gate "kernel [--no-mem-option] [--type=TYPE] FILE [ARG ...]", 30157c478bd9Sstevel@tonic-gate "Attempt to load the primary boot image from FILE. The rest of the" 30167c478bd9Sstevel@tonic-gate " line is passed verbatim as the \"kernel command line\". Any modules" 30177c478bd9Sstevel@tonic-gate " must be reloaded after using this command. The option --type is used" 30187c478bd9Sstevel@tonic-gate " to suggest what type of kernel to be loaded. TYPE must be either of" 30197c478bd9Sstevel@tonic-gate " \"netbsd\", \"freebsd\", \"openbsd\", \"linux\", \"biglinux\" and" 30207c478bd9Sstevel@tonic-gate " \"multiboot\". The option --no-mem-option tells GRUB not to pass a" 30217c478bd9Sstevel@tonic-gate " Linux's mem option automatically." 30227c478bd9Sstevel@tonic-gate }; 30237c478bd9Sstevel@tonic-gate 3024342440ecSPrasad Singamsetty int 3025342440ecSPrasad Singamsetty min_mem64_func(char *arg, int flags) 3026342440ecSPrasad Singamsetty { 3027342440ecSPrasad Singamsetty if (!safe_parse_maxint(&arg, &min_mem64)) 3028342440ecSPrasad Singamsetty return (1); 3029342440ecSPrasad Singamsetty } 3030342440ecSPrasad Singamsetty 3031342440ecSPrasad Singamsetty static struct builtin builtin_min_mem64 = 3032342440ecSPrasad Singamsetty { 3033342440ecSPrasad Singamsetty "min_mem64", 3034342440ecSPrasad Singamsetty min_mem64_func, 3035342440ecSPrasad Singamsetty BUILTIN_CMDLINE | BUILTIN_MENU | BUILTIN_SCRIPT | BUILTIN_HELP_LIST, 3036342440ecSPrasad Singamsetty "min_mem64 <memory in MB>", 3037342440ecSPrasad Singamsetty "Sets minimum memory (in MB) required for $ISADIR to expand to amd64, " 3038342440ecSPrasad Singamsetty "even on 64-bit capable hardware." 3039342440ecSPrasad Singamsetty }; 3040342440ecSPrasad Singamsetty 3041342440ecSPrasad Singamsetty int 3042342440ecSPrasad Singamsetty check_min_mem64() 3043342440ecSPrasad Singamsetty { 3044342440ecSPrasad Singamsetty if (min_mem64 == 0) 3045342440ecSPrasad Singamsetty return (1); 3046342440ecSPrasad Singamsetty 3047342440ecSPrasad Singamsetty if ((mbi.mem_upper / 10240) * 11 >= min_mem64) 3048342440ecSPrasad Singamsetty return (1); 3049342440ecSPrasad Singamsetty 3050342440ecSPrasad Singamsetty return (0); 3051342440ecSPrasad Singamsetty } 3052ae115bc7Smrj 3053ae115bc7Smrj static int detect_target_operating_mode(); 3054ae115bc7Smrj 3055ae115bc7Smrj int 3056ae115bc7Smrj amd64_config_cpu(void) 3057ae115bc7Smrj { 3058ae115bc7Smrj struct amd64_cpuid_regs __vcr, *vcr = &__vcr; 3059ae115bc7Smrj uint32_t maxeax; 3060ae115bc7Smrj uint32_t max_maxeax = 0x100; 3061ae115bc7Smrj char vendor[13]; 3062ae115bc7Smrj int isamd64 = 0; 3063ae115bc7Smrj uint32_t stdfeatures = 0, xtdfeatures = 0; 3064ae115bc7Smrj uint64_t efer; 3065ae115bc7Smrj 3066ae115bc7Smrj /* 3067ae115bc7Smrj * This check may seem silly, but if the C preprocesor symbol __amd64 3068ae115bc7Smrj * is #defined during compilation, something that may outwardly seem 3069ae115bc7Smrj * like a good idea, uts/common/sys/isa_defs.h will #define _LP64, 3070ae115bc7Smrj * which will cause uts/common/sys/int_types.h to typedef uint64_t as 3071ae115bc7Smrj * an unsigned long - which is only 4 bytes in size when using a 32-bit 3072ae115bc7Smrj * compiler. 3073ae115bc7Smrj * 3074ae115bc7Smrj * If that happens, all the page table translation routines will fail 3075ae115bc7Smrj * horribly, so check the size of uint64_t just to insure some degree 3076ae115bc7Smrj * of sanity in future operations. 3077ae115bc7Smrj */ 3078ae115bc7Smrj /*LINTED [sizeof result is invarient]*/ 3079ae115bc7Smrj if (sizeof (uint64_t) != 8) 3080ae115bc7Smrj prom_panic("grub compiled improperly, unable to boot " 3081ae115bc7Smrj "64-bit AMD64 executables"); 3082ae115bc7Smrj 3083ae115bc7Smrj /* 3084ae115bc7Smrj * If the CPU doesn't support the CPUID instruction, it's definitely 3085ae115bc7Smrj * not an AMD64. 3086ae115bc7Smrj */ 3087ae115bc7Smrj if (amd64_cpuid_supported() == 0) 3088ae115bc7Smrj return (0); 3089ae115bc7Smrj 3090ae115bc7Smrj amd64_cpuid_insn(0, vcr); 3091ae115bc7Smrj 3092ae115bc7Smrj maxeax = vcr->r_eax; 3093ae115bc7Smrj { 3094ae115bc7Smrj /*LINTED [vendor string from cpuid data]*/ 3095ae115bc7Smrj uint32_t *iptr = (uint32_t *)vendor; 3096ae115bc7Smrj 3097ae115bc7Smrj *iptr++ = vcr->r_ebx; 3098ae115bc7Smrj *iptr++ = vcr->r_edx; 3099ae115bc7Smrj *iptr++ = vcr->r_ecx; 3100ae115bc7Smrj 3101ae115bc7Smrj vendor[12] = '\0'; 3102ae115bc7Smrj } 3103ae115bc7Smrj 3104ae115bc7Smrj if (maxeax > max_maxeax) { 3105ae115bc7Smrj grub_printf("cpu: warning, maxeax was 0x%x -> 0x%x\n", 3106ae115bc7Smrj maxeax, max_maxeax); 3107ae115bc7Smrj maxeax = max_maxeax; 3108ae115bc7Smrj } 3109ae115bc7Smrj 3110ae115bc7Smrj if (maxeax < 1) 3111ae115bc7Smrj return (0); /* no additional functions, not an AMD64 */ 3112ae115bc7Smrj else { 3113ae115bc7Smrj uint_t family, model, step; 3114ae115bc7Smrj 3115ae115bc7Smrj amd64_cpuid_insn(1, vcr); 3116ae115bc7Smrj 3117ae115bc7Smrj /* 3118ae115bc7Smrj * All AMD64/IA32e processors technically SHOULD report 3119ae115bc7Smrj * themselves as being in family 0xf, but for some reason 3120ae115bc7Smrj * Simics doesn't, and this may change in the future, so 3121ae115bc7Smrj * don't error out if it's not true. 3122ae115bc7Smrj */ 3123ae115bc7Smrj if ((family = BITX(vcr->r_eax, 11, 8)) == 0xf) 3124ae115bc7Smrj family += BITX(vcr->r_eax, 27, 20); 3125ae115bc7Smrj 3126ae115bc7Smrj if ((model = BITX(vcr->r_eax, 7, 4)) == 0xf) 3127ae115bc7Smrj model += BITX(vcr->r_eax, 19, 16) << 4; 3128ae115bc7Smrj step = BITX(vcr->r_eax, 3, 0); 3129ae115bc7Smrj 3130ae115bc7Smrj grub_printf("cpu: '%s' family %d model %d step %d\n", 3131ae115bc7Smrj vendor, family, model, step); 3132ae115bc7Smrj stdfeatures = vcr->r_edx; 3133ae115bc7Smrj } 3134ae115bc7Smrj 3135ae115bc7Smrj amd64_cpuid_insn(0x80000000, vcr); 3136ae115bc7Smrj 3137ae115bc7Smrj if (vcr->r_eax & 0x80000000) { 3138ae115bc7Smrj uint32_t xmaxeax = vcr->r_eax; 3139ae115bc7Smrj const uint32_t max_xmaxeax = 0x80000100; 3140ae115bc7Smrj 3141ae115bc7Smrj if (xmaxeax > max_xmaxeax) { 3142ae115bc7Smrj grub_printf("amd64: warning, xmaxeax was " 3143ae115bc7Smrj "0x%x -> 0x%x\n", xmaxeax, max_xmaxeax); 3144ae115bc7Smrj xmaxeax = max_xmaxeax; 3145ae115bc7Smrj } 3146ae115bc7Smrj 3147ae115bc7Smrj if (xmaxeax >= 0x80000001) { 3148ae115bc7Smrj amd64_cpuid_insn(0x80000001, vcr); 3149ae115bc7Smrj xtdfeatures = vcr->r_edx; 3150ae115bc7Smrj } 3151ae115bc7Smrj } 3152ae115bc7Smrj 3153ae115bc7Smrj if (BITX(xtdfeatures, 29, 29)) /* long mode */ 3154ae115bc7Smrj isamd64++; 3155ae115bc7Smrj else 3156ae115bc7Smrj grub_printf("amd64: CPU does NOT support long mode\n"); 3157ae115bc7Smrj 3158ae115bc7Smrj if (!BITX(stdfeatures, 0, 0)) { 3159ae115bc7Smrj grub_printf("amd64: CPU does NOT support FPU\n"); 3160ae115bc7Smrj isamd64--; 3161ae115bc7Smrj } 3162ae115bc7Smrj 3163ae115bc7Smrj if (!BITX(stdfeatures, 4, 4)) { 3164ae115bc7Smrj grub_printf("amd64: CPU does NOT support TSC\n"); 3165ae115bc7Smrj isamd64--; 3166ae115bc7Smrj } 3167ae115bc7Smrj 3168ae115bc7Smrj if (!BITX(stdfeatures, 5, 5)) { 3169ae115bc7Smrj grub_printf("amd64: CPU does NOT support MSRs\n"); 3170ae115bc7Smrj isamd64--; 3171ae115bc7Smrj } 3172ae115bc7Smrj 3173ae115bc7Smrj if (!BITX(stdfeatures, 6, 6)) { 3174ae115bc7Smrj grub_printf("amd64: CPU does NOT support PAE\n"); 3175ae115bc7Smrj isamd64--; 3176ae115bc7Smrj } 3177ae115bc7Smrj 3178ae115bc7Smrj if (!BITX(stdfeatures, 8, 8)) { 3179ae115bc7Smrj grub_printf("amd64: CPU does NOT support CX8\n"); 3180ae115bc7Smrj isamd64--; 3181ae115bc7Smrj } 3182ae115bc7Smrj 3183ae115bc7Smrj if (!BITX(stdfeatures, 13, 13)) { 3184ae115bc7Smrj grub_printf("amd64: CPU does NOT support PGE\n"); 3185ae115bc7Smrj isamd64--; 3186ae115bc7Smrj } 3187ae115bc7Smrj 3188ae115bc7Smrj if (!BITX(stdfeatures, 19, 19)) { 3189ae115bc7Smrj grub_printf("amd64: CPU does NOT support CLFSH\n"); 3190ae115bc7Smrj isamd64--; 3191ae115bc7Smrj } 3192ae115bc7Smrj 3193ae115bc7Smrj if (!BITX(stdfeatures, 23, 23)) { 3194ae115bc7Smrj grub_printf("amd64: CPU does NOT support MMX\n"); 3195ae115bc7Smrj isamd64--; 3196ae115bc7Smrj } 3197ae115bc7Smrj 3198ae115bc7Smrj if (!BITX(stdfeatures, 24, 24)) { 3199ae115bc7Smrj grub_printf("amd64: CPU does NOT support FXSR\n"); 3200ae115bc7Smrj isamd64--; 3201ae115bc7Smrj } 3202ae115bc7Smrj 3203ae115bc7Smrj if (!BITX(stdfeatures, 25, 25)) { 3204ae115bc7Smrj grub_printf("amd64: CPU does NOT support SSE\n"); 3205ae115bc7Smrj isamd64--; 3206ae115bc7Smrj } 3207ae115bc7Smrj 3208ae115bc7Smrj if (!BITX(stdfeatures, 26, 26)) { 3209ae115bc7Smrj grub_printf("amd64: CPU does NOT support SSE2\n"); 3210ae115bc7Smrj isamd64--; 3211ae115bc7Smrj } 3212ae115bc7Smrj 3213ae115bc7Smrj if (isamd64 < 1) { 3214ae115bc7Smrj grub_printf("amd64: CPU does not support amd64 executables.\n"); 3215ae115bc7Smrj return (0); 3216ae115bc7Smrj } 3217ae115bc7Smrj 3218ae115bc7Smrj amd64_rdmsr(MSR_AMD_EFER, &efer); 3219ae115bc7Smrj if (efer & AMD_EFER_SCE) 3220ae115bc7Smrj grub_printf("amd64: EFER_SCE (syscall/sysret) already " 3221ae115bc7Smrj "enabled\n"); 3222ae115bc7Smrj if (efer & AMD_EFER_NXE) 3223ae115bc7Smrj grub_printf("amd64: EFER_NXE (no-exec prot) already enabled\n"); 3224ae115bc7Smrj if (efer & AMD_EFER_LME) 3225ae115bc7Smrj grub_printf("amd64: EFER_LME (long mode) already enabled\n"); 3226ae115bc7Smrj 3227ae115bc7Smrj return (detect_target_operating_mode()); 3228ae115bc7Smrj } 3229ae115bc7Smrj 3230ae115bc7Smrj static int 3231ae115bc7Smrj detect_target_operating_mode() 3232ae115bc7Smrj { 3233ae115bc7Smrj int ret, ah; 3234ae115bc7Smrj 3235ae115bc7Smrj ah = get_target_operating_mode(); 3236ae115bc7Smrj 3237ae115bc7Smrj ah = ah >> 8; 3238ae115bc7Smrj 3239ae115bc7Smrj /* XXX still need to pass back the return from the call */ 3240ae115bc7Smrj ret = 0; 3241ae115bc7Smrj 3242ae115bc7Smrj if (ah == 0x86 && (ret & CB) != 0) { 3243ae115bc7Smrj grub_printf("[BIOS 'Detect Target Operating Mode' " 3244ae115bc7Smrj "callback unsupported on this platform]\n"); 3245ae115bc7Smrj return (1); /* unsupported, ignore */ 3246ae115bc7Smrj } 3247ae115bc7Smrj 3248ae115bc7Smrj if (ah == 0x0 && (ret & CB) == 0) { 3249ae115bc7Smrj grub_printf("[BIOS accepted mixed-mode target setting!]\n"); 3250ae115bc7Smrj return (1); /* told the bios what we're up to */ 3251ae115bc7Smrj } 3252ae115bc7Smrj 3253ae115bc7Smrj if (ah == 0 && ret & CB) { 3254ae115bc7Smrj grub_printf("fatal: BIOS reports this machine CANNOT run in " 3255ae115bc7Smrj "mixed 32/64-bit mode!\n"); 3256ae115bc7Smrj return (0); 3257ae115bc7Smrj } 3258ae115bc7Smrj 3259ae115bc7Smrj grub_printf("warning: BIOS Detect Target Operating Mode callback " 3260ae115bc7Smrj "confused.\n %%ax >> 8 = 0x%x, carry = %d\n", ah, 3261ae115bc7Smrj ret & CB ? 1 : 0); 3262ae115bc7Smrj 3263ae115bc7Smrj return (1); 3264ae115bc7Smrj } 3265ae115bc7Smrj 3266ae115bc7Smrj 3267ae115bc7Smrj int 3268ae115bc7Smrj isamd64() 3269ae115bc7Smrj { 3270ae115bc7Smrj static int ret = -1; 3271ae115bc7Smrj 3272ae115bc7Smrj if (ret == -1) 3273ae115bc7Smrj ret = amd64_config_cpu(); 3274ae115bc7Smrj 3275ae115bc7Smrj return (ret); 3276ae115bc7Smrj } 3277ae115bc7Smrj 3278b1b8ab34Slling static void 3279b1b8ab34Slling expand_arch (char *arg, char *newarg) 3280ae115bc7Smrj { 3281ae115bc7Smrj char *index; 3282ae115bc7Smrj 3283ae115bc7Smrj newarg[0] = '\0'; 3284ae115bc7Smrj 3285ae115bc7Smrj while ((index = strstr(arg, "$ISADIR")) != NULL) { 3286ae115bc7Smrj 3287ae115bc7Smrj index[0] = '\0'; 3288ae115bc7Smrj strncat(newarg, arg, MAX_CMDLINE); 3289ae115bc7Smrj index[0] = '$'; 3290ae115bc7Smrj 3291342440ecSPrasad Singamsetty if (isamd64() && check_min_mem64()) 3292ae115bc7Smrj strncat(newarg, "amd64", MAX_CMDLINE); 3293ae115bc7Smrj 3294ae115bc7Smrj arg = index + 7; 3295ae115bc7Smrj } 3296ae115bc7Smrj 3297ae115bc7Smrj strncat(newarg, arg, MAX_CMDLINE); 3298b1b8ab34Slling return; 3299ae115bc7Smrj } 3300ae115bc7Smrj 3301ae115bc7Smrj /* kernel$ */ 3302ae115bc7Smrj static int 3303ae115bc7Smrj kernel_dollar_func (char *arg, int flags) 3304ae115bc7Smrj { 3305b1b8ab34Slling char newarg[MAX_CMDLINE]; /* everything boils down to MAX_CMDLINE */ 3306b1b8ab34Slling 3307b1b8ab34Slling grub_printf("loading '%s' ...\n", arg); 3308b1b8ab34Slling expand_arch(arg, newarg); 3309b1b8ab34Slling 3310b1b8ab34Slling if (kernel_func(newarg, flags)) 3311b1b8ab34Slling return (1); 3312b1b8ab34Slling 3313b1b8ab34Slling mb_cmdline = (char *)MB_CMDLINE_BUF; 3314ffb5616eSLin Ling if (expand_dollar_bootfs(newarg, mb_cmdline)) { 3315ffb5616eSLin Ling grub_printf("cannot expand $ZFS-BOOTFS for dataset %s\n", 3316ffb5616eSLin Ling current_bootfs); 3317b1b8ab34Slling return (1); 3318ffb5616eSLin Ling } 3319b1b8ab34Slling 3320b1b8ab34Slling grub_printf("'%s' is loaded\n", mb_cmdline); 3321b1b8ab34Slling mb_cmdline += grub_strlen(mb_cmdline) + 1; 3322b1b8ab34Slling 3323b1b8ab34Slling return (0); 3324ae115bc7Smrj } 3325ae115bc7Smrj 3326ae115bc7Smrj static struct builtin builtin_kernel_dollar = 3327ae115bc7Smrj { 3328ae115bc7Smrj "kernel$", 3329ae115bc7Smrj kernel_dollar_func, 3330ae115bc7Smrj BUILTIN_CMDLINE | BUILTIN_HELP_LIST, 3331ae115bc7Smrj "kernel$ [--no-mem-option] [--type=TYPE] FILE [ARG ...]", 3332ae115bc7Smrj " Just like kernel, but with $ISADIR expansion." 3333ae115bc7Smrj }; 3334ae115bc7Smrj 33357c478bd9Sstevel@tonic-gate 33367c478bd9Sstevel@tonic-gate /* lock */ 33377c478bd9Sstevel@tonic-gate static int 33387c478bd9Sstevel@tonic-gate lock_func (char *arg, int flags) 33397c478bd9Sstevel@tonic-gate { 33407c478bd9Sstevel@tonic-gate if (! auth && password) 33417c478bd9Sstevel@tonic-gate { 33427c478bd9Sstevel@tonic-gate errnum = ERR_PRIVILEGED; 33437c478bd9Sstevel@tonic-gate return 1; 33447c478bd9Sstevel@tonic-gate } 33457c478bd9Sstevel@tonic-gate 33467c478bd9Sstevel@tonic-gate return 0; 33477c478bd9Sstevel@tonic-gate } 33487c478bd9Sstevel@tonic-gate 33497c478bd9Sstevel@tonic-gate static struct builtin builtin_lock = 33507c478bd9Sstevel@tonic-gate { 33517c478bd9Sstevel@tonic-gate "lock", 33527c478bd9Sstevel@tonic-gate lock_func, 33537c478bd9Sstevel@tonic-gate BUILTIN_CMDLINE, 33547c478bd9Sstevel@tonic-gate "lock", 33557c478bd9Sstevel@tonic-gate "Break a command execution unless the user is authenticated." 33567c478bd9Sstevel@tonic-gate }; 33577c478bd9Sstevel@tonic-gate 33587c478bd9Sstevel@tonic-gate 33597c478bd9Sstevel@tonic-gate /* makeactive */ 33607c478bd9Sstevel@tonic-gate static int 33617c478bd9Sstevel@tonic-gate makeactive_func (char *arg, int flags) 33627c478bd9Sstevel@tonic-gate { 33637c478bd9Sstevel@tonic-gate if (! make_saved_active ()) 33647c478bd9Sstevel@tonic-gate return 1; 33657c478bd9Sstevel@tonic-gate 33667c478bd9Sstevel@tonic-gate return 0; 33677c478bd9Sstevel@tonic-gate } 33687c478bd9Sstevel@tonic-gate 33697c478bd9Sstevel@tonic-gate static struct builtin builtin_makeactive = 33707c478bd9Sstevel@tonic-gate { 33717c478bd9Sstevel@tonic-gate "makeactive", 33727c478bd9Sstevel@tonic-gate makeactive_func, 33737c478bd9Sstevel@tonic-gate BUILTIN_CMDLINE | BUILTIN_HELP_LIST, 33747c478bd9Sstevel@tonic-gate "makeactive", 33757c478bd9Sstevel@tonic-gate "Set the active partition on the root disk to GRUB's root device." 33767c478bd9Sstevel@tonic-gate " This command is limited to _primary_ PC partitions on a hard disk." 33777c478bd9Sstevel@tonic-gate }; 33787c478bd9Sstevel@tonic-gate 33797c478bd9Sstevel@tonic-gate 33807c478bd9Sstevel@tonic-gate /* map */ 33817c478bd9Sstevel@tonic-gate /* Map FROM_DRIVE to TO_DRIVE. */ 33827c478bd9Sstevel@tonic-gate static int 33837c478bd9Sstevel@tonic-gate map_func (char *arg, int flags) 33847c478bd9Sstevel@tonic-gate { 33857c478bd9Sstevel@tonic-gate char *to_drive; 33867c478bd9Sstevel@tonic-gate char *from_drive; 33877c478bd9Sstevel@tonic-gate unsigned long to, from; 33887c478bd9Sstevel@tonic-gate int i; 33897c478bd9Sstevel@tonic-gate 33907c478bd9Sstevel@tonic-gate to_drive = arg; 33917c478bd9Sstevel@tonic-gate from_drive = skip_to (0, arg); 33927c478bd9Sstevel@tonic-gate 33937c478bd9Sstevel@tonic-gate /* Get the drive number for TO_DRIVE. */ 33947c478bd9Sstevel@tonic-gate set_device (to_drive); 33957c478bd9Sstevel@tonic-gate if (errnum) 33967c478bd9Sstevel@tonic-gate return 1; 33977c478bd9Sstevel@tonic-gate to = current_drive; 33987c478bd9Sstevel@tonic-gate 33997c478bd9Sstevel@tonic-gate /* Get the drive number for FROM_DRIVE. */ 34007c478bd9Sstevel@tonic-gate set_device (from_drive); 34017c478bd9Sstevel@tonic-gate if (errnum) 34027c478bd9Sstevel@tonic-gate return 1; 34037c478bd9Sstevel@tonic-gate from = current_drive; 34047c478bd9Sstevel@tonic-gate 34057c478bd9Sstevel@tonic-gate /* Search for an empty slot in BIOS_DRIVE_MAP. */ 34067c478bd9Sstevel@tonic-gate for (i = 0; i < DRIVE_MAP_SIZE; i++) 34077c478bd9Sstevel@tonic-gate { 34087c478bd9Sstevel@tonic-gate /* Perhaps the user wants to override the map. */ 34097c478bd9Sstevel@tonic-gate if ((bios_drive_map[i] & 0xff) == from) 34107c478bd9Sstevel@tonic-gate break; 34117c478bd9Sstevel@tonic-gate 34127c478bd9Sstevel@tonic-gate if (! bios_drive_map[i]) 34137c478bd9Sstevel@tonic-gate break; 34147c478bd9Sstevel@tonic-gate } 34157c478bd9Sstevel@tonic-gate 34167c478bd9Sstevel@tonic-gate if (i == DRIVE_MAP_SIZE) 34177c478bd9Sstevel@tonic-gate { 34187c478bd9Sstevel@tonic-gate errnum = ERR_WONT_FIT; 34197c478bd9Sstevel@tonic-gate return 1; 34207c478bd9Sstevel@tonic-gate } 34217c478bd9Sstevel@tonic-gate 34227c478bd9Sstevel@tonic-gate if (to == from) 34237c478bd9Sstevel@tonic-gate /* If TO is equal to FROM, delete the entry. */ 34247c478bd9Sstevel@tonic-gate grub_memmove ((char *) &bios_drive_map[i], (char *) &bios_drive_map[i + 1], 34257c478bd9Sstevel@tonic-gate sizeof (unsigned short) * (DRIVE_MAP_SIZE - i)); 34267c478bd9Sstevel@tonic-gate else 34277c478bd9Sstevel@tonic-gate bios_drive_map[i] = from | (to << 8); 34287c478bd9Sstevel@tonic-gate 34297c478bd9Sstevel@tonic-gate return 0; 34307c478bd9Sstevel@tonic-gate } 34317c478bd9Sstevel@tonic-gate 34327c478bd9Sstevel@tonic-gate static struct builtin builtin_map = 34337c478bd9Sstevel@tonic-gate { 34347c478bd9Sstevel@tonic-gate "map", 34357c478bd9Sstevel@tonic-gate map_func, 34367c478bd9Sstevel@tonic-gate BUILTIN_CMDLINE | BUILTIN_HELP_LIST, 34377c478bd9Sstevel@tonic-gate "map TO_DRIVE FROM_DRIVE", 34387c478bd9Sstevel@tonic-gate "Map the drive FROM_DRIVE to the drive TO_DRIVE. This is necessary" 34397c478bd9Sstevel@tonic-gate " when you chain-load some operating systems, such as DOS, if such an" 34407c478bd9Sstevel@tonic-gate " OS resides at a non-first drive." 34417c478bd9Sstevel@tonic-gate }; 34427c478bd9Sstevel@tonic-gate 34437c478bd9Sstevel@tonic-gate 34447c478bd9Sstevel@tonic-gate #ifdef USE_MD5_PASSWORDS 34457c478bd9Sstevel@tonic-gate /* md5crypt */ 34467c478bd9Sstevel@tonic-gate static int 34477c478bd9Sstevel@tonic-gate md5crypt_func (char *arg, int flags) 34487c478bd9Sstevel@tonic-gate { 34497c478bd9Sstevel@tonic-gate char crypted[36]; 34507c478bd9Sstevel@tonic-gate char key[32]; 34517c478bd9Sstevel@tonic-gate unsigned int seed; 34527c478bd9Sstevel@tonic-gate int i; 34537c478bd9Sstevel@tonic-gate const char *const seedchars = 34547c478bd9Sstevel@tonic-gate "./0123456789ABCDEFGHIJKLMNOPQRST" 34557c478bd9Sstevel@tonic-gate "UVWXYZabcdefghijklmnopqrstuvwxyz"; 34567c478bd9Sstevel@tonic-gate 34577c478bd9Sstevel@tonic-gate /* First create a salt. */ 34587c478bd9Sstevel@tonic-gate 34597c478bd9Sstevel@tonic-gate /* The magical prefix. */ 34607c478bd9Sstevel@tonic-gate grub_memset (crypted, 0, sizeof (crypted)); 34617c478bd9Sstevel@tonic-gate grub_memmove (crypted, "$1$", 3); 34627c478bd9Sstevel@tonic-gate 34637c478bd9Sstevel@tonic-gate /* Create the length of a salt. */ 34647c478bd9Sstevel@tonic-gate seed = currticks (); 34657c478bd9Sstevel@tonic-gate 34667c478bd9Sstevel@tonic-gate /* Generate a salt. */ 34677c478bd9Sstevel@tonic-gate for (i = 0; i < 8 && seed; i++) 34687c478bd9Sstevel@tonic-gate { 34697c478bd9Sstevel@tonic-gate /* FIXME: This should be more random. */ 34707c478bd9Sstevel@tonic-gate crypted[3 + i] = seedchars[seed & 0x3f]; 34717c478bd9Sstevel@tonic-gate seed >>= 6; 34727c478bd9Sstevel@tonic-gate } 34737c478bd9Sstevel@tonic-gate 34747c478bd9Sstevel@tonic-gate /* A salt must be terminated with `$', if it is less than 8 chars. */ 34757c478bd9Sstevel@tonic-gate crypted[3 + i] = '$'; 34767c478bd9Sstevel@tonic-gate 34777c478bd9Sstevel@tonic-gate #ifdef DEBUG_MD5CRYPT 34787c478bd9Sstevel@tonic-gate grub_printf ("salt = %s\n", crypted); 34797c478bd9Sstevel@tonic-gate #endif 34807c478bd9Sstevel@tonic-gate 34817c478bd9Sstevel@tonic-gate /* Get a password. */ 34827c478bd9Sstevel@tonic-gate grub_memset (key, 0, sizeof (key)); 34837c478bd9Sstevel@tonic-gate get_cmdline ("Password: ", key, sizeof (key) - 1, '*', 0); 34847c478bd9Sstevel@tonic-gate 34857c478bd9Sstevel@tonic-gate /* Crypt the key. */ 34867c478bd9Sstevel@tonic-gate make_md5_password (key, crypted); 34877c478bd9Sstevel@tonic-gate 34887c478bd9Sstevel@tonic-gate grub_printf ("Encrypted: %s\n", crypted); 34897c478bd9Sstevel@tonic-gate return 0; 34907c478bd9Sstevel@tonic-gate } 34917c478bd9Sstevel@tonic-gate 34927c478bd9Sstevel@tonic-gate static struct builtin builtin_md5crypt = 34937c478bd9Sstevel@tonic-gate { 34947c478bd9Sstevel@tonic-gate "md5crypt", 34957c478bd9Sstevel@tonic-gate md5crypt_func, 34967c478bd9Sstevel@tonic-gate BUILTIN_CMDLINE | BUILTIN_HELP_LIST, 34977c478bd9Sstevel@tonic-gate "md5crypt", 34987c478bd9Sstevel@tonic-gate "Generate a password in MD5 format." 34997c478bd9Sstevel@tonic-gate }; 35007c478bd9Sstevel@tonic-gate #endif /* USE_MD5_PASSWORDS */ 35017c478bd9Sstevel@tonic-gate 35027c478bd9Sstevel@tonic-gate 35037c478bd9Sstevel@tonic-gate /* module */ 35047c478bd9Sstevel@tonic-gate static int 35057c478bd9Sstevel@tonic-gate module_func (char *arg, int flags) 35067c478bd9Sstevel@tonic-gate { 35077c478bd9Sstevel@tonic-gate int len = grub_strlen (arg); 35087c478bd9Sstevel@tonic-gate 35097c478bd9Sstevel@tonic-gate switch (kernel_type) 35107c478bd9Sstevel@tonic-gate { 35117c478bd9Sstevel@tonic-gate case KERNEL_TYPE_MULTIBOOT: 35127c478bd9Sstevel@tonic-gate if (mb_cmdline + len + 1 > (char *) MB_CMDLINE_BUF + MB_CMDLINE_BUFLEN) 35137c478bd9Sstevel@tonic-gate { 35147c478bd9Sstevel@tonic-gate errnum = ERR_WONT_FIT; 35157c478bd9Sstevel@tonic-gate return 1; 35167c478bd9Sstevel@tonic-gate } 35177c478bd9Sstevel@tonic-gate grub_memmove (mb_cmdline, arg, len + 1); 35187c478bd9Sstevel@tonic-gate if (! load_module (arg, mb_cmdline)) 35197c478bd9Sstevel@tonic-gate return 1; 3520b1b8ab34Slling 3521b1b8ab34Slling mb_cmdline += grub_strlen(mb_cmdline) + 1; 35227c478bd9Sstevel@tonic-gate break; 35237c478bd9Sstevel@tonic-gate 35247c478bd9Sstevel@tonic-gate case KERNEL_TYPE_LINUX: 35257c478bd9Sstevel@tonic-gate case KERNEL_TYPE_BIG_LINUX: 35267c478bd9Sstevel@tonic-gate if (! load_initrd (arg)) 35277c478bd9Sstevel@tonic-gate return 1; 35287c478bd9Sstevel@tonic-gate break; 35297c478bd9Sstevel@tonic-gate 35307c478bd9Sstevel@tonic-gate default: 35317c478bd9Sstevel@tonic-gate errnum = ERR_NEED_MB_KERNEL; 35327c478bd9Sstevel@tonic-gate return 1; 35337c478bd9Sstevel@tonic-gate } 35347c478bd9Sstevel@tonic-gate 35357c478bd9Sstevel@tonic-gate return 0; 35367c478bd9Sstevel@tonic-gate } 35377c478bd9Sstevel@tonic-gate 35387c478bd9Sstevel@tonic-gate static struct builtin builtin_module = 35397c478bd9Sstevel@tonic-gate { 35407c478bd9Sstevel@tonic-gate "module", 35417c478bd9Sstevel@tonic-gate module_func, 35427c478bd9Sstevel@tonic-gate BUILTIN_CMDLINE | BUILTIN_HELP_LIST, 35437c478bd9Sstevel@tonic-gate "module FILE [ARG ...]", 35447c478bd9Sstevel@tonic-gate "Load a boot module FILE for a Multiboot format boot image (no" 35457c478bd9Sstevel@tonic-gate " interpretation of the file contents is made, so users of this" 35467c478bd9Sstevel@tonic-gate " command must know what the kernel in question expects). The" 35477c478bd9Sstevel@tonic-gate " rest of the line is passed as the \"module command line\", like" 35487c478bd9Sstevel@tonic-gate " the `kernel' command." 35497c478bd9Sstevel@tonic-gate }; 35507c478bd9Sstevel@tonic-gate 3551ae115bc7Smrj /* module$ */ 3552ae115bc7Smrj static int 3553ae115bc7Smrj module_dollar_func (char *arg, int flags) 3554ae115bc7Smrj { 3555b1b8ab34Slling char newarg[MAX_CMDLINE]; /* everything boils down to MAX_CMDLINE */ 3556b1b8ab34Slling char *cmdline_sav; 3557b1b8ab34Slling 3558b1b8ab34Slling grub_printf("loading '%s' ...\n", arg); 3559b1b8ab34Slling expand_arch(arg, newarg); 3560b1b8ab34Slling 3561b1b8ab34Slling cmdline_sav = (char *)mb_cmdline; 3562b1b8ab34Slling if (module_func(newarg, flags)) 3563b1b8ab34Slling return (1); 3564b1b8ab34Slling 3565ffb5616eSLin Ling if (expand_dollar_bootfs(newarg, cmdline_sav)) { 3566ffb5616eSLin Ling grub_printf("cannot expand $ZFS-BOOTFS for dataset %s\n", 3567ffb5616eSLin Ling current_bootfs); 3568b1b8ab34Slling return (1); 3569ffb5616eSLin Ling } 3570b1b8ab34Slling 3571b1b8ab34Slling grub_printf("'%s' is loaded\n", (char *)cmdline_sav); 3572b1b8ab34Slling mb_cmdline += grub_strlen(cmdline_sav) + 1; 3573b1b8ab34Slling 3574b1b8ab34Slling return (0); 3575ae115bc7Smrj } 3576ae115bc7Smrj 3577ae115bc7Smrj static struct builtin builtin_module_dollar = 3578ae115bc7Smrj { 3579ae115bc7Smrj "module$", 3580ae115bc7Smrj module_dollar_func, 3581ae115bc7Smrj BUILTIN_CMDLINE | BUILTIN_HELP_LIST, 3582ae115bc7Smrj "module FILE [ARG ...]", 3583ae115bc7Smrj " Just like module, but with $ISADIR expansion." 3584ae115bc7Smrj }; 3585ae115bc7Smrj 35867c478bd9Sstevel@tonic-gate 35877c478bd9Sstevel@tonic-gate /* modulenounzip */ 35887c478bd9Sstevel@tonic-gate static int 35897c478bd9Sstevel@tonic-gate modulenounzip_func (char *arg, int flags) 35907c478bd9Sstevel@tonic-gate { 35917c478bd9Sstevel@tonic-gate int ret; 35927c478bd9Sstevel@tonic-gate 35937c478bd9Sstevel@tonic-gate #ifndef NO_DECOMPRESSION 35947c478bd9Sstevel@tonic-gate no_decompression = 1; 35957c478bd9Sstevel@tonic-gate #endif 35967c478bd9Sstevel@tonic-gate 35977c478bd9Sstevel@tonic-gate ret = module_func (arg, flags); 35987c478bd9Sstevel@tonic-gate 35997c478bd9Sstevel@tonic-gate #ifndef NO_DECOMPRESSION 36007c478bd9Sstevel@tonic-gate no_decompression = 0; 36017c478bd9Sstevel@tonic-gate #endif 36027c478bd9Sstevel@tonic-gate 36037c478bd9Sstevel@tonic-gate return ret; 36047c478bd9Sstevel@tonic-gate } 36057c478bd9Sstevel@tonic-gate 36067c478bd9Sstevel@tonic-gate static struct builtin builtin_modulenounzip = 36077c478bd9Sstevel@tonic-gate { 36087c478bd9Sstevel@tonic-gate "modulenounzip", 36097c478bd9Sstevel@tonic-gate modulenounzip_func, 36107c478bd9Sstevel@tonic-gate BUILTIN_CMDLINE | BUILTIN_HELP_LIST, 36117c478bd9Sstevel@tonic-gate "modulenounzip FILE [ARG ...]", 36127c478bd9Sstevel@tonic-gate "The same as `module', except that automatic decompression is" 36137c478bd9Sstevel@tonic-gate " disabled." 36147c478bd9Sstevel@tonic-gate }; 36157c478bd9Sstevel@tonic-gate 36167c478bd9Sstevel@tonic-gate 36177c478bd9Sstevel@tonic-gate /* pager [on|off] */ 36187c478bd9Sstevel@tonic-gate static int 36197c478bd9Sstevel@tonic-gate pager_func (char *arg, int flags) 36207c478bd9Sstevel@tonic-gate { 36217c478bd9Sstevel@tonic-gate /* If ARG is empty, toggle the flag. */ 36227c478bd9Sstevel@tonic-gate if (! *arg) 36237c478bd9Sstevel@tonic-gate use_pager = ! use_pager; 36247c478bd9Sstevel@tonic-gate else if (grub_memcmp (arg, "on", 2) == 0) 36257c478bd9Sstevel@tonic-gate use_pager = 1; 36267c478bd9Sstevel@tonic-gate else if (grub_memcmp (arg, "off", 3) == 0) 36277c478bd9Sstevel@tonic-gate use_pager = 0; 36287c478bd9Sstevel@tonic-gate else 36297c478bd9Sstevel@tonic-gate { 36307c478bd9Sstevel@tonic-gate errnum = ERR_BAD_ARGUMENT; 36317c478bd9Sstevel@tonic-gate return 1; 36327c478bd9Sstevel@tonic-gate } 36337c478bd9Sstevel@tonic-gate 36347c478bd9Sstevel@tonic-gate grub_printf (" Internal pager is now %s\n", use_pager ? "on" : "off"); 36357c478bd9Sstevel@tonic-gate return 0; 36367c478bd9Sstevel@tonic-gate } 36377c478bd9Sstevel@tonic-gate 36387c478bd9Sstevel@tonic-gate static struct builtin builtin_pager = 36397c478bd9Sstevel@tonic-gate { 36407c478bd9Sstevel@tonic-gate "pager", 36417c478bd9Sstevel@tonic-gate pager_func, 36427c478bd9Sstevel@tonic-gate BUILTIN_CMDLINE | BUILTIN_MENU | BUILTIN_HELP_LIST, 36437c478bd9Sstevel@tonic-gate "pager [FLAG]", 36447c478bd9Sstevel@tonic-gate "Toggle pager mode with no argument. If FLAG is given and its value" 36457c478bd9Sstevel@tonic-gate " is `on', turn on the mode. If FLAG is `off', turn off the mode." 36467c478bd9Sstevel@tonic-gate }; 36477c478bd9Sstevel@tonic-gate 36487c478bd9Sstevel@tonic-gate 36497c478bd9Sstevel@tonic-gate /* partnew PART TYPE START LEN */ 36507c478bd9Sstevel@tonic-gate static int 36517c478bd9Sstevel@tonic-gate partnew_func (char *arg, int flags) 36527c478bd9Sstevel@tonic-gate { 36537c478bd9Sstevel@tonic-gate int new_type, new_start, new_len; 36547c478bd9Sstevel@tonic-gate int start_cl, start_ch, start_dh; 36557c478bd9Sstevel@tonic-gate int end_cl, end_ch, end_dh; 36567c478bd9Sstevel@tonic-gate int entry; 36577c478bd9Sstevel@tonic-gate char mbr[512]; 36587c478bd9Sstevel@tonic-gate 36597c478bd9Sstevel@tonic-gate /* Convert a LBA address to a CHS address in the INT 13 format. */ 36607c478bd9Sstevel@tonic-gate auto void lba_to_chs (int lba, int *cl, int *ch, int *dh); 36617c478bd9Sstevel@tonic-gate void lba_to_chs (int lba, int *cl, int *ch, int *dh) 36627c478bd9Sstevel@tonic-gate { 36637c478bd9Sstevel@tonic-gate int cylinder, head, sector; 36647c478bd9Sstevel@tonic-gate 36657c478bd9Sstevel@tonic-gate sector = lba % buf_geom.sectors + 1; 36667c478bd9Sstevel@tonic-gate head = (lba / buf_geom.sectors) % buf_geom.heads; 36677c478bd9Sstevel@tonic-gate cylinder = lba / (buf_geom.sectors * buf_geom.heads); 36687c478bd9Sstevel@tonic-gate 36697c478bd9Sstevel@tonic-gate if (cylinder >= buf_geom.cylinders) 36707c478bd9Sstevel@tonic-gate cylinder = buf_geom.cylinders - 1; 36717c478bd9Sstevel@tonic-gate 36727c478bd9Sstevel@tonic-gate *cl = sector | ((cylinder & 0x300) >> 2); 36737c478bd9Sstevel@tonic-gate *ch = cylinder & 0xFF; 36747c478bd9Sstevel@tonic-gate *dh = head; 36757c478bd9Sstevel@tonic-gate } 36767c478bd9Sstevel@tonic-gate 36777c478bd9Sstevel@tonic-gate /* Get the drive and the partition. */ 36787c478bd9Sstevel@tonic-gate if (! set_device (arg)) 36797c478bd9Sstevel@tonic-gate return 1; 36807c478bd9Sstevel@tonic-gate 36817c478bd9Sstevel@tonic-gate /* The drive must be a hard disk. */ 36827c478bd9Sstevel@tonic-gate if (! (current_drive & 0x80)) 36837c478bd9Sstevel@tonic-gate { 36847c478bd9Sstevel@tonic-gate errnum = ERR_BAD_ARGUMENT; 36857c478bd9Sstevel@tonic-gate return 1; 36867c478bd9Sstevel@tonic-gate } 36877c478bd9Sstevel@tonic-gate 36887c478bd9Sstevel@tonic-gate /* The partition must a primary partition. */ 36897c478bd9Sstevel@tonic-gate if ((current_partition >> 16) > 3 36907c478bd9Sstevel@tonic-gate || (current_partition & 0xFFFF) != 0xFFFF) 36917c478bd9Sstevel@tonic-gate { 36927c478bd9Sstevel@tonic-gate errnum = ERR_BAD_ARGUMENT; 36937c478bd9Sstevel@tonic-gate return 1; 36947c478bd9Sstevel@tonic-gate } 36957c478bd9Sstevel@tonic-gate 36967c478bd9Sstevel@tonic-gate entry = current_partition >> 16; 36977c478bd9Sstevel@tonic-gate 36987c478bd9Sstevel@tonic-gate /* Get the new partition type. */ 36997c478bd9Sstevel@tonic-gate arg = skip_to (0, arg); 37007c478bd9Sstevel@tonic-gate if (! safe_parse_maxint (&arg, &new_type)) 37017c478bd9Sstevel@tonic-gate return 1; 37027c478bd9Sstevel@tonic-gate 37037c478bd9Sstevel@tonic-gate /* The partition type is unsigned char. */ 37047c478bd9Sstevel@tonic-gate if (new_type > 0xFF) 37057c478bd9Sstevel@tonic-gate { 37067c478bd9Sstevel@tonic-gate errnum = ERR_BAD_ARGUMENT; 37077c478bd9Sstevel@tonic-gate return 1; 37087c478bd9Sstevel@tonic-gate } 37097c478bd9Sstevel@tonic-gate 37107c478bd9Sstevel@tonic-gate /* Get the new partition start. */ 37117c478bd9Sstevel@tonic-gate arg = skip_to (0, arg); 37127c478bd9Sstevel@tonic-gate if (! safe_parse_maxint (&arg, &new_start)) 37137c478bd9Sstevel@tonic-gate return 1; 37147c478bd9Sstevel@tonic-gate 37157c478bd9Sstevel@tonic-gate /* Get the new partition length. */ 37167c478bd9Sstevel@tonic-gate arg = skip_to (0, arg); 37177c478bd9Sstevel@tonic-gate if (! safe_parse_maxint (&arg, &new_len)) 37187c478bd9Sstevel@tonic-gate return 1; 37197c478bd9Sstevel@tonic-gate 37207c478bd9Sstevel@tonic-gate /* Read the MBR. */ 37217c478bd9Sstevel@tonic-gate if (! rawread (current_drive, 0, 0, SECTOR_SIZE, mbr)) 37227c478bd9Sstevel@tonic-gate return 1; 37237c478bd9Sstevel@tonic-gate 37247c478bd9Sstevel@tonic-gate /* Check if the new partition will fit in the disk. */ 37257c478bd9Sstevel@tonic-gate if (new_start + new_len > buf_geom.total_sectors) 37267c478bd9Sstevel@tonic-gate { 37277c478bd9Sstevel@tonic-gate errnum = ERR_GEOM; 37287c478bd9Sstevel@tonic-gate return 1; 37297c478bd9Sstevel@tonic-gate } 37307c478bd9Sstevel@tonic-gate 37317c478bd9Sstevel@tonic-gate /* Store the partition information in the MBR. */ 37327c478bd9Sstevel@tonic-gate lba_to_chs (new_start, &start_cl, &start_ch, &start_dh); 37337c478bd9Sstevel@tonic-gate lba_to_chs (new_start + new_len - 1, &end_cl, &end_ch, &end_dh); 37347c478bd9Sstevel@tonic-gate 37357c478bd9Sstevel@tonic-gate PC_SLICE_FLAG (mbr, entry) = 0; 37367c478bd9Sstevel@tonic-gate PC_SLICE_HEAD (mbr, entry) = start_dh; 37377c478bd9Sstevel@tonic-gate PC_SLICE_SEC (mbr, entry) = start_cl; 37387c478bd9Sstevel@tonic-gate PC_SLICE_CYL (mbr, entry) = start_ch; 37397c478bd9Sstevel@tonic-gate PC_SLICE_TYPE (mbr, entry) = new_type; 37407c478bd9Sstevel@tonic-gate PC_SLICE_EHEAD (mbr, entry) = end_dh; 37417c478bd9Sstevel@tonic-gate PC_SLICE_ESEC (mbr, entry) = end_cl; 37427c478bd9Sstevel@tonic-gate PC_SLICE_ECYL (mbr, entry) = end_ch; 37437c478bd9Sstevel@tonic-gate PC_SLICE_START (mbr, entry) = new_start; 37447c478bd9Sstevel@tonic-gate PC_SLICE_LENGTH (mbr, entry) = new_len; 37457c478bd9Sstevel@tonic-gate 37467c478bd9Sstevel@tonic-gate /* Make sure that the MBR has a valid signature. */ 37477c478bd9Sstevel@tonic-gate PC_MBR_SIG (mbr) = PC_MBR_SIGNATURE; 37487c478bd9Sstevel@tonic-gate 37497c478bd9Sstevel@tonic-gate /* Write back the MBR to the disk. */ 3750342440ecSPrasad Singamsetty buf_track = BUF_CACHE_INVALID; 37517c478bd9Sstevel@tonic-gate if (! rawwrite (current_drive, 0, mbr)) 37527c478bd9Sstevel@tonic-gate return 1; 37537c478bd9Sstevel@tonic-gate 37547c478bd9Sstevel@tonic-gate return 0; 37557c478bd9Sstevel@tonic-gate } 37567c478bd9Sstevel@tonic-gate 37577c478bd9Sstevel@tonic-gate static struct builtin builtin_partnew = 37587c478bd9Sstevel@tonic-gate { 37597c478bd9Sstevel@tonic-gate "partnew", 37607c478bd9Sstevel@tonic-gate partnew_func, 37617c478bd9Sstevel@tonic-gate BUILTIN_CMDLINE | BUILTIN_MENU | BUILTIN_HELP_LIST, 37627c478bd9Sstevel@tonic-gate "partnew PART TYPE START LEN", 37637c478bd9Sstevel@tonic-gate "Create a primary partition at the starting address START with the" 37647c478bd9Sstevel@tonic-gate " length LEN, with the type TYPE. START and LEN are in sector units." 37657c478bd9Sstevel@tonic-gate }; 37667c478bd9Sstevel@tonic-gate 37677c478bd9Sstevel@tonic-gate 37687c478bd9Sstevel@tonic-gate /* parttype PART TYPE */ 37697c478bd9Sstevel@tonic-gate static int 37707c478bd9Sstevel@tonic-gate parttype_func (char *arg, int flags) 37717c478bd9Sstevel@tonic-gate { 37727c478bd9Sstevel@tonic-gate int new_type; 37737c478bd9Sstevel@tonic-gate unsigned long part = 0xFFFFFF; 37747c478bd9Sstevel@tonic-gate unsigned long start, len, offset, ext_offset; 37757c478bd9Sstevel@tonic-gate int entry, type; 37767c478bd9Sstevel@tonic-gate char mbr[512]; 37777c478bd9Sstevel@tonic-gate 37787c478bd9Sstevel@tonic-gate /* Get the drive and the partition. */ 37797c478bd9Sstevel@tonic-gate if (! set_device (arg)) 37807c478bd9Sstevel@tonic-gate return 1; 37817c478bd9Sstevel@tonic-gate 37827c478bd9Sstevel@tonic-gate /* The drive must be a hard disk. */ 37837c478bd9Sstevel@tonic-gate if (! (current_drive & 0x80)) 37847c478bd9Sstevel@tonic-gate { 37857c478bd9Sstevel@tonic-gate errnum = ERR_BAD_ARGUMENT; 37867c478bd9Sstevel@tonic-gate return 1; 37877c478bd9Sstevel@tonic-gate } 37887c478bd9Sstevel@tonic-gate 37897c478bd9Sstevel@tonic-gate /* The partition must be a PC slice. */ 37907c478bd9Sstevel@tonic-gate if ((current_partition >> 16) == 0xFF 37917c478bd9Sstevel@tonic-gate || (current_partition & 0xFFFF) != 0xFFFF) 37927c478bd9Sstevel@tonic-gate { 37937c478bd9Sstevel@tonic-gate errnum = ERR_BAD_ARGUMENT; 37947c478bd9Sstevel@tonic-gate return 1; 37957c478bd9Sstevel@tonic-gate } 37967c478bd9Sstevel@tonic-gate 37977c478bd9Sstevel@tonic-gate /* Get the new partition type. */ 37987c478bd9Sstevel@tonic-gate arg = skip_to (0, arg); 37997c478bd9Sstevel@tonic-gate if (! safe_parse_maxint (&arg, &new_type)) 38007c478bd9Sstevel@tonic-gate return 1; 38017c478bd9Sstevel@tonic-gate 38027c478bd9Sstevel@tonic-gate /* The partition type is unsigned char. */ 38037c478bd9Sstevel@tonic-gate if (new_type > 0xFF) 38047c478bd9Sstevel@tonic-gate { 38057c478bd9Sstevel@tonic-gate errnum = ERR_BAD_ARGUMENT; 38067c478bd9Sstevel@tonic-gate return 1; 38077c478bd9Sstevel@tonic-gate } 38087c478bd9Sstevel@tonic-gate 38097c478bd9Sstevel@tonic-gate /* Look for the partition. */ 38107c478bd9Sstevel@tonic-gate while (next_partition (current_drive, 0xFFFFFF, &part, &type, 38117c478bd9Sstevel@tonic-gate &start, &len, &offset, &entry, 38127c478bd9Sstevel@tonic-gate &ext_offset, mbr)) 38137c478bd9Sstevel@tonic-gate { 38147c478bd9Sstevel@tonic-gate if (part == current_partition) 38157c478bd9Sstevel@tonic-gate { 38167c478bd9Sstevel@tonic-gate /* Found. */ 38177c478bd9Sstevel@tonic-gate 38187c478bd9Sstevel@tonic-gate /* Set the type to NEW_TYPE. */ 38197c478bd9Sstevel@tonic-gate PC_SLICE_TYPE (mbr, entry) = new_type; 38207c478bd9Sstevel@tonic-gate 38217c478bd9Sstevel@tonic-gate /* Write back the MBR to the disk. */ 3822342440ecSPrasad Singamsetty buf_track = BUF_CACHE_INVALID; 38237c478bd9Sstevel@tonic-gate if (! rawwrite (current_drive, offset, mbr)) 38247c478bd9Sstevel@tonic-gate return 1; 38257c478bd9Sstevel@tonic-gate 38267c478bd9Sstevel@tonic-gate /* Succeed. */ 38277c478bd9Sstevel@tonic-gate return 0; 38287c478bd9Sstevel@tonic-gate } 38297c478bd9Sstevel@tonic-gate } 38307c478bd9Sstevel@tonic-gate 38317c478bd9Sstevel@tonic-gate /* The partition was not found. ERRNUM was set by next_partition. */ 38327c478bd9Sstevel@tonic-gate return 1; 38337c478bd9Sstevel@tonic-gate } 38347c478bd9Sstevel@tonic-gate 38357c478bd9Sstevel@tonic-gate static struct builtin builtin_parttype = 38367c478bd9Sstevel@tonic-gate { 38377c478bd9Sstevel@tonic-gate "parttype", 38387c478bd9Sstevel@tonic-gate parttype_func, 38397c478bd9Sstevel@tonic-gate BUILTIN_CMDLINE | BUILTIN_MENU | BUILTIN_HELP_LIST, 38407c478bd9Sstevel@tonic-gate "parttype PART TYPE", 38417c478bd9Sstevel@tonic-gate "Change the type of the partition PART to TYPE." 38427c478bd9Sstevel@tonic-gate }; 38437c478bd9Sstevel@tonic-gate 38447c478bd9Sstevel@tonic-gate 38457c478bd9Sstevel@tonic-gate /* password */ 38467c478bd9Sstevel@tonic-gate static int 38477c478bd9Sstevel@tonic-gate password_func (char *arg, int flags) 38487c478bd9Sstevel@tonic-gate { 38497c478bd9Sstevel@tonic-gate int len; 38507c478bd9Sstevel@tonic-gate password_t type = PASSWORD_PLAIN; 38517c478bd9Sstevel@tonic-gate 38527c478bd9Sstevel@tonic-gate #ifdef USE_MD5_PASSWORDS 38537c478bd9Sstevel@tonic-gate if (grub_memcmp (arg, "--md5", 5) == 0) 38547c478bd9Sstevel@tonic-gate { 38557c478bd9Sstevel@tonic-gate type = PASSWORD_MD5; 38567c478bd9Sstevel@tonic-gate arg = skip_to (0, arg); 38577c478bd9Sstevel@tonic-gate } 38587c478bd9Sstevel@tonic-gate #endif 38597c478bd9Sstevel@tonic-gate if (grub_memcmp (arg, "--", 2) == 0) 38607c478bd9Sstevel@tonic-gate { 38617c478bd9Sstevel@tonic-gate type = PASSWORD_UNSUPPORTED; 38627c478bd9Sstevel@tonic-gate arg = skip_to (0, arg); 38637c478bd9Sstevel@tonic-gate } 38647c478bd9Sstevel@tonic-gate 38657c478bd9Sstevel@tonic-gate if ((flags & (BUILTIN_CMDLINE | BUILTIN_SCRIPT)) != 0) 38667c478bd9Sstevel@tonic-gate { 38677c478bd9Sstevel@tonic-gate /* Do password check! */ 38687c478bd9Sstevel@tonic-gate char entered[32]; 38697c478bd9Sstevel@tonic-gate 38707c478bd9Sstevel@tonic-gate /* Wipe out any previously entered password */ 38717c478bd9Sstevel@tonic-gate entered[0] = 0; 38727c478bd9Sstevel@tonic-gate get_cmdline ("Password: ", entered, 31, '*', 0); 38737c478bd9Sstevel@tonic-gate 38747c478bd9Sstevel@tonic-gate nul_terminate (arg); 38757c478bd9Sstevel@tonic-gate if (check_password (entered, arg, type) != 0) 38767c478bd9Sstevel@tonic-gate { 38777c478bd9Sstevel@tonic-gate errnum = ERR_PRIVILEGED; 38787c478bd9Sstevel@tonic-gate return 1; 38797c478bd9Sstevel@tonic-gate } 38807c478bd9Sstevel@tonic-gate } 38817c478bd9Sstevel@tonic-gate else 38827c478bd9Sstevel@tonic-gate { 38837c478bd9Sstevel@tonic-gate len = grub_strlen (arg); 38847c478bd9Sstevel@tonic-gate 38857c478bd9Sstevel@tonic-gate /* PASSWORD NUL NUL ... */ 38867c478bd9Sstevel@tonic-gate if (len + 2 > PASSWORD_BUFLEN) 38877c478bd9Sstevel@tonic-gate { 38887c478bd9Sstevel@tonic-gate errnum = ERR_WONT_FIT; 38897c478bd9Sstevel@tonic-gate return 1; 38907c478bd9Sstevel@tonic-gate } 38917c478bd9Sstevel@tonic-gate 38927c478bd9Sstevel@tonic-gate /* Copy the password and clear the rest of the buffer. */ 38937c478bd9Sstevel@tonic-gate password = (char *) PASSWORD_BUF; 38947c478bd9Sstevel@tonic-gate grub_memmove (password, arg, len); 38957c478bd9Sstevel@tonic-gate grub_memset (password + len, 0, PASSWORD_BUFLEN - len); 38967c478bd9Sstevel@tonic-gate password_type = type; 38977c478bd9Sstevel@tonic-gate } 38987c478bd9Sstevel@tonic-gate return 0; 38997c478bd9Sstevel@tonic-gate } 39007c478bd9Sstevel@tonic-gate 39017c478bd9Sstevel@tonic-gate static struct builtin builtin_password = 39027c478bd9Sstevel@tonic-gate { 39037c478bd9Sstevel@tonic-gate "password", 39047c478bd9Sstevel@tonic-gate password_func, 39057c478bd9Sstevel@tonic-gate BUILTIN_MENU | BUILTIN_CMDLINE | BUILTIN_NO_ECHO, 39067c478bd9Sstevel@tonic-gate "password [--md5] PASSWD [FILE]", 39077c478bd9Sstevel@tonic-gate "If used in the first section of a menu file, disable all" 39087c478bd9Sstevel@tonic-gate " interactive editing control (menu entry editor and" 39097c478bd9Sstevel@tonic-gate " command line). If the password PASSWD is entered, it loads the" 39107c478bd9Sstevel@tonic-gate " FILE as a new config file and restarts the GRUB Stage 2. If you" 39117c478bd9Sstevel@tonic-gate " omit the argument FILE, then GRUB just unlocks privileged" 39127c478bd9Sstevel@tonic-gate " instructions. You can also use it in the script section, in" 39137c478bd9Sstevel@tonic-gate " which case it will ask for the password, before continueing." 39147c478bd9Sstevel@tonic-gate " The option --md5 tells GRUB that PASSWD is encrypted with" 39157c478bd9Sstevel@tonic-gate " md5crypt." 39167c478bd9Sstevel@tonic-gate }; 39177c478bd9Sstevel@tonic-gate 39187c478bd9Sstevel@tonic-gate 39197c478bd9Sstevel@tonic-gate /* pause */ 39207c478bd9Sstevel@tonic-gate static int 39217c478bd9Sstevel@tonic-gate pause_func (char *arg, int flags) 39227c478bd9Sstevel@tonic-gate { 39237c478bd9Sstevel@tonic-gate printf("%s\n", arg); 39247c478bd9Sstevel@tonic-gate 39257c478bd9Sstevel@tonic-gate /* If ESC is returned, then abort this entry. */ 39267c478bd9Sstevel@tonic-gate if (ASCII_CHAR (getkey ()) == 27) 39277c478bd9Sstevel@tonic-gate return 1; 39287c478bd9Sstevel@tonic-gate 39297c478bd9Sstevel@tonic-gate return 0; 39307c478bd9Sstevel@tonic-gate } 39317c478bd9Sstevel@tonic-gate 39327c478bd9Sstevel@tonic-gate static struct builtin builtin_pause = 39337c478bd9Sstevel@tonic-gate { 39347c478bd9Sstevel@tonic-gate "pause", 39357c478bd9Sstevel@tonic-gate pause_func, 39367c478bd9Sstevel@tonic-gate BUILTIN_CMDLINE | BUILTIN_NO_ECHO, 39377c478bd9Sstevel@tonic-gate "pause [MESSAGE ...]", 39387c478bd9Sstevel@tonic-gate "Print MESSAGE, then wait until a key is pressed." 39397c478bd9Sstevel@tonic-gate }; 39407c478bd9Sstevel@tonic-gate 39417c478bd9Sstevel@tonic-gate 39427c478bd9Sstevel@tonic-gate #ifdef GRUB_UTIL 39437c478bd9Sstevel@tonic-gate /* quit */ 39447c478bd9Sstevel@tonic-gate static int 39457c478bd9Sstevel@tonic-gate quit_func (char *arg, int flags) 39467c478bd9Sstevel@tonic-gate { 39477c478bd9Sstevel@tonic-gate stop (); 39487c478bd9Sstevel@tonic-gate 39497c478bd9Sstevel@tonic-gate /* Never reach here. */ 39507c478bd9Sstevel@tonic-gate return 0; 39517c478bd9Sstevel@tonic-gate } 39527c478bd9Sstevel@tonic-gate 39537c478bd9Sstevel@tonic-gate static struct builtin builtin_quit = 39547c478bd9Sstevel@tonic-gate { 39557c478bd9Sstevel@tonic-gate "quit", 39567c478bd9Sstevel@tonic-gate quit_func, 39577c478bd9Sstevel@tonic-gate BUILTIN_CMDLINE | BUILTIN_HELP_LIST, 39587c478bd9Sstevel@tonic-gate "quit", 39597c478bd9Sstevel@tonic-gate "Exit from the GRUB shell." 39607c478bd9Sstevel@tonic-gate }; 39617c478bd9Sstevel@tonic-gate #endif /* GRUB_UTIL */ 39627c478bd9Sstevel@tonic-gate 39637c478bd9Sstevel@tonic-gate 39647c478bd9Sstevel@tonic-gate #ifdef SUPPORT_NETBOOT 39657c478bd9Sstevel@tonic-gate /* rarp */ 39667c478bd9Sstevel@tonic-gate static int 39677c478bd9Sstevel@tonic-gate rarp_func (char *arg, int flags) 39687c478bd9Sstevel@tonic-gate { 39697c478bd9Sstevel@tonic-gate if (! rarp ()) 39707c478bd9Sstevel@tonic-gate { 39717c478bd9Sstevel@tonic-gate if (errnum == ERR_NONE) 39727c478bd9Sstevel@tonic-gate errnum = ERR_DEV_VALUES; 39737c478bd9Sstevel@tonic-gate 39747c478bd9Sstevel@tonic-gate return 1; 39757c478bd9Sstevel@tonic-gate } 39767c478bd9Sstevel@tonic-gate 39777c478bd9Sstevel@tonic-gate /* Notify the configuration. */ 39787c478bd9Sstevel@tonic-gate print_network_configuration (); 39797c478bd9Sstevel@tonic-gate return 0; 39807c478bd9Sstevel@tonic-gate } 39817c478bd9Sstevel@tonic-gate 39827c478bd9Sstevel@tonic-gate static struct builtin builtin_rarp = 39837c478bd9Sstevel@tonic-gate { 39847c478bd9Sstevel@tonic-gate "rarp", 39857c478bd9Sstevel@tonic-gate rarp_func, 39867c478bd9Sstevel@tonic-gate BUILTIN_CMDLINE | BUILTIN_MENU | BUILTIN_HELP_LIST, 39877c478bd9Sstevel@tonic-gate "rarp", 39887c478bd9Sstevel@tonic-gate "Initialize a network device via RARP." 39897c478bd9Sstevel@tonic-gate }; 39907c478bd9Sstevel@tonic-gate #endif /* SUPPORT_NETBOOT */ 39917c478bd9Sstevel@tonic-gate 39927c478bd9Sstevel@tonic-gate 39937c478bd9Sstevel@tonic-gate static int 39947c478bd9Sstevel@tonic-gate read_func (char *arg, int flags) 39957c478bd9Sstevel@tonic-gate { 39967c478bd9Sstevel@tonic-gate int addr; 39977c478bd9Sstevel@tonic-gate 39987c478bd9Sstevel@tonic-gate if (! safe_parse_maxint (&arg, &addr)) 39997c478bd9Sstevel@tonic-gate return 1; 40007c478bd9Sstevel@tonic-gate 40017c478bd9Sstevel@tonic-gate grub_printf ("Address 0x%x: Value 0x%x\n", 40027c478bd9Sstevel@tonic-gate addr, *((unsigned *) RAW_ADDR (addr))); 40037c478bd9Sstevel@tonic-gate return 0; 40047c478bd9Sstevel@tonic-gate } 40057c478bd9Sstevel@tonic-gate 40067c478bd9Sstevel@tonic-gate static struct builtin builtin_read = 40077c478bd9Sstevel@tonic-gate { 40087c478bd9Sstevel@tonic-gate "read", 40097c478bd9Sstevel@tonic-gate read_func, 40107c478bd9Sstevel@tonic-gate BUILTIN_CMDLINE, 40117c478bd9Sstevel@tonic-gate "read ADDR", 40127c478bd9Sstevel@tonic-gate "Read a 32-bit value from memory at address ADDR and" 40137c478bd9Sstevel@tonic-gate " display it in hex format." 40147c478bd9Sstevel@tonic-gate }; 40157c478bd9Sstevel@tonic-gate 40167c478bd9Sstevel@tonic-gate 40177c478bd9Sstevel@tonic-gate /* reboot */ 40187c478bd9Sstevel@tonic-gate static int 40197c478bd9Sstevel@tonic-gate reboot_func (char *arg, int flags) 40207c478bd9Sstevel@tonic-gate { 40217c478bd9Sstevel@tonic-gate grub_reboot (); 40227c478bd9Sstevel@tonic-gate 40237c478bd9Sstevel@tonic-gate /* Never reach here. */ 40247c478bd9Sstevel@tonic-gate return 1; 40257c478bd9Sstevel@tonic-gate } 40267c478bd9Sstevel@tonic-gate 40277c478bd9Sstevel@tonic-gate static struct builtin builtin_reboot = 40287c478bd9Sstevel@tonic-gate { 40297c478bd9Sstevel@tonic-gate "reboot", 40307c478bd9Sstevel@tonic-gate reboot_func, 40317c478bd9Sstevel@tonic-gate BUILTIN_CMDLINE | BUILTIN_HELP_LIST, 40327c478bd9Sstevel@tonic-gate "reboot", 40337c478bd9Sstevel@tonic-gate "Reboot your system." 40347c478bd9Sstevel@tonic-gate }; 40357c478bd9Sstevel@tonic-gate 40367c478bd9Sstevel@tonic-gate 40377c478bd9Sstevel@tonic-gate /* Print the root device information. */ 40387c478bd9Sstevel@tonic-gate static void 40397c478bd9Sstevel@tonic-gate print_root_device (void) 40407c478bd9Sstevel@tonic-gate { 40417c478bd9Sstevel@tonic-gate if (saved_drive == NETWORK_DRIVE) 40427c478bd9Sstevel@tonic-gate { 40437c478bd9Sstevel@tonic-gate /* Network drive. */ 40447c478bd9Sstevel@tonic-gate grub_printf (" (nd):"); 40457c478bd9Sstevel@tonic-gate } 40467c478bd9Sstevel@tonic-gate else if (saved_drive & 0x80) 40477c478bd9Sstevel@tonic-gate { 40487c478bd9Sstevel@tonic-gate /* Hard disk drive. */ 40497c478bd9Sstevel@tonic-gate grub_printf (" (hd%d", saved_drive - 0x80); 40507c478bd9Sstevel@tonic-gate 40517c478bd9Sstevel@tonic-gate if ((saved_partition & 0xFF0000) != 0xFF0000) 40527c478bd9Sstevel@tonic-gate grub_printf (",%d", saved_partition >> 16); 40537c478bd9Sstevel@tonic-gate 40547c478bd9Sstevel@tonic-gate if ((saved_partition & 0x00FF00) != 0x00FF00) 40557c478bd9Sstevel@tonic-gate grub_printf (",%c", ((saved_partition >> 8) & 0xFF) + 'a'); 40567c478bd9Sstevel@tonic-gate 40577c478bd9Sstevel@tonic-gate grub_printf ("):"); 40587c478bd9Sstevel@tonic-gate } 40597c478bd9Sstevel@tonic-gate else 40607c478bd9Sstevel@tonic-gate { 40617c478bd9Sstevel@tonic-gate /* Floppy disk drive. */ 40627c478bd9Sstevel@tonic-gate grub_printf (" (fd%d):", saved_drive); 40637c478bd9Sstevel@tonic-gate } 40647c478bd9Sstevel@tonic-gate 40657c478bd9Sstevel@tonic-gate /* Print the filesystem information. */ 40667c478bd9Sstevel@tonic-gate current_partition = saved_partition; 40677c478bd9Sstevel@tonic-gate current_drive = saved_drive; 40687c478bd9Sstevel@tonic-gate print_fsys_type (); 40697c478bd9Sstevel@tonic-gate } 40707c478bd9Sstevel@tonic-gate 40717c478bd9Sstevel@tonic-gate static int 40727c478bd9Sstevel@tonic-gate real_root_func (char *arg, int attempt_mount) 40737c478bd9Sstevel@tonic-gate { 40747c478bd9Sstevel@tonic-gate int hdbias = 0; 40757c478bd9Sstevel@tonic-gate char *biasptr; 40767c478bd9Sstevel@tonic-gate char *next; 40777c478bd9Sstevel@tonic-gate 40787c478bd9Sstevel@tonic-gate /* If ARG is empty, just print the current root device. */ 40797c478bd9Sstevel@tonic-gate if (! *arg) 40807c478bd9Sstevel@tonic-gate { 40817c478bd9Sstevel@tonic-gate print_root_device (); 40827c478bd9Sstevel@tonic-gate return 0; 40837c478bd9Sstevel@tonic-gate } 40847c478bd9Sstevel@tonic-gate 40857c478bd9Sstevel@tonic-gate /* Call set_device to get the drive and the partition in ARG. */ 40867c478bd9Sstevel@tonic-gate next = set_device (arg); 40877c478bd9Sstevel@tonic-gate if (! next) 40887c478bd9Sstevel@tonic-gate return 1; 40897c478bd9Sstevel@tonic-gate 40907c478bd9Sstevel@tonic-gate /* Ignore ERR_FSYS_MOUNT. */ 40917c478bd9Sstevel@tonic-gate if (attempt_mount) 40927c478bd9Sstevel@tonic-gate { 40937c478bd9Sstevel@tonic-gate if (! open_device () && errnum != ERR_FSYS_MOUNT) 40947c478bd9Sstevel@tonic-gate return 1; 40957c478bd9Sstevel@tonic-gate } 40967c478bd9Sstevel@tonic-gate else 40977c478bd9Sstevel@tonic-gate { 40987c478bd9Sstevel@tonic-gate /* This is necessary, because the location of a partition table 40997c478bd9Sstevel@tonic-gate must be set appropriately. */ 41007c478bd9Sstevel@tonic-gate if (open_partition ()) 41017c478bd9Sstevel@tonic-gate { 41027c478bd9Sstevel@tonic-gate set_bootdev (0); 41037c478bd9Sstevel@tonic-gate if (errnum) 41047c478bd9Sstevel@tonic-gate return 1; 41057c478bd9Sstevel@tonic-gate } 41067c478bd9Sstevel@tonic-gate } 41077c478bd9Sstevel@tonic-gate 41087c478bd9Sstevel@tonic-gate /* Clear ERRNUM. */ 41097c478bd9Sstevel@tonic-gate errnum = 0; 41107c478bd9Sstevel@tonic-gate saved_partition = current_partition; 41117c478bd9Sstevel@tonic-gate saved_drive = current_drive; 41127c478bd9Sstevel@tonic-gate 41137c478bd9Sstevel@tonic-gate if (attempt_mount) 41147c478bd9Sstevel@tonic-gate { 41157c478bd9Sstevel@tonic-gate /* BSD and chainloading evil hacks !! */ 41167c478bd9Sstevel@tonic-gate biasptr = skip_to (0, next); 41177c478bd9Sstevel@tonic-gate safe_parse_maxint (&biasptr, &hdbias); 41187c478bd9Sstevel@tonic-gate errnum = 0; 41197c478bd9Sstevel@tonic-gate bootdev = set_bootdev (hdbias); 41207c478bd9Sstevel@tonic-gate if (errnum) 41217c478bd9Sstevel@tonic-gate return 1; 41227c478bd9Sstevel@tonic-gate 41237c478bd9Sstevel@tonic-gate /* Print the type of the filesystem. */ 41247c478bd9Sstevel@tonic-gate print_fsys_type (); 41257c478bd9Sstevel@tonic-gate } 41267c478bd9Sstevel@tonic-gate 41277c478bd9Sstevel@tonic-gate return 0; 41287c478bd9Sstevel@tonic-gate } 41297c478bd9Sstevel@tonic-gate 41307c478bd9Sstevel@tonic-gate static int 41317c478bd9Sstevel@tonic-gate root_func (char *arg, int flags) 41327c478bd9Sstevel@tonic-gate { 4133b1b8ab34Slling is_zfs_mount = 0; 41347c478bd9Sstevel@tonic-gate return real_root_func (arg, 1); 41357c478bd9Sstevel@tonic-gate } 41367c478bd9Sstevel@tonic-gate 41377c478bd9Sstevel@tonic-gate static struct builtin builtin_root = 41387c478bd9Sstevel@tonic-gate { 41397c478bd9Sstevel@tonic-gate "root", 41407c478bd9Sstevel@tonic-gate root_func, 41417c478bd9Sstevel@tonic-gate BUILTIN_CMDLINE | BUILTIN_HELP_LIST, 41427c478bd9Sstevel@tonic-gate "root [DEVICE [HDBIAS]]", 41437c478bd9Sstevel@tonic-gate "Set the current \"root device\" to the device DEVICE, then" 41447c478bd9Sstevel@tonic-gate " attempt to mount it to get the partition size (for passing the" 41457c478bd9Sstevel@tonic-gate " partition descriptor in `ES:ESI', used by some chain-loaded" 41467c478bd9Sstevel@tonic-gate " bootloaders), the BSD drive-type (for booting BSD kernels using" 41477c478bd9Sstevel@tonic-gate " their native boot format), and correctly determine " 41487c478bd9Sstevel@tonic-gate " the PC partition where a BSD sub-partition is located. The" 41497c478bd9Sstevel@tonic-gate " optional HDBIAS parameter is a number to tell a BSD kernel" 41507c478bd9Sstevel@tonic-gate " how many BIOS drive numbers are on controllers before the current" 41517c478bd9Sstevel@tonic-gate " one. For example, if there is an IDE disk and a SCSI disk, and your" 41527c478bd9Sstevel@tonic-gate " FreeBSD root partition is on the SCSI disk, then use a `1' for HDBIAS." 41537c478bd9Sstevel@tonic-gate }; 41547c478bd9Sstevel@tonic-gate 4155eb2bd662Svikram 4156eb2bd662Svikram /* findroot */ 4157eb2bd662Svikram static int 4158eb2bd662Svikram findroot_func (char *arg, int flags) 4159eb2bd662Svikram { 4160eb2bd662Svikram int ret; 4161eb2bd662Svikram char root[32]; 4162eb2bd662Svikram 4163eb2bd662Svikram if (grub_strlen(arg) >= BOOTSIGN_ARGLEN) { 4164eb2bd662Svikram errnum = ERR_BAD_ARGUMENT; 4165eb2bd662Svikram return 1; 4166eb2bd662Svikram } 4167eb2bd662Svikram 4168eb2bd662Svikram if (arg[0] == '\0') { 4169eb2bd662Svikram errnum = ERR_BAD_ARGUMENT; 4170eb2bd662Svikram return 1; 4171eb2bd662Svikram } 4172eb2bd662Svikram 4173eb2bd662Svikram if (grub_strchr(arg, '/')) { 4174eb2bd662Svikram errnum = ERR_BAD_ARGUMENT; 4175eb2bd662Svikram return 1; 4176eb2bd662Svikram } 4177eb2bd662Svikram 4178051aabe6Staylor find_best_root = 1; 4179051aabe6Staylor best_drive = 0; 4180051aabe6Staylor best_part = 0; 4181eb2bd662Svikram ret = find_common(arg, root, 1, flags); 4182eb2bd662Svikram if (ret != 0) 4183eb2bd662Svikram return (ret); 4184051aabe6Staylor find_best_root = 0; 4185eb2bd662Svikram 4186eb2bd662Svikram return real_root_func (root, 1); 4187eb2bd662Svikram } 4188eb2bd662Svikram 4189eb2bd662Svikram static struct builtin builtin_findroot = 4190eb2bd662Svikram { 4191eb2bd662Svikram "findroot", 4192eb2bd662Svikram findroot_func, 4193eb2bd662Svikram BUILTIN_CMDLINE | BUILTIN_HELP_LIST, 4194963390b4Svikram "findroot <SIGNATURE | (SIGNATURE,partition[,slice])>", 4195963390b4Svikram "Searches across all partitions for the file name SIGNATURE." 4196963390b4Svikram " GRUB looks only in the directory /boot/grub/bootsign for the" 4197963390b4Svikram " filename and it stops as soon as it finds the first instance of" 4198963390b4Svikram " the file - so to be useful the name of the signature file must be" 4199963390b4Svikram " unique across all partitions. Once the signature file is found," 4200963390b4Svikram " GRUB invokes the \"root\" command on that partition." 4201eb2bd662Svikram " An optional partition and slice may be specified to optimize the search." 4202eb2bd662Svikram }; 4203eb2bd662Svikram 4204b1b8ab34Slling 4205b1b8ab34Slling /* 4206b1b8ab34Slling * COMMAND to override the default root filesystem for ZFS 4207b1b8ab34Slling * bootfs pool/fs 4208b1b8ab34Slling */ 4209b1b8ab34Slling static int 4210b1b8ab34Slling bootfs_func (char *arg, int flags) 4211b1b8ab34Slling { 4212b1b8ab34Slling int hdbias = 0; 4213b1b8ab34Slling char *biasptr; 4214b1b8ab34Slling char *next; 4215b1b8ab34Slling 4216b1b8ab34Slling if (! *arg) { 4217b1b8ab34Slling if (current_bootfs[0] != '\0') 4218b1b8ab34Slling grub_printf ("The zfs boot filesystem is set to '%s'.\n", 4219b1b8ab34Slling current_bootfs); 4220b1b8ab34Slling else if (current_rootpool[0] != 0 && current_bootfs_obj != 0) 4221b1b8ab34Slling grub_printf("The zfs boot filesystem is <default: %s/%u>.", 4222b1b8ab34Slling current_rootpool, current_bootfs_obj); 4223b1b8ab34Slling else 422411a41203Slling grub_printf ("The zfs boot filesystem will be derived from " 422511a41203Slling "the default bootfs pool property.\n"); 4226b1b8ab34Slling 4227b1b8ab34Slling return (1); 4228b1b8ab34Slling } 4229b1b8ab34Slling 4230b1b8ab34Slling /* Verify the zfs filesystem name */ 4231b1b8ab34Slling if (arg[0] == '/' || arg[0] == '\0') { 4232b1b8ab34Slling errnum = ERR_BAD_ARGUMENT; 4233b1b8ab34Slling return 0; 4234b1b8ab34Slling } 4235b35c6776Staylor if (current_rootpool[0] != 0 && grub_strncmp(arg, 4236b35c6776Staylor current_rootpool, strlen(current_rootpool))) { 4237b35c6776Staylor errnum = ERR_BAD_ARGUMENT; 4238b35c6776Staylor return 0; 4239b35c6776Staylor } 4240b1b8ab34Slling 4241b1b8ab34Slling if (set_bootfs(arg) == 0) { 4242b1b8ab34Slling errnum = ERR_BAD_ARGUMENT; 4243b1b8ab34Slling return 0; 4244b1b8ab34Slling } 4245b1b8ab34Slling 4246b1b8ab34Slling return (1); 4247b1b8ab34Slling } 4248b1b8ab34Slling 4249b1b8ab34Slling static struct builtin builtin_bootfs = 4250b1b8ab34Slling { 4251b1b8ab34Slling "bootfs", 4252b1b8ab34Slling bootfs_func, 4253b1b8ab34Slling BUILTIN_CMDLINE | BUILTIN_HELP_LIST, 4254b1b8ab34Slling "bootfs [ZFSBOOTFS]", 4255b1b8ab34Slling "Set the current zfs boot filesystem to ZFSBOOTFS (rootpool/rootfs)." 4256b1b8ab34Slling }; 4257b1b8ab34Slling 42587c478bd9Sstevel@tonic-gate 42597c478bd9Sstevel@tonic-gate /* rootnoverify */ 42607c478bd9Sstevel@tonic-gate static int 42617c478bd9Sstevel@tonic-gate rootnoverify_func (char *arg, int flags) 42627c478bd9Sstevel@tonic-gate { 42637c478bd9Sstevel@tonic-gate return real_root_func (arg, 0); 42647c478bd9Sstevel@tonic-gate } 42657c478bd9Sstevel@tonic-gate 42667c478bd9Sstevel@tonic-gate static struct builtin builtin_rootnoverify = 42677c478bd9Sstevel@tonic-gate { 42687c478bd9Sstevel@tonic-gate "rootnoverify", 42697c478bd9Sstevel@tonic-gate rootnoverify_func, 42707c478bd9Sstevel@tonic-gate BUILTIN_CMDLINE | BUILTIN_HELP_LIST, 42717c478bd9Sstevel@tonic-gate "rootnoverify [DEVICE [HDBIAS]]", 42727c478bd9Sstevel@tonic-gate "Similar to `root', but don't attempt to mount the partition. This" 42737c478bd9Sstevel@tonic-gate " is useful for when an OS is outside of the area of the disk that" 42747c478bd9Sstevel@tonic-gate " GRUB can read, but setting the correct root device is still" 42757c478bd9Sstevel@tonic-gate " desired. Note that the items mentioned in `root' which" 42767c478bd9Sstevel@tonic-gate " derived from attempting the mount will NOT work correctly." 42777c478bd9Sstevel@tonic-gate }; 42787c478bd9Sstevel@tonic-gate 42797c478bd9Sstevel@tonic-gate 42807c478bd9Sstevel@tonic-gate /* savedefault */ 42817c478bd9Sstevel@tonic-gate static int 42827c478bd9Sstevel@tonic-gate savedefault_func (char *arg, int flags) 42837c478bd9Sstevel@tonic-gate { 42847c478bd9Sstevel@tonic-gate #if !defined(SUPPORT_DISKLESS) && !defined(GRUB_UTIL) 42857c478bd9Sstevel@tonic-gate unsigned long tmp_drive = saved_drive; 42867c478bd9Sstevel@tonic-gate unsigned long tmp_partition = saved_partition; 42877c478bd9Sstevel@tonic-gate char *default_file = (char *) DEFAULT_FILE_BUF; 42887c478bd9Sstevel@tonic-gate char buf[10]; 42897c478bd9Sstevel@tonic-gate char sect[SECTOR_SIZE]; 42907c478bd9Sstevel@tonic-gate int entryno; 42917c478bd9Sstevel@tonic-gate int sector_count = 0; 4292342440ecSPrasad Singamsetty unsigned int saved_sectors[2]; 42937c478bd9Sstevel@tonic-gate int saved_offsets[2]; 42947c478bd9Sstevel@tonic-gate int saved_lengths[2]; 42957c478bd9Sstevel@tonic-gate 4296b1b8ab34Slling /* not supported for zfs root */ 4297b1b8ab34Slling if (is_zfs_mount == 1) { 4298b1b8ab34Slling return (0); /* no-op */ 4299b1b8ab34Slling } 4300b1b8ab34Slling 43017c478bd9Sstevel@tonic-gate /* Save sector information about at most two sectors. */ 43021b8adde7SWilliam Kucharski auto void disk_read_savesect_func (unsigned int sector, int offset, 43031b8adde7SWilliam Kucharski int length); 43041b8adde7SWilliam Kucharski void disk_read_savesect_func (unsigned int sector, int offset, int length) 43057c478bd9Sstevel@tonic-gate { 43067c478bd9Sstevel@tonic-gate if (sector_count < 2) 43077c478bd9Sstevel@tonic-gate { 43087c478bd9Sstevel@tonic-gate saved_sectors[sector_count] = sector; 43097c478bd9Sstevel@tonic-gate saved_offsets[sector_count] = offset; 43107c478bd9Sstevel@tonic-gate saved_lengths[sector_count] = length; 43117c478bd9Sstevel@tonic-gate } 43127c478bd9Sstevel@tonic-gate sector_count++; 43137c478bd9Sstevel@tonic-gate } 43147c478bd9Sstevel@tonic-gate 43157c478bd9Sstevel@tonic-gate /* This command is only useful when you boot an entry from the menu 43167c478bd9Sstevel@tonic-gate interface. */ 43177c478bd9Sstevel@tonic-gate if (! (flags & BUILTIN_SCRIPT)) 43187c478bd9Sstevel@tonic-gate { 43197c478bd9Sstevel@tonic-gate errnum = ERR_UNRECOGNIZED; 43207c478bd9Sstevel@tonic-gate return 1; 43217c478bd9Sstevel@tonic-gate } 43227c478bd9Sstevel@tonic-gate 43237c478bd9Sstevel@tonic-gate /* Determine a saved entry number. */ 43247c478bd9Sstevel@tonic-gate if (*arg) 43257c478bd9Sstevel@tonic-gate { 43267c478bd9Sstevel@tonic-gate if (grub_memcmp (arg, "fallback", sizeof ("fallback") - 1) == 0) 43277c478bd9Sstevel@tonic-gate { 43287c478bd9Sstevel@tonic-gate int i; 43297c478bd9Sstevel@tonic-gate int index = 0; 43307c478bd9Sstevel@tonic-gate 43317c478bd9Sstevel@tonic-gate for (i = 0; i < MAX_FALLBACK_ENTRIES; i++) 43327c478bd9Sstevel@tonic-gate { 43337c478bd9Sstevel@tonic-gate if (fallback_entries[i] < 0) 43347c478bd9Sstevel@tonic-gate break; 43357c478bd9Sstevel@tonic-gate if (fallback_entries[i] == current_entryno) 43367c478bd9Sstevel@tonic-gate { 43377c478bd9Sstevel@tonic-gate index = i + 1; 43387c478bd9Sstevel@tonic-gate break; 43397c478bd9Sstevel@tonic-gate } 43407c478bd9Sstevel@tonic-gate } 43417c478bd9Sstevel@tonic-gate 43427c478bd9Sstevel@tonic-gate if (index >= MAX_FALLBACK_ENTRIES || fallback_entries[index] < 0) 43437c478bd9Sstevel@tonic-gate { 43447c478bd9Sstevel@tonic-gate /* This is the last. */ 43457c478bd9Sstevel@tonic-gate errnum = ERR_BAD_ARGUMENT; 43467c478bd9Sstevel@tonic-gate return 1; 43477c478bd9Sstevel@tonic-gate } 43487c478bd9Sstevel@tonic-gate 43497c478bd9Sstevel@tonic-gate entryno = fallback_entries[index]; 43507c478bd9Sstevel@tonic-gate } 43517c478bd9Sstevel@tonic-gate else if (! safe_parse_maxint (&arg, &entryno)) 43527c478bd9Sstevel@tonic-gate return 1; 43537c478bd9Sstevel@tonic-gate } 43547c478bd9Sstevel@tonic-gate else 43557c478bd9Sstevel@tonic-gate entryno = current_entryno; 43567c478bd9Sstevel@tonic-gate 43577c478bd9Sstevel@tonic-gate /* Open the default file. */ 43587c478bd9Sstevel@tonic-gate saved_drive = boot_drive; 43597c478bd9Sstevel@tonic-gate saved_partition = install_partition; 43607c478bd9Sstevel@tonic-gate if (grub_open (default_file)) 43617c478bd9Sstevel@tonic-gate { 43627c478bd9Sstevel@tonic-gate int len; 43637c478bd9Sstevel@tonic-gate 43647c478bd9Sstevel@tonic-gate disk_read_hook = disk_read_savesect_func; 43657c478bd9Sstevel@tonic-gate len = grub_read (buf, sizeof (buf)); 43667c478bd9Sstevel@tonic-gate disk_read_hook = 0; 43677c478bd9Sstevel@tonic-gate grub_close (); 43687c478bd9Sstevel@tonic-gate 43697c478bd9Sstevel@tonic-gate if (len != sizeof (buf)) 43707c478bd9Sstevel@tonic-gate { 43717c478bd9Sstevel@tonic-gate /* This is too small. Do not modify the file manually, please! */ 43727c478bd9Sstevel@tonic-gate errnum = ERR_READ; 43737c478bd9Sstevel@tonic-gate goto fail; 43747c478bd9Sstevel@tonic-gate } 43757c478bd9Sstevel@tonic-gate 43767c478bd9Sstevel@tonic-gate if (sector_count > 2) 43777c478bd9Sstevel@tonic-gate { 43787c478bd9Sstevel@tonic-gate /* Is this possible?! Too fragmented! */ 43797c478bd9Sstevel@tonic-gate errnum = ERR_FSYS_CORRUPT; 43807c478bd9Sstevel@tonic-gate goto fail; 43817c478bd9Sstevel@tonic-gate } 43827c478bd9Sstevel@tonic-gate 43837c478bd9Sstevel@tonic-gate /* Set up a string to be written. */ 43847c478bd9Sstevel@tonic-gate grub_memset (buf, '\n', sizeof (buf)); 43857c478bd9Sstevel@tonic-gate grub_sprintf (buf, "%d", entryno); 43867c478bd9Sstevel@tonic-gate 43877c478bd9Sstevel@tonic-gate if (saved_lengths[0] < sizeof (buf)) 43887c478bd9Sstevel@tonic-gate { 43897c478bd9Sstevel@tonic-gate /* The file is anchored to another file and the first few bytes 43907c478bd9Sstevel@tonic-gate are spanned in two sectors. Uggh... */ 43917c478bd9Sstevel@tonic-gate if (! rawread (current_drive, saved_sectors[0], 0, SECTOR_SIZE, 43927c478bd9Sstevel@tonic-gate sect)) 43937c478bd9Sstevel@tonic-gate goto fail; 43947c478bd9Sstevel@tonic-gate grub_memmove (sect + saved_offsets[0], buf, saved_lengths[0]); 43957c478bd9Sstevel@tonic-gate if (! rawwrite (current_drive, saved_sectors[0], sect)) 43967c478bd9Sstevel@tonic-gate goto fail; 43977c478bd9Sstevel@tonic-gate 43987c478bd9Sstevel@tonic-gate if (! rawread (current_drive, saved_sectors[1], 0, SECTOR_SIZE, 43997c478bd9Sstevel@tonic-gate sect)) 44007c478bd9Sstevel@tonic-gate goto fail; 44017c478bd9Sstevel@tonic-gate grub_memmove (sect + saved_offsets[1], 44027c478bd9Sstevel@tonic-gate buf + saved_lengths[0], 44037c478bd9Sstevel@tonic-gate sizeof (buf) - saved_lengths[0]); 44047c478bd9Sstevel@tonic-gate if (! rawwrite (current_drive, saved_sectors[1], sect)) 44057c478bd9Sstevel@tonic-gate goto fail; 44067c478bd9Sstevel@tonic-gate } 44077c478bd9Sstevel@tonic-gate else 44087c478bd9Sstevel@tonic-gate { 44097c478bd9Sstevel@tonic-gate /* This is a simple case. It fits into a single sector. */ 44107c478bd9Sstevel@tonic-gate if (! rawread (current_drive, saved_sectors[0], 0, SECTOR_SIZE, 44117c478bd9Sstevel@tonic-gate sect)) 44127c478bd9Sstevel@tonic-gate goto fail; 44137c478bd9Sstevel@tonic-gate grub_memmove (sect + saved_offsets[0], buf, sizeof (buf)); 44147c478bd9Sstevel@tonic-gate if (! rawwrite (current_drive, saved_sectors[0], sect)) 44157c478bd9Sstevel@tonic-gate goto fail; 44167c478bd9Sstevel@tonic-gate } 44177c478bd9Sstevel@tonic-gate 44187c478bd9Sstevel@tonic-gate /* Clear the cache. */ 4419342440ecSPrasad Singamsetty buf_track = BUF_CACHE_INVALID; 44207c478bd9Sstevel@tonic-gate } 44217c478bd9Sstevel@tonic-gate 44227c478bd9Sstevel@tonic-gate fail: 44237c478bd9Sstevel@tonic-gate saved_drive = tmp_drive; 44247c478bd9Sstevel@tonic-gate saved_partition = tmp_partition; 44257c478bd9Sstevel@tonic-gate return errnum; 44267c478bd9Sstevel@tonic-gate #else /* ! SUPPORT_DISKLESS && ! GRUB_UTIL */ 44277c478bd9Sstevel@tonic-gate errnum = ERR_UNRECOGNIZED; 44287c478bd9Sstevel@tonic-gate return 1; 44297c478bd9Sstevel@tonic-gate #endif /* ! SUPPORT_DISKLESS && ! GRUB_UTIL */ 44307c478bd9Sstevel@tonic-gate } 44317c478bd9Sstevel@tonic-gate 44327c478bd9Sstevel@tonic-gate static struct builtin builtin_savedefault = 44337c478bd9Sstevel@tonic-gate { 44347c478bd9Sstevel@tonic-gate "savedefault", 44357c478bd9Sstevel@tonic-gate savedefault_func, 44367c478bd9Sstevel@tonic-gate BUILTIN_CMDLINE, 44377c478bd9Sstevel@tonic-gate "savedefault [NUM | `fallback']", 44387c478bd9Sstevel@tonic-gate "Save the current entry as the default boot entry if no argument is" 44397c478bd9Sstevel@tonic-gate " specified. If a number is specified, this number is saved. If" 44407c478bd9Sstevel@tonic-gate " `fallback' is used, next fallback entry is saved." 44417c478bd9Sstevel@tonic-gate }; 44427c478bd9Sstevel@tonic-gate 44437c478bd9Sstevel@tonic-gate 44447c478bd9Sstevel@tonic-gate #ifdef SUPPORT_SERIAL 44457c478bd9Sstevel@tonic-gate /* serial */ 44467c478bd9Sstevel@tonic-gate static int 44477c478bd9Sstevel@tonic-gate serial_func (char *arg, int flags) 44487c478bd9Sstevel@tonic-gate { 44497c478bd9Sstevel@tonic-gate unsigned short port = serial_hw_get_port (0); 44507c478bd9Sstevel@tonic-gate unsigned int speed = 9600; 44517c478bd9Sstevel@tonic-gate int word_len = UART_8BITS_WORD; 44527c478bd9Sstevel@tonic-gate int parity = UART_NO_PARITY; 44537c478bd9Sstevel@tonic-gate int stop_bit_len = UART_1_STOP_BIT; 44547c478bd9Sstevel@tonic-gate 44557c478bd9Sstevel@tonic-gate /* Process GNU-style long options. 44567c478bd9Sstevel@tonic-gate FIXME: We should implement a getopt-like function, to avoid 44577c478bd9Sstevel@tonic-gate duplications. */ 44587c478bd9Sstevel@tonic-gate while (1) 44597c478bd9Sstevel@tonic-gate { 44607c478bd9Sstevel@tonic-gate if (grub_memcmp (arg, "--unit=", sizeof ("--unit=") - 1) == 0) 44617c478bd9Sstevel@tonic-gate { 44627c478bd9Sstevel@tonic-gate char *p = arg + sizeof ("--unit=") - 1; 44637c478bd9Sstevel@tonic-gate int unit; 44647c478bd9Sstevel@tonic-gate 44657c478bd9Sstevel@tonic-gate if (! safe_parse_maxint (&p, &unit)) 44667c478bd9Sstevel@tonic-gate return 1; 44677c478bd9Sstevel@tonic-gate 44687c478bd9Sstevel@tonic-gate if (unit < 0 || unit > 3) 44697c478bd9Sstevel@tonic-gate { 44707c478bd9Sstevel@tonic-gate errnum = ERR_DEV_VALUES; 44717c478bd9Sstevel@tonic-gate return 1; 44727c478bd9Sstevel@tonic-gate } 44737c478bd9Sstevel@tonic-gate 44747c478bd9Sstevel@tonic-gate port = serial_hw_get_port (unit); 44757c478bd9Sstevel@tonic-gate } 44767c478bd9Sstevel@tonic-gate else if (grub_memcmp (arg, "--speed=", sizeof ("--speed=") - 1) == 0) 44777c478bd9Sstevel@tonic-gate { 44787c478bd9Sstevel@tonic-gate char *p = arg + sizeof ("--speed=") - 1; 44797c478bd9Sstevel@tonic-gate int num; 44807c478bd9Sstevel@tonic-gate 44817c478bd9Sstevel@tonic-gate if (! safe_parse_maxint (&p, &num)) 44827c478bd9Sstevel@tonic-gate return 1; 44837c478bd9Sstevel@tonic-gate 44847c478bd9Sstevel@tonic-gate speed = (unsigned int) num; 44857c478bd9Sstevel@tonic-gate } 44867c478bd9Sstevel@tonic-gate else if (grub_memcmp (arg, "--port=", sizeof ("--port=") - 1) == 0) 44877c478bd9Sstevel@tonic-gate { 44887c478bd9Sstevel@tonic-gate char *p = arg + sizeof ("--port=") - 1; 44897c478bd9Sstevel@tonic-gate int num; 44907c478bd9Sstevel@tonic-gate 44917c478bd9Sstevel@tonic-gate if (! safe_parse_maxint (&p, &num)) 44927c478bd9Sstevel@tonic-gate return 1; 44937c478bd9Sstevel@tonic-gate 44947c478bd9Sstevel@tonic-gate port = (unsigned short) num; 44957c478bd9Sstevel@tonic-gate } 44967c478bd9Sstevel@tonic-gate else if (grub_memcmp (arg, "--word=", sizeof ("--word=") - 1) == 0) 44977c478bd9Sstevel@tonic-gate { 44987c478bd9Sstevel@tonic-gate char *p = arg + sizeof ("--word=") - 1; 44997c478bd9Sstevel@tonic-gate int len; 45007c478bd9Sstevel@tonic-gate 45017c478bd9Sstevel@tonic-gate if (! safe_parse_maxint (&p, &len)) 45027c478bd9Sstevel@tonic-gate return 1; 45037c478bd9Sstevel@tonic-gate 45047c478bd9Sstevel@tonic-gate switch (len) 45057c478bd9Sstevel@tonic-gate { 45067c478bd9Sstevel@tonic-gate case 5: word_len = UART_5BITS_WORD; break; 45077c478bd9Sstevel@tonic-gate case 6: word_len = UART_6BITS_WORD; break; 45087c478bd9Sstevel@tonic-gate case 7: word_len = UART_7BITS_WORD; break; 45097c478bd9Sstevel@tonic-gate case 8: word_len = UART_8BITS_WORD; break; 45107c478bd9Sstevel@tonic-gate default: 45117c478bd9Sstevel@tonic-gate errnum = ERR_BAD_ARGUMENT; 45127c478bd9Sstevel@tonic-gate return 1; 45137c478bd9Sstevel@tonic-gate } 45147c478bd9Sstevel@tonic-gate } 45157c478bd9Sstevel@tonic-gate else if (grub_memcmp (arg, "--stop=", sizeof ("--stop=") - 1) == 0) 45167c478bd9Sstevel@tonic-gate { 45177c478bd9Sstevel@tonic-gate char *p = arg + sizeof ("--stop=") - 1; 45187c478bd9Sstevel@tonic-gate int len; 45197c478bd9Sstevel@tonic-gate 45207c478bd9Sstevel@tonic-gate if (! safe_parse_maxint (&p, &len)) 45217c478bd9Sstevel@tonic-gate return 1; 45227c478bd9Sstevel@tonic-gate 45237c478bd9Sstevel@tonic-gate switch (len) 45247c478bd9Sstevel@tonic-gate { 45257c478bd9Sstevel@tonic-gate case 1: stop_bit_len = UART_1_STOP_BIT; break; 45267c478bd9Sstevel@tonic-gate case 2: stop_bit_len = UART_2_STOP_BITS; break; 45277c478bd9Sstevel@tonic-gate default: 45287c478bd9Sstevel@tonic-gate errnum = ERR_BAD_ARGUMENT; 45297c478bd9Sstevel@tonic-gate return 1; 45307c478bd9Sstevel@tonic-gate } 45317c478bd9Sstevel@tonic-gate } 45327c478bd9Sstevel@tonic-gate else if (grub_memcmp (arg, "--parity=", sizeof ("--parity=") - 1) == 0) 45337c478bd9Sstevel@tonic-gate { 45347c478bd9Sstevel@tonic-gate char *p = arg + sizeof ("--parity=") - 1; 45357c478bd9Sstevel@tonic-gate 45367c478bd9Sstevel@tonic-gate if (grub_memcmp (p, "no", sizeof ("no") - 1) == 0) 45377c478bd9Sstevel@tonic-gate parity = UART_NO_PARITY; 45387c478bd9Sstevel@tonic-gate else if (grub_memcmp (p, "odd", sizeof ("odd") - 1) == 0) 45397c478bd9Sstevel@tonic-gate parity = UART_ODD_PARITY; 45407c478bd9Sstevel@tonic-gate else if (grub_memcmp (p, "even", sizeof ("even") - 1) == 0) 45417c478bd9Sstevel@tonic-gate parity = UART_EVEN_PARITY; 45427c478bd9Sstevel@tonic-gate else 45437c478bd9Sstevel@tonic-gate { 45447c478bd9Sstevel@tonic-gate errnum = ERR_BAD_ARGUMENT; 45457c478bd9Sstevel@tonic-gate return 1; 45467c478bd9Sstevel@tonic-gate } 45477c478bd9Sstevel@tonic-gate } 45487c478bd9Sstevel@tonic-gate # ifdef GRUB_UTIL 45497c478bd9Sstevel@tonic-gate /* In the grub shell, don't use any port number but open a tty 45507c478bd9Sstevel@tonic-gate device instead. */ 45517c478bd9Sstevel@tonic-gate else if (grub_memcmp (arg, "--device=", sizeof ("--device=") - 1) == 0) 45527c478bd9Sstevel@tonic-gate { 45537c478bd9Sstevel@tonic-gate char *p = arg + sizeof ("--device=") - 1; 45547c478bd9Sstevel@tonic-gate char dev[256]; /* XXX */ 45557c478bd9Sstevel@tonic-gate char *q = dev; 45567c478bd9Sstevel@tonic-gate 45577c478bd9Sstevel@tonic-gate while (*p && ! grub_isspace (*p)) 45587c478bd9Sstevel@tonic-gate *q++ = *p++; 45597c478bd9Sstevel@tonic-gate 45607c478bd9Sstevel@tonic-gate *q = 0; 45617c478bd9Sstevel@tonic-gate serial_set_device (dev); 45627c478bd9Sstevel@tonic-gate } 45637c478bd9Sstevel@tonic-gate # endif /* GRUB_UTIL */ 45647c478bd9Sstevel@tonic-gate else 45657c478bd9Sstevel@tonic-gate break; 45667c478bd9Sstevel@tonic-gate 45677c478bd9Sstevel@tonic-gate arg = skip_to (0, arg); 45687c478bd9Sstevel@tonic-gate } 45697c478bd9Sstevel@tonic-gate 45707c478bd9Sstevel@tonic-gate /* Initialize the serial unit. */ 45717c478bd9Sstevel@tonic-gate if (! serial_hw_init (port, speed, word_len, parity, stop_bit_len)) 45727c478bd9Sstevel@tonic-gate { 45737c478bd9Sstevel@tonic-gate errnum = ERR_BAD_ARGUMENT; 45747c478bd9Sstevel@tonic-gate return 1; 45757c478bd9Sstevel@tonic-gate } 45767c478bd9Sstevel@tonic-gate 45777c478bd9Sstevel@tonic-gate return 0; 45787c478bd9Sstevel@tonic-gate } 45797c478bd9Sstevel@tonic-gate 45807c478bd9Sstevel@tonic-gate static struct builtin builtin_serial = 45817c478bd9Sstevel@tonic-gate { 45827c478bd9Sstevel@tonic-gate "serial", 45837c478bd9Sstevel@tonic-gate serial_func, 45847c478bd9Sstevel@tonic-gate BUILTIN_MENU | BUILTIN_CMDLINE | BUILTIN_HELP_LIST, 45857c478bd9Sstevel@tonic-gate "serial [--unit=UNIT] [--port=PORT] [--speed=SPEED] [--word=WORD] [--parity=PARITY] [--stop=STOP] [--device=DEV]", 45867c478bd9Sstevel@tonic-gate "Initialize a serial device. UNIT is a digit that specifies which serial" 45877c478bd9Sstevel@tonic-gate " device is used (e.g. 0 == COM1). If you need to specify the port number," 45887c478bd9Sstevel@tonic-gate " set it by --port. SPEED is the DTE-DTE speed. WORD is the word length," 45897c478bd9Sstevel@tonic-gate " PARITY is the type of parity, which is one of `no', `odd' and `even'." 45907c478bd9Sstevel@tonic-gate " STOP is the length of stop bit(s). The option --device can be used only" 45917c478bd9Sstevel@tonic-gate " in the grub shell, which specifies the file name of a tty device. The" 45927c478bd9Sstevel@tonic-gate " default values are COM1, 9600, 8N1." 45937c478bd9Sstevel@tonic-gate }; 45947c478bd9Sstevel@tonic-gate #endif /* SUPPORT_SERIAL */ 45957c478bd9Sstevel@tonic-gate 45967c478bd9Sstevel@tonic-gate 45977c478bd9Sstevel@tonic-gate /* setkey */ 45987c478bd9Sstevel@tonic-gate struct keysym 45997c478bd9Sstevel@tonic-gate { 46007c478bd9Sstevel@tonic-gate char *unshifted_name; /* the name in unshifted state */ 46017c478bd9Sstevel@tonic-gate char *shifted_name; /* the name in shifted state */ 46027c478bd9Sstevel@tonic-gate unsigned char unshifted_ascii; /* the ascii code in unshifted state */ 46037c478bd9Sstevel@tonic-gate unsigned char shifted_ascii; /* the ascii code in shifted state */ 46047c478bd9Sstevel@tonic-gate unsigned char keycode; /* keyboard scancode */ 46057c478bd9Sstevel@tonic-gate }; 46067c478bd9Sstevel@tonic-gate 46077c478bd9Sstevel@tonic-gate /* The table for key symbols. If the "shifted" member of an entry is 46087c478bd9Sstevel@tonic-gate NULL, the entry does not have shifted state. */ 46097c478bd9Sstevel@tonic-gate static struct keysym keysym_table[] = 46107c478bd9Sstevel@tonic-gate { 46117c478bd9Sstevel@tonic-gate {"escape", 0, 0x1b, 0, 0x01}, 46127c478bd9Sstevel@tonic-gate {"1", "exclam", '1', '!', 0x02}, 46137c478bd9Sstevel@tonic-gate {"2", "at", '2', '@', 0x03}, 46147c478bd9Sstevel@tonic-gate {"3", "numbersign", '3', '#', 0x04}, 46157c478bd9Sstevel@tonic-gate {"4", "dollar", '4', '$', 0x05}, 46167c478bd9Sstevel@tonic-gate {"5", "percent", '5', '%', 0x06}, 46177c478bd9Sstevel@tonic-gate {"6", "caret", '6', '^', 0x07}, 46187c478bd9Sstevel@tonic-gate {"7", "ampersand", '7', '&', 0x08}, 46197c478bd9Sstevel@tonic-gate {"8", "asterisk", '8', '*', 0x09}, 46207c478bd9Sstevel@tonic-gate {"9", "parenleft", '9', '(', 0x0a}, 46217c478bd9Sstevel@tonic-gate {"0", "parenright", '0', ')', 0x0b}, 46227c478bd9Sstevel@tonic-gate {"minus", "underscore", '-', '_', 0x0c}, 46237c478bd9Sstevel@tonic-gate {"equal", "plus", '=', '+', 0x0d}, 46247c478bd9Sstevel@tonic-gate {"backspace", 0, '\b', 0, 0x0e}, 46257c478bd9Sstevel@tonic-gate {"tab", 0, '\t', 0, 0x0f}, 46267c478bd9Sstevel@tonic-gate {"q", "Q", 'q', 'Q', 0x10}, 46277c478bd9Sstevel@tonic-gate {"w", "W", 'w', 'W', 0x11}, 46287c478bd9Sstevel@tonic-gate {"e", "E", 'e', 'E', 0x12}, 46297c478bd9Sstevel@tonic-gate {"r", "R", 'r', 'R', 0x13}, 46307c478bd9Sstevel@tonic-gate {"t", "T", 't', 'T', 0x14}, 46317c478bd9Sstevel@tonic-gate {"y", "Y", 'y', 'Y', 0x15}, 46327c478bd9Sstevel@tonic-gate {"u", "U", 'u', 'U', 0x16}, 46337c478bd9Sstevel@tonic-gate {"i", "I", 'i', 'I', 0x17}, 46347c478bd9Sstevel@tonic-gate {"o", "O", 'o', 'O', 0x18}, 46357c478bd9Sstevel@tonic-gate {"p", "P", 'p', 'P', 0x19}, 46367c478bd9Sstevel@tonic-gate {"bracketleft", "braceleft", '[', '{', 0x1a}, 46377c478bd9Sstevel@tonic-gate {"bracketright", "braceright", ']', '}', 0x1b}, 46387c478bd9Sstevel@tonic-gate {"enter", 0, '\n', 0, 0x1c}, 46397c478bd9Sstevel@tonic-gate {"control", 0, 0, 0, 0x1d}, 46407c478bd9Sstevel@tonic-gate {"a", "A", 'a', 'A', 0x1e}, 46417c478bd9Sstevel@tonic-gate {"s", "S", 's', 'S', 0x1f}, 46427c478bd9Sstevel@tonic-gate {"d", "D", 'd', 'D', 0x20}, 46437c478bd9Sstevel@tonic-gate {"f", "F", 'f', 'F', 0x21}, 46447c478bd9Sstevel@tonic-gate {"g", "G", 'g', 'G', 0x22}, 46457c478bd9Sstevel@tonic-gate {"h", "H", 'h', 'H', 0x23}, 46467c478bd9Sstevel@tonic-gate {"j", "J", 'j', 'J', 0x24}, 46477c478bd9Sstevel@tonic-gate {"k", "K", 'k', 'K', 0x25}, 46487c478bd9Sstevel@tonic-gate {"l", "L", 'l', 'L', 0x26}, 46497c478bd9Sstevel@tonic-gate {"semicolon", "colon", ';', ':', 0x27}, 46507c478bd9Sstevel@tonic-gate {"quote", "doublequote", '\'', '"', 0x28}, 46517c478bd9Sstevel@tonic-gate {"backquote", "tilde", '`', '~', 0x29}, 46527c478bd9Sstevel@tonic-gate {"shift", 0, 0, 0, 0x2a}, 46537c478bd9Sstevel@tonic-gate {"backslash", "bar", '\\', '|', 0x2b}, 46547c478bd9Sstevel@tonic-gate {"z", "Z", 'z', 'Z', 0x2c}, 46557c478bd9Sstevel@tonic-gate {"x", "X", 'x', 'X', 0x2d}, 46567c478bd9Sstevel@tonic-gate {"c", "C", 'c', 'C', 0x2e}, 46577c478bd9Sstevel@tonic-gate {"v", "V", 'v', 'V', 0x2f}, 46587c478bd9Sstevel@tonic-gate {"b", "B", 'b', 'B', 0x30}, 46597c478bd9Sstevel@tonic-gate {"n", "N", 'n', 'N', 0x31}, 46607c478bd9Sstevel@tonic-gate {"m", "M", 'm', 'M', 0x32}, 46617c478bd9Sstevel@tonic-gate {"comma", "less", ',', '<', 0x33}, 46627c478bd9Sstevel@tonic-gate {"period", "greater", '.', '>', 0x34}, 46637c478bd9Sstevel@tonic-gate {"slash", "question", '/', '?', 0x35}, 46647c478bd9Sstevel@tonic-gate {"alt", 0, 0, 0, 0x38}, 46657c478bd9Sstevel@tonic-gate {"space", 0, ' ', 0, 0x39}, 46667c478bd9Sstevel@tonic-gate {"capslock", 0, 0, 0, 0x3a}, 46677c478bd9Sstevel@tonic-gate {"F1", 0, 0, 0, 0x3b}, 46687c478bd9Sstevel@tonic-gate {"F2", 0, 0, 0, 0x3c}, 46697c478bd9Sstevel@tonic-gate {"F3", 0, 0, 0, 0x3d}, 46707c478bd9Sstevel@tonic-gate {"F4", 0, 0, 0, 0x3e}, 46717c478bd9Sstevel@tonic-gate {"F5", 0, 0, 0, 0x3f}, 46727c478bd9Sstevel@tonic-gate {"F6", 0, 0, 0, 0x40}, 46737c478bd9Sstevel@tonic-gate {"F7", 0, 0, 0, 0x41}, 46747c478bd9Sstevel@tonic-gate {"F8", 0, 0, 0, 0x42}, 46757c478bd9Sstevel@tonic-gate {"F9", 0, 0, 0, 0x43}, 46767c478bd9Sstevel@tonic-gate {"F10", 0, 0, 0, 0x44}, 46777c478bd9Sstevel@tonic-gate /* Caution: do not add NumLock here! we cannot deal with it properly. */ 46787c478bd9Sstevel@tonic-gate {"delete", 0, 0x7f, 0, 0x53} 46797c478bd9Sstevel@tonic-gate }; 46807c478bd9Sstevel@tonic-gate 46817c478bd9Sstevel@tonic-gate static int 46827c478bd9Sstevel@tonic-gate setkey_func (char *arg, int flags) 46837c478bd9Sstevel@tonic-gate { 46847c478bd9Sstevel@tonic-gate char *to_key, *from_key; 46857c478bd9Sstevel@tonic-gate int to_code, from_code; 46867c478bd9Sstevel@tonic-gate int map_in_interrupt = 0; 46877c478bd9Sstevel@tonic-gate 46881b8adde7SWilliam Kucharski auto int find_key_code (char *key); 46891b8adde7SWilliam Kucharski auto int find_ascii_code (char *key); 46901b8adde7SWilliam Kucharski 46911b8adde7SWilliam Kucharski auto int find_key_code (char *key) 46927c478bd9Sstevel@tonic-gate { 46937c478bd9Sstevel@tonic-gate int i; 46947c478bd9Sstevel@tonic-gate 46957c478bd9Sstevel@tonic-gate for (i = 0; i < sizeof (keysym_table) / sizeof (keysym_table[0]); i++) 46967c478bd9Sstevel@tonic-gate { 46977c478bd9Sstevel@tonic-gate if (keysym_table[i].unshifted_name && 46987c478bd9Sstevel@tonic-gate grub_strcmp (key, keysym_table[i].unshifted_name) == 0) 46997c478bd9Sstevel@tonic-gate return keysym_table[i].keycode; 47007c478bd9Sstevel@tonic-gate else if (keysym_table[i].shifted_name && 47017c478bd9Sstevel@tonic-gate grub_strcmp (key, keysym_table[i].shifted_name) == 0) 47027c478bd9Sstevel@tonic-gate return keysym_table[i].keycode; 47037c478bd9Sstevel@tonic-gate } 47047c478bd9Sstevel@tonic-gate 47057c478bd9Sstevel@tonic-gate return 0; 47067c478bd9Sstevel@tonic-gate } 47077c478bd9Sstevel@tonic-gate 47081b8adde7SWilliam Kucharski auto int find_ascii_code (char *key) 47097c478bd9Sstevel@tonic-gate { 47107c478bd9Sstevel@tonic-gate int i; 47117c478bd9Sstevel@tonic-gate 47127c478bd9Sstevel@tonic-gate for (i = 0; i < sizeof (keysym_table) / sizeof (keysym_table[0]); i++) 47137c478bd9Sstevel@tonic-gate { 47147c478bd9Sstevel@tonic-gate if (keysym_table[i].unshifted_name && 47157c478bd9Sstevel@tonic-gate grub_strcmp (key, keysym_table[i].unshifted_name) == 0) 47167c478bd9Sstevel@tonic-gate return keysym_table[i].unshifted_ascii; 47177c478bd9Sstevel@tonic-gate else if (keysym_table[i].shifted_name && 47187c478bd9Sstevel@tonic-gate grub_strcmp (key, keysym_table[i].shifted_name) == 0) 47197c478bd9Sstevel@tonic-gate return keysym_table[i].shifted_ascii; 47207c478bd9Sstevel@tonic-gate } 47217c478bd9Sstevel@tonic-gate 47227c478bd9Sstevel@tonic-gate return 0; 47237c478bd9Sstevel@tonic-gate } 47247c478bd9Sstevel@tonic-gate 47257c478bd9Sstevel@tonic-gate to_key = arg; 47267c478bd9Sstevel@tonic-gate from_key = skip_to (0, to_key); 47277c478bd9Sstevel@tonic-gate 47287c478bd9Sstevel@tonic-gate if (! *to_key) 47297c478bd9Sstevel@tonic-gate { 47307c478bd9Sstevel@tonic-gate /* If the user specifies no argument, reset the key mappings. */ 47317c478bd9Sstevel@tonic-gate grub_memset (bios_key_map, 0, KEY_MAP_SIZE * sizeof (unsigned short)); 47327c478bd9Sstevel@tonic-gate grub_memset (ascii_key_map, 0, KEY_MAP_SIZE * sizeof (unsigned short)); 47337c478bd9Sstevel@tonic-gate 47347c478bd9Sstevel@tonic-gate return 0; 47357c478bd9Sstevel@tonic-gate } 47367c478bd9Sstevel@tonic-gate else if (! *from_key) 47377c478bd9Sstevel@tonic-gate { 47387c478bd9Sstevel@tonic-gate /* The user must specify two arguments or zero argument. */ 47397c478bd9Sstevel@tonic-gate errnum = ERR_BAD_ARGUMENT; 47407c478bd9Sstevel@tonic-gate return 1; 47417c478bd9Sstevel@tonic-gate } 47427c478bd9Sstevel@tonic-gate 47437c478bd9Sstevel@tonic-gate nul_terminate (to_key); 47447c478bd9Sstevel@tonic-gate nul_terminate (from_key); 47457c478bd9Sstevel@tonic-gate 47467c478bd9Sstevel@tonic-gate to_code = find_ascii_code (to_key); 47477c478bd9Sstevel@tonic-gate from_code = find_ascii_code (from_key); 47487c478bd9Sstevel@tonic-gate if (! to_code || ! from_code) 47497c478bd9Sstevel@tonic-gate { 47507c478bd9Sstevel@tonic-gate map_in_interrupt = 1; 47517c478bd9Sstevel@tonic-gate to_code = find_key_code (to_key); 47527c478bd9Sstevel@tonic-gate from_code = find_key_code (from_key); 47537c478bd9Sstevel@tonic-gate if (! to_code || ! from_code) 47547c478bd9Sstevel@tonic-gate { 47557c478bd9Sstevel@tonic-gate errnum = ERR_BAD_ARGUMENT; 47567c478bd9Sstevel@tonic-gate return 1; 47577c478bd9Sstevel@tonic-gate } 47587c478bd9Sstevel@tonic-gate } 47597c478bd9Sstevel@tonic-gate 47607c478bd9Sstevel@tonic-gate if (map_in_interrupt) 47617c478bd9Sstevel@tonic-gate { 47627c478bd9Sstevel@tonic-gate int i; 47637c478bd9Sstevel@tonic-gate 47647c478bd9Sstevel@tonic-gate /* Find an empty slot. */ 47657c478bd9Sstevel@tonic-gate for (i = 0; i < KEY_MAP_SIZE; i++) 47667c478bd9Sstevel@tonic-gate { 47677c478bd9Sstevel@tonic-gate if ((bios_key_map[i] & 0xff) == from_code) 47687c478bd9Sstevel@tonic-gate /* Perhaps the user wants to overwrite the map. */ 47697c478bd9Sstevel@tonic-gate break; 47707c478bd9Sstevel@tonic-gate 47717c478bd9Sstevel@tonic-gate if (! bios_key_map[i]) 47727c478bd9Sstevel@tonic-gate break; 47737c478bd9Sstevel@tonic-gate } 47747c478bd9Sstevel@tonic-gate 47757c478bd9Sstevel@tonic-gate if (i == KEY_MAP_SIZE) 47767c478bd9Sstevel@tonic-gate { 47777c478bd9Sstevel@tonic-gate errnum = ERR_WONT_FIT; 47787c478bd9Sstevel@tonic-gate return 1; 47797c478bd9Sstevel@tonic-gate } 47807c478bd9Sstevel@tonic-gate 47817c478bd9Sstevel@tonic-gate if (to_code == from_code) 47827c478bd9Sstevel@tonic-gate /* If TO is equal to FROM, delete the entry. */ 47837c478bd9Sstevel@tonic-gate grub_memmove ((char *) &bios_key_map[i], 47847c478bd9Sstevel@tonic-gate (char *) &bios_key_map[i + 1], 47857c478bd9Sstevel@tonic-gate sizeof (unsigned short) * (KEY_MAP_SIZE - i)); 47867c478bd9Sstevel@tonic-gate else 47877c478bd9Sstevel@tonic-gate bios_key_map[i] = (to_code << 8) | from_code; 47887c478bd9Sstevel@tonic-gate 47897c478bd9Sstevel@tonic-gate /* Ugly but should work. */ 47907c478bd9Sstevel@tonic-gate unset_int15_handler (); 47917c478bd9Sstevel@tonic-gate set_int15_handler (); 47927c478bd9Sstevel@tonic-gate } 47937c478bd9Sstevel@tonic-gate else 47947c478bd9Sstevel@tonic-gate { 47957c478bd9Sstevel@tonic-gate int i; 47967c478bd9Sstevel@tonic-gate 47977c478bd9Sstevel@tonic-gate /* Find an empty slot. */ 47987c478bd9Sstevel@tonic-gate for (i = 0; i < KEY_MAP_SIZE; i++) 47997c478bd9Sstevel@tonic-gate { 48007c478bd9Sstevel@tonic-gate if ((ascii_key_map[i] & 0xff) == from_code) 48017c478bd9Sstevel@tonic-gate /* Perhaps the user wants to overwrite the map. */ 48027c478bd9Sstevel@tonic-gate break; 48037c478bd9Sstevel@tonic-gate 48047c478bd9Sstevel@tonic-gate if (! ascii_key_map[i]) 48057c478bd9Sstevel@tonic-gate break; 48067c478bd9Sstevel@tonic-gate } 48077c478bd9Sstevel@tonic-gate 48087c478bd9Sstevel@tonic-gate if (i == KEY_MAP_SIZE) 48097c478bd9Sstevel@tonic-gate { 48107c478bd9Sstevel@tonic-gate errnum = ERR_WONT_FIT; 48117c478bd9Sstevel@tonic-gate return 1; 48127c478bd9Sstevel@tonic-gate } 48137c478bd9Sstevel@tonic-gate 48147c478bd9Sstevel@tonic-gate if (to_code == from_code) 48157c478bd9Sstevel@tonic-gate /* If TO is equal to FROM, delete the entry. */ 48167c478bd9Sstevel@tonic-gate grub_memmove ((char *) &ascii_key_map[i], 48177c478bd9Sstevel@tonic-gate (char *) &ascii_key_map[i + 1], 48187c478bd9Sstevel@tonic-gate sizeof (unsigned short) * (KEY_MAP_SIZE - i)); 48197c478bd9Sstevel@tonic-gate else 48207c478bd9Sstevel@tonic-gate ascii_key_map[i] = (to_code << 8) | from_code; 48217c478bd9Sstevel@tonic-gate } 48227c478bd9Sstevel@tonic-gate 48237c478bd9Sstevel@tonic-gate return 0; 48247c478bd9Sstevel@tonic-gate } 48257c478bd9Sstevel@tonic-gate 48267c478bd9Sstevel@tonic-gate static struct builtin builtin_setkey = 48277c478bd9Sstevel@tonic-gate { 48287c478bd9Sstevel@tonic-gate "setkey", 48297c478bd9Sstevel@tonic-gate setkey_func, 48307c478bd9Sstevel@tonic-gate BUILTIN_CMDLINE | BUILTIN_MENU | BUILTIN_HELP_LIST, 48317c478bd9Sstevel@tonic-gate "setkey [TO_KEY FROM_KEY]", 48327c478bd9Sstevel@tonic-gate "Change the keyboard map. The key FROM_KEY is mapped to the key TO_KEY." 48337c478bd9Sstevel@tonic-gate " A key must be an alphabet, a digit, or one of these: escape, exclam," 48347c478bd9Sstevel@tonic-gate " at, numbersign, dollar, percent, caret, ampersand, asterisk, parenleft," 48357c478bd9Sstevel@tonic-gate " parenright, minus, underscore, equal, plus, backspace, tab, bracketleft," 48367c478bd9Sstevel@tonic-gate " braceleft, bracketright, braceright, enter, control, semicolon, colon," 48377c478bd9Sstevel@tonic-gate " quote, doublequote, backquote, tilde, shift, backslash, bar, comma," 48387c478bd9Sstevel@tonic-gate " less, period, greater, slash, question, alt, space, capslock, FX (X" 48397c478bd9Sstevel@tonic-gate " is a digit), and delete. If no argument is specified, reset key" 48407c478bd9Sstevel@tonic-gate " mappings." 48417c478bd9Sstevel@tonic-gate }; 48427c478bd9Sstevel@tonic-gate 48437c478bd9Sstevel@tonic-gate 48447c478bd9Sstevel@tonic-gate /* setup */ 48457c478bd9Sstevel@tonic-gate static int 48467c478bd9Sstevel@tonic-gate setup_func (char *arg, int flags) 48477c478bd9Sstevel@tonic-gate { 48487c478bd9Sstevel@tonic-gate /* Point to the string of the installed drive/partition. */ 48497c478bd9Sstevel@tonic-gate char *install_ptr; 48507c478bd9Sstevel@tonic-gate /* Point to the string of the drive/parition where the GRUB images 48517c478bd9Sstevel@tonic-gate reside. */ 48527c478bd9Sstevel@tonic-gate char *image_ptr; 48537c478bd9Sstevel@tonic-gate unsigned long installed_drive, installed_partition; 48547c478bd9Sstevel@tonic-gate unsigned long image_drive, image_partition; 48557c478bd9Sstevel@tonic-gate unsigned long tmp_drive, tmp_partition; 48567c478bd9Sstevel@tonic-gate char stage1[64]; 48577c478bd9Sstevel@tonic-gate char stage2[64]; 48587c478bd9Sstevel@tonic-gate char config_filename[64]; 48597c478bd9Sstevel@tonic-gate char real_config_filename[64]; 48607c478bd9Sstevel@tonic-gate char cmd_arg[256]; 48617c478bd9Sstevel@tonic-gate char device[16]; 48627c478bd9Sstevel@tonic-gate char *buffer = (char *) RAW_ADDR (0x100000); 48637c478bd9Sstevel@tonic-gate int is_force_lba = 0; 48647c478bd9Sstevel@tonic-gate char *stage2_arg = 0; 48657c478bd9Sstevel@tonic-gate char *prefix = 0; 48667c478bd9Sstevel@tonic-gate 48677c478bd9Sstevel@tonic-gate auto int check_file (char *file); 48687c478bd9Sstevel@tonic-gate auto void sprint_device (int drive, int partition); 48697c478bd9Sstevel@tonic-gate auto int embed_stage1_5 (char * stage1_5, int drive, int partition); 48707c478bd9Sstevel@tonic-gate 48717c478bd9Sstevel@tonic-gate /* Check if the file FILE exists like Autoconf. */ 48727c478bd9Sstevel@tonic-gate int check_file (char *file) 48737c478bd9Sstevel@tonic-gate { 48747c478bd9Sstevel@tonic-gate int ret; 48757c478bd9Sstevel@tonic-gate 48767c478bd9Sstevel@tonic-gate grub_printf (" Checking if \"%s\" exists... ", file); 48777c478bd9Sstevel@tonic-gate ret = grub_open (file); 48787c478bd9Sstevel@tonic-gate if (ret) 48797c478bd9Sstevel@tonic-gate { 48807c478bd9Sstevel@tonic-gate grub_close (); 48817c478bd9Sstevel@tonic-gate grub_printf ("yes\n"); 48827c478bd9Sstevel@tonic-gate } 48837c478bd9Sstevel@tonic-gate else 48847c478bd9Sstevel@tonic-gate grub_printf ("no\n"); 48857c478bd9Sstevel@tonic-gate 48867c478bd9Sstevel@tonic-gate return ret; 48877c478bd9Sstevel@tonic-gate } 48887c478bd9Sstevel@tonic-gate 48897c478bd9Sstevel@tonic-gate /* Construct a device name in DEVICE. */ 48907c478bd9Sstevel@tonic-gate void sprint_device (int drive, int partition) 48917c478bd9Sstevel@tonic-gate { 48927c478bd9Sstevel@tonic-gate grub_sprintf (device, "(%cd%d", 48937c478bd9Sstevel@tonic-gate (drive & 0x80) ? 'h' : 'f', 48947c478bd9Sstevel@tonic-gate drive & ~0x80); 48957c478bd9Sstevel@tonic-gate if ((partition & 0xFF0000) != 0xFF0000) 48967c478bd9Sstevel@tonic-gate { 48977c478bd9Sstevel@tonic-gate char tmp[16]; 48987c478bd9Sstevel@tonic-gate grub_sprintf (tmp, ",%d", (partition >> 16) & 0xFF); 48997c478bd9Sstevel@tonic-gate grub_strncat (device, tmp, 256); 49007c478bd9Sstevel@tonic-gate } 49017c478bd9Sstevel@tonic-gate if ((partition & 0x00FF00) != 0x00FF00) 49027c478bd9Sstevel@tonic-gate { 49037c478bd9Sstevel@tonic-gate char tmp[16]; 49047c478bd9Sstevel@tonic-gate grub_sprintf (tmp, ",%c", 'a' + ((partition >> 8) & 0xFF)); 49057c478bd9Sstevel@tonic-gate grub_strncat (device, tmp, 256); 49067c478bd9Sstevel@tonic-gate } 49077c478bd9Sstevel@tonic-gate grub_strncat (device, ")", 256); 49087c478bd9Sstevel@tonic-gate } 49097c478bd9Sstevel@tonic-gate 49107c478bd9Sstevel@tonic-gate int embed_stage1_5 (char *stage1_5, int drive, int partition) 49117c478bd9Sstevel@tonic-gate { 49127c478bd9Sstevel@tonic-gate /* We install GRUB into the MBR, so try to embed the 49137c478bd9Sstevel@tonic-gate Stage 1.5 in the sectors right after the MBR. */ 49147c478bd9Sstevel@tonic-gate sprint_device (drive, partition); 49157c478bd9Sstevel@tonic-gate grub_sprintf (cmd_arg, "%s %s", stage1_5, device); 49167c478bd9Sstevel@tonic-gate 49177c478bd9Sstevel@tonic-gate /* Notify what will be run. */ 49187c478bd9Sstevel@tonic-gate grub_printf (" Running \"embed %s\"... ", cmd_arg); 49197c478bd9Sstevel@tonic-gate 49207c478bd9Sstevel@tonic-gate embed_func (cmd_arg, flags); 49217c478bd9Sstevel@tonic-gate if (! errnum) 49227c478bd9Sstevel@tonic-gate { 49237c478bd9Sstevel@tonic-gate /* Construct the blocklist representation. */ 49247c478bd9Sstevel@tonic-gate grub_sprintf (buffer, "%s%s", device, embed_info); 49257c478bd9Sstevel@tonic-gate grub_printf ("succeeded\n"); 49267c478bd9Sstevel@tonic-gate return 1; 49277c478bd9Sstevel@tonic-gate } 49287c478bd9Sstevel@tonic-gate else 49297c478bd9Sstevel@tonic-gate { 49307c478bd9Sstevel@tonic-gate grub_printf ("failed (this is not fatal)\n"); 49317c478bd9Sstevel@tonic-gate return 0; 49327c478bd9Sstevel@tonic-gate } 49337c478bd9Sstevel@tonic-gate } 49347c478bd9Sstevel@tonic-gate 49357c478bd9Sstevel@tonic-gate struct stage1_5_map { 49367c478bd9Sstevel@tonic-gate char *fsys; 49377c478bd9Sstevel@tonic-gate char *name; 49387c478bd9Sstevel@tonic-gate }; 49397c478bd9Sstevel@tonic-gate struct stage1_5_map stage1_5_map[] = 49407c478bd9Sstevel@tonic-gate { 49417c478bd9Sstevel@tonic-gate {"ext2fs", "/e2fs_stage1_5"}, 49427c478bd9Sstevel@tonic-gate {"fat", "/fat_stage1_5"}, 49437c478bd9Sstevel@tonic-gate {"ufs2", "/ufs2_stage1_5"}, 49447c478bd9Sstevel@tonic-gate {"ffs", "/ffs_stage1_5"}, 49457c478bd9Sstevel@tonic-gate {"iso9660", "/iso9660_stage1_5"}, 49467c478bd9Sstevel@tonic-gate {"jfs", "/jfs_stage1_5"}, 49477c478bd9Sstevel@tonic-gate {"minix", "/minix_stage1_5"}, 49487c478bd9Sstevel@tonic-gate {"reiserfs", "/reiserfs_stage1_5"}, 49497c478bd9Sstevel@tonic-gate {"vstafs", "/vstafs_stage1_5"}, 49507c478bd9Sstevel@tonic-gate {"xfs", "/xfs_stage1_5"}, 49517c478bd9Sstevel@tonic-gate {"ufs", "/ufs_stage1_5"} 49527c478bd9Sstevel@tonic-gate }; 49537c478bd9Sstevel@tonic-gate 49547c478bd9Sstevel@tonic-gate tmp_drive = saved_drive; 49557c478bd9Sstevel@tonic-gate tmp_partition = saved_partition; 49567c478bd9Sstevel@tonic-gate 49577c478bd9Sstevel@tonic-gate /* Check if the user specifies --force-lba. */ 49587c478bd9Sstevel@tonic-gate while (1) 49597c478bd9Sstevel@tonic-gate { 49607c478bd9Sstevel@tonic-gate if (grub_memcmp ("--force-lba", arg, sizeof ("--force-lba") - 1) == 0) 49617c478bd9Sstevel@tonic-gate { 49627c478bd9Sstevel@tonic-gate is_force_lba = 1; 49637c478bd9Sstevel@tonic-gate arg = skip_to (0, arg); 49647c478bd9Sstevel@tonic-gate } 49657c478bd9Sstevel@tonic-gate else if (grub_memcmp ("--prefix=", arg, sizeof ("--prefix=") - 1) == 0) 49667c478bd9Sstevel@tonic-gate { 49677c478bd9Sstevel@tonic-gate prefix = arg + sizeof ("--prefix=") - 1; 49687c478bd9Sstevel@tonic-gate arg = skip_to (0, arg); 49697c478bd9Sstevel@tonic-gate nul_terminate (prefix); 49707c478bd9Sstevel@tonic-gate } 49717c478bd9Sstevel@tonic-gate #ifdef GRUB_UTIL 49727c478bd9Sstevel@tonic-gate else if (grub_memcmp ("--stage2=", arg, sizeof ("--stage2=") - 1) == 0) 49737c478bd9Sstevel@tonic-gate { 49747c478bd9Sstevel@tonic-gate stage2_arg = arg; 49757c478bd9Sstevel@tonic-gate arg = skip_to (0, arg); 49767c478bd9Sstevel@tonic-gate nul_terminate (stage2_arg); 49777c478bd9Sstevel@tonic-gate } 49787c478bd9Sstevel@tonic-gate #endif /* GRUB_UTIL */ 49797c478bd9Sstevel@tonic-gate else 49807c478bd9Sstevel@tonic-gate break; 49817c478bd9Sstevel@tonic-gate } 49827c478bd9Sstevel@tonic-gate 49837c478bd9Sstevel@tonic-gate install_ptr = arg; 49847c478bd9Sstevel@tonic-gate image_ptr = skip_to (0, install_ptr); 49857c478bd9Sstevel@tonic-gate 49867c478bd9Sstevel@tonic-gate /* Make sure that INSTALL_PTR is valid. */ 49877c478bd9Sstevel@tonic-gate set_device (install_ptr); 49887c478bd9Sstevel@tonic-gate if (errnum) 49897c478bd9Sstevel@tonic-gate return 1; 49907c478bd9Sstevel@tonic-gate 49917c478bd9Sstevel@tonic-gate installed_drive = current_drive; 49927c478bd9Sstevel@tonic-gate installed_partition = current_partition; 49937c478bd9Sstevel@tonic-gate 49947c478bd9Sstevel@tonic-gate /* Mount the drive pointed by IMAGE_PTR. */ 49957c478bd9Sstevel@tonic-gate if (*image_ptr) 49967c478bd9Sstevel@tonic-gate { 49977c478bd9Sstevel@tonic-gate /* If the drive/partition where the images reside is specified, 49987c478bd9Sstevel@tonic-gate get the drive and the partition. */ 49997c478bd9Sstevel@tonic-gate set_device (image_ptr); 50007c478bd9Sstevel@tonic-gate if (errnum) 50017c478bd9Sstevel@tonic-gate return 1; 50027c478bd9Sstevel@tonic-gate } 50037c478bd9Sstevel@tonic-gate else 50047c478bd9Sstevel@tonic-gate { 50057c478bd9Sstevel@tonic-gate /* If omitted, use SAVED_PARTITION and SAVED_DRIVE. */ 50067c478bd9Sstevel@tonic-gate current_drive = saved_drive; 50077c478bd9Sstevel@tonic-gate current_partition = saved_partition; 50087c478bd9Sstevel@tonic-gate } 50097c478bd9Sstevel@tonic-gate 50107c478bd9Sstevel@tonic-gate image_drive = saved_drive = current_drive; 50117c478bd9Sstevel@tonic-gate image_partition = saved_partition = current_partition; 50127c478bd9Sstevel@tonic-gate 50137c478bd9Sstevel@tonic-gate /* Open it. */ 50147c478bd9Sstevel@tonic-gate if (! open_device ()) 50157c478bd9Sstevel@tonic-gate goto fail; 50167c478bd9Sstevel@tonic-gate 50177c478bd9Sstevel@tonic-gate /* Check if stage1 exists. If the user doesn't specify the option 50187c478bd9Sstevel@tonic-gate `--prefix', attempt /boot/grub and /grub. */ 50197c478bd9Sstevel@tonic-gate /* NOTE: It is dangerous to run this command without `--prefix' in the 50207c478bd9Sstevel@tonic-gate grub shell, since that affects `--stage2'. */ 50217c478bd9Sstevel@tonic-gate if (! prefix) 50227c478bd9Sstevel@tonic-gate { 50237c478bd9Sstevel@tonic-gate prefix = "/boot/grub"; 50247c478bd9Sstevel@tonic-gate grub_sprintf (stage1, "%s%s", prefix, "/stage1"); 50257c478bd9Sstevel@tonic-gate if (! check_file (stage1)) 50267c478bd9Sstevel@tonic-gate { 50277c478bd9Sstevel@tonic-gate errnum = ERR_NONE; 50287c478bd9Sstevel@tonic-gate prefix = "/grub"; 50297c478bd9Sstevel@tonic-gate grub_sprintf (stage1, "%s%s", prefix, "/stage1"); 50307c478bd9Sstevel@tonic-gate if (! check_file (stage1)) 50317c478bd9Sstevel@tonic-gate goto fail; 50327c478bd9Sstevel@tonic-gate } 50337c478bd9Sstevel@tonic-gate } 50347c478bd9Sstevel@tonic-gate else 50357c478bd9Sstevel@tonic-gate { 50367c478bd9Sstevel@tonic-gate grub_sprintf (stage1, "%s%s", prefix, "/stage1"); 50377c478bd9Sstevel@tonic-gate if (! check_file (stage1)) 50387c478bd9Sstevel@tonic-gate goto fail; 50397c478bd9Sstevel@tonic-gate } 50407c478bd9Sstevel@tonic-gate 50417c478bd9Sstevel@tonic-gate /* The prefix was determined. */ 50427c478bd9Sstevel@tonic-gate grub_sprintf (stage2, "%s%s", prefix, "/stage2"); 50437c478bd9Sstevel@tonic-gate grub_sprintf (config_filename, "%s%s", prefix, "/menu.lst"); 50447c478bd9Sstevel@tonic-gate *real_config_filename = 0; 50457c478bd9Sstevel@tonic-gate 50467c478bd9Sstevel@tonic-gate /* Check if stage2 exists. */ 50477c478bd9Sstevel@tonic-gate if (! check_file (stage2)) 50487c478bd9Sstevel@tonic-gate goto fail; 50497c478bd9Sstevel@tonic-gate 50507c478bd9Sstevel@tonic-gate { 50517c478bd9Sstevel@tonic-gate char *fsys = fsys_table[fsys_type].name; 50527c478bd9Sstevel@tonic-gate int i; 50537c478bd9Sstevel@tonic-gate int size = sizeof (stage1_5_map) / sizeof (stage1_5_map[0]); 50547c478bd9Sstevel@tonic-gate 50557c478bd9Sstevel@tonic-gate /* Iterate finding the same filesystem name as FSYS. */ 50567c478bd9Sstevel@tonic-gate for (i = 0; i < size; i++) 50577c478bd9Sstevel@tonic-gate if (grub_strcmp (fsys, stage1_5_map[i].fsys) == 0) 50587c478bd9Sstevel@tonic-gate { 50597c478bd9Sstevel@tonic-gate /* OK, check if the Stage 1.5 exists. */ 50607c478bd9Sstevel@tonic-gate char stage1_5[64]; 50617c478bd9Sstevel@tonic-gate 50627c478bd9Sstevel@tonic-gate grub_sprintf (stage1_5, "%s%s", prefix, stage1_5_map[i].name); 50637c478bd9Sstevel@tonic-gate if (check_file (stage1_5)) 50647c478bd9Sstevel@tonic-gate { 50657c478bd9Sstevel@tonic-gate if (embed_stage1_5 (stage1_5, 50667c478bd9Sstevel@tonic-gate installed_drive, installed_partition) 50677c478bd9Sstevel@tonic-gate || embed_stage1_5 (stage1_5, 50687c478bd9Sstevel@tonic-gate image_drive, image_partition)) 50697c478bd9Sstevel@tonic-gate { 50707c478bd9Sstevel@tonic-gate grub_strcpy (real_config_filename, config_filename); 50717c478bd9Sstevel@tonic-gate sprint_device (image_drive, image_partition); 50727c478bd9Sstevel@tonic-gate grub_sprintf (config_filename, "%s%s", device, stage2); 50737c478bd9Sstevel@tonic-gate grub_strcpy (stage2, buffer); 50747c478bd9Sstevel@tonic-gate } 50757c478bd9Sstevel@tonic-gate } 50767c478bd9Sstevel@tonic-gate errnum = 0; 50777c478bd9Sstevel@tonic-gate break; 50787c478bd9Sstevel@tonic-gate } 50797c478bd9Sstevel@tonic-gate } 50807c478bd9Sstevel@tonic-gate 50817c478bd9Sstevel@tonic-gate /* Construct a string that is used by the command "install" as its 50827c478bd9Sstevel@tonic-gate arguments. */ 50837c478bd9Sstevel@tonic-gate sprint_device (installed_drive, installed_partition); 50847c478bd9Sstevel@tonic-gate 50857c478bd9Sstevel@tonic-gate #if 1 50867c478bd9Sstevel@tonic-gate /* Don't embed a drive number unnecessarily. */ 50877c478bd9Sstevel@tonic-gate grub_sprintf (cmd_arg, "%s%s%s%s %s%s %s p %s %s", 50887c478bd9Sstevel@tonic-gate is_force_lba? "--force-lba " : "", 50897c478bd9Sstevel@tonic-gate stage2_arg? stage2_arg : "", 50907c478bd9Sstevel@tonic-gate stage2_arg? " " : "", 50917c478bd9Sstevel@tonic-gate stage1, 50927c478bd9Sstevel@tonic-gate (installed_drive != image_drive) ? "d " : "", 50937c478bd9Sstevel@tonic-gate device, 50947c478bd9Sstevel@tonic-gate stage2, 50957c478bd9Sstevel@tonic-gate config_filename, 50967c478bd9Sstevel@tonic-gate real_config_filename); 50977c478bd9Sstevel@tonic-gate #else /* NOT USED */ 50987c478bd9Sstevel@tonic-gate /* This code was used, because we belived some BIOSes had a problem 50997c478bd9Sstevel@tonic-gate that they didn't pass a booting drive correctly. It turned out, 51007c478bd9Sstevel@tonic-gate however, stage1 could trash a booting drive when checking LBA support, 51017c478bd9Sstevel@tonic-gate because some BIOSes modified the register %dx in INT 13H, AH=48H. 51027c478bd9Sstevel@tonic-gate So it becamed unclear whether GRUB should use a pre-defined booting 51037c478bd9Sstevel@tonic-gate drive or not. If the problem still exists, it would be necessary to 51047c478bd9Sstevel@tonic-gate switch back to this code. */ 51057c478bd9Sstevel@tonic-gate grub_sprintf (cmd_arg, "%s%s%s%s d %s %s p %s %s", 51067c478bd9Sstevel@tonic-gate is_force_lba? "--force-lba " : "", 51077c478bd9Sstevel@tonic-gate stage2_arg? stage2_arg : "", 51087c478bd9Sstevel@tonic-gate stage2_arg? " " : "", 51097c478bd9Sstevel@tonic-gate stage1, 51107c478bd9Sstevel@tonic-gate device, 51117c478bd9Sstevel@tonic-gate stage2, 51127c478bd9Sstevel@tonic-gate config_filename, 51137c478bd9Sstevel@tonic-gate real_config_filename); 51147c478bd9Sstevel@tonic-gate #endif /* NOT USED */ 51157c478bd9Sstevel@tonic-gate 51167c478bd9Sstevel@tonic-gate /* Notify what will be run. */ 51177c478bd9Sstevel@tonic-gate grub_printf (" Running \"install %s\"... ", cmd_arg); 51187c478bd9Sstevel@tonic-gate 51197c478bd9Sstevel@tonic-gate /* Make sure that SAVED_DRIVE and SAVED_PARTITION are identical 51207c478bd9Sstevel@tonic-gate with IMAGE_DRIVE and IMAGE_PARTITION, respectively. */ 51217c478bd9Sstevel@tonic-gate saved_drive = image_drive; 51227c478bd9Sstevel@tonic-gate saved_partition = image_partition; 51237c478bd9Sstevel@tonic-gate 51247c478bd9Sstevel@tonic-gate /* Run the command. */ 51257c478bd9Sstevel@tonic-gate if (! install_func (cmd_arg, flags)) 51267c478bd9Sstevel@tonic-gate grub_printf ("succeeded\nDone.\n"); 51277c478bd9Sstevel@tonic-gate else 51287c478bd9Sstevel@tonic-gate grub_printf ("failed\n"); 51297c478bd9Sstevel@tonic-gate 51307c478bd9Sstevel@tonic-gate fail: 51317c478bd9Sstevel@tonic-gate saved_drive = tmp_drive; 51327c478bd9Sstevel@tonic-gate saved_partition = tmp_partition; 51337c478bd9Sstevel@tonic-gate return errnum; 51347c478bd9Sstevel@tonic-gate } 51357c478bd9Sstevel@tonic-gate 51367c478bd9Sstevel@tonic-gate static struct builtin builtin_setup = 51377c478bd9Sstevel@tonic-gate { 51387c478bd9Sstevel@tonic-gate "setup", 51397c478bd9Sstevel@tonic-gate setup_func, 51407c478bd9Sstevel@tonic-gate BUILTIN_CMDLINE | BUILTIN_HELP_LIST, 51417c478bd9Sstevel@tonic-gate "setup [--prefix=DIR] [--stage2=STAGE2_FILE] [--force-lba] INSTALL_DEVICE [IMAGE_DEVICE]", 51427c478bd9Sstevel@tonic-gate "Set up the installation of GRUB automatically. This command uses" 51437c478bd9Sstevel@tonic-gate " the more flexible command \"install\" in the backend and installs" 51447c478bd9Sstevel@tonic-gate " GRUB into the device INSTALL_DEVICE. If IMAGE_DEVICE is specified," 51457c478bd9Sstevel@tonic-gate " then find the GRUB images in the device IMAGE_DEVICE, otherwise" 51467c478bd9Sstevel@tonic-gate " use the current \"root device\", which can be set by the command" 51477c478bd9Sstevel@tonic-gate " \"root\". If you know that your BIOS should support LBA but GRUB" 51487c478bd9Sstevel@tonic-gate " doesn't work in LBA mode, specify the option `--force-lba'." 51497c478bd9Sstevel@tonic-gate " If you install GRUB under the grub shell and you cannot unmount the" 51507c478bd9Sstevel@tonic-gate " partition where GRUB images reside, specify the option `--stage2'" 51517c478bd9Sstevel@tonic-gate " to tell GRUB the file name under your OS." 51527c478bd9Sstevel@tonic-gate }; 51537c478bd9Sstevel@tonic-gate 51547c478bd9Sstevel@tonic-gate 51557c478bd9Sstevel@tonic-gate #if defined(SUPPORT_SERIAL) || defined(SUPPORT_HERCULES) || defined(SUPPORT_GRAPHICS) 51567c478bd9Sstevel@tonic-gate /* terminal */ 51577c478bd9Sstevel@tonic-gate static int 51587c478bd9Sstevel@tonic-gate terminal_func (char *arg, int flags) 51597c478bd9Sstevel@tonic-gate { 51607c478bd9Sstevel@tonic-gate /* The index of the default terminal in TERM_TABLE. */ 51617c478bd9Sstevel@tonic-gate int default_term = -1; 51627c478bd9Sstevel@tonic-gate struct term_entry *prev_term = current_term; 51637c478bd9Sstevel@tonic-gate int to = -1; 51647c478bd9Sstevel@tonic-gate int lines = 0; 51657c478bd9Sstevel@tonic-gate int no_message = 0; 51667c478bd9Sstevel@tonic-gate unsigned long term_flags = 0; 51677c478bd9Sstevel@tonic-gate /* XXX: Assume less than 32 terminals. */ 51687c478bd9Sstevel@tonic-gate unsigned long term_bitmap = 0; 51697c478bd9Sstevel@tonic-gate 51707c478bd9Sstevel@tonic-gate /* Get GNU-style long options. */ 51717c478bd9Sstevel@tonic-gate while (1) 51727c478bd9Sstevel@tonic-gate { 51737c478bd9Sstevel@tonic-gate if (grub_memcmp (arg, "--dumb", sizeof ("--dumb") - 1) == 0) 51747c478bd9Sstevel@tonic-gate term_flags |= TERM_DUMB; 51757c478bd9Sstevel@tonic-gate else if (grub_memcmp (arg, "--no-echo", sizeof ("--no-echo") - 1) == 0) 51767c478bd9Sstevel@tonic-gate /* ``--no-echo'' implies ``--no-edit''. */ 51777c478bd9Sstevel@tonic-gate term_flags |= (TERM_NO_ECHO | TERM_NO_EDIT); 51787c478bd9Sstevel@tonic-gate else if (grub_memcmp (arg, "--no-edit", sizeof ("--no-edit") - 1) == 0) 51797c478bd9Sstevel@tonic-gate term_flags |= TERM_NO_EDIT; 51807c478bd9Sstevel@tonic-gate else if (grub_memcmp (arg, "--timeout=", sizeof ("--timeout=") - 1) == 0) 51817c478bd9Sstevel@tonic-gate { 51827c478bd9Sstevel@tonic-gate char *val = arg + sizeof ("--timeout=") - 1; 51837c478bd9Sstevel@tonic-gate 51847c478bd9Sstevel@tonic-gate if (! safe_parse_maxint (&val, &to)) 51857c478bd9Sstevel@tonic-gate return 1; 51867c478bd9Sstevel@tonic-gate } 51877c478bd9Sstevel@tonic-gate else if (grub_memcmp (arg, "--lines=", sizeof ("--lines=") - 1) == 0) 51887c478bd9Sstevel@tonic-gate { 51897c478bd9Sstevel@tonic-gate char *val = arg + sizeof ("--lines=") - 1; 51907c478bd9Sstevel@tonic-gate 51917c478bd9Sstevel@tonic-gate if (! safe_parse_maxint (&val, &lines)) 51927c478bd9Sstevel@tonic-gate return 1; 51937c478bd9Sstevel@tonic-gate 51947c478bd9Sstevel@tonic-gate /* Probably less than four is meaningless.... */ 51957c478bd9Sstevel@tonic-gate if (lines < 4) 51967c478bd9Sstevel@tonic-gate { 51977c478bd9Sstevel@tonic-gate errnum = ERR_BAD_ARGUMENT; 51987c478bd9Sstevel@tonic-gate return 1; 51997c478bd9Sstevel@tonic-gate } 52007c478bd9Sstevel@tonic-gate } 52017c478bd9Sstevel@tonic-gate else if (grub_memcmp (arg, "--silent", sizeof ("--silent") - 1) == 0) 52027c478bd9Sstevel@tonic-gate no_message = 1; 52037c478bd9Sstevel@tonic-gate else 52047c478bd9Sstevel@tonic-gate break; 52057c478bd9Sstevel@tonic-gate 52067c478bd9Sstevel@tonic-gate arg = skip_to (0, arg); 52077c478bd9Sstevel@tonic-gate } 52087c478bd9Sstevel@tonic-gate 52097c478bd9Sstevel@tonic-gate /* If no argument is specified, show current setting. */ 52107c478bd9Sstevel@tonic-gate if (! *arg) 52117c478bd9Sstevel@tonic-gate { 52127c478bd9Sstevel@tonic-gate grub_printf ("%s%s%s%s\n", 52137c478bd9Sstevel@tonic-gate current_term->name, 52147c478bd9Sstevel@tonic-gate current_term->flags & TERM_DUMB ? " (dumb)" : "", 52157c478bd9Sstevel@tonic-gate current_term->flags & TERM_NO_EDIT ? " (no edit)" : "", 52167c478bd9Sstevel@tonic-gate current_term->flags & TERM_NO_ECHO ? " (no echo)" : ""); 52177c478bd9Sstevel@tonic-gate return 0; 52187c478bd9Sstevel@tonic-gate } 52197c478bd9Sstevel@tonic-gate 52207c478bd9Sstevel@tonic-gate while (*arg) 52217c478bd9Sstevel@tonic-gate { 52227c478bd9Sstevel@tonic-gate int i; 52237c478bd9Sstevel@tonic-gate char *next = skip_to (0, arg); 52247c478bd9Sstevel@tonic-gate 52257c478bd9Sstevel@tonic-gate nul_terminate (arg); 52267c478bd9Sstevel@tonic-gate 52277c478bd9Sstevel@tonic-gate for (i = 0; term_table[i].name; i++) 52287c478bd9Sstevel@tonic-gate { 52297c478bd9Sstevel@tonic-gate if (grub_strcmp (arg, term_table[i].name) == 0) 52307c478bd9Sstevel@tonic-gate { 52317c478bd9Sstevel@tonic-gate if (term_table[i].flags & TERM_NEED_INIT) 52327c478bd9Sstevel@tonic-gate { 52337c478bd9Sstevel@tonic-gate errnum = ERR_DEV_NEED_INIT; 52347c478bd9Sstevel@tonic-gate return 1; 52357c478bd9Sstevel@tonic-gate } 52367c478bd9Sstevel@tonic-gate 52377c478bd9Sstevel@tonic-gate if (default_term < 0) 52387c478bd9Sstevel@tonic-gate default_term = i; 52397c478bd9Sstevel@tonic-gate 52407c478bd9Sstevel@tonic-gate term_bitmap |= (1 << i); 52417c478bd9Sstevel@tonic-gate break; 52427c478bd9Sstevel@tonic-gate } 52437c478bd9Sstevel@tonic-gate } 52447c478bd9Sstevel@tonic-gate 52457c478bd9Sstevel@tonic-gate if (! term_table[i].name) 52467c478bd9Sstevel@tonic-gate { 52477c478bd9Sstevel@tonic-gate errnum = ERR_BAD_ARGUMENT; 52487c478bd9Sstevel@tonic-gate return 1; 52497c478bd9Sstevel@tonic-gate } 52507c478bd9Sstevel@tonic-gate 52517c478bd9Sstevel@tonic-gate arg = next; 52527c478bd9Sstevel@tonic-gate } 52537c478bd9Sstevel@tonic-gate 52547c478bd9Sstevel@tonic-gate /* If multiple terminals are specified, wait until the user pushes any 52557c478bd9Sstevel@tonic-gate key on one of the terminals. */ 52567c478bd9Sstevel@tonic-gate if (term_bitmap & ~(1 << default_term)) 52577c478bd9Sstevel@tonic-gate { 52587c478bd9Sstevel@tonic-gate int time1, time2 = -1; 52597c478bd9Sstevel@tonic-gate 52607c478bd9Sstevel@tonic-gate /* XXX: Disable the pager. */ 52617c478bd9Sstevel@tonic-gate count_lines = -1; 52627c478bd9Sstevel@tonic-gate 52637c478bd9Sstevel@tonic-gate /* Get current time. */ 52647c478bd9Sstevel@tonic-gate while ((time1 = getrtsecs ()) == 0xFF) 52657c478bd9Sstevel@tonic-gate ; 52667c478bd9Sstevel@tonic-gate 52677c478bd9Sstevel@tonic-gate /* Wait for a key input. */ 52687c478bd9Sstevel@tonic-gate while (to) 52697c478bd9Sstevel@tonic-gate { 52707c478bd9Sstevel@tonic-gate int i; 52717c478bd9Sstevel@tonic-gate 52727c478bd9Sstevel@tonic-gate for (i = 0; term_table[i].name; i++) 52737c478bd9Sstevel@tonic-gate { 52747c478bd9Sstevel@tonic-gate if (term_bitmap & (1 << i)) 52757c478bd9Sstevel@tonic-gate { 52767c478bd9Sstevel@tonic-gate if (term_table[i].checkkey () >= 0) 52777c478bd9Sstevel@tonic-gate { 52787c478bd9Sstevel@tonic-gate (void) term_table[i].getkey (); 52797c478bd9Sstevel@tonic-gate default_term = i; 52807c478bd9Sstevel@tonic-gate 52817c478bd9Sstevel@tonic-gate goto end; 52827c478bd9Sstevel@tonic-gate } 52837c478bd9Sstevel@tonic-gate } 52847c478bd9Sstevel@tonic-gate } 52857c478bd9Sstevel@tonic-gate 52867c478bd9Sstevel@tonic-gate /* Prompt the user, once per sec. */ 52877c478bd9Sstevel@tonic-gate if ((time1 = getrtsecs ()) != time2 && time1 != 0xFF) 52887c478bd9Sstevel@tonic-gate { 52897c478bd9Sstevel@tonic-gate if (! no_message) 52907c478bd9Sstevel@tonic-gate { 52917c478bd9Sstevel@tonic-gate /* Need to set CURRENT_TERM to each of selected 52927c478bd9Sstevel@tonic-gate terminals. */ 52937c478bd9Sstevel@tonic-gate for (i = 0; term_table[i].name; i++) 52947c478bd9Sstevel@tonic-gate if (term_bitmap & (1 << i)) 52957c478bd9Sstevel@tonic-gate { 52967c478bd9Sstevel@tonic-gate current_term = term_table + i; 52977c478bd9Sstevel@tonic-gate grub_printf ("\rPress any key to continue.\n"); 52987c478bd9Sstevel@tonic-gate } 52997c478bd9Sstevel@tonic-gate 53007c478bd9Sstevel@tonic-gate /* Restore CURRENT_TERM. */ 53017c478bd9Sstevel@tonic-gate current_term = prev_term; 53027c478bd9Sstevel@tonic-gate } 53037c478bd9Sstevel@tonic-gate 53047c478bd9Sstevel@tonic-gate time2 = time1; 53057c478bd9Sstevel@tonic-gate if (to > 0) 53067c478bd9Sstevel@tonic-gate to--; 53077c478bd9Sstevel@tonic-gate } 53087c478bd9Sstevel@tonic-gate } 53097c478bd9Sstevel@tonic-gate } 53107c478bd9Sstevel@tonic-gate 53117c478bd9Sstevel@tonic-gate end: 53127c478bd9Sstevel@tonic-gate current_term = term_table + default_term; 53137c478bd9Sstevel@tonic-gate current_term->flags = term_flags; 53149b4e3ac2SWilliam Kucharski 53157c478bd9Sstevel@tonic-gate if (lines) 53167c478bd9Sstevel@tonic-gate max_lines = lines; 53177c478bd9Sstevel@tonic-gate else 53187c478bd9Sstevel@tonic-gate max_lines = current_term->max_lines; 53197c478bd9Sstevel@tonic-gate 53207c478bd9Sstevel@tonic-gate /* If the interface is currently the command-line, 53217c478bd9Sstevel@tonic-gate restart it to repaint the screen. */ 53227c478bd9Sstevel@tonic-gate if ((current_term != prev_term) && (flags & BUILTIN_CMDLINE)){ 53237c478bd9Sstevel@tonic-gate if (prev_term->shutdown) 53247c478bd9Sstevel@tonic-gate prev_term->shutdown(); 53257c478bd9Sstevel@tonic-gate if (current_term->startup) 53267c478bd9Sstevel@tonic-gate current_term->startup(); 53277c478bd9Sstevel@tonic-gate grub_longjmp (restart_cmdline_env, 0); 53287c478bd9Sstevel@tonic-gate } 53297c478bd9Sstevel@tonic-gate 53307c478bd9Sstevel@tonic-gate return 0; 53317c478bd9Sstevel@tonic-gate } 53327c478bd9Sstevel@tonic-gate 53337c478bd9Sstevel@tonic-gate static struct builtin builtin_terminal = 53347c478bd9Sstevel@tonic-gate { 53357c478bd9Sstevel@tonic-gate "terminal", 53367c478bd9Sstevel@tonic-gate terminal_func, 53377c478bd9Sstevel@tonic-gate BUILTIN_MENU | BUILTIN_CMDLINE | BUILTIN_HELP_LIST, 53387c478bd9Sstevel@tonic-gate "terminal [--dumb] [--no-echo] [--no-edit] [--timeout=SECS] [--lines=LINES] [--silent] [console] [serial] [hercules] [graphics]", 53397c478bd9Sstevel@tonic-gate "Select a terminal. When multiple terminals are specified, wait until" 53407c478bd9Sstevel@tonic-gate " you push any key to continue. If both console and serial are specified," 53417c478bd9Sstevel@tonic-gate " the terminal to which you input a key first will be selected. If no" 53427c478bd9Sstevel@tonic-gate " argument is specified, print current setting. The option --dumb" 53437c478bd9Sstevel@tonic-gate " specifies that your terminal is dumb, otherwise, vt100-compatibility" 53447c478bd9Sstevel@tonic-gate " is assumed. If you specify --no-echo, input characters won't be echoed." 53457c478bd9Sstevel@tonic-gate " If you specify --no-edit, the BASH-like editing feature will be disabled." 53467c478bd9Sstevel@tonic-gate " If --timeout is present, this command will wait at most for SECS" 53477c478bd9Sstevel@tonic-gate " seconds. The option --lines specifies the maximum number of lines." 53487c478bd9Sstevel@tonic-gate " The option --silent is used to suppress messages." 53497c478bd9Sstevel@tonic-gate }; 53507c478bd9Sstevel@tonic-gate #endif /* SUPPORT_SERIAL || SUPPORT_HERCULES || SUPPORT_GRAPHICS */ 53517c478bd9Sstevel@tonic-gate 53527c478bd9Sstevel@tonic-gate 53537c478bd9Sstevel@tonic-gate #ifdef SUPPORT_SERIAL 53547c478bd9Sstevel@tonic-gate static int 53557c478bd9Sstevel@tonic-gate terminfo_func (char *arg, int flags) 53567c478bd9Sstevel@tonic-gate { 53577c478bd9Sstevel@tonic-gate struct terminfo term; 53587c478bd9Sstevel@tonic-gate 53597c478bd9Sstevel@tonic-gate if (*arg) 53607c478bd9Sstevel@tonic-gate { 53617c478bd9Sstevel@tonic-gate struct 53627c478bd9Sstevel@tonic-gate { 53637c478bd9Sstevel@tonic-gate const char *name; 53647c478bd9Sstevel@tonic-gate char *var; 53657c478bd9Sstevel@tonic-gate } 53667c478bd9Sstevel@tonic-gate options[] = 53677c478bd9Sstevel@tonic-gate { 53687c478bd9Sstevel@tonic-gate {"--name=", term.name}, 53697c478bd9Sstevel@tonic-gate {"--cursor-address=", term.cursor_address}, 53707c478bd9Sstevel@tonic-gate {"--clear-screen=", term.clear_screen}, 53717c478bd9Sstevel@tonic-gate {"--enter-standout-mode=", term.enter_standout_mode}, 53727c478bd9Sstevel@tonic-gate {"--exit-standout-mode=", term.exit_standout_mode} 53737c478bd9Sstevel@tonic-gate }; 53747c478bd9Sstevel@tonic-gate 53757c478bd9Sstevel@tonic-gate grub_memset (&term, 0, sizeof (term)); 53767c478bd9Sstevel@tonic-gate 53777c478bd9Sstevel@tonic-gate while (*arg) 53787c478bd9Sstevel@tonic-gate { 53797c478bd9Sstevel@tonic-gate int i; 53807c478bd9Sstevel@tonic-gate char *next = skip_to (0, arg); 53817c478bd9Sstevel@tonic-gate 53827c478bd9Sstevel@tonic-gate nul_terminate (arg); 53837c478bd9Sstevel@tonic-gate 53847c478bd9Sstevel@tonic-gate for (i = 0; i < sizeof (options) / sizeof (options[0]); i++) 53857c478bd9Sstevel@tonic-gate { 53867c478bd9Sstevel@tonic-gate const char *name = options[i].name; 53877c478bd9Sstevel@tonic-gate int len = grub_strlen (name); 53887c478bd9Sstevel@tonic-gate 53897c478bd9Sstevel@tonic-gate if (! grub_memcmp (arg, name, len)) 53907c478bd9Sstevel@tonic-gate { 53917c478bd9Sstevel@tonic-gate grub_strcpy (options[i].var, ti_unescape_string (arg + len)); 53927c478bd9Sstevel@tonic-gate break; 53937c478bd9Sstevel@tonic-gate } 53947c478bd9Sstevel@tonic-gate } 53957c478bd9Sstevel@tonic-gate 53967c478bd9Sstevel@tonic-gate if (i == sizeof (options) / sizeof (options[0])) 53977c478bd9Sstevel@tonic-gate { 53987c478bd9Sstevel@tonic-gate errnum = ERR_BAD_ARGUMENT; 53997c478bd9Sstevel@tonic-gate return errnum; 54007c478bd9Sstevel@tonic-gate } 54017c478bd9Sstevel@tonic-gate 54027c478bd9Sstevel@tonic-gate arg = next; 54037c478bd9Sstevel@tonic-gate } 54047c478bd9Sstevel@tonic-gate 54057c478bd9Sstevel@tonic-gate if (term.name[0] == 0 || term.cursor_address[0] == 0) 54067c478bd9Sstevel@tonic-gate { 54077c478bd9Sstevel@tonic-gate errnum = ERR_BAD_ARGUMENT; 54087c478bd9Sstevel@tonic-gate return errnum; 54097c478bd9Sstevel@tonic-gate } 54107c478bd9Sstevel@tonic-gate 54117c478bd9Sstevel@tonic-gate ti_set_term (&term); 54127c478bd9Sstevel@tonic-gate } 54137c478bd9Sstevel@tonic-gate else 54147c478bd9Sstevel@tonic-gate { 54157c478bd9Sstevel@tonic-gate /* No option specifies printing out current settings. */ 54167c478bd9Sstevel@tonic-gate ti_get_term (&term); 54177c478bd9Sstevel@tonic-gate 54187c478bd9Sstevel@tonic-gate grub_printf ("name=%s\n", 54197c478bd9Sstevel@tonic-gate ti_escape_string (term.name)); 54207c478bd9Sstevel@tonic-gate grub_printf ("cursor_address=%s\n", 54217c478bd9Sstevel@tonic-gate ti_escape_string (term.cursor_address)); 54227c478bd9Sstevel@tonic-gate grub_printf ("clear_screen=%s\n", 54237c478bd9Sstevel@tonic-gate ti_escape_string (term.clear_screen)); 54247c478bd9Sstevel@tonic-gate grub_printf ("enter_standout_mode=%s\n", 54257c478bd9Sstevel@tonic-gate ti_escape_string (term.enter_standout_mode)); 54267c478bd9Sstevel@tonic-gate grub_printf ("exit_standout_mode=%s\n", 54277c478bd9Sstevel@tonic-gate ti_escape_string (term.exit_standout_mode)); 54287c478bd9Sstevel@tonic-gate } 54297c478bd9Sstevel@tonic-gate 54307c478bd9Sstevel@tonic-gate return 0; 54317c478bd9Sstevel@tonic-gate } 54327c478bd9Sstevel@tonic-gate 54337c478bd9Sstevel@tonic-gate static struct builtin builtin_terminfo = 54347c478bd9Sstevel@tonic-gate { 54357c478bd9Sstevel@tonic-gate "terminfo", 54367c478bd9Sstevel@tonic-gate terminfo_func, 54377c478bd9Sstevel@tonic-gate BUILTIN_MENU | BUILTIN_CMDLINE | BUILTIN_HELP_LIST, 54387c478bd9Sstevel@tonic-gate "terminfo [--name=NAME --cursor-address=SEQ [--clear-screen=SEQ]" 54397c478bd9Sstevel@tonic-gate " [--enter-standout-mode=SEQ] [--exit-standout-mode=SEQ]]", 54407c478bd9Sstevel@tonic-gate 54417c478bd9Sstevel@tonic-gate "Define the capabilities of your terminal. Use this command to" 54427c478bd9Sstevel@tonic-gate " define escape sequences, if it is not vt100-compatible." 54437c478bd9Sstevel@tonic-gate " You may use \\e for ESC and ^X for a control character." 54447c478bd9Sstevel@tonic-gate " If no option is specified, the current settings are printed." 54457c478bd9Sstevel@tonic-gate }; 54467c478bd9Sstevel@tonic-gate #endif /* SUPPORT_SERIAL */ 54477c478bd9Sstevel@tonic-gate 54487c478bd9Sstevel@tonic-gate 54497c478bd9Sstevel@tonic-gate /* testload */ 54507c478bd9Sstevel@tonic-gate static int 54517c478bd9Sstevel@tonic-gate testload_func (char *arg, int flags) 54527c478bd9Sstevel@tonic-gate { 54537c478bd9Sstevel@tonic-gate int i; 54547c478bd9Sstevel@tonic-gate 54557c478bd9Sstevel@tonic-gate kernel_type = KERNEL_TYPE_NONE; 54567c478bd9Sstevel@tonic-gate 54577c478bd9Sstevel@tonic-gate if (! grub_open (arg)) 54587c478bd9Sstevel@tonic-gate return 1; 54597c478bd9Sstevel@tonic-gate 54607c478bd9Sstevel@tonic-gate disk_read_hook = disk_read_print_func; 54617c478bd9Sstevel@tonic-gate 54627c478bd9Sstevel@tonic-gate /* Perform filesystem test on the specified file. */ 54637c478bd9Sstevel@tonic-gate /* Read whole file first. */ 54647c478bd9Sstevel@tonic-gate grub_printf ("Whole file: "); 54657c478bd9Sstevel@tonic-gate 54667c478bd9Sstevel@tonic-gate grub_read ((char *) RAW_ADDR (0x100000), -1); 54677c478bd9Sstevel@tonic-gate 54687c478bd9Sstevel@tonic-gate /* Now compare two sections of the file read differently. */ 54697c478bd9Sstevel@tonic-gate 54707c478bd9Sstevel@tonic-gate for (i = 0; i < 0x10ac0; i++) 54717c478bd9Sstevel@tonic-gate { 54727c478bd9Sstevel@tonic-gate *((unsigned char *) RAW_ADDR (0x200000 + i)) = 0; 54737c478bd9Sstevel@tonic-gate *((unsigned char *) RAW_ADDR (0x300000 + i)) = 1; 54747c478bd9Sstevel@tonic-gate } 54757c478bd9Sstevel@tonic-gate 54767c478bd9Sstevel@tonic-gate /* First partial read. */ 54777c478bd9Sstevel@tonic-gate grub_printf ("\nPartial read 1: "); 54787c478bd9Sstevel@tonic-gate 54797c478bd9Sstevel@tonic-gate grub_seek (0); 54807c478bd9Sstevel@tonic-gate grub_read ((char *) RAW_ADDR (0x200000), 0x7); 54817c478bd9Sstevel@tonic-gate grub_read ((char *) RAW_ADDR (0x200007), 0x100); 54827c478bd9Sstevel@tonic-gate grub_read ((char *) RAW_ADDR (0x200107), 0x10); 54837c478bd9Sstevel@tonic-gate grub_read ((char *) RAW_ADDR (0x200117), 0x999); 54847c478bd9Sstevel@tonic-gate grub_read ((char *) RAW_ADDR (0x200ab0), 0x10); 54857c478bd9Sstevel@tonic-gate grub_read ((char *) RAW_ADDR (0x200ac0), 0x10000); 54867c478bd9Sstevel@tonic-gate 54877c478bd9Sstevel@tonic-gate /* Second partial read. */ 54887c478bd9Sstevel@tonic-gate grub_printf ("\nPartial read 2: "); 54897c478bd9Sstevel@tonic-gate 54907c478bd9Sstevel@tonic-gate grub_seek (0); 54917c478bd9Sstevel@tonic-gate grub_read ((char *) RAW_ADDR (0x300000), 0x10000); 54927c478bd9Sstevel@tonic-gate grub_read ((char *) RAW_ADDR (0x310000), 0x10); 54937c478bd9Sstevel@tonic-gate grub_read ((char *) RAW_ADDR (0x310010), 0x7); 54947c478bd9Sstevel@tonic-gate grub_read ((char *) RAW_ADDR (0x310017), 0x10); 54957c478bd9Sstevel@tonic-gate grub_read ((char *) RAW_ADDR (0x310027), 0x999); 54967c478bd9Sstevel@tonic-gate grub_read ((char *) RAW_ADDR (0x3109c0), 0x100); 54977c478bd9Sstevel@tonic-gate 54987c478bd9Sstevel@tonic-gate grub_printf ("\nHeader1 = 0x%x, next = 0x%x, next = 0x%x, next = 0x%x\n", 54997c478bd9Sstevel@tonic-gate *((int *) RAW_ADDR (0x200000)), 55007c478bd9Sstevel@tonic-gate *((int *) RAW_ADDR (0x200004)), 55017c478bd9Sstevel@tonic-gate *((int *) RAW_ADDR (0x200008)), 55027c478bd9Sstevel@tonic-gate *((int *) RAW_ADDR (0x20000c))); 55037c478bd9Sstevel@tonic-gate 55047c478bd9Sstevel@tonic-gate grub_printf ("Header2 = 0x%x, next = 0x%x, next = 0x%x, next = 0x%x\n", 55057c478bd9Sstevel@tonic-gate *((int *) RAW_ADDR (0x300000)), 55067c478bd9Sstevel@tonic-gate *((int *) RAW_ADDR (0x300004)), 55077c478bd9Sstevel@tonic-gate *((int *) RAW_ADDR (0x300008)), 55087c478bd9Sstevel@tonic-gate *((int *) RAW_ADDR (0x30000c))); 55097c478bd9Sstevel@tonic-gate 55107c478bd9Sstevel@tonic-gate for (i = 0; i < 0x10ac0; i++) 55117c478bd9Sstevel@tonic-gate if (*((unsigned char *) RAW_ADDR (0x200000 + i)) 55127c478bd9Sstevel@tonic-gate != *((unsigned char *) RAW_ADDR (0x300000 + i))) 55137c478bd9Sstevel@tonic-gate break; 55147c478bd9Sstevel@tonic-gate 55157c478bd9Sstevel@tonic-gate grub_printf ("Max is 0x10ac0: i=0x%x, filepos=0x%x\n", i, filepos); 55167c478bd9Sstevel@tonic-gate disk_read_hook = 0; 55177c478bd9Sstevel@tonic-gate grub_close (); 55187c478bd9Sstevel@tonic-gate return 0; 55197c478bd9Sstevel@tonic-gate } 55207c478bd9Sstevel@tonic-gate 55217c478bd9Sstevel@tonic-gate static struct builtin builtin_testload = 55227c478bd9Sstevel@tonic-gate { 55237c478bd9Sstevel@tonic-gate "testload", 55247c478bd9Sstevel@tonic-gate testload_func, 55257c478bd9Sstevel@tonic-gate BUILTIN_CMDLINE, 55267c478bd9Sstevel@tonic-gate "testload FILE", 55277c478bd9Sstevel@tonic-gate "Read the entire contents of FILE in several different ways and" 55287c478bd9Sstevel@tonic-gate " compares them, to test the filesystem code. The output is somewhat" 55297c478bd9Sstevel@tonic-gate " cryptic, but if no errors are reported and the final `i=X," 55307c478bd9Sstevel@tonic-gate " filepos=Y' reading has X and Y equal, then it is definitely" 55317c478bd9Sstevel@tonic-gate " consistent, and very likely works correctly subject to a" 55327c478bd9Sstevel@tonic-gate " consistent offset error. If this test succeeds, then a good next" 55337c478bd9Sstevel@tonic-gate " step is to try loading a kernel." 55347c478bd9Sstevel@tonic-gate }; 55357c478bd9Sstevel@tonic-gate 55367c478bd9Sstevel@tonic-gate 55377c478bd9Sstevel@tonic-gate /* testvbe MODE */ 55387c478bd9Sstevel@tonic-gate static int 55397c478bd9Sstevel@tonic-gate testvbe_func (char *arg, int flags) 55407c478bd9Sstevel@tonic-gate { 55417c478bd9Sstevel@tonic-gate int mode_number; 55427c478bd9Sstevel@tonic-gate struct vbe_controller controller; 55437c478bd9Sstevel@tonic-gate struct vbe_mode mode; 55447c478bd9Sstevel@tonic-gate 55457c478bd9Sstevel@tonic-gate if (! *arg) 55467c478bd9Sstevel@tonic-gate { 55477c478bd9Sstevel@tonic-gate errnum = ERR_BAD_ARGUMENT; 55487c478bd9Sstevel@tonic-gate return 1; 55497c478bd9Sstevel@tonic-gate } 55507c478bd9Sstevel@tonic-gate 55517c478bd9Sstevel@tonic-gate if (! safe_parse_maxint (&arg, &mode_number)) 55527c478bd9Sstevel@tonic-gate return 1; 55537c478bd9Sstevel@tonic-gate 55547c478bd9Sstevel@tonic-gate /* Preset `VBE2'. */ 55557c478bd9Sstevel@tonic-gate grub_memmove (controller.signature, "VBE2", 4); 55567c478bd9Sstevel@tonic-gate 55577c478bd9Sstevel@tonic-gate /* Detect VBE BIOS. */ 55587c478bd9Sstevel@tonic-gate if (get_vbe_controller_info (&controller) != 0x004F) 55597c478bd9Sstevel@tonic-gate { 55607c478bd9Sstevel@tonic-gate grub_printf (" VBE BIOS is not present.\n"); 55617c478bd9Sstevel@tonic-gate return 0; 55627c478bd9Sstevel@tonic-gate } 55637c478bd9Sstevel@tonic-gate 55647c478bd9Sstevel@tonic-gate if (controller.version < 0x0200) 55657c478bd9Sstevel@tonic-gate { 55667c478bd9Sstevel@tonic-gate grub_printf (" VBE version %d.%d is not supported.\n", 55677c478bd9Sstevel@tonic-gate (int) (controller.version >> 8), 55687c478bd9Sstevel@tonic-gate (int) (controller.version & 0xFF)); 55697c478bd9Sstevel@tonic-gate return 0; 55707c478bd9Sstevel@tonic-gate } 55717c478bd9Sstevel@tonic-gate 55727c478bd9Sstevel@tonic-gate if (get_vbe_mode_info (mode_number, &mode) != 0x004F 55737c478bd9Sstevel@tonic-gate || (mode.mode_attributes & 0x0091) != 0x0091) 55747c478bd9Sstevel@tonic-gate { 55757c478bd9Sstevel@tonic-gate grub_printf (" Mode 0x%x is not supported.\n", mode_number); 55767c478bd9Sstevel@tonic-gate return 0; 55777c478bd9Sstevel@tonic-gate } 55787c478bd9Sstevel@tonic-gate 55797c478bd9Sstevel@tonic-gate /* Now trip to the graphics mode. */ 55807c478bd9Sstevel@tonic-gate if (set_vbe_mode (mode_number | (1 << 14)) != 0x004F) 55817c478bd9Sstevel@tonic-gate { 55827c478bd9Sstevel@tonic-gate grub_printf (" Switching to Mode 0x%x failed.\n", mode_number); 55837c478bd9Sstevel@tonic-gate return 0; 55847c478bd9Sstevel@tonic-gate } 55857c478bd9Sstevel@tonic-gate 55867c478bd9Sstevel@tonic-gate /* Draw something on the screen... */ 55877c478bd9Sstevel@tonic-gate { 55887c478bd9Sstevel@tonic-gate unsigned char *base_buf = (unsigned char *) mode.phys_base; 55897c478bd9Sstevel@tonic-gate int scanline = controller.version >= 0x0300 55907c478bd9Sstevel@tonic-gate ? mode.linear_bytes_per_scanline : mode.bytes_per_scanline; 55917c478bd9Sstevel@tonic-gate /* FIXME: this assumes that any depth is a modulo of 8. */ 55927c478bd9Sstevel@tonic-gate int bpp = mode.bits_per_pixel / 8; 55937c478bd9Sstevel@tonic-gate int width = mode.x_resolution; 55947c478bd9Sstevel@tonic-gate int height = mode.y_resolution; 55957c478bd9Sstevel@tonic-gate int x, y; 55967c478bd9Sstevel@tonic-gate unsigned color = 0; 55977c478bd9Sstevel@tonic-gate 55987c478bd9Sstevel@tonic-gate /* Iterate drawing on the screen, until the user hits any key. */ 55997c478bd9Sstevel@tonic-gate while (checkkey () == -1) 56007c478bd9Sstevel@tonic-gate { 56017c478bd9Sstevel@tonic-gate for (y = 0; y < height; y++) 56027c478bd9Sstevel@tonic-gate { 56037c478bd9Sstevel@tonic-gate unsigned char *line_buf = base_buf + scanline * y; 56047c478bd9Sstevel@tonic-gate 56057c478bd9Sstevel@tonic-gate for (x = 0; x < width; x++) 56067c478bd9Sstevel@tonic-gate { 56077c478bd9Sstevel@tonic-gate unsigned char *buf = line_buf + bpp * x; 56087c478bd9Sstevel@tonic-gate int i; 56097c478bd9Sstevel@tonic-gate 56107c478bd9Sstevel@tonic-gate for (i = 0; i < bpp; i++, buf++) 56117c478bd9Sstevel@tonic-gate *buf = (color >> (i * 8)) & 0xff; 56127c478bd9Sstevel@tonic-gate } 56137c478bd9Sstevel@tonic-gate 56147c478bd9Sstevel@tonic-gate color++; 56157c478bd9Sstevel@tonic-gate } 56167c478bd9Sstevel@tonic-gate } 56177c478bd9Sstevel@tonic-gate 56187c478bd9Sstevel@tonic-gate /* Discard the input. */ 56197c478bd9Sstevel@tonic-gate getkey (); 56207c478bd9Sstevel@tonic-gate } 56217c478bd9Sstevel@tonic-gate 56227c478bd9Sstevel@tonic-gate /* Back to the default text mode. */ 56237c478bd9Sstevel@tonic-gate if (set_vbe_mode (0x03) != 0x004F) 56247c478bd9Sstevel@tonic-gate { 56257c478bd9Sstevel@tonic-gate /* Why?! */ 56267c478bd9Sstevel@tonic-gate grub_reboot (); 56277c478bd9Sstevel@tonic-gate } 56287c478bd9Sstevel@tonic-gate 56297c478bd9Sstevel@tonic-gate return 0; 56307c478bd9Sstevel@tonic-gate } 56317c478bd9Sstevel@tonic-gate 56327c478bd9Sstevel@tonic-gate static struct builtin builtin_testvbe = 56337c478bd9Sstevel@tonic-gate { 56347c478bd9Sstevel@tonic-gate "testvbe", 56357c478bd9Sstevel@tonic-gate testvbe_func, 56367c478bd9Sstevel@tonic-gate BUILTIN_CMDLINE | BUILTIN_HELP_LIST, 56377c478bd9Sstevel@tonic-gate "testvbe MODE", 56387c478bd9Sstevel@tonic-gate "Test the VBE mode MODE. Hit any key to return." 56397c478bd9Sstevel@tonic-gate }; 56407c478bd9Sstevel@tonic-gate 56417c478bd9Sstevel@tonic-gate 56427c478bd9Sstevel@tonic-gate #ifdef SUPPORT_NETBOOT 56437c478bd9Sstevel@tonic-gate /* tftpserver */ 56447c478bd9Sstevel@tonic-gate static int 56457c478bd9Sstevel@tonic-gate tftpserver_func (char *arg, int flags) 56467c478bd9Sstevel@tonic-gate { 56477c478bd9Sstevel@tonic-gate if (! *arg || ! ifconfig (0, 0, 0, arg)) 56487c478bd9Sstevel@tonic-gate { 56497c478bd9Sstevel@tonic-gate errnum = ERR_BAD_ARGUMENT; 56507c478bd9Sstevel@tonic-gate return 1; 56517c478bd9Sstevel@tonic-gate } 56527c478bd9Sstevel@tonic-gate 56537c478bd9Sstevel@tonic-gate print_network_configuration (); 56547c478bd9Sstevel@tonic-gate return 0; 56557c478bd9Sstevel@tonic-gate } 56567c478bd9Sstevel@tonic-gate 56577c478bd9Sstevel@tonic-gate static struct builtin builtin_tftpserver = 56587c478bd9Sstevel@tonic-gate { 56597c478bd9Sstevel@tonic-gate "tftpserver", 56607c478bd9Sstevel@tonic-gate tftpserver_func, 56617c478bd9Sstevel@tonic-gate BUILTIN_CMDLINE | BUILTIN_MENU | BUILTIN_HELP_LIST, 56627c478bd9Sstevel@tonic-gate "tftpserver IPADDR", 56637c478bd9Sstevel@tonic-gate "Override the TFTP server address." 56647c478bd9Sstevel@tonic-gate }; 56657c478bd9Sstevel@tonic-gate #endif /* SUPPORT_NETBOOT */ 56667c478bd9Sstevel@tonic-gate 56677c478bd9Sstevel@tonic-gate 56687c478bd9Sstevel@tonic-gate /* timeout */ 56697c478bd9Sstevel@tonic-gate static int 56707c478bd9Sstevel@tonic-gate timeout_func (char *arg, int flags) 56717c478bd9Sstevel@tonic-gate { 56727c478bd9Sstevel@tonic-gate if (! safe_parse_maxint (&arg, &grub_timeout)) 56737c478bd9Sstevel@tonic-gate return 1; 56747c478bd9Sstevel@tonic-gate 56757c478bd9Sstevel@tonic-gate return 0; 56767c478bd9Sstevel@tonic-gate } 56777c478bd9Sstevel@tonic-gate 56787c478bd9Sstevel@tonic-gate static struct builtin builtin_timeout = 56797c478bd9Sstevel@tonic-gate { 56807c478bd9Sstevel@tonic-gate "timeout", 56817c478bd9Sstevel@tonic-gate timeout_func, 56827c478bd9Sstevel@tonic-gate BUILTIN_MENU, 56837c478bd9Sstevel@tonic-gate #if 0 56847c478bd9Sstevel@tonic-gate "timeout SEC", 56857c478bd9Sstevel@tonic-gate "Set a timeout, in SEC seconds, before automatically booting the" 56867c478bd9Sstevel@tonic-gate " default entry (normally the first entry defined)." 56877c478bd9Sstevel@tonic-gate #endif 56887c478bd9Sstevel@tonic-gate }; 56897c478bd9Sstevel@tonic-gate 56907c478bd9Sstevel@tonic-gate 56917c478bd9Sstevel@tonic-gate /* title */ 56927c478bd9Sstevel@tonic-gate static int 56937c478bd9Sstevel@tonic-gate title_func (char *arg, int flags) 56947c478bd9Sstevel@tonic-gate { 56957c478bd9Sstevel@tonic-gate /* This function is not actually used at least currently. */ 56967c478bd9Sstevel@tonic-gate return 0; 56977c478bd9Sstevel@tonic-gate } 56987c478bd9Sstevel@tonic-gate 56997c478bd9Sstevel@tonic-gate static struct builtin builtin_title = 57007c478bd9Sstevel@tonic-gate { 57017c478bd9Sstevel@tonic-gate "title", 57027c478bd9Sstevel@tonic-gate title_func, 57037c478bd9Sstevel@tonic-gate BUILTIN_TITLE, 57047c478bd9Sstevel@tonic-gate #if 0 57057c478bd9Sstevel@tonic-gate "title [NAME ...]", 57067c478bd9Sstevel@tonic-gate "Start a new boot entry, and set its name to the contents of the" 57077c478bd9Sstevel@tonic-gate " rest of the line, starting with the first non-space character." 57087c478bd9Sstevel@tonic-gate #endif 57097c478bd9Sstevel@tonic-gate }; 57107c478bd9Sstevel@tonic-gate 57117c478bd9Sstevel@tonic-gate 57127c478bd9Sstevel@tonic-gate /* unhide */ 57137c478bd9Sstevel@tonic-gate static int 57147c478bd9Sstevel@tonic-gate unhide_func (char *arg, int flags) 57157c478bd9Sstevel@tonic-gate { 57167c478bd9Sstevel@tonic-gate if (! set_device (arg)) 57177c478bd9Sstevel@tonic-gate return 1; 57187c478bd9Sstevel@tonic-gate 57197c478bd9Sstevel@tonic-gate if (! set_partition_hidden_flag (0)) 57207c478bd9Sstevel@tonic-gate return 1; 57217c478bd9Sstevel@tonic-gate 57227c478bd9Sstevel@tonic-gate return 0; 57237c478bd9Sstevel@tonic-gate } 57247c478bd9Sstevel@tonic-gate 57257c478bd9Sstevel@tonic-gate static struct builtin builtin_unhide = 57267c478bd9Sstevel@tonic-gate { 57277c478bd9Sstevel@tonic-gate "unhide", 57287c478bd9Sstevel@tonic-gate unhide_func, 57297c478bd9Sstevel@tonic-gate BUILTIN_CMDLINE | BUILTIN_MENU | BUILTIN_HELP_LIST, 57307c478bd9Sstevel@tonic-gate "unhide PARTITION", 57317c478bd9Sstevel@tonic-gate "Unhide PARTITION by clearing the \"hidden\" bit in its" 57327c478bd9Sstevel@tonic-gate " partition type code." 57337c478bd9Sstevel@tonic-gate }; 57347c478bd9Sstevel@tonic-gate 57357c478bd9Sstevel@tonic-gate 57367c478bd9Sstevel@tonic-gate /* uppermem */ 57377c478bd9Sstevel@tonic-gate static int 57387c478bd9Sstevel@tonic-gate uppermem_func (char *arg, int flags) 57397c478bd9Sstevel@tonic-gate { 57407c478bd9Sstevel@tonic-gate if (! safe_parse_maxint (&arg, (int *) &mbi.mem_upper)) 57417c478bd9Sstevel@tonic-gate return 1; 57427c478bd9Sstevel@tonic-gate 57437c478bd9Sstevel@tonic-gate mbi.flags &= ~MB_INFO_MEM_MAP; 57447c478bd9Sstevel@tonic-gate return 0; 57457c478bd9Sstevel@tonic-gate } 57467c478bd9Sstevel@tonic-gate 57477c478bd9Sstevel@tonic-gate static struct builtin builtin_uppermem = 57487c478bd9Sstevel@tonic-gate { 57497c478bd9Sstevel@tonic-gate "uppermem", 57507c478bd9Sstevel@tonic-gate uppermem_func, 57517c478bd9Sstevel@tonic-gate BUILTIN_CMDLINE | BUILTIN_HELP_LIST, 57527c478bd9Sstevel@tonic-gate "uppermem KBYTES", 57537c478bd9Sstevel@tonic-gate "Force GRUB to assume that only KBYTES kilobytes of upper memory are" 57547c478bd9Sstevel@tonic-gate " installed. Any system address range maps are discarded." 57557c478bd9Sstevel@tonic-gate }; 57567c478bd9Sstevel@tonic-gate 57577c478bd9Sstevel@tonic-gate 57587c478bd9Sstevel@tonic-gate /* vbeprobe */ 57597c478bd9Sstevel@tonic-gate static int 57607c478bd9Sstevel@tonic-gate vbeprobe_func (char *arg, int flags) 57617c478bd9Sstevel@tonic-gate { 57627c478bd9Sstevel@tonic-gate struct vbe_controller controller; 57637c478bd9Sstevel@tonic-gate unsigned short *mode_list; 57647c478bd9Sstevel@tonic-gate int mode_number = -1; 57657c478bd9Sstevel@tonic-gate 57667c478bd9Sstevel@tonic-gate auto unsigned long vbe_far_ptr_to_linear (unsigned long); 57677c478bd9Sstevel@tonic-gate 57687c478bd9Sstevel@tonic-gate unsigned long vbe_far_ptr_to_linear (unsigned long ptr) 57697c478bd9Sstevel@tonic-gate { 57707c478bd9Sstevel@tonic-gate unsigned short seg = (ptr >> 16); 57717c478bd9Sstevel@tonic-gate unsigned short off = (ptr & 0xFFFF); 57727c478bd9Sstevel@tonic-gate 57737c478bd9Sstevel@tonic-gate return (seg << 4) + off; 57747c478bd9Sstevel@tonic-gate } 57757c478bd9Sstevel@tonic-gate 57767c478bd9Sstevel@tonic-gate if (*arg) 57777c478bd9Sstevel@tonic-gate { 57787c478bd9Sstevel@tonic-gate if (! safe_parse_maxint (&arg, &mode_number)) 57797c478bd9Sstevel@tonic-gate return 1; 57807c478bd9Sstevel@tonic-gate } 57817c478bd9Sstevel@tonic-gate 57827c478bd9Sstevel@tonic-gate /* Set the signature to `VBE2', to obtain VBE 3.0 information. */ 57837c478bd9Sstevel@tonic-gate grub_memmove (controller.signature, "VBE2", 4); 57847c478bd9Sstevel@tonic-gate 57857c478bd9Sstevel@tonic-gate if (get_vbe_controller_info (&controller) != 0x004F) 57867c478bd9Sstevel@tonic-gate { 57877c478bd9Sstevel@tonic-gate grub_printf (" VBE BIOS is not present.\n"); 57887c478bd9Sstevel@tonic-gate return 0; 57897c478bd9Sstevel@tonic-gate } 57907c478bd9Sstevel@tonic-gate 57917c478bd9Sstevel@tonic-gate /* Check the version. */ 57927c478bd9Sstevel@tonic-gate if (controller.version < 0x0200) 57937c478bd9Sstevel@tonic-gate { 57947c478bd9Sstevel@tonic-gate grub_printf (" VBE version %d.%d is not supported.\n", 57957c478bd9Sstevel@tonic-gate (int) (controller.version >> 8), 57967c478bd9Sstevel@tonic-gate (int) (controller.version & 0xFF)); 57977c478bd9Sstevel@tonic-gate return 0; 57987c478bd9Sstevel@tonic-gate } 57997c478bd9Sstevel@tonic-gate 58007c478bd9Sstevel@tonic-gate /* Print some information. */ 58017c478bd9Sstevel@tonic-gate grub_printf (" VBE version %d.%d\n", 58027c478bd9Sstevel@tonic-gate (int) (controller.version >> 8), 58037c478bd9Sstevel@tonic-gate (int) (controller.version & 0xFF)); 58047c478bd9Sstevel@tonic-gate 58057c478bd9Sstevel@tonic-gate /* Iterate probing modes. */ 58067c478bd9Sstevel@tonic-gate for (mode_list 58077c478bd9Sstevel@tonic-gate = (unsigned short *) vbe_far_ptr_to_linear (controller.video_mode); 58087c478bd9Sstevel@tonic-gate *mode_list != 0xFFFF; 58097c478bd9Sstevel@tonic-gate mode_list++) 58107c478bd9Sstevel@tonic-gate { 58117c478bd9Sstevel@tonic-gate struct vbe_mode mode; 58127c478bd9Sstevel@tonic-gate 58137c478bd9Sstevel@tonic-gate if (get_vbe_mode_info (*mode_list, &mode) != 0x004F) 58147c478bd9Sstevel@tonic-gate continue; 58157c478bd9Sstevel@tonic-gate 58167c478bd9Sstevel@tonic-gate /* Skip this, if this is not supported or linear frame buffer 58177c478bd9Sstevel@tonic-gate mode is not support. */ 58187c478bd9Sstevel@tonic-gate if ((mode.mode_attributes & 0x0081) != 0x0081) 58197c478bd9Sstevel@tonic-gate continue; 58207c478bd9Sstevel@tonic-gate 58217c478bd9Sstevel@tonic-gate if (mode_number == -1 || mode_number == *mode_list) 58227c478bd9Sstevel@tonic-gate { 58237c478bd9Sstevel@tonic-gate char *model; 58247c478bd9Sstevel@tonic-gate switch (mode.memory_model) 58257c478bd9Sstevel@tonic-gate { 58267c478bd9Sstevel@tonic-gate case 0x00: model = "Text"; break; 58277c478bd9Sstevel@tonic-gate case 0x01: model = "CGA graphics"; break; 58287c478bd9Sstevel@tonic-gate case 0x02: model = "Hercules graphics"; break; 58297c478bd9Sstevel@tonic-gate case 0x03: model = "Planar"; break; 58307c478bd9Sstevel@tonic-gate case 0x04: model = "Packed pixel"; break; 58317c478bd9Sstevel@tonic-gate case 0x05: model = "Non-chain 4, 256 color"; break; 58327c478bd9Sstevel@tonic-gate case 0x06: model = "Direct Color"; break; 58337c478bd9Sstevel@tonic-gate case 0x07: model = "YUV"; break; 58347c478bd9Sstevel@tonic-gate default: model = "Unknown"; break; 58357c478bd9Sstevel@tonic-gate } 58367c478bd9Sstevel@tonic-gate 58377c478bd9Sstevel@tonic-gate grub_printf (" 0x%x: %s, %ux%ux%u\n", 58387c478bd9Sstevel@tonic-gate (unsigned) *mode_list, 58397c478bd9Sstevel@tonic-gate model, 58407c478bd9Sstevel@tonic-gate (unsigned) mode.x_resolution, 58417c478bd9Sstevel@tonic-gate (unsigned) mode.y_resolution, 58427c478bd9Sstevel@tonic-gate (unsigned) mode.bits_per_pixel); 58437c478bd9Sstevel@tonic-gate 58447c478bd9Sstevel@tonic-gate if (mode_number != -1) 58457c478bd9Sstevel@tonic-gate break; 58467c478bd9Sstevel@tonic-gate } 58477c478bd9Sstevel@tonic-gate } 58487c478bd9Sstevel@tonic-gate 58497c478bd9Sstevel@tonic-gate if (mode_number != -1 && mode_number != *mode_list) 58507c478bd9Sstevel@tonic-gate grub_printf (" Mode 0x%x is not found or supported.\n", mode_number); 58517c478bd9Sstevel@tonic-gate 58527c478bd9Sstevel@tonic-gate return 0; 58537c478bd9Sstevel@tonic-gate } 58547c478bd9Sstevel@tonic-gate 58557c478bd9Sstevel@tonic-gate static struct builtin builtin_vbeprobe = 58567c478bd9Sstevel@tonic-gate { 58577c478bd9Sstevel@tonic-gate "vbeprobe", 58587c478bd9Sstevel@tonic-gate vbeprobe_func, 58597c478bd9Sstevel@tonic-gate BUILTIN_CMDLINE | BUILTIN_HELP_LIST, 58607c478bd9Sstevel@tonic-gate "vbeprobe [MODE]", 58617c478bd9Sstevel@tonic-gate "Probe VBE information. If the mode number MODE is specified, show only" 58627c478bd9Sstevel@tonic-gate " the information about only the mode." 58637c478bd9Sstevel@tonic-gate }; 58647c478bd9Sstevel@tonic-gate 58657c478bd9Sstevel@tonic-gate 58667c478bd9Sstevel@tonic-gate /* The table of builtin commands. Sorted in dictionary order. */ 58677c478bd9Sstevel@tonic-gate struct builtin *builtin_table[] = 58687c478bd9Sstevel@tonic-gate { 58697c478bd9Sstevel@tonic-gate #ifdef SUPPORT_GRAPHICS 58707c478bd9Sstevel@tonic-gate &builtin_background, 58717c478bd9Sstevel@tonic-gate #endif 58727c478bd9Sstevel@tonic-gate &builtin_blocklist, 58737c478bd9Sstevel@tonic-gate &builtin_boot, 5874b1b8ab34Slling &builtin_bootfs, 58757c478bd9Sstevel@tonic-gate #ifdef SUPPORT_NETBOOT 58767c478bd9Sstevel@tonic-gate &builtin_bootp, 58777c478bd9Sstevel@tonic-gate #endif /* SUPPORT_NETBOOT */ 58787c478bd9Sstevel@tonic-gate &builtin_cat, 58797c478bd9Sstevel@tonic-gate &builtin_chainloader, 58807c478bd9Sstevel@tonic-gate &builtin_clear, 58817c478bd9Sstevel@tonic-gate &builtin_cmp, 58827c478bd9Sstevel@tonic-gate &builtin_color, 58837c478bd9Sstevel@tonic-gate &builtin_configfile, 58847c478bd9Sstevel@tonic-gate &builtin_debug, 58857c478bd9Sstevel@tonic-gate &builtin_default, 58867c478bd9Sstevel@tonic-gate #ifdef GRUB_UTIL 58877c478bd9Sstevel@tonic-gate &builtin_device, 58887c478bd9Sstevel@tonic-gate #endif /* GRUB_UTIL */ 58897c478bd9Sstevel@tonic-gate #ifdef SUPPORT_NETBOOT 58907c478bd9Sstevel@tonic-gate &builtin_dhcp, 58917c478bd9Sstevel@tonic-gate #endif /* SUPPORT_NETBOOT */ 58927c478bd9Sstevel@tonic-gate &builtin_displayapm, 58937c478bd9Sstevel@tonic-gate &builtin_displaymem, 58947c478bd9Sstevel@tonic-gate #ifdef GRUB_UTIL 58957c478bd9Sstevel@tonic-gate &builtin_dump, 58967c478bd9Sstevel@tonic-gate #endif /* GRUB_UTIL */ 58977c478bd9Sstevel@tonic-gate &builtin_embed, 58987c478bd9Sstevel@tonic-gate &builtin_fallback, 58997c478bd9Sstevel@tonic-gate &builtin_find, 5900eb2bd662Svikram &builtin_findroot, 59017c478bd9Sstevel@tonic-gate #ifdef SUPPORT_GRAPHICS 59027c478bd9Sstevel@tonic-gate &builtin_foreground, 59037c478bd9Sstevel@tonic-gate #endif 59047c478bd9Sstevel@tonic-gate &builtin_fstest, 59057c478bd9Sstevel@tonic-gate &builtin_geometry, 59067c478bd9Sstevel@tonic-gate &builtin_halt, 59077c478bd9Sstevel@tonic-gate &builtin_help, 59087c478bd9Sstevel@tonic-gate &builtin_hiddenmenu, 59097c478bd9Sstevel@tonic-gate &builtin_hide, 59107c478bd9Sstevel@tonic-gate #ifdef SUPPORT_NETBOOT 59117c478bd9Sstevel@tonic-gate &builtin_ifconfig, 59127c478bd9Sstevel@tonic-gate #endif /* SUPPORT_NETBOOT */ 59137c478bd9Sstevel@tonic-gate &builtin_impsprobe, 59147ce76caaSEnrico Perla - Sun Microsystems &builtin_info, 59157c478bd9Sstevel@tonic-gate &builtin_initrd, 59167c478bd9Sstevel@tonic-gate &builtin_install, 59177c478bd9Sstevel@tonic-gate &builtin_ioprobe, 59187c478bd9Sstevel@tonic-gate &builtin_kernel, 5919ae115bc7Smrj &builtin_kernel_dollar, 59207c478bd9Sstevel@tonic-gate &builtin_lock, 59217c478bd9Sstevel@tonic-gate &builtin_makeactive, 59227c478bd9Sstevel@tonic-gate &builtin_map, 59237c478bd9Sstevel@tonic-gate #ifdef USE_MD5_PASSWORDS 59247c478bd9Sstevel@tonic-gate &builtin_md5crypt, 59257c478bd9Sstevel@tonic-gate #endif /* USE_MD5_PASSWORDS */ 5926342440ecSPrasad Singamsetty &builtin_min_mem64, 59277c478bd9Sstevel@tonic-gate &builtin_module, 5928ae115bc7Smrj &builtin_module_dollar, 59297c478bd9Sstevel@tonic-gate &builtin_modulenounzip, 59307c478bd9Sstevel@tonic-gate &builtin_pager, 59317c478bd9Sstevel@tonic-gate &builtin_partnew, 59327c478bd9Sstevel@tonic-gate &builtin_parttype, 59337c478bd9Sstevel@tonic-gate &builtin_password, 59347c478bd9Sstevel@tonic-gate &builtin_pause, 59357c478bd9Sstevel@tonic-gate #if defined(RPC_DEBUG) && defined(SUPPORT_NETBOOT) 59367c478bd9Sstevel@tonic-gate &builtin_portmap, 59377c478bd9Sstevel@tonic-gate #endif /* RPC_DEBUG && SUPPORT_NETBOOT */ 59387c478bd9Sstevel@tonic-gate #ifdef GRUB_UTIL 59397c478bd9Sstevel@tonic-gate &builtin_quit, 59407c478bd9Sstevel@tonic-gate #endif /* GRUB_UTIL */ 59417c478bd9Sstevel@tonic-gate #ifdef SUPPORT_NETBOOT 59427c478bd9Sstevel@tonic-gate &builtin_rarp, 59437c478bd9Sstevel@tonic-gate #endif /* SUPPORT_NETBOOT */ 59447c478bd9Sstevel@tonic-gate &builtin_read, 59457c478bd9Sstevel@tonic-gate &builtin_reboot, 59467c478bd9Sstevel@tonic-gate &builtin_root, 59477c478bd9Sstevel@tonic-gate &builtin_rootnoverify, 59487c478bd9Sstevel@tonic-gate &builtin_savedefault, 59497c478bd9Sstevel@tonic-gate #ifdef SUPPORT_SERIAL 59507c478bd9Sstevel@tonic-gate &builtin_serial, 59517c478bd9Sstevel@tonic-gate #endif /* SUPPORT_SERIAL */ 59527c478bd9Sstevel@tonic-gate &builtin_setkey, 59537c478bd9Sstevel@tonic-gate &builtin_setup, 59547c478bd9Sstevel@tonic-gate #ifdef SUPPORT_GRAPHICS 59557c478bd9Sstevel@tonic-gate &builtin_splashimage, 59567c478bd9Sstevel@tonic-gate #endif /* SUPPORT_GRAPHICS */ 59577c478bd9Sstevel@tonic-gate #if defined(SUPPORT_SERIAL) || defined(SUPPORT_HERCULES) || defined(SUPPORT_GRAPHICS) 59587c478bd9Sstevel@tonic-gate &builtin_terminal, 59597c478bd9Sstevel@tonic-gate #endif /* SUPPORT_SERIAL || SUPPORT_HERCULES || SUPPORT_GRAPHICS */ 59607c478bd9Sstevel@tonic-gate #ifdef SUPPORT_SERIAL 59617c478bd9Sstevel@tonic-gate &builtin_terminfo, 59627c478bd9Sstevel@tonic-gate #endif /* SUPPORT_SERIAL */ 59637c478bd9Sstevel@tonic-gate &builtin_testload, 59647c478bd9Sstevel@tonic-gate &builtin_testvbe, 59657c478bd9Sstevel@tonic-gate #ifdef SUPPORT_NETBOOT 59667c478bd9Sstevel@tonic-gate &builtin_tftpserver, 59677c478bd9Sstevel@tonic-gate #endif /* SUPPORT_NETBOOT */ 59687c478bd9Sstevel@tonic-gate &builtin_timeout, 59697c478bd9Sstevel@tonic-gate &builtin_title, 59707c478bd9Sstevel@tonic-gate &builtin_unhide, 59717c478bd9Sstevel@tonic-gate &builtin_uppermem, 59727c478bd9Sstevel@tonic-gate &builtin_vbeprobe, 59731fac5a60Ssetje &builtin_verbose, 59747c478bd9Sstevel@tonic-gate 0 59757c478bd9Sstevel@tonic-gate }; 5976