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 9477c478bd9Sstevel@tonic-gate static void solaris_config_file (void) 9487c478bd9Sstevel@tonic-gate { 9497c478bd9Sstevel@tonic-gate static char menufile[64]; 9507c478bd9Sstevel@tonic-gate static char hexdigit[] = "0123456789ABCDEF"; 9517c478bd9Sstevel@tonic-gate char *c = menufile; 9527c478bd9Sstevel@tonic-gate int i; 9536759d08fScasper int err; 9547c478bd9Sstevel@tonic-gate 9557c478bd9Sstevel@tonic-gate /* if config_file is from DHCP option 150, keep the setting */ 9567c478bd9Sstevel@tonic-gate if (grub_strcmp(config_file, "/boot/grub/menu.lst") != 0) 9577c478bd9Sstevel@tonic-gate return; 9587c478bd9Sstevel@tonic-gate 9592269adc8Sszhou /* default solaris configfile name menu.lst.01<ether_addr> */ 9602269adc8Sszhou grub_strcpy(c, "menu.lst.01"); 9617c478bd9Sstevel@tonic-gate c += grub_strlen(c); 9627c478bd9Sstevel@tonic-gate for (i = 0; i < ETH_ALEN; i++) { 9637c478bd9Sstevel@tonic-gate unsigned char b = arptable[ARP_CLIENT].node[i]; 9647c478bd9Sstevel@tonic-gate *c++ = hexdigit[b >> 4]; 9657c478bd9Sstevel@tonic-gate *c++ = hexdigit[b & 0xf]; 9667c478bd9Sstevel@tonic-gate } 9677c478bd9Sstevel@tonic-gate *c = 0; 9687c478bd9Sstevel@tonic-gate 9696759d08fScasper /* 9706759d08fScasper * If the file exists, make it the default. Else, fallback 9716759d08fScasper * to what it was. Make sure we don't change errnum in the 9726759d08fScasper * process. 9737c478bd9Sstevel@tonic-gate */ 9746759d08fScasper err = errnum; 9757c478bd9Sstevel@tonic-gate if (grub_open(menufile)) { 9767c478bd9Sstevel@tonic-gate grub_strcpy(config_file, menufile); 9777c478bd9Sstevel@tonic-gate grub_close(); 9782269adc8Sszhou } else { 9792269adc8Sszhou char *cp = config_file; 9802269adc8Sszhou /* skip leading slashes for tftp */ 981266095caSszhou while (*cp == '/') 982266095caSszhou ++cp; 9832269adc8Sszhou grub_memmove (config_file, cp, strlen(cp) + 1); 9847c478bd9Sstevel@tonic-gate } 9856759d08fScasper errnum = err; 9867c478bd9Sstevel@tonic-gate } 9877c478bd9Sstevel@tonic-gate 9887c478bd9Sstevel@tonic-gate static struct builtin builtin_dhcp = 9897c478bd9Sstevel@tonic-gate { 9907c478bd9Sstevel@tonic-gate "dhcp", 9917c478bd9Sstevel@tonic-gate dhcp_func, 9927c478bd9Sstevel@tonic-gate BUILTIN_CMDLINE | BUILTIN_MENU | BUILTIN_HELP_LIST, 9937c478bd9Sstevel@tonic-gate "dhcp", 9947c478bd9Sstevel@tonic-gate "Initialize a network device via DHCP." 9957c478bd9Sstevel@tonic-gate }; 9967c478bd9Sstevel@tonic-gate #endif /* SUPPORT_NETBOOT */ 9977c478bd9Sstevel@tonic-gate 9987c478bd9Sstevel@tonic-gate static int terminal_func (char *arg, int flags); 9997c478bd9Sstevel@tonic-gate 10001fac5a60Ssetje static int verbose_func(char *arg, int flags) { 10011fac5a60Ssetje 10021fac5a60Ssetje if (grub_strcmp(arg, "off") == 0) { 10031fac5a60Ssetje silent.status = DEFER_SILENT; 10041fac5a60Ssetje return; 10051fac5a60Ssetje } else 10061fac5a60Ssetje if (flags == BUILTIN_CMDLINE) { 10071fac5a60Ssetje silent.status = DEFER_VERBOSE; 10081fac5a60Ssetje return; 10091fac5a60Ssetje } 10101fac5a60Ssetje 10111fac5a60Ssetje silent.status = VERBOSE; 10121fac5a60Ssetje 1013ae115bc7Smrj /* get back to text console */ 10141fac5a60Ssetje if (current_term->shutdown) { 10151fac5a60Ssetje (*current_term->shutdown)(); 10161fac5a60Ssetje current_term = term_table; /* assumption: console is first */ 10171fac5a60Ssetje } 10181fac5a60Ssetje 10191fac5a60Ssetje /* dump the buffer */ 10201fac5a60Ssetje if (!silent.looped) { 10211fac5a60Ssetje /* if the buffer hasn't looped, just print it */ 10221fac5a60Ssetje printf("%s", silent.buffer); 10231fac5a60Ssetje } else { 10241fac5a60Ssetje /* 10251fac5a60Ssetje * If the buffer has looped, first print the oldest part of the buffer, 10261fac5a60Ssetje * which is one past the current null. Then print the newer part which 10271fac5a60Ssetje * starts at the beginning of the buffer. 10281fac5a60Ssetje */ 10291fac5a60Ssetje printf("%s", silent.buffer_start + 1); 10301fac5a60Ssetje printf("%s", silent.buffer); 10311fac5a60Ssetje } 10321fac5a60Ssetje 10331fac5a60Ssetje return 0; 10341fac5a60Ssetje } 10351fac5a60Ssetje 10361fac5a60Ssetje static struct builtin builtin_verbose = 10371fac5a60Ssetje { 10381fac5a60Ssetje "verbose", 10391fac5a60Ssetje verbose_func, 10401fac5a60Ssetje BUILTIN_CMDLINE | BUILTIN_MENU | BUILTIN_SCRIPT | BUILTIN_HELP_LIST, 10411fac5a60Ssetje "verbose", 10421fac5a60Ssetje "Verbose output during menu entry (script) execution." 10431fac5a60Ssetje }; 10441fac5a60Ssetje 10457c478bd9Sstevel@tonic-gate #ifdef SUPPORT_GRAPHICS 10467c478bd9Sstevel@tonic-gate 10477c478bd9Sstevel@tonic-gate static int splashimage_func(char *arg, int flags) { 10487c478bd9Sstevel@tonic-gate char splashimage[64]; 10497c478bd9Sstevel@tonic-gate int i; 10501fac5a60Ssetje 10517c478bd9Sstevel@tonic-gate /* filename can only be 64 characters due to our buffer size */ 10527c478bd9Sstevel@tonic-gate if (strlen(arg) > 63) 10537c478bd9Sstevel@tonic-gate return 1; 10547c478bd9Sstevel@tonic-gate 10551fac5a60Ssetje if (flags == BUILTIN_SCRIPT) 10561fac5a60Ssetje flags = BUILTIN_CMDLINE; 10571fac5a60Ssetje 10587c478bd9Sstevel@tonic-gate strcpy(splashimage, arg); 10597c478bd9Sstevel@tonic-gate 1060*41c4174fSWilliam Kucharski if (!graphics_set_splash(splashimage)) 1061*41c4174fSWilliam Kucharski return 1; 1062*41c4174fSWilliam Kucharski 10637c478bd9Sstevel@tonic-gate /* get rid of TERM_NEED_INIT from the graphics terminal. */ 10647c478bd9Sstevel@tonic-gate for (i = 0; term_table[i].name; i++) { 10657c478bd9Sstevel@tonic-gate if (grub_strcmp (term_table[i].name, "graphics") == 0) { 10667c478bd9Sstevel@tonic-gate term_table[i].flags &= ~TERM_NEED_INIT; 10677c478bd9Sstevel@tonic-gate break; 10687c478bd9Sstevel@tonic-gate } 10697c478bd9Sstevel@tonic-gate } 10707c478bd9Sstevel@tonic-gate 10717c478bd9Sstevel@tonic-gate if (flags == BUILTIN_CMDLINE && graphics_inited) { 10721fac5a60Ssetje /* 10731fac5a60Ssetje * calling graphics_end() here flickers the screen black. OTOH not 10741fac5a60Ssetje * calling it gets us odd plane interlacing / early palette switching ? 10751fac5a60Ssetje * ideally one should figure out how to double buffer and switch... 10761fac5a60Ssetje */ 10777c478bd9Sstevel@tonic-gate graphics_end(); 10787c478bd9Sstevel@tonic-gate graphics_init(); 10797c478bd9Sstevel@tonic-gate graphics_cls(); 10807c478bd9Sstevel@tonic-gate } 10817c478bd9Sstevel@tonic-gate 10827c478bd9Sstevel@tonic-gate /* FIXME: should we be explicitly switching the terminal as a 10837c478bd9Sstevel@tonic-gate * side effect here? */ 10847c478bd9Sstevel@tonic-gate terminal_func("graphics", flags); 10857c478bd9Sstevel@tonic-gate 10861fac5a60Ssetje reset_term = 0; 10871fac5a60Ssetje 10887c478bd9Sstevel@tonic-gate return 0; 10897c478bd9Sstevel@tonic-gate } 10907c478bd9Sstevel@tonic-gate 10917c478bd9Sstevel@tonic-gate static struct builtin builtin_splashimage = 10927c478bd9Sstevel@tonic-gate { 10937c478bd9Sstevel@tonic-gate "splashimage", 10947c478bd9Sstevel@tonic-gate splashimage_func, 10951fac5a60Ssetje BUILTIN_CMDLINE | BUILTIN_MENU | BUILTIN_SCRIPT | BUILTIN_HELP_LIST, 10967c478bd9Sstevel@tonic-gate "splashimage FILE", 10977c478bd9Sstevel@tonic-gate "Load FILE as the background image when in graphics mode." 10987c478bd9Sstevel@tonic-gate }; 10997c478bd9Sstevel@tonic-gate 11007c478bd9Sstevel@tonic-gate 11017c478bd9Sstevel@tonic-gate /* foreground */ 11027c478bd9Sstevel@tonic-gate static int 11037c478bd9Sstevel@tonic-gate foreground_func(char *arg, int flags) 11047c478bd9Sstevel@tonic-gate { 11057c478bd9Sstevel@tonic-gate if (grub_strlen(arg) == 6) { 11067c478bd9Sstevel@tonic-gate int r = ((hex(arg[0]) << 4) | hex(arg[1])) >> 2; 11077c478bd9Sstevel@tonic-gate int g = ((hex(arg[2]) << 4) | hex(arg[3])) >> 2; 11087c478bd9Sstevel@tonic-gate int b = ((hex(arg[4]) << 4) | hex(arg[5])) >> 2; 11097c478bd9Sstevel@tonic-gate 11107c478bd9Sstevel@tonic-gate foreground = (r << 16) | (g << 8) | b; 11117c478bd9Sstevel@tonic-gate if (graphics_inited) 11127c478bd9Sstevel@tonic-gate graphics_set_palette(15, r, g, b); 11137c478bd9Sstevel@tonic-gate 11147c478bd9Sstevel@tonic-gate return (0); 11157c478bd9Sstevel@tonic-gate } 11167c478bd9Sstevel@tonic-gate 11177c478bd9Sstevel@tonic-gate return (1); 11187c478bd9Sstevel@tonic-gate } 11197c478bd9Sstevel@tonic-gate 11207c478bd9Sstevel@tonic-gate static struct builtin builtin_foreground = 11217c478bd9Sstevel@tonic-gate { 11227c478bd9Sstevel@tonic-gate "foreground", 11237c478bd9Sstevel@tonic-gate foreground_func, 112467ce1dadSJan Setje-Eilers BUILTIN_CMDLINE | BUILTIN_MENU | BUILTIN_HELP_LIST | BUILTIN_SCRIPT, 11257c478bd9Sstevel@tonic-gate "foreground RRGGBB", 11267c478bd9Sstevel@tonic-gate "Sets the foreground color when in graphics mode." 11277c478bd9Sstevel@tonic-gate "RR is red, GG is green, and BB blue. Numbers must be in hexadecimal." 11287c478bd9Sstevel@tonic-gate }; 11297c478bd9Sstevel@tonic-gate 11307c478bd9Sstevel@tonic-gate 11317c478bd9Sstevel@tonic-gate /* background */ 11327c478bd9Sstevel@tonic-gate static int 11337c478bd9Sstevel@tonic-gate background_func(char *arg, int flags) 11347c478bd9Sstevel@tonic-gate { 11357c478bd9Sstevel@tonic-gate if (grub_strlen(arg) == 6) { 11367c478bd9Sstevel@tonic-gate int r = ((hex(arg[0]) << 4) | hex(arg[1])) >> 2; 11377c478bd9Sstevel@tonic-gate int g = ((hex(arg[2]) << 4) | hex(arg[3])) >> 2; 11387c478bd9Sstevel@tonic-gate int b = ((hex(arg[4]) << 4) | hex(arg[5])) >> 2; 11397c478bd9Sstevel@tonic-gate 11407c478bd9Sstevel@tonic-gate background = (r << 16) | (g << 8) | b; 11417c478bd9Sstevel@tonic-gate if (graphics_inited) 11427c478bd9Sstevel@tonic-gate graphics_set_palette(0, r, g, b); 11437c478bd9Sstevel@tonic-gate return (0); 11447c478bd9Sstevel@tonic-gate } 11457c478bd9Sstevel@tonic-gate 11467c478bd9Sstevel@tonic-gate return (1); 11477c478bd9Sstevel@tonic-gate } 11487c478bd9Sstevel@tonic-gate 11497c478bd9Sstevel@tonic-gate static struct builtin builtin_background = 11507c478bd9Sstevel@tonic-gate { 11517c478bd9Sstevel@tonic-gate "background", 11527c478bd9Sstevel@tonic-gate background_func, 115367ce1dadSJan Setje-Eilers BUILTIN_CMDLINE | BUILTIN_MENU | BUILTIN_HELP_LIST | BUILTIN_SCRIPT, 11547c478bd9Sstevel@tonic-gate "background RRGGBB", 11557c478bd9Sstevel@tonic-gate "Sets the background color when in graphics mode." 11567c478bd9Sstevel@tonic-gate "RR is red, GG is green, and BB blue. Numbers must be in hexadecimal." 11577c478bd9Sstevel@tonic-gate }; 11587c478bd9Sstevel@tonic-gate 11597c478bd9Sstevel@tonic-gate #endif /* SUPPORT_GRAPHICS */ 11607c478bd9Sstevel@tonic-gate 11617c478bd9Sstevel@tonic-gate 11627c478bd9Sstevel@tonic-gate /* clear */ 11637c478bd9Sstevel@tonic-gate static int 11647c478bd9Sstevel@tonic-gate clear_func() 11657c478bd9Sstevel@tonic-gate { 11667c478bd9Sstevel@tonic-gate if (current_term->cls) 11677c478bd9Sstevel@tonic-gate current_term->cls(); 11687c478bd9Sstevel@tonic-gate 11697c478bd9Sstevel@tonic-gate return 0; 11707c478bd9Sstevel@tonic-gate } 11717c478bd9Sstevel@tonic-gate 11727c478bd9Sstevel@tonic-gate static struct builtin builtin_clear = 11737c478bd9Sstevel@tonic-gate { 11747c478bd9Sstevel@tonic-gate "clear", 11757c478bd9Sstevel@tonic-gate clear_func, 11767c478bd9Sstevel@tonic-gate BUILTIN_CMDLINE | BUILTIN_HELP_LIST, 11777c478bd9Sstevel@tonic-gate "clear", 11787c478bd9Sstevel@tonic-gate "Clear the screen" 11797c478bd9Sstevel@tonic-gate }; 11807c478bd9Sstevel@tonic-gate 11817c478bd9Sstevel@tonic-gate /* displayapm */ 11827c478bd9Sstevel@tonic-gate static int 11837c478bd9Sstevel@tonic-gate displayapm_func (char *arg, int flags) 11847c478bd9Sstevel@tonic-gate { 11857c478bd9Sstevel@tonic-gate if (mbi.flags & MB_INFO_APM_TABLE) 11867c478bd9Sstevel@tonic-gate { 11877c478bd9Sstevel@tonic-gate grub_printf ("APM BIOS information:\n" 11887c478bd9Sstevel@tonic-gate " Version: 0x%x\n" 11897c478bd9Sstevel@tonic-gate " 32-bit CS: 0x%x\n" 11907c478bd9Sstevel@tonic-gate " Offset: 0x%x\n" 11917c478bd9Sstevel@tonic-gate " 16-bit CS: 0x%x\n" 11927c478bd9Sstevel@tonic-gate " 16-bit DS: 0x%x\n" 11937c478bd9Sstevel@tonic-gate " 32-bit CS length: 0x%x\n" 11947c478bd9Sstevel@tonic-gate " 16-bit CS length: 0x%x\n" 11957c478bd9Sstevel@tonic-gate " 16-bit DS length: 0x%x\n", 11967c478bd9Sstevel@tonic-gate (unsigned) apm_bios_info.version, 11977c478bd9Sstevel@tonic-gate (unsigned) apm_bios_info.cseg, 11987c478bd9Sstevel@tonic-gate apm_bios_info.offset, 11997c478bd9Sstevel@tonic-gate (unsigned) apm_bios_info.cseg_16, 12007c478bd9Sstevel@tonic-gate (unsigned) apm_bios_info.dseg_16, 12017c478bd9Sstevel@tonic-gate (unsigned) apm_bios_info.cseg_len, 12027c478bd9Sstevel@tonic-gate (unsigned) apm_bios_info.cseg_16_len, 12037c478bd9Sstevel@tonic-gate (unsigned) apm_bios_info.dseg_16_len); 12047c478bd9Sstevel@tonic-gate } 12057c478bd9Sstevel@tonic-gate else 12067c478bd9Sstevel@tonic-gate { 12077c478bd9Sstevel@tonic-gate grub_printf ("No APM BIOS found or probe failed\n"); 12087c478bd9Sstevel@tonic-gate } 12097c478bd9Sstevel@tonic-gate 12107c478bd9Sstevel@tonic-gate return 0; 12117c478bd9Sstevel@tonic-gate } 12127c478bd9Sstevel@tonic-gate 12137c478bd9Sstevel@tonic-gate static struct builtin builtin_displayapm = 12147c478bd9Sstevel@tonic-gate { 12157c478bd9Sstevel@tonic-gate "displayapm", 12167c478bd9Sstevel@tonic-gate displayapm_func, 12177c478bd9Sstevel@tonic-gate BUILTIN_CMDLINE | BUILTIN_HELP_LIST, 12187c478bd9Sstevel@tonic-gate "displayapm", 12197c478bd9Sstevel@tonic-gate "Display APM BIOS information." 12207c478bd9Sstevel@tonic-gate }; 12217c478bd9Sstevel@tonic-gate 12227c478bd9Sstevel@tonic-gate 12237c478bd9Sstevel@tonic-gate /* displaymem */ 12247c478bd9Sstevel@tonic-gate static int 12257c478bd9Sstevel@tonic-gate displaymem_func (char *arg, int flags) 12267c478bd9Sstevel@tonic-gate { 12277c478bd9Sstevel@tonic-gate if (get_eisamemsize () != -1) 12287c478bd9Sstevel@tonic-gate grub_printf (" EISA Memory BIOS Interface is present\n"); 12297c478bd9Sstevel@tonic-gate if (get_mmap_entry ((void *) SCRATCHADDR, 0) != 0 12307c478bd9Sstevel@tonic-gate || *((int *) SCRATCHADDR) != 0) 12317c478bd9Sstevel@tonic-gate grub_printf (" Address Map BIOS Interface is present\n"); 12327c478bd9Sstevel@tonic-gate 12337c478bd9Sstevel@tonic-gate grub_printf (" Lower memory: %uK, " 12347c478bd9Sstevel@tonic-gate "Upper memory (to first chipset hole): %uK\n", 12357c478bd9Sstevel@tonic-gate mbi.mem_lower, mbi.mem_upper); 12367c478bd9Sstevel@tonic-gate 1237342440ecSPrasad Singamsetty if (min_mem64 != 0) 1238342440ecSPrasad Singamsetty grub_printf (" Memory limit for 64-bit ISADIR expansion: %uMB\n", 1239342440ecSPrasad Singamsetty min_mem64); 1240342440ecSPrasad Singamsetty 12417c478bd9Sstevel@tonic-gate if (mbi.flags & MB_INFO_MEM_MAP) 12427c478bd9Sstevel@tonic-gate { 12437c478bd9Sstevel@tonic-gate struct AddrRangeDesc *map = (struct AddrRangeDesc *) mbi.mmap_addr; 12447c478bd9Sstevel@tonic-gate int end_addr = mbi.mmap_addr + mbi.mmap_length; 12457c478bd9Sstevel@tonic-gate 12467c478bd9Sstevel@tonic-gate grub_printf (" [Address Range Descriptor entries " 12477c478bd9Sstevel@tonic-gate "immediately follow (values are 64-bit)]\n"); 12487c478bd9Sstevel@tonic-gate while (end_addr > (int) map) 12497c478bd9Sstevel@tonic-gate { 12507c478bd9Sstevel@tonic-gate char *str; 12517c478bd9Sstevel@tonic-gate 12527c478bd9Sstevel@tonic-gate if (map->Type == MB_ARD_MEMORY) 12537c478bd9Sstevel@tonic-gate str = "Usable RAM"; 12547c478bd9Sstevel@tonic-gate else 12557c478bd9Sstevel@tonic-gate str = "Reserved"; 12567c478bd9Sstevel@tonic-gate grub_printf (" %s: Base Address: 0x%x X 4GB + 0x%x,\n" 1257342440ecSPrasad Singamsetty " Length: 0x%x X 4GB + 0x%x bytes\n", 1258342440ecSPrasad Singamsetty str, 1259342440ecSPrasad Singamsetty (unsigned long) (map->BaseAddr >> 32), 1260342440ecSPrasad Singamsetty (unsigned long) (map->BaseAddr & 0xFFFFFFFF), 1261342440ecSPrasad Singamsetty (unsigned long) (map->Length >> 32), 1262342440ecSPrasad Singamsetty (unsigned long) (map->Length & 0xFFFFFFFF)); 12637c478bd9Sstevel@tonic-gate 12647c478bd9Sstevel@tonic-gate map = ((struct AddrRangeDesc *) (((int) map) + 4 + map->size)); 12657c478bd9Sstevel@tonic-gate } 12667c478bd9Sstevel@tonic-gate } 12677c478bd9Sstevel@tonic-gate 12687c478bd9Sstevel@tonic-gate return 0; 12697c478bd9Sstevel@tonic-gate } 12707c478bd9Sstevel@tonic-gate 12717c478bd9Sstevel@tonic-gate static struct builtin builtin_displaymem = 12727c478bd9Sstevel@tonic-gate { 12737c478bd9Sstevel@tonic-gate "displaymem", 12747c478bd9Sstevel@tonic-gate displaymem_func, 12757c478bd9Sstevel@tonic-gate BUILTIN_CMDLINE | BUILTIN_HELP_LIST, 12767c478bd9Sstevel@tonic-gate "displaymem", 12777c478bd9Sstevel@tonic-gate "Display what GRUB thinks the system address space map of the" 12787c478bd9Sstevel@tonic-gate " machine is, including all regions of physical RAM installed." 12797c478bd9Sstevel@tonic-gate }; 12807c478bd9Sstevel@tonic-gate 12817c478bd9Sstevel@tonic-gate 12827c478bd9Sstevel@tonic-gate /* dump FROM TO */ 12837c478bd9Sstevel@tonic-gate #ifdef GRUB_UTIL 12847c478bd9Sstevel@tonic-gate static int 12857c478bd9Sstevel@tonic-gate dump_func (char *arg, int flags) 12867c478bd9Sstevel@tonic-gate { 12877c478bd9Sstevel@tonic-gate char *from, *to; 12887c478bd9Sstevel@tonic-gate FILE *fp; 12897c478bd9Sstevel@tonic-gate char c; 12907c478bd9Sstevel@tonic-gate 12917c478bd9Sstevel@tonic-gate from = arg; 12927c478bd9Sstevel@tonic-gate to = skip_to (0, arg); 12937c478bd9Sstevel@tonic-gate if (! *from || ! *to) 12947c478bd9Sstevel@tonic-gate { 12957c478bd9Sstevel@tonic-gate errnum = ERR_BAD_ARGUMENT; 12967c478bd9Sstevel@tonic-gate return 1; 12977c478bd9Sstevel@tonic-gate } 12987c478bd9Sstevel@tonic-gate 12997c478bd9Sstevel@tonic-gate nul_terminate (from); 13007c478bd9Sstevel@tonic-gate nul_terminate (to); 13017c478bd9Sstevel@tonic-gate 13027c478bd9Sstevel@tonic-gate if (! grub_open (from)) 13037c478bd9Sstevel@tonic-gate return 1; 13047c478bd9Sstevel@tonic-gate 13057c478bd9Sstevel@tonic-gate fp = fopen (to, "w"); 13067c478bd9Sstevel@tonic-gate if (! fp) 13077c478bd9Sstevel@tonic-gate { 13087c478bd9Sstevel@tonic-gate errnum = ERR_WRITE; 13097c478bd9Sstevel@tonic-gate return 1; 13107c478bd9Sstevel@tonic-gate } 13117c478bd9Sstevel@tonic-gate 13127c478bd9Sstevel@tonic-gate while (grub_read (&c, 1)) 13137c478bd9Sstevel@tonic-gate if (fputc (c, fp) == EOF) 13147c478bd9Sstevel@tonic-gate { 13157c478bd9Sstevel@tonic-gate errnum = ERR_WRITE; 13167c478bd9Sstevel@tonic-gate fclose (fp); 13177c478bd9Sstevel@tonic-gate return 1; 13187c478bd9Sstevel@tonic-gate } 13197c478bd9Sstevel@tonic-gate 13207c478bd9Sstevel@tonic-gate if (fclose (fp) == EOF) 13217c478bd9Sstevel@tonic-gate { 13227c478bd9Sstevel@tonic-gate errnum = ERR_WRITE; 13237c478bd9Sstevel@tonic-gate return 1; 13247c478bd9Sstevel@tonic-gate } 13257c478bd9Sstevel@tonic-gate 13267c478bd9Sstevel@tonic-gate grub_close (); 13277c478bd9Sstevel@tonic-gate return 0; 13287c478bd9Sstevel@tonic-gate } 13297c478bd9Sstevel@tonic-gate 13307c478bd9Sstevel@tonic-gate static struct builtin builtin_dump = 13317c478bd9Sstevel@tonic-gate { 13327c478bd9Sstevel@tonic-gate "dump", 13337c478bd9Sstevel@tonic-gate dump_func, 13347c478bd9Sstevel@tonic-gate BUILTIN_CMDLINE, 13357c478bd9Sstevel@tonic-gate "dump FROM TO", 13367c478bd9Sstevel@tonic-gate "Dump the contents of the file FROM to the file TO. FROM must be" 13377c478bd9Sstevel@tonic-gate " a GRUB file and TO must be an OS file." 13387c478bd9Sstevel@tonic-gate }; 13397c478bd9Sstevel@tonic-gate #endif /* GRUB_UTIL */ 13407c478bd9Sstevel@tonic-gate 13417c478bd9Sstevel@tonic-gate 13427c478bd9Sstevel@tonic-gate static char embed_info[32]; 13437c478bd9Sstevel@tonic-gate /* embed */ 13447c478bd9Sstevel@tonic-gate /* Embed a Stage 1.5 in the first cylinder after MBR or in the 13457c478bd9Sstevel@tonic-gate bootloader block in a FFS. */ 13467c478bd9Sstevel@tonic-gate static int 13477c478bd9Sstevel@tonic-gate embed_func (char *arg, int flags) 13487c478bd9Sstevel@tonic-gate { 13497c478bd9Sstevel@tonic-gate char *stage1_5; 13507c478bd9Sstevel@tonic-gate char *device; 13517c478bd9Sstevel@tonic-gate char *stage1_5_buffer = (char *) RAW_ADDR (0x100000); 13527c478bd9Sstevel@tonic-gate int len, size; 13537c478bd9Sstevel@tonic-gate int sector; 13547c478bd9Sstevel@tonic-gate 13557c478bd9Sstevel@tonic-gate stage1_5 = arg; 13567c478bd9Sstevel@tonic-gate device = skip_to (0, stage1_5); 13577c478bd9Sstevel@tonic-gate 13587c478bd9Sstevel@tonic-gate /* Open a Stage 1.5. */ 13597c478bd9Sstevel@tonic-gate if (! grub_open (stage1_5)) 13607c478bd9Sstevel@tonic-gate return 1; 13617c478bd9Sstevel@tonic-gate 13627c478bd9Sstevel@tonic-gate /* Read the whole of the Stage 1.5. */ 13637c478bd9Sstevel@tonic-gate len = grub_read (stage1_5_buffer, -1); 13647c478bd9Sstevel@tonic-gate grub_close (); 13657c478bd9Sstevel@tonic-gate 13667c478bd9Sstevel@tonic-gate if (errnum) 13677c478bd9Sstevel@tonic-gate return 1; 13687c478bd9Sstevel@tonic-gate 13697c478bd9Sstevel@tonic-gate size = (len + SECTOR_SIZE - 1) / SECTOR_SIZE; 13707c478bd9Sstevel@tonic-gate 13717c478bd9Sstevel@tonic-gate /* Get the device where the Stage 1.5 will be embedded. */ 13727c478bd9Sstevel@tonic-gate set_device (device); 13737c478bd9Sstevel@tonic-gate if (errnum) 13747c478bd9Sstevel@tonic-gate return 1; 13757c478bd9Sstevel@tonic-gate 13767c478bd9Sstevel@tonic-gate if (current_partition == 0xFFFFFF) 13777c478bd9Sstevel@tonic-gate { 13787c478bd9Sstevel@tonic-gate /* Embed it after the MBR. */ 13797c478bd9Sstevel@tonic-gate 13807c478bd9Sstevel@tonic-gate char mbr[SECTOR_SIZE]; 13817c478bd9Sstevel@tonic-gate char ezbios_check[2*SECTOR_SIZE]; 13827c478bd9Sstevel@tonic-gate int i; 13837c478bd9Sstevel@tonic-gate 13847c478bd9Sstevel@tonic-gate /* Open the partition. */ 13857c478bd9Sstevel@tonic-gate if (! open_partition ()) 13867c478bd9Sstevel@tonic-gate return 1; 13877c478bd9Sstevel@tonic-gate 13887c478bd9Sstevel@tonic-gate /* No floppy has MBR. */ 13897c478bd9Sstevel@tonic-gate if (! (current_drive & 0x80)) 13907c478bd9Sstevel@tonic-gate { 13917c478bd9Sstevel@tonic-gate errnum = ERR_DEV_VALUES; 13927c478bd9Sstevel@tonic-gate return 1; 13937c478bd9Sstevel@tonic-gate } 13947c478bd9Sstevel@tonic-gate 13957c478bd9Sstevel@tonic-gate /* Read the MBR of CURRENT_DRIVE. */ 13967c478bd9Sstevel@tonic-gate if (! rawread (current_drive, PC_MBR_SECTOR, 0, SECTOR_SIZE, mbr)) 13977c478bd9Sstevel@tonic-gate return 1; 13987c478bd9Sstevel@tonic-gate 13997c478bd9Sstevel@tonic-gate /* Sanity check. */ 14007c478bd9Sstevel@tonic-gate if (! PC_MBR_CHECK_SIG (mbr)) 14017c478bd9Sstevel@tonic-gate { 14027c478bd9Sstevel@tonic-gate errnum = ERR_BAD_PART_TABLE; 14037c478bd9Sstevel@tonic-gate return 1; 14047c478bd9Sstevel@tonic-gate } 14057c478bd9Sstevel@tonic-gate 14067c478bd9Sstevel@tonic-gate /* Check if the disk can store the Stage 1.5. */ 14077c478bd9Sstevel@tonic-gate for (i = 0; i < 4; i++) 14087c478bd9Sstevel@tonic-gate if (PC_SLICE_TYPE (mbr, i) && PC_SLICE_START (mbr, i) - 1 < size) 14097c478bd9Sstevel@tonic-gate { 14107c478bd9Sstevel@tonic-gate errnum = ERR_NO_DISK_SPACE; 14117c478bd9Sstevel@tonic-gate return 1; 14127c478bd9Sstevel@tonic-gate } 14137c478bd9Sstevel@tonic-gate 14147c478bd9Sstevel@tonic-gate /* Check for EZ-BIOS signature. It should be in the third 14157c478bd9Sstevel@tonic-gate * sector, but due to remapping it can appear in the second, so 14167c478bd9Sstevel@tonic-gate * load and check both. 14177c478bd9Sstevel@tonic-gate */ 14187c478bd9Sstevel@tonic-gate if (! rawread (current_drive, 1, 0, 2 * SECTOR_SIZE, ezbios_check)) 14197c478bd9Sstevel@tonic-gate return 1; 14207c478bd9Sstevel@tonic-gate 14217c478bd9Sstevel@tonic-gate if (! memcmp (ezbios_check + 3, "AERMH", 5) 14227c478bd9Sstevel@tonic-gate || ! memcmp (ezbios_check + 512 + 3, "AERMH", 5)) 14237c478bd9Sstevel@tonic-gate { 14247c478bd9Sstevel@tonic-gate /* The space after the MBR is used by EZ-BIOS which we must 14257c478bd9Sstevel@tonic-gate * not overwrite. 14267c478bd9Sstevel@tonic-gate */ 14277c478bd9Sstevel@tonic-gate errnum = ERR_NO_DISK_SPACE; 14287c478bd9Sstevel@tonic-gate return 1; 14297c478bd9Sstevel@tonic-gate } 14307c478bd9Sstevel@tonic-gate 14317c478bd9Sstevel@tonic-gate sector = 1; 14327c478bd9Sstevel@tonic-gate } 14337c478bd9Sstevel@tonic-gate else 14347c478bd9Sstevel@tonic-gate { 14357c478bd9Sstevel@tonic-gate /* Embed it in the bootloader block in the filesystem. */ 14367c478bd9Sstevel@tonic-gate int start_sector; 14377c478bd9Sstevel@tonic-gate 14387c478bd9Sstevel@tonic-gate /* Open the partition. */ 14397c478bd9Sstevel@tonic-gate if (! open_device ()) 14407c478bd9Sstevel@tonic-gate return 1; 14417c478bd9Sstevel@tonic-gate 14427c478bd9Sstevel@tonic-gate /* Check if the current slice supports embedding. */ 14437c478bd9Sstevel@tonic-gate if (fsys_table[fsys_type].embed_func == 0 14447c478bd9Sstevel@tonic-gate || ! fsys_table[fsys_type].embed_func (&start_sector, size)) 14457c478bd9Sstevel@tonic-gate { 14467c478bd9Sstevel@tonic-gate errnum = ERR_DEV_VALUES; 14477c478bd9Sstevel@tonic-gate return 1; 14487c478bd9Sstevel@tonic-gate } 14497c478bd9Sstevel@tonic-gate 14507c478bd9Sstevel@tonic-gate sector = part_start + start_sector; 14517c478bd9Sstevel@tonic-gate } 14527c478bd9Sstevel@tonic-gate 14537c478bd9Sstevel@tonic-gate /* Clear the cache. */ 1454342440ecSPrasad Singamsetty buf_track = BUF_CACHE_INVALID; 14557c478bd9Sstevel@tonic-gate 14567c478bd9Sstevel@tonic-gate /* Now perform the embedding. */ 14577c478bd9Sstevel@tonic-gate if (! devwrite (sector - part_start, size, stage1_5_buffer)) 14587c478bd9Sstevel@tonic-gate return 1; 14597c478bd9Sstevel@tonic-gate 14607c478bd9Sstevel@tonic-gate grub_printf (" %d sectors are embedded.\n", size); 14617c478bd9Sstevel@tonic-gate grub_sprintf (embed_info, "%d+%d", sector - part_start, size); 14627c478bd9Sstevel@tonic-gate return 0; 14637c478bd9Sstevel@tonic-gate } 14647c478bd9Sstevel@tonic-gate 14657c478bd9Sstevel@tonic-gate static struct builtin builtin_embed = 14667c478bd9Sstevel@tonic-gate { 14677c478bd9Sstevel@tonic-gate "embed", 14687c478bd9Sstevel@tonic-gate embed_func, 14697c478bd9Sstevel@tonic-gate BUILTIN_CMDLINE, 14707c478bd9Sstevel@tonic-gate "embed STAGE1_5 DEVICE", 14717c478bd9Sstevel@tonic-gate "Embed the Stage 1.5 STAGE1_5 in the sectors after MBR if DEVICE" 14727c478bd9Sstevel@tonic-gate " is a drive, or in the \"bootloader\" area if DEVICE is a FFS partition." 14737c478bd9Sstevel@tonic-gate " Print the number of sectors which STAGE1_5 occupies if successful." 14747c478bd9Sstevel@tonic-gate }; 14757c478bd9Sstevel@tonic-gate 14767c478bd9Sstevel@tonic-gate 14777c478bd9Sstevel@tonic-gate /* fallback */ 14787c478bd9Sstevel@tonic-gate static int 14797c478bd9Sstevel@tonic-gate fallback_func (char *arg, int flags) 14807c478bd9Sstevel@tonic-gate { 14817c478bd9Sstevel@tonic-gate int i = 0; 14827c478bd9Sstevel@tonic-gate 14837c478bd9Sstevel@tonic-gate while (*arg) 14847c478bd9Sstevel@tonic-gate { 14857c478bd9Sstevel@tonic-gate int entry; 14867c478bd9Sstevel@tonic-gate int j; 14877c478bd9Sstevel@tonic-gate 14887c478bd9Sstevel@tonic-gate if (! safe_parse_maxint (&arg, &entry)) 14897c478bd9Sstevel@tonic-gate return 1; 14907c478bd9Sstevel@tonic-gate 14917c478bd9Sstevel@tonic-gate /* Remove duplications to prevent infinite looping. */ 14927c478bd9Sstevel@tonic-gate for (j = 0; j < i; j++) 14937c478bd9Sstevel@tonic-gate if (entry == fallback_entries[j]) 14947c478bd9Sstevel@tonic-gate break; 14957c478bd9Sstevel@tonic-gate if (j != i) 14967c478bd9Sstevel@tonic-gate continue; 14977c478bd9Sstevel@tonic-gate 14987c478bd9Sstevel@tonic-gate fallback_entries[i++] = entry; 14997c478bd9Sstevel@tonic-gate if (i == MAX_FALLBACK_ENTRIES) 15007c478bd9Sstevel@tonic-gate break; 15017c478bd9Sstevel@tonic-gate 15027c478bd9Sstevel@tonic-gate arg = skip_to (0, arg); 15037c478bd9Sstevel@tonic-gate } 15047c478bd9Sstevel@tonic-gate 15057c478bd9Sstevel@tonic-gate if (i < MAX_FALLBACK_ENTRIES) 15067c478bd9Sstevel@tonic-gate fallback_entries[i] = -1; 15077c478bd9Sstevel@tonic-gate 15087c478bd9Sstevel@tonic-gate fallback_entryno = (i == 0) ? -1 : 0; 15097c478bd9Sstevel@tonic-gate 15107c478bd9Sstevel@tonic-gate return 0; 15117c478bd9Sstevel@tonic-gate } 15127c478bd9Sstevel@tonic-gate 15137c478bd9Sstevel@tonic-gate static struct builtin builtin_fallback = 15147c478bd9Sstevel@tonic-gate { 15157c478bd9Sstevel@tonic-gate "fallback", 15167c478bd9Sstevel@tonic-gate fallback_func, 15177c478bd9Sstevel@tonic-gate BUILTIN_MENU, 15187c478bd9Sstevel@tonic-gate #if 0 15197c478bd9Sstevel@tonic-gate "fallback NUM...", 15207c478bd9Sstevel@tonic-gate "Go into unattended boot mode: if the default boot entry has any" 15217c478bd9Sstevel@tonic-gate " errors, instead of waiting for the user to do anything, it" 15227c478bd9Sstevel@tonic-gate " immediately starts over using the NUM entry (same numbering as the" 15237c478bd9Sstevel@tonic-gate " `default' command). This obviously won't help if the machine" 15247c478bd9Sstevel@tonic-gate " was rebooted by a kernel that GRUB loaded." 15257c478bd9Sstevel@tonic-gate #endif 15267c478bd9Sstevel@tonic-gate }; 15277c478bd9Sstevel@tonic-gate 15287c478bd9Sstevel@tonic-gate 1529051aabe6Staylor 1530051aabe6Staylor void 1531051aabe6Staylor set_root (char *root, unsigned long drive, unsigned long part) 1532051aabe6Staylor { 1533051aabe6Staylor int bsd_part = (part >> 8) & 0xFF; 1534051aabe6Staylor int pc_slice = part >> 16; 1535051aabe6Staylor 1536051aabe6Staylor if (bsd_part == 0xFF) { 1537051aabe6Staylor grub_sprintf (root, "(hd%d,%d)\n", drive - 0x80, pc_slice); 1538051aabe6Staylor } else { 1539051aabe6Staylor grub_sprintf (root, "(hd%d,%d,%c)\n", 1540051aabe6Staylor drive - 0x80, pc_slice, bsd_part + 'a'); 1541051aabe6Staylor } 1542051aabe6Staylor } 1543051aabe6Staylor 15447c478bd9Sstevel@tonic-gate static int 1545eb2bd662Svikram find_common (char *arg, char *root, int for_root, int flags) 15467c478bd9Sstevel@tonic-gate { 1547eb2bd662Svikram char *filename = NULL; 1548eb2bd662Svikram static char argpart[32]; 1549eb2bd662Svikram static char device[32]; 1550eb2bd662Svikram char *tmp_argpart = NULL; 15517c478bd9Sstevel@tonic-gate unsigned long drive; 15527c478bd9Sstevel@tonic-gate unsigned long tmp_drive = saved_drive; 15537c478bd9Sstevel@tonic-gate unsigned long tmp_partition = saved_partition; 15547c478bd9Sstevel@tonic-gate int got_file = 0; 1555eb2bd662Svikram static char bootsign[BOOTSIGN_LEN]; 1556eb2bd662Svikram 1557eb2bd662Svikram /* 1558eb2bd662Svikram * If argument has partition information (findroot command only), then 1559eb2bd662Svikram * it can't be a floppy 1560eb2bd662Svikram */ 1561eb2bd662Svikram if (for_root && arg[0] == '(') { 1562eb2bd662Svikram tmp_argpart = grub_strchr(arg + 1, ','); 1563eb2bd662Svikram if (tmp_argpart == NULL) 1564eb2bd662Svikram goto out; 1565eb2bd662Svikram grub_strcpy(argpart, tmp_argpart); 1566eb2bd662Svikram *tmp_argpart = '\0'; 1567eb2bd662Svikram arg++; 1568eb2bd662Svikram grub_sprintf(bootsign, "%s/%s", BOOTSIGN_DIR, arg); 1569eb2bd662Svikram filename = bootsign; 1570eb2bd662Svikram goto harddisk; 1571eb2bd662Svikram } else if (for_root) { 1572eb2bd662Svikram /* Boot signature without partition/slice information */ 1573eb2bd662Svikram grub_sprintf(bootsign, "%s/%s", BOOTSIGN_DIR, arg); 1574eb2bd662Svikram filename = bootsign; 1575eb2bd662Svikram } else { 1576eb2bd662Svikram /* plain vanilla find cmd */ 1577eb2bd662Svikram filename = arg; 1578eb2bd662Svikram } 15797c478bd9Sstevel@tonic-gate 15807c478bd9Sstevel@tonic-gate /* Floppies. */ 15817c478bd9Sstevel@tonic-gate for (drive = 0; drive < 8; drive++) 15827c478bd9Sstevel@tonic-gate { 15837c478bd9Sstevel@tonic-gate current_drive = drive; 15847c478bd9Sstevel@tonic-gate current_partition = 0xFFFFFF; 15857c478bd9Sstevel@tonic-gate 15867c478bd9Sstevel@tonic-gate if (open_device ()) 15877c478bd9Sstevel@tonic-gate { 15887c478bd9Sstevel@tonic-gate saved_drive = current_drive; 15897c478bd9Sstevel@tonic-gate saved_partition = current_partition; 15907c478bd9Sstevel@tonic-gate if (grub_open (filename)) 15917c478bd9Sstevel@tonic-gate { 15927c478bd9Sstevel@tonic-gate grub_close (); 15937c478bd9Sstevel@tonic-gate got_file = 1; 1594eb2bd662Svikram if (for_root) { 1595eb2bd662Svikram grub_sprintf(root, "(fd%d)", drive); 1596eb2bd662Svikram goto out; 1597eb2bd662Svikram } else 1598eb2bd662Svikram grub_printf (" (fd%d)\n", drive); 15997c478bd9Sstevel@tonic-gate } 16007c478bd9Sstevel@tonic-gate } 16017c478bd9Sstevel@tonic-gate 16027c478bd9Sstevel@tonic-gate errnum = ERR_NONE; 16037c478bd9Sstevel@tonic-gate } 16047c478bd9Sstevel@tonic-gate 1605eb2bd662Svikram harddisk: 16067c478bd9Sstevel@tonic-gate /* Hard disks. */ 16077c478bd9Sstevel@tonic-gate for (drive = 0x80; drive < 0x88; drive++) 16087c478bd9Sstevel@tonic-gate { 16097c478bd9Sstevel@tonic-gate unsigned long part = 0xFFFFFF; 16107c478bd9Sstevel@tonic-gate unsigned long start, len, offset, ext_offset; 16117c478bd9Sstevel@tonic-gate int type, entry; 16127c478bd9Sstevel@tonic-gate char buf[SECTOR_SIZE]; 16137c478bd9Sstevel@tonic-gate 1614eb2bd662Svikram if (for_root && tmp_argpart) { 1615051aabe6Staylor grub_sprintf(device, "(hd%d%s", drive - 0x80, argpart); 1616eb2bd662Svikram set_device(device); 1617eb2bd662Svikram errnum = ERR_NONE; 1618eb2bd662Svikram part = current_partition; 1619eb2bd662Svikram if (open_device ()) { 1620eb2bd662Svikram saved_drive = current_drive; 1621eb2bd662Svikram saved_partition = current_partition; 1622eb2bd662Svikram errnum = ERR_NONE; 1623eb2bd662Svikram if (grub_open (filename)) { 1624eb2bd662Svikram grub_close (); 1625eb2bd662Svikram got_file = 1; 1626051aabe6Staylor if (is_zfs_mount == 0) { 1627051aabe6Staylor set_root(root, current_drive, current_partition); 1628051aabe6Staylor goto out; 1629051aabe6Staylor } else { 1630051aabe6Staylor best_drive = current_drive; 1631051aabe6Staylor best_part = current_partition; 1632051aabe6Staylor } 1633eb2bd662Svikram } 1634eb2bd662Svikram } 1635eb2bd662Svikram errnum = ERR_NONE; 1636eb2bd662Svikram continue; 1637eb2bd662Svikram } 16387c478bd9Sstevel@tonic-gate current_drive = drive; 16397c478bd9Sstevel@tonic-gate while (next_partition (drive, 0xFFFFFF, &part, &type, 16407c478bd9Sstevel@tonic-gate &start, &len, &offset, &entry, 16417c478bd9Sstevel@tonic-gate &ext_offset, buf)) 16427c478bd9Sstevel@tonic-gate { 16437c478bd9Sstevel@tonic-gate if (type != PC_SLICE_TYPE_NONE 16447c478bd9Sstevel@tonic-gate && ! IS_PC_SLICE_TYPE_BSD (type) 16457c478bd9Sstevel@tonic-gate && ! IS_PC_SLICE_TYPE_EXTENDED (type)) 16467c478bd9Sstevel@tonic-gate { 16477c478bd9Sstevel@tonic-gate current_partition = part; 16487c478bd9Sstevel@tonic-gate if (open_device ()) 16497c478bd9Sstevel@tonic-gate { 16507c478bd9Sstevel@tonic-gate saved_drive = current_drive; 16517c478bd9Sstevel@tonic-gate saved_partition = current_partition; 16527c478bd9Sstevel@tonic-gate if (grub_open (filename)) 16537c478bd9Sstevel@tonic-gate { 1654051aabe6Staylor char tmproot[32]; 1655051aabe6Staylor 16567c478bd9Sstevel@tonic-gate grub_close (); 1657eb2bd662Svikram got_file = 1; 1658051aabe6Staylor set_root(tmproot, drive, part); 1659051aabe6Staylor if (for_root) { 1660051aabe6Staylor grub_memcpy(root, tmproot, sizeof(tmproot)); 1661051aabe6Staylor if (is_zfs_mount == 0) { 1662051aabe6Staylor goto out; 1663051aabe6Staylor } else { 1664051aabe6Staylor best_drive = current_drive; 1665051aabe6Staylor best_part = current_partition; 1666051aabe6Staylor } 1667eb2bd662Svikram } else { 1668051aabe6Staylor grub_printf("%s", tmproot); 1669eb2bd662Svikram } 16707c478bd9Sstevel@tonic-gate } 16717c478bd9Sstevel@tonic-gate } 16727c478bd9Sstevel@tonic-gate } 16737c478bd9Sstevel@tonic-gate 16747c478bd9Sstevel@tonic-gate /* We want to ignore any error here. */ 16757c478bd9Sstevel@tonic-gate errnum = ERR_NONE; 16767c478bd9Sstevel@tonic-gate } 16777c478bd9Sstevel@tonic-gate 16787c478bd9Sstevel@tonic-gate /* next_partition always sets ERRNUM in the last call, so clear 16797c478bd9Sstevel@tonic-gate it. */ 16807c478bd9Sstevel@tonic-gate errnum = ERR_NONE; 16817c478bd9Sstevel@tonic-gate } 16827c478bd9Sstevel@tonic-gate 1683eb2bd662Svikram out: 1684051aabe6Staylor if (is_zfs_mount && for_root) { 1685051aabe6Staylor set_root(root, best_drive, best_part); 1686051aabe6Staylor buf_drive = -1; 1687051aabe6Staylor } else { 1688051aabe6Staylor saved_drive = tmp_drive; 1689051aabe6Staylor saved_partition = tmp_partition; 1690051aabe6Staylor } 1691eb2bd662Svikram if (tmp_argpart) 1692eb2bd662Svikram *tmp_argpart = ','; 16937c478bd9Sstevel@tonic-gate 16947c478bd9Sstevel@tonic-gate if (got_file) 16957c478bd9Sstevel@tonic-gate { 16967c478bd9Sstevel@tonic-gate errnum = ERR_NONE; 16977c478bd9Sstevel@tonic-gate return 0; 16987c478bd9Sstevel@tonic-gate } 16997c478bd9Sstevel@tonic-gate 17007c478bd9Sstevel@tonic-gate errnum = ERR_FILE_NOT_FOUND; 17017c478bd9Sstevel@tonic-gate return 1; 17027c478bd9Sstevel@tonic-gate } 17037c478bd9Sstevel@tonic-gate 1704eb2bd662Svikram /* find */ 1705eb2bd662Svikram /* Search for the filename ARG in all of partitions. */ 1706eb2bd662Svikram static int 1707eb2bd662Svikram find_func (char *arg, int flags) 1708eb2bd662Svikram { 1709eb2bd662Svikram return (find_common(arg, NULL, 0, flags)); 1710eb2bd662Svikram } 1711eb2bd662Svikram 17127c478bd9Sstevel@tonic-gate static struct builtin builtin_find = 17137c478bd9Sstevel@tonic-gate { 17147c478bd9Sstevel@tonic-gate "find", 17157c478bd9Sstevel@tonic-gate find_func, 17167c478bd9Sstevel@tonic-gate BUILTIN_CMDLINE | BUILTIN_HELP_LIST, 17177c478bd9Sstevel@tonic-gate "find FILENAME", 17187c478bd9Sstevel@tonic-gate "Search for the filename FILENAME in all of partitions and print the list of" 17197c478bd9Sstevel@tonic-gate " the devices which contain the file." 17207c478bd9Sstevel@tonic-gate }; 17217c478bd9Sstevel@tonic-gate 17227c478bd9Sstevel@tonic-gate 17237c478bd9Sstevel@tonic-gate /* fstest */ 17247c478bd9Sstevel@tonic-gate static int 17257c478bd9Sstevel@tonic-gate fstest_func (char *arg, int flags) 17267c478bd9Sstevel@tonic-gate { 17277c478bd9Sstevel@tonic-gate if (disk_read_hook) 17287c478bd9Sstevel@tonic-gate { 17297c478bd9Sstevel@tonic-gate disk_read_hook = NULL; 17307c478bd9Sstevel@tonic-gate printf (" Filesystem tracing is now off\n"); 17317c478bd9Sstevel@tonic-gate } 17327c478bd9Sstevel@tonic-gate else 17337c478bd9Sstevel@tonic-gate { 17347c478bd9Sstevel@tonic-gate disk_read_hook = disk_read_print_func; 17357c478bd9Sstevel@tonic-gate printf (" Filesystem tracing is now on\n"); 17367c478bd9Sstevel@tonic-gate } 17377c478bd9Sstevel@tonic-gate 17387c478bd9Sstevel@tonic-gate return 0; 17397c478bd9Sstevel@tonic-gate } 17407c478bd9Sstevel@tonic-gate 17417c478bd9Sstevel@tonic-gate static struct builtin builtin_fstest = 17427c478bd9Sstevel@tonic-gate { 17437c478bd9Sstevel@tonic-gate "fstest", 17447c478bd9Sstevel@tonic-gate fstest_func, 17457c478bd9Sstevel@tonic-gate BUILTIN_CMDLINE, 17467c478bd9Sstevel@tonic-gate "fstest", 17477c478bd9Sstevel@tonic-gate "Toggle filesystem test mode." 17487c478bd9Sstevel@tonic-gate }; 17497c478bd9Sstevel@tonic-gate 17507c478bd9Sstevel@tonic-gate 17517c478bd9Sstevel@tonic-gate /* geometry */ 17527c478bd9Sstevel@tonic-gate static int 17537c478bd9Sstevel@tonic-gate geometry_func (char *arg, int flags) 17547c478bd9Sstevel@tonic-gate { 17557c478bd9Sstevel@tonic-gate struct geometry geom; 17567c478bd9Sstevel@tonic-gate char *msg; 17577c478bd9Sstevel@tonic-gate char *device = arg; 17587c478bd9Sstevel@tonic-gate #ifdef GRUB_UTIL 17597c478bd9Sstevel@tonic-gate char *ptr; 17607c478bd9Sstevel@tonic-gate #endif 17617c478bd9Sstevel@tonic-gate 17627c478bd9Sstevel@tonic-gate /* Get the device number. */ 17637c478bd9Sstevel@tonic-gate set_device (device); 17647c478bd9Sstevel@tonic-gate if (errnum) 17657c478bd9Sstevel@tonic-gate return 1; 17667c478bd9Sstevel@tonic-gate 17677c478bd9Sstevel@tonic-gate /* Check for the geometry. */ 17687c478bd9Sstevel@tonic-gate if (get_diskinfo (current_drive, &geom)) 17697c478bd9Sstevel@tonic-gate { 17707c478bd9Sstevel@tonic-gate errnum = ERR_NO_DISK; 17717c478bd9Sstevel@tonic-gate return 1; 17727c478bd9Sstevel@tonic-gate } 17737c478bd9Sstevel@tonic-gate 17747c478bd9Sstevel@tonic-gate /* Attempt to read the first sector, because some BIOSes turns out not 17757c478bd9Sstevel@tonic-gate to support LBA even though they set the bit 0 in the support 17767c478bd9Sstevel@tonic-gate bitmap, only after reading something actually. */ 17777c478bd9Sstevel@tonic-gate if (biosdisk (BIOSDISK_READ, current_drive, &geom, 0, 1, SCRATCHSEG)) 17787c478bd9Sstevel@tonic-gate { 17797c478bd9Sstevel@tonic-gate errnum = ERR_READ; 17807c478bd9Sstevel@tonic-gate return 1; 17817c478bd9Sstevel@tonic-gate } 17827c478bd9Sstevel@tonic-gate 17837c478bd9Sstevel@tonic-gate #ifdef GRUB_UTIL 17847c478bd9Sstevel@tonic-gate ptr = skip_to (0, device); 17857c478bd9Sstevel@tonic-gate if (*ptr) 17867c478bd9Sstevel@tonic-gate { 17877c478bd9Sstevel@tonic-gate char *cylinder, *head, *sector, *total_sector; 17887c478bd9Sstevel@tonic-gate int num_cylinder, num_head, num_sector, num_total_sector; 17897c478bd9Sstevel@tonic-gate 17907c478bd9Sstevel@tonic-gate cylinder = ptr; 17917c478bd9Sstevel@tonic-gate head = skip_to (0, cylinder); 17927c478bd9Sstevel@tonic-gate sector = skip_to (0, head); 17937c478bd9Sstevel@tonic-gate total_sector = skip_to (0, sector); 17947c478bd9Sstevel@tonic-gate if (! safe_parse_maxint (&cylinder, &num_cylinder) 17957c478bd9Sstevel@tonic-gate || ! safe_parse_maxint (&head, &num_head) 17967c478bd9Sstevel@tonic-gate || ! safe_parse_maxint (§or, &num_sector)) 17977c478bd9Sstevel@tonic-gate return 1; 17987c478bd9Sstevel@tonic-gate 17997c478bd9Sstevel@tonic-gate disks[current_drive].cylinders = num_cylinder; 18007c478bd9Sstevel@tonic-gate disks[current_drive].heads = num_head; 18017c478bd9Sstevel@tonic-gate disks[current_drive].sectors = num_sector; 18027c478bd9Sstevel@tonic-gate 18037c478bd9Sstevel@tonic-gate if (safe_parse_maxint (&total_sector, &num_total_sector)) 18047c478bd9Sstevel@tonic-gate disks[current_drive].total_sectors = num_total_sector; 18057c478bd9Sstevel@tonic-gate else 18067c478bd9Sstevel@tonic-gate disks[current_drive].total_sectors 18077c478bd9Sstevel@tonic-gate = num_cylinder * num_head * num_sector; 18087c478bd9Sstevel@tonic-gate errnum = 0; 18097c478bd9Sstevel@tonic-gate 18107c478bd9Sstevel@tonic-gate geom = disks[current_drive]; 18117c478bd9Sstevel@tonic-gate buf_drive = -1; 18127c478bd9Sstevel@tonic-gate } 18137c478bd9Sstevel@tonic-gate #endif /* GRUB_UTIL */ 18147c478bd9Sstevel@tonic-gate 18157c478bd9Sstevel@tonic-gate #ifdef GRUB_UTIL 18167c478bd9Sstevel@tonic-gate msg = device_map[current_drive]; 18177c478bd9Sstevel@tonic-gate #else 18187c478bd9Sstevel@tonic-gate if (geom.flags & BIOSDISK_FLAG_LBA_EXTENSION) 18197c478bd9Sstevel@tonic-gate msg = "LBA"; 18207c478bd9Sstevel@tonic-gate else 18217c478bd9Sstevel@tonic-gate msg = "CHS"; 18227c478bd9Sstevel@tonic-gate #endif 18237c478bd9Sstevel@tonic-gate 18247c478bd9Sstevel@tonic-gate grub_printf ("drive 0x%x: C/H/S = %d/%d/%d, " 1825342440ecSPrasad Singamsetty "The number of sectors = %u, %s\n", 18267c478bd9Sstevel@tonic-gate current_drive, 18277c478bd9Sstevel@tonic-gate geom.cylinders, geom.heads, geom.sectors, 18287c478bd9Sstevel@tonic-gate geom.total_sectors, msg); 18297c478bd9Sstevel@tonic-gate real_open_partition (1); 18307c478bd9Sstevel@tonic-gate 18317c478bd9Sstevel@tonic-gate return 0; 18327c478bd9Sstevel@tonic-gate } 18337c478bd9Sstevel@tonic-gate 18347c478bd9Sstevel@tonic-gate static struct builtin builtin_geometry = 18357c478bd9Sstevel@tonic-gate { 18367c478bd9Sstevel@tonic-gate "geometry", 18377c478bd9Sstevel@tonic-gate geometry_func, 18387c478bd9Sstevel@tonic-gate BUILTIN_CMDLINE | BUILTIN_HELP_LIST, 18397c478bd9Sstevel@tonic-gate "geometry DRIVE [CYLINDER HEAD SECTOR [TOTAL_SECTOR]]", 18407c478bd9Sstevel@tonic-gate "Print the information for a drive DRIVE. In the grub shell, you can" 18417c478bd9Sstevel@tonic-gate " set the geometry of the drive arbitrarily. The number of the cylinders," 18427c478bd9Sstevel@tonic-gate " the one of the heads, the one of the sectors and the one of the total" 18437c478bd9Sstevel@tonic-gate " sectors are set to CYLINDER, HEAD, SECTOR and TOTAL_SECTOR," 18447c478bd9Sstevel@tonic-gate " respectively. If you omit TOTAL_SECTOR, then it will be calculated based" 18457c478bd9Sstevel@tonic-gate " on the C/H/S values automatically." 18467c478bd9Sstevel@tonic-gate }; 18477c478bd9Sstevel@tonic-gate 18487c478bd9Sstevel@tonic-gate 18497c478bd9Sstevel@tonic-gate /* halt */ 18507c478bd9Sstevel@tonic-gate static int 18517c478bd9Sstevel@tonic-gate halt_func (char *arg, int flags) 18527c478bd9Sstevel@tonic-gate { 18537c478bd9Sstevel@tonic-gate int no_apm; 18547c478bd9Sstevel@tonic-gate 18557c478bd9Sstevel@tonic-gate no_apm = (grub_memcmp (arg, "--no-apm", 8) == 0); 18567c478bd9Sstevel@tonic-gate grub_halt (no_apm); 18577c478bd9Sstevel@tonic-gate 18587c478bd9Sstevel@tonic-gate /* Never reach here. */ 18597c478bd9Sstevel@tonic-gate return 1; 18607c478bd9Sstevel@tonic-gate } 18617c478bd9Sstevel@tonic-gate 18627c478bd9Sstevel@tonic-gate static struct builtin builtin_halt = 18637c478bd9Sstevel@tonic-gate { 18647c478bd9Sstevel@tonic-gate "halt", 18657c478bd9Sstevel@tonic-gate halt_func, 18667c478bd9Sstevel@tonic-gate BUILTIN_CMDLINE | BUILTIN_HELP_LIST, 18677c478bd9Sstevel@tonic-gate "halt [--no-apm]", 18687c478bd9Sstevel@tonic-gate "Halt your system. If APM is avaiable on it, turn off the power using" 18697c478bd9Sstevel@tonic-gate " the APM BIOS, unless you specify the option `--no-apm'." 18707c478bd9Sstevel@tonic-gate }; 18717c478bd9Sstevel@tonic-gate 18727c478bd9Sstevel@tonic-gate 18737c478bd9Sstevel@tonic-gate /* help */ 18747c478bd9Sstevel@tonic-gate #define MAX_SHORT_DOC_LEN 39 18757c478bd9Sstevel@tonic-gate #define MAX_LONG_DOC_LEN 66 18767c478bd9Sstevel@tonic-gate 18777c478bd9Sstevel@tonic-gate static int 18787c478bd9Sstevel@tonic-gate help_func (char *arg, int flags) 18797c478bd9Sstevel@tonic-gate { 18807c478bd9Sstevel@tonic-gate int all = 0; 18817c478bd9Sstevel@tonic-gate 18827c478bd9Sstevel@tonic-gate if (grub_memcmp (arg, "--all", sizeof ("--all") - 1) == 0) 18837c478bd9Sstevel@tonic-gate { 18847c478bd9Sstevel@tonic-gate all = 1; 18857c478bd9Sstevel@tonic-gate arg = skip_to (0, arg); 18867c478bd9Sstevel@tonic-gate } 18877c478bd9Sstevel@tonic-gate 18887c478bd9Sstevel@tonic-gate if (! *arg) 18897c478bd9Sstevel@tonic-gate { 18907c478bd9Sstevel@tonic-gate /* Invoked with no argument. Print the list of the short docs. */ 18917c478bd9Sstevel@tonic-gate struct builtin **builtin; 18927c478bd9Sstevel@tonic-gate int left = 1; 18937c478bd9Sstevel@tonic-gate 18947c478bd9Sstevel@tonic-gate for (builtin = builtin_table; *builtin != 0; builtin++) 18957c478bd9Sstevel@tonic-gate { 18967c478bd9Sstevel@tonic-gate int len; 18977c478bd9Sstevel@tonic-gate int i; 18987c478bd9Sstevel@tonic-gate 18997c478bd9Sstevel@tonic-gate /* If this cannot be used in the command-line interface, 19007c478bd9Sstevel@tonic-gate skip this. */ 19017c478bd9Sstevel@tonic-gate if (! ((*builtin)->flags & BUILTIN_CMDLINE)) 19027c478bd9Sstevel@tonic-gate continue; 19037c478bd9Sstevel@tonic-gate 19047c478bd9Sstevel@tonic-gate /* If this doesn't need to be listed automatically and "--all" 19057c478bd9Sstevel@tonic-gate is not specified, skip this. */ 19067c478bd9Sstevel@tonic-gate if (! all && ! ((*builtin)->flags & BUILTIN_HELP_LIST)) 19077c478bd9Sstevel@tonic-gate continue; 19087c478bd9Sstevel@tonic-gate 19097c478bd9Sstevel@tonic-gate len = grub_strlen ((*builtin)->short_doc); 19107c478bd9Sstevel@tonic-gate /* If the length of SHORT_DOC is too long, truncate it. */ 19117c478bd9Sstevel@tonic-gate if (len > MAX_SHORT_DOC_LEN - 1) 19127c478bd9Sstevel@tonic-gate len = MAX_SHORT_DOC_LEN - 1; 19137c478bd9Sstevel@tonic-gate 19147c478bd9Sstevel@tonic-gate for (i = 0; i < len; i++) 19157c478bd9Sstevel@tonic-gate grub_putchar ((*builtin)->short_doc[i]); 19167c478bd9Sstevel@tonic-gate 19177c478bd9Sstevel@tonic-gate for (; i < MAX_SHORT_DOC_LEN; i++) 19187c478bd9Sstevel@tonic-gate grub_putchar (' '); 19197c478bd9Sstevel@tonic-gate 19207c478bd9Sstevel@tonic-gate if (! left) 19217c478bd9Sstevel@tonic-gate grub_putchar ('\n'); 19227c478bd9Sstevel@tonic-gate 19237c478bd9Sstevel@tonic-gate left = ! left; 19247c478bd9Sstevel@tonic-gate } 19257c478bd9Sstevel@tonic-gate 19267c478bd9Sstevel@tonic-gate /* If the last entry was at the left column, no newline was printed 19277c478bd9Sstevel@tonic-gate at the end. */ 19287c478bd9Sstevel@tonic-gate if (! left) 19297c478bd9Sstevel@tonic-gate grub_putchar ('\n'); 19307c478bd9Sstevel@tonic-gate } 19317c478bd9Sstevel@tonic-gate else 19327c478bd9Sstevel@tonic-gate { 19337c478bd9Sstevel@tonic-gate /* Invoked with one or more patterns. */ 19347c478bd9Sstevel@tonic-gate do 19357c478bd9Sstevel@tonic-gate { 19367c478bd9Sstevel@tonic-gate struct builtin **builtin; 19377c478bd9Sstevel@tonic-gate char *next_arg; 19387c478bd9Sstevel@tonic-gate 19397c478bd9Sstevel@tonic-gate /* Get the next argument. */ 19407c478bd9Sstevel@tonic-gate next_arg = skip_to (0, arg); 19417c478bd9Sstevel@tonic-gate 19427c478bd9Sstevel@tonic-gate /* Terminate ARG. */ 19437c478bd9Sstevel@tonic-gate nul_terminate (arg); 19447c478bd9Sstevel@tonic-gate 19457c478bd9Sstevel@tonic-gate for (builtin = builtin_table; *builtin; builtin++) 19467c478bd9Sstevel@tonic-gate { 19477c478bd9Sstevel@tonic-gate /* Skip this if this is only for the configuration file. */ 19487c478bd9Sstevel@tonic-gate if (! ((*builtin)->flags & BUILTIN_CMDLINE)) 19497c478bd9Sstevel@tonic-gate continue; 19507c478bd9Sstevel@tonic-gate 19517c478bd9Sstevel@tonic-gate if (substring (arg, (*builtin)->name) < 1) 19527c478bd9Sstevel@tonic-gate { 19537c478bd9Sstevel@tonic-gate char *doc = (*builtin)->long_doc; 19547c478bd9Sstevel@tonic-gate 19557c478bd9Sstevel@tonic-gate /* At first, print the name and the short doc. */ 19567c478bd9Sstevel@tonic-gate grub_printf ("%s: %s\n", 19577c478bd9Sstevel@tonic-gate (*builtin)->name, (*builtin)->short_doc); 19587c478bd9Sstevel@tonic-gate 19597c478bd9Sstevel@tonic-gate /* Print the long doc. */ 19607c478bd9Sstevel@tonic-gate while (*doc) 19617c478bd9Sstevel@tonic-gate { 19627c478bd9Sstevel@tonic-gate int len = grub_strlen (doc); 19637c478bd9Sstevel@tonic-gate int i; 19647c478bd9Sstevel@tonic-gate 19657c478bd9Sstevel@tonic-gate /* If LEN is too long, fold DOC. */ 19667c478bd9Sstevel@tonic-gate if (len > MAX_LONG_DOC_LEN) 19677c478bd9Sstevel@tonic-gate { 19687c478bd9Sstevel@tonic-gate /* Fold this line at the position of a space. */ 19697c478bd9Sstevel@tonic-gate for (len = MAX_LONG_DOC_LEN; len > 0; len--) 19707c478bd9Sstevel@tonic-gate if (doc[len - 1] == ' ') 19717c478bd9Sstevel@tonic-gate break; 19727c478bd9Sstevel@tonic-gate } 19737c478bd9Sstevel@tonic-gate 19747c478bd9Sstevel@tonic-gate grub_printf (" "); 19757c478bd9Sstevel@tonic-gate for (i = 0; i < len; i++) 19767c478bd9Sstevel@tonic-gate grub_putchar (*doc++); 19777c478bd9Sstevel@tonic-gate grub_putchar ('\n'); 19787c478bd9Sstevel@tonic-gate } 19797c478bd9Sstevel@tonic-gate } 19807c478bd9Sstevel@tonic-gate } 19817c478bd9Sstevel@tonic-gate 19827c478bd9Sstevel@tonic-gate arg = next_arg; 19837c478bd9Sstevel@tonic-gate } 19847c478bd9Sstevel@tonic-gate while (*arg); 19857c478bd9Sstevel@tonic-gate } 19867c478bd9Sstevel@tonic-gate 19877c478bd9Sstevel@tonic-gate return 0; 19887c478bd9Sstevel@tonic-gate } 19897c478bd9Sstevel@tonic-gate 19907c478bd9Sstevel@tonic-gate static struct builtin builtin_help = 19917c478bd9Sstevel@tonic-gate { 19927c478bd9Sstevel@tonic-gate "help", 19937c478bd9Sstevel@tonic-gate help_func, 19947c478bd9Sstevel@tonic-gate BUILTIN_CMDLINE | BUILTIN_HELP_LIST, 19957c478bd9Sstevel@tonic-gate "help [--all] [PATTERN ...]", 19967c478bd9Sstevel@tonic-gate "Display helpful information about builtin commands. Not all commands" 19977c478bd9Sstevel@tonic-gate " aren't shown without the option `--all'." 19987c478bd9Sstevel@tonic-gate }; 19997c478bd9Sstevel@tonic-gate 20007c478bd9Sstevel@tonic-gate 20017c478bd9Sstevel@tonic-gate /* hiddenmenu */ 20027c478bd9Sstevel@tonic-gate static int 20037c478bd9Sstevel@tonic-gate hiddenmenu_func (char *arg, int flags) 20047c478bd9Sstevel@tonic-gate { 20057c478bd9Sstevel@tonic-gate show_menu = 0; 20067c478bd9Sstevel@tonic-gate return 0; 20077c478bd9Sstevel@tonic-gate } 20087c478bd9Sstevel@tonic-gate 20097c478bd9Sstevel@tonic-gate static struct builtin builtin_hiddenmenu = 20107c478bd9Sstevel@tonic-gate { 20117c478bd9Sstevel@tonic-gate "hiddenmenu", 20127c478bd9Sstevel@tonic-gate hiddenmenu_func, 20137c478bd9Sstevel@tonic-gate BUILTIN_MENU, 20147c478bd9Sstevel@tonic-gate #if 0 20157c478bd9Sstevel@tonic-gate "hiddenmenu", 20167c478bd9Sstevel@tonic-gate "Hide the menu." 20177c478bd9Sstevel@tonic-gate #endif 20187c478bd9Sstevel@tonic-gate }; 20197c478bd9Sstevel@tonic-gate 20207c478bd9Sstevel@tonic-gate 20217c478bd9Sstevel@tonic-gate /* hide */ 20227c478bd9Sstevel@tonic-gate static int 20237c478bd9Sstevel@tonic-gate hide_func (char *arg, int flags) 20247c478bd9Sstevel@tonic-gate { 20257c478bd9Sstevel@tonic-gate if (! set_device (arg)) 20267c478bd9Sstevel@tonic-gate return 1; 20277c478bd9Sstevel@tonic-gate 20287c478bd9Sstevel@tonic-gate if (! set_partition_hidden_flag (1)) 20297c478bd9Sstevel@tonic-gate return 1; 20307c478bd9Sstevel@tonic-gate 20317c478bd9Sstevel@tonic-gate return 0; 20327c478bd9Sstevel@tonic-gate } 20337c478bd9Sstevel@tonic-gate 20347c478bd9Sstevel@tonic-gate static struct builtin builtin_hide = 20357c478bd9Sstevel@tonic-gate { 20367c478bd9Sstevel@tonic-gate "hide", 20377c478bd9Sstevel@tonic-gate hide_func, 20387c478bd9Sstevel@tonic-gate BUILTIN_CMDLINE | BUILTIN_MENU | BUILTIN_HELP_LIST, 20397c478bd9Sstevel@tonic-gate "hide PARTITION", 20407c478bd9Sstevel@tonic-gate "Hide PARTITION by setting the \"hidden\" bit in" 20417c478bd9Sstevel@tonic-gate " its partition type code." 20427c478bd9Sstevel@tonic-gate }; 20437c478bd9Sstevel@tonic-gate 20447c478bd9Sstevel@tonic-gate 20457c478bd9Sstevel@tonic-gate #ifdef SUPPORT_NETBOOT 20467c478bd9Sstevel@tonic-gate /* ifconfig */ 20477c478bd9Sstevel@tonic-gate static int 20487c478bd9Sstevel@tonic-gate ifconfig_func (char *arg, int flags) 20497c478bd9Sstevel@tonic-gate { 20507c478bd9Sstevel@tonic-gate char *svr = 0, *ip = 0, *gw = 0, *sm = 0; 20517c478bd9Sstevel@tonic-gate 20527c478bd9Sstevel@tonic-gate if (! grub_eth_probe ()) 20537c478bd9Sstevel@tonic-gate { 20547c478bd9Sstevel@tonic-gate grub_printf ("No ethernet card found.\n"); 20557c478bd9Sstevel@tonic-gate errnum = ERR_DEV_VALUES; 20567c478bd9Sstevel@tonic-gate return 1; 20577c478bd9Sstevel@tonic-gate } 20587c478bd9Sstevel@tonic-gate 20597c478bd9Sstevel@tonic-gate while (*arg) 20607c478bd9Sstevel@tonic-gate { 20617c478bd9Sstevel@tonic-gate if (! grub_memcmp ("--server=", arg, sizeof ("--server=") - 1)) 20627c478bd9Sstevel@tonic-gate svr = arg + sizeof("--server=") - 1; 20637c478bd9Sstevel@tonic-gate else if (! grub_memcmp ("--address=", arg, sizeof ("--address=") - 1)) 20647c478bd9Sstevel@tonic-gate ip = arg + sizeof ("--address=") - 1; 20657c478bd9Sstevel@tonic-gate else if (! grub_memcmp ("--gateway=", arg, sizeof ("--gateway=") - 1)) 20667c478bd9Sstevel@tonic-gate gw = arg + sizeof ("--gateway=") - 1; 20677c478bd9Sstevel@tonic-gate else if (! grub_memcmp ("--mask=", arg, sizeof("--mask=") - 1)) 20687c478bd9Sstevel@tonic-gate sm = arg + sizeof ("--mask=") - 1; 20697c478bd9Sstevel@tonic-gate else 20707c478bd9Sstevel@tonic-gate { 20717c478bd9Sstevel@tonic-gate errnum = ERR_BAD_ARGUMENT; 20727c478bd9Sstevel@tonic-gate return 1; 20737c478bd9Sstevel@tonic-gate } 20747c478bd9Sstevel@tonic-gate 20757c478bd9Sstevel@tonic-gate arg = skip_to (0, arg); 20767c478bd9Sstevel@tonic-gate } 20777c478bd9Sstevel@tonic-gate 20787c478bd9Sstevel@tonic-gate if (! ifconfig (ip, sm, gw, svr)) 20797c478bd9Sstevel@tonic-gate { 20807c478bd9Sstevel@tonic-gate errnum = ERR_BAD_ARGUMENT; 20817c478bd9Sstevel@tonic-gate return 1; 20827c478bd9Sstevel@tonic-gate } 20837c478bd9Sstevel@tonic-gate 20847c478bd9Sstevel@tonic-gate print_network_configuration (); 20857c478bd9Sstevel@tonic-gate return 0; 20867c478bd9Sstevel@tonic-gate } 20877c478bd9Sstevel@tonic-gate 20887c478bd9Sstevel@tonic-gate static struct builtin builtin_ifconfig = 20897c478bd9Sstevel@tonic-gate { 20907c478bd9Sstevel@tonic-gate "ifconfig", 20917c478bd9Sstevel@tonic-gate ifconfig_func, 20927c478bd9Sstevel@tonic-gate BUILTIN_CMDLINE | BUILTIN_MENU | BUILTIN_HELP_LIST, 20937c478bd9Sstevel@tonic-gate "ifconfig [--address=IP] [--gateway=IP] [--mask=MASK] [--server=IP]", 20947c478bd9Sstevel@tonic-gate "Configure the IP address, the netmask, the gateway and the server" 20957c478bd9Sstevel@tonic-gate " address or print current network configuration." 20967c478bd9Sstevel@tonic-gate }; 20977c478bd9Sstevel@tonic-gate #endif /* SUPPORT_NETBOOT */ 20987c478bd9Sstevel@tonic-gate 20997c478bd9Sstevel@tonic-gate 21007c478bd9Sstevel@tonic-gate /* impsprobe */ 21017c478bd9Sstevel@tonic-gate static int 21027c478bd9Sstevel@tonic-gate impsprobe_func (char *arg, int flags) 21037c478bd9Sstevel@tonic-gate { 21047c478bd9Sstevel@tonic-gate #ifdef GRUB_UTIL 21057c478bd9Sstevel@tonic-gate /* In the grub shell, we cannot probe IMPS. */ 21067c478bd9Sstevel@tonic-gate errnum = ERR_UNRECOGNIZED; 21077c478bd9Sstevel@tonic-gate return 1; 21087c478bd9Sstevel@tonic-gate #else /* ! GRUB_UTIL */ 21097c478bd9Sstevel@tonic-gate if (!imps_probe ()) 21107c478bd9Sstevel@tonic-gate printf (" No MPS information found or probe failed\n"); 21117c478bd9Sstevel@tonic-gate 21127c478bd9Sstevel@tonic-gate return 0; 21137c478bd9Sstevel@tonic-gate #endif /* ! GRUB_UTIL */ 21147c478bd9Sstevel@tonic-gate } 21157c478bd9Sstevel@tonic-gate 21167c478bd9Sstevel@tonic-gate static struct builtin builtin_impsprobe = 21177c478bd9Sstevel@tonic-gate { 21187c478bd9Sstevel@tonic-gate "impsprobe", 21197c478bd9Sstevel@tonic-gate impsprobe_func, 21207c478bd9Sstevel@tonic-gate BUILTIN_CMDLINE, 21217c478bd9Sstevel@tonic-gate "impsprobe", 21227c478bd9Sstevel@tonic-gate "Probe the Intel Multiprocessor Specification 1.1 or 1.4" 21237c478bd9Sstevel@tonic-gate " configuration table and boot the various CPUs which are found into" 21247c478bd9Sstevel@tonic-gate " a tight loop." 21257c478bd9Sstevel@tonic-gate }; 21267c478bd9Sstevel@tonic-gate 21277c478bd9Sstevel@tonic-gate 21287c478bd9Sstevel@tonic-gate /* initrd */ 21297c478bd9Sstevel@tonic-gate static int 21307c478bd9Sstevel@tonic-gate initrd_func (char *arg, int flags) 21317c478bd9Sstevel@tonic-gate { 21327c478bd9Sstevel@tonic-gate switch (kernel_type) 21337c478bd9Sstevel@tonic-gate { 21347c478bd9Sstevel@tonic-gate case KERNEL_TYPE_LINUX: 21357c478bd9Sstevel@tonic-gate case KERNEL_TYPE_BIG_LINUX: 21367c478bd9Sstevel@tonic-gate if (! load_initrd (arg)) 21377c478bd9Sstevel@tonic-gate return 1; 21387c478bd9Sstevel@tonic-gate break; 21397c478bd9Sstevel@tonic-gate 21407c478bd9Sstevel@tonic-gate default: 21417c478bd9Sstevel@tonic-gate errnum = ERR_NEED_LX_KERNEL; 21427c478bd9Sstevel@tonic-gate return 1; 21437c478bd9Sstevel@tonic-gate } 21447c478bd9Sstevel@tonic-gate 21457c478bd9Sstevel@tonic-gate return 0; 21467c478bd9Sstevel@tonic-gate } 21477c478bd9Sstevel@tonic-gate 21487c478bd9Sstevel@tonic-gate static struct builtin builtin_initrd = 21497c478bd9Sstevel@tonic-gate { 21507c478bd9Sstevel@tonic-gate "initrd", 21517c478bd9Sstevel@tonic-gate initrd_func, 21527c478bd9Sstevel@tonic-gate BUILTIN_CMDLINE | BUILTIN_HELP_LIST, 21537c478bd9Sstevel@tonic-gate "initrd FILE [ARG ...]", 21547c478bd9Sstevel@tonic-gate "Load an initial ramdisk FILE for a Linux format boot image and set the" 21557c478bd9Sstevel@tonic-gate " appropriate parameters in the Linux setup area in memory." 21567c478bd9Sstevel@tonic-gate }; 21577c478bd9Sstevel@tonic-gate 21587c478bd9Sstevel@tonic-gate 21597c478bd9Sstevel@tonic-gate /* install */ 21607c478bd9Sstevel@tonic-gate static int 21617c478bd9Sstevel@tonic-gate install_func (char *arg, int flags) 21627c478bd9Sstevel@tonic-gate { 21637c478bd9Sstevel@tonic-gate char *stage1_file, *dest_dev, *file, *addr; 21647c478bd9Sstevel@tonic-gate char *stage1_buffer = (char *) RAW_ADDR (0x100000); 21657c478bd9Sstevel@tonic-gate char *stage2_buffer = stage1_buffer + SECTOR_SIZE; 21667c478bd9Sstevel@tonic-gate char *old_sect = stage2_buffer + SECTOR_SIZE; 21677c478bd9Sstevel@tonic-gate char *stage2_first_buffer = old_sect + SECTOR_SIZE; 21687c478bd9Sstevel@tonic-gate char *stage2_second_buffer = stage2_first_buffer + SECTOR_SIZE; 21697c478bd9Sstevel@tonic-gate /* XXX: Probably SECTOR_SIZE is reasonable. */ 21707c478bd9Sstevel@tonic-gate char *config_filename = stage2_second_buffer + SECTOR_SIZE; 21717c478bd9Sstevel@tonic-gate char *dummy = config_filename + SECTOR_SIZE; 21727c478bd9Sstevel@tonic-gate int new_drive = GRUB_INVALID_DRIVE; 2173342440ecSPrasad Singamsetty int dest_drive, dest_partition; 2174342440ecSPrasad Singamsetty unsigned int dest_sector; 21757c478bd9Sstevel@tonic-gate int src_drive, src_partition, src_part_start; 21767c478bd9Sstevel@tonic-gate int i; 21777c478bd9Sstevel@tonic-gate struct geometry dest_geom, src_geom; 2178342440ecSPrasad Singamsetty unsigned int saved_sector; 2179342440ecSPrasad Singamsetty unsigned int stage2_first_sector, stage2_second_sector; 21807c478bd9Sstevel@tonic-gate char *ptr; 21817c478bd9Sstevel@tonic-gate int installaddr, installlist; 21827c478bd9Sstevel@tonic-gate /* Point to the location of the name of a configuration file in Stage 2. */ 21837c478bd9Sstevel@tonic-gate char *config_file_location; 21847c478bd9Sstevel@tonic-gate /* If FILE is a Stage 1.5? */ 21857c478bd9Sstevel@tonic-gate int is_stage1_5 = 0; 21867c478bd9Sstevel@tonic-gate /* Must call grub_close? */ 21877c478bd9Sstevel@tonic-gate int is_open = 0; 21887c478bd9Sstevel@tonic-gate /* If LBA is forced? */ 21897c478bd9Sstevel@tonic-gate int is_force_lba = 0; 21907c478bd9Sstevel@tonic-gate /* Was the last sector full? */ 21917c478bd9Sstevel@tonic-gate int last_length = SECTOR_SIZE; 21927c478bd9Sstevel@tonic-gate 21937c478bd9Sstevel@tonic-gate #ifdef GRUB_UTIL 21947c478bd9Sstevel@tonic-gate /* If the Stage 2 is in a partition mounted by an OS, this will store 21957c478bd9Sstevel@tonic-gate the filename under the OS. */ 21967c478bd9Sstevel@tonic-gate char *stage2_os_file = 0; 21977c478bd9Sstevel@tonic-gate #endif /* GRUB_UTIL */ 21987c478bd9Sstevel@tonic-gate 21991b8adde7SWilliam Kucharski auto void disk_read_savesect_func (unsigned int sector, int offset, 22001b8adde7SWilliam Kucharski int length); 22011b8adde7SWilliam Kucharski auto void disk_read_blocklist_func (unsigned int sector, int offset, 22021b8adde7SWilliam Kucharski int length); 22031b8adde7SWilliam Kucharski 22047c478bd9Sstevel@tonic-gate /* Save the first sector of Stage2 in STAGE2_SECT. */ 22051b8adde7SWilliam Kucharski auto void disk_read_savesect_func (unsigned int sector, int offset, 22061b8adde7SWilliam Kucharski int length) 22077c478bd9Sstevel@tonic-gate { 22087c478bd9Sstevel@tonic-gate if (debug) 2209342440ecSPrasad Singamsetty printf ("[%u]", sector); 22107c478bd9Sstevel@tonic-gate 22117c478bd9Sstevel@tonic-gate /* ReiserFS has files which sometimes contain data not aligned 22127c478bd9Sstevel@tonic-gate on sector boundaries. Returning an error is better than 22137c478bd9Sstevel@tonic-gate silently failing. */ 22147c478bd9Sstevel@tonic-gate if (offset != 0 || length != SECTOR_SIZE) 22157c478bd9Sstevel@tonic-gate errnum = ERR_UNALIGNED; 22167c478bd9Sstevel@tonic-gate 22177c478bd9Sstevel@tonic-gate saved_sector = sector; 22187c478bd9Sstevel@tonic-gate } 22197c478bd9Sstevel@tonic-gate 22207c478bd9Sstevel@tonic-gate /* Write SECTOR to INSTALLLIST, and update INSTALLADDR and 22217c478bd9Sstevel@tonic-gate INSTALLSECT. */ 22221b8adde7SWilliam Kucharski auto void disk_read_blocklist_func (unsigned int sector, int offset, 22231b8adde7SWilliam Kucharski int length) 22247c478bd9Sstevel@tonic-gate { 22257c478bd9Sstevel@tonic-gate if (debug) 2226342440ecSPrasad Singamsetty printf("[%u]", sector); 22277c478bd9Sstevel@tonic-gate 22287c478bd9Sstevel@tonic-gate if (offset != 0 || last_length != SECTOR_SIZE) 22297c478bd9Sstevel@tonic-gate { 22307c478bd9Sstevel@tonic-gate /* We found a non-sector-aligned data block. */ 22317c478bd9Sstevel@tonic-gate errnum = ERR_UNALIGNED; 22327c478bd9Sstevel@tonic-gate return; 22337c478bd9Sstevel@tonic-gate } 22347c478bd9Sstevel@tonic-gate 22357c478bd9Sstevel@tonic-gate last_length = length; 22367c478bd9Sstevel@tonic-gate 22377c478bd9Sstevel@tonic-gate if (*((unsigned long *) (installlist - 4)) 22387c478bd9Sstevel@tonic-gate + *((unsigned short *) installlist) != sector 22397c478bd9Sstevel@tonic-gate || installlist == (int) stage2_first_buffer + SECTOR_SIZE + 4) 22407c478bd9Sstevel@tonic-gate { 22417c478bd9Sstevel@tonic-gate installlist -= 8; 22427c478bd9Sstevel@tonic-gate 22437c478bd9Sstevel@tonic-gate if (*((unsigned long *) (installlist - 8))) 22447c478bd9Sstevel@tonic-gate errnum = ERR_WONT_FIT; 22457c478bd9Sstevel@tonic-gate else 22467c478bd9Sstevel@tonic-gate { 22477c478bd9Sstevel@tonic-gate *((unsigned short *) (installlist + 2)) = (installaddr >> 4); 22487c478bd9Sstevel@tonic-gate *((unsigned long *) (installlist - 4)) = sector; 22497c478bd9Sstevel@tonic-gate } 22507c478bd9Sstevel@tonic-gate } 22517c478bd9Sstevel@tonic-gate 22527c478bd9Sstevel@tonic-gate *((unsigned short *) installlist) += 1; 22537c478bd9Sstevel@tonic-gate installaddr += 512; 22547c478bd9Sstevel@tonic-gate } 22557c478bd9Sstevel@tonic-gate 22567c478bd9Sstevel@tonic-gate /* First, check the GNU-style long option. */ 22577c478bd9Sstevel@tonic-gate while (1) 22587c478bd9Sstevel@tonic-gate { 22597c478bd9Sstevel@tonic-gate if (grub_memcmp ("--force-lba", arg, sizeof ("--force-lba") - 1) == 0) 22607c478bd9Sstevel@tonic-gate { 22617c478bd9Sstevel@tonic-gate is_force_lba = 1; 22627c478bd9Sstevel@tonic-gate arg = skip_to (0, arg); 22637c478bd9Sstevel@tonic-gate } 22647c478bd9Sstevel@tonic-gate #ifdef GRUB_UTIL 22657c478bd9Sstevel@tonic-gate else if (grub_memcmp ("--stage2=", arg, sizeof ("--stage2=") - 1) == 0) 22667c478bd9Sstevel@tonic-gate { 22677c478bd9Sstevel@tonic-gate stage2_os_file = arg + sizeof ("--stage2=") - 1; 22687c478bd9Sstevel@tonic-gate arg = skip_to (0, arg); 22697c478bd9Sstevel@tonic-gate nul_terminate (stage2_os_file); 22707c478bd9Sstevel@tonic-gate } 22717c478bd9Sstevel@tonic-gate #endif /* GRUB_UTIL */ 22727c478bd9Sstevel@tonic-gate else 22737c478bd9Sstevel@tonic-gate break; 22747c478bd9Sstevel@tonic-gate } 22757c478bd9Sstevel@tonic-gate 22767c478bd9Sstevel@tonic-gate stage1_file = arg; 22777c478bd9Sstevel@tonic-gate dest_dev = skip_to (0, stage1_file); 22787c478bd9Sstevel@tonic-gate if (*dest_dev == 'd') 22797c478bd9Sstevel@tonic-gate { 22807c478bd9Sstevel@tonic-gate new_drive = 0; 22817c478bd9Sstevel@tonic-gate dest_dev = skip_to (0, dest_dev); 22827c478bd9Sstevel@tonic-gate } 22837c478bd9Sstevel@tonic-gate file = skip_to (0, dest_dev); 22847c478bd9Sstevel@tonic-gate addr = skip_to (0, file); 22857c478bd9Sstevel@tonic-gate 22867c478bd9Sstevel@tonic-gate /* Get the installation address. */ 22877c478bd9Sstevel@tonic-gate if (! safe_parse_maxint (&addr, &installaddr)) 22887c478bd9Sstevel@tonic-gate { 22897c478bd9Sstevel@tonic-gate /* ADDR is not specified. */ 22907c478bd9Sstevel@tonic-gate installaddr = 0; 22917c478bd9Sstevel@tonic-gate ptr = addr; 22927c478bd9Sstevel@tonic-gate errnum = 0; 22937c478bd9Sstevel@tonic-gate } 22947c478bd9Sstevel@tonic-gate else 22957c478bd9Sstevel@tonic-gate ptr = skip_to (0, addr); 22967c478bd9Sstevel@tonic-gate 22977c478bd9Sstevel@tonic-gate #ifndef NO_DECOMPRESSION 22987c478bd9Sstevel@tonic-gate /* Do not decompress Stage 1 or Stage 2. */ 22997c478bd9Sstevel@tonic-gate no_decompression = 1; 23007c478bd9Sstevel@tonic-gate #endif 23017c478bd9Sstevel@tonic-gate 23027c478bd9Sstevel@tonic-gate /* Read Stage 1. */ 23037c478bd9Sstevel@tonic-gate is_open = grub_open (stage1_file); 23047c478bd9Sstevel@tonic-gate if (! is_open 23057c478bd9Sstevel@tonic-gate || ! grub_read (stage1_buffer, SECTOR_SIZE) == SECTOR_SIZE) 23067c478bd9Sstevel@tonic-gate goto fail; 23077c478bd9Sstevel@tonic-gate 23087c478bd9Sstevel@tonic-gate /* Read the old sector from DEST_DEV. */ 23097c478bd9Sstevel@tonic-gate if (! set_device (dest_dev) 23107c478bd9Sstevel@tonic-gate || ! open_partition () 23117c478bd9Sstevel@tonic-gate || ! devread (0, 0, SECTOR_SIZE, old_sect)) 23127c478bd9Sstevel@tonic-gate goto fail; 23137c478bd9Sstevel@tonic-gate 23147c478bd9Sstevel@tonic-gate /* Store the information for the destination device. */ 23157c478bd9Sstevel@tonic-gate dest_drive = current_drive; 23167c478bd9Sstevel@tonic-gate dest_partition = current_partition; 23177c478bd9Sstevel@tonic-gate dest_geom = buf_geom; 23187c478bd9Sstevel@tonic-gate dest_sector = part_start; 23197c478bd9Sstevel@tonic-gate 23207c478bd9Sstevel@tonic-gate /* Copy the possible DOS BPB, 59 bytes at byte offset 3. */ 23217c478bd9Sstevel@tonic-gate grub_memmove (stage1_buffer + BOOTSEC_BPB_OFFSET, 23227c478bd9Sstevel@tonic-gate old_sect + BOOTSEC_BPB_OFFSET, 23237c478bd9Sstevel@tonic-gate BOOTSEC_BPB_LENGTH); 23247c478bd9Sstevel@tonic-gate 23257c478bd9Sstevel@tonic-gate /* If for a hard disk, copy the possible MBR/extended part table. */ 23267c478bd9Sstevel@tonic-gate if (dest_drive & 0x80) 23277c478bd9Sstevel@tonic-gate grub_memmove (stage1_buffer + STAGE1_WINDOWS_NT_MAGIC, 23287c478bd9Sstevel@tonic-gate old_sect + STAGE1_WINDOWS_NT_MAGIC, 23297c478bd9Sstevel@tonic-gate STAGE1_PARTEND - STAGE1_WINDOWS_NT_MAGIC); 23307c478bd9Sstevel@tonic-gate 23317c478bd9Sstevel@tonic-gate /* Check for the version and the signature of Stage 1. */ 23327c478bd9Sstevel@tonic-gate if (*((short *)(stage1_buffer + STAGE1_VER_MAJ_OFFS)) != COMPAT_VERSION 23337c478bd9Sstevel@tonic-gate || (*((unsigned short *) (stage1_buffer + BOOTSEC_SIG_OFFSET)) 23347c478bd9Sstevel@tonic-gate != BOOTSEC_SIGNATURE)) 23357c478bd9Sstevel@tonic-gate { 23367c478bd9Sstevel@tonic-gate errnum = ERR_BAD_VERSION; 23377c478bd9Sstevel@tonic-gate goto fail; 23387c478bd9Sstevel@tonic-gate } 23397c478bd9Sstevel@tonic-gate 23407c478bd9Sstevel@tonic-gate /* This below is not true any longer. But should we leave this alone? */ 23417c478bd9Sstevel@tonic-gate 23427c478bd9Sstevel@tonic-gate /* If DEST_DRIVE is a floppy, Stage 2 must have the iteration probe 23437c478bd9Sstevel@tonic-gate routine. */ 23447c478bd9Sstevel@tonic-gate if (! (dest_drive & 0x80) 23457c478bd9Sstevel@tonic-gate && (*((unsigned char *) (stage1_buffer + BOOTSEC_PART_OFFSET)) == 0x80 23467c478bd9Sstevel@tonic-gate || stage1_buffer[BOOTSEC_PART_OFFSET] == 0)) 23477c478bd9Sstevel@tonic-gate { 23487c478bd9Sstevel@tonic-gate errnum = ERR_BAD_VERSION; 23497c478bd9Sstevel@tonic-gate goto fail; 23507c478bd9Sstevel@tonic-gate } 23517c478bd9Sstevel@tonic-gate 23527c478bd9Sstevel@tonic-gate grub_close (); 23537c478bd9Sstevel@tonic-gate 23547c478bd9Sstevel@tonic-gate /* Open Stage 2. */ 23557c478bd9Sstevel@tonic-gate is_open = grub_open (file); 23567c478bd9Sstevel@tonic-gate if (! is_open) 23577c478bd9Sstevel@tonic-gate goto fail; 23587c478bd9Sstevel@tonic-gate 23597c478bd9Sstevel@tonic-gate src_drive = current_drive; 23607c478bd9Sstevel@tonic-gate src_partition = current_partition; 23617c478bd9Sstevel@tonic-gate src_part_start = part_start; 23627c478bd9Sstevel@tonic-gate src_geom = buf_geom; 23637c478bd9Sstevel@tonic-gate 23647c478bd9Sstevel@tonic-gate if (! new_drive) 23657c478bd9Sstevel@tonic-gate new_drive = src_drive; 23667c478bd9Sstevel@tonic-gate else if (src_drive != dest_drive) 23677c478bd9Sstevel@tonic-gate grub_printf ("Warning: the option `d' was not used, but the Stage 1 will" 23687c478bd9Sstevel@tonic-gate " be installed on a\ndifferent drive than the drive where" 23697c478bd9Sstevel@tonic-gate " the Stage 2 resides.\n"); 23707c478bd9Sstevel@tonic-gate 23717c478bd9Sstevel@tonic-gate /* Set the boot drive. */ 23727c478bd9Sstevel@tonic-gate *((unsigned char *) (stage1_buffer + STAGE1_BOOT_DRIVE)) = new_drive; 23737c478bd9Sstevel@tonic-gate 23747c478bd9Sstevel@tonic-gate /* Set the "force LBA" flag. */ 23757c478bd9Sstevel@tonic-gate *((unsigned char *) (stage1_buffer + STAGE1_FORCE_LBA)) = is_force_lba; 23767c478bd9Sstevel@tonic-gate 23771b8adde7SWilliam Kucharski /* If DEST_DRIVE is a hard disk, enable the workaround, which is 23781b8adde7SWilliam Kucharski for buggy BIOSes which don't pass boot drive correctly. Instead, 23791b8adde7SWilliam Kucharski they pass 0x00 or 0x01 even when booted from 0x80. */ 23801b8adde7SWilliam Kucharski if (dest_drive & BIOS_FLAG_FIXED_DISK) 23811b8adde7SWilliam Kucharski /* Replace the jmp (2 bytes) with double nop's. */ 23821b8adde7SWilliam Kucharski *((unsigned short *) (stage1_buffer + STAGE1_BOOT_DRIVE_CHECK)) 23831b8adde7SWilliam Kucharski = 0x9090; 23841b8adde7SWilliam Kucharski 23857c478bd9Sstevel@tonic-gate /* Read the first sector of Stage 2. */ 23867c478bd9Sstevel@tonic-gate disk_read_hook = disk_read_savesect_func; 23877c478bd9Sstevel@tonic-gate if (grub_read (stage2_first_buffer, SECTOR_SIZE) != SECTOR_SIZE) 23887c478bd9Sstevel@tonic-gate goto fail; 23897c478bd9Sstevel@tonic-gate 23907c478bd9Sstevel@tonic-gate stage2_first_sector = saved_sector; 23917c478bd9Sstevel@tonic-gate 23927c478bd9Sstevel@tonic-gate /* Read the second sector of Stage 2. */ 23937c478bd9Sstevel@tonic-gate if (grub_read (stage2_second_buffer, SECTOR_SIZE) != SECTOR_SIZE) 23947c478bd9Sstevel@tonic-gate goto fail; 23957c478bd9Sstevel@tonic-gate 23967c478bd9Sstevel@tonic-gate stage2_second_sector = saved_sector; 23977c478bd9Sstevel@tonic-gate 23987c478bd9Sstevel@tonic-gate /* Check for the version of Stage 2. */ 23997c478bd9Sstevel@tonic-gate if (*((short *) (stage2_second_buffer + STAGE2_VER_MAJ_OFFS)) 24007c478bd9Sstevel@tonic-gate != COMPAT_VERSION) 24017c478bd9Sstevel@tonic-gate { 24027c478bd9Sstevel@tonic-gate errnum = ERR_BAD_VERSION; 24037c478bd9Sstevel@tonic-gate goto fail; 24047c478bd9Sstevel@tonic-gate } 24057c478bd9Sstevel@tonic-gate 24067c478bd9Sstevel@tonic-gate /* Check for the Stage 2 id. */ 24077c478bd9Sstevel@tonic-gate if (stage2_second_buffer[STAGE2_STAGE2_ID] != STAGE2_ID_STAGE2) 24087c478bd9Sstevel@tonic-gate is_stage1_5 = 1; 24097c478bd9Sstevel@tonic-gate 24107c478bd9Sstevel@tonic-gate /* If INSTALLADDR is not specified explicitly in the command-line, 24117c478bd9Sstevel@tonic-gate determine it by the Stage 2 id. */ 24127c478bd9Sstevel@tonic-gate if (! installaddr) 24137c478bd9Sstevel@tonic-gate { 24147c478bd9Sstevel@tonic-gate if (! is_stage1_5) 24157c478bd9Sstevel@tonic-gate /* Stage 2. */ 24167c478bd9Sstevel@tonic-gate installaddr = 0x8000; 24177c478bd9Sstevel@tonic-gate else 24187c478bd9Sstevel@tonic-gate /* Stage 1.5. */ 24197c478bd9Sstevel@tonic-gate installaddr = 0x2000; 24207c478bd9Sstevel@tonic-gate } 24217c478bd9Sstevel@tonic-gate 24227c478bd9Sstevel@tonic-gate *((unsigned long *) (stage1_buffer + STAGE1_STAGE2_SECTOR)) 24237c478bd9Sstevel@tonic-gate = stage2_first_sector; 24247c478bd9Sstevel@tonic-gate *((unsigned short *) (stage1_buffer + STAGE1_STAGE2_ADDRESS)) 24257c478bd9Sstevel@tonic-gate = installaddr; 24267c478bd9Sstevel@tonic-gate *((unsigned short *) (stage1_buffer + STAGE1_STAGE2_SEGMENT)) 24277c478bd9Sstevel@tonic-gate = installaddr >> 4; 24287c478bd9Sstevel@tonic-gate 24297c478bd9Sstevel@tonic-gate i = (int) stage2_first_buffer + SECTOR_SIZE - 4; 24307c478bd9Sstevel@tonic-gate while (*((unsigned long *) i)) 24317c478bd9Sstevel@tonic-gate { 24327c478bd9Sstevel@tonic-gate if (i < (int) stage2_first_buffer 24337c478bd9Sstevel@tonic-gate || (*((int *) (i - 4)) & 0x80000000) 24347c478bd9Sstevel@tonic-gate || *((unsigned short *) i) >= 0xA00 24357c478bd9Sstevel@tonic-gate || *((short *) (i + 2)) == 0) 24367c478bd9Sstevel@tonic-gate { 24377c478bd9Sstevel@tonic-gate errnum = ERR_BAD_VERSION; 24387c478bd9Sstevel@tonic-gate goto fail; 24397c478bd9Sstevel@tonic-gate } 24407c478bd9Sstevel@tonic-gate 24417c478bd9Sstevel@tonic-gate *((int *) i) = 0; 24427c478bd9Sstevel@tonic-gate *((int *) (i - 4)) = 0; 24437c478bd9Sstevel@tonic-gate i -= 8; 24447c478bd9Sstevel@tonic-gate } 24457c478bd9Sstevel@tonic-gate 24467c478bd9Sstevel@tonic-gate installlist = (int) stage2_first_buffer + SECTOR_SIZE + 4; 24477c478bd9Sstevel@tonic-gate installaddr += SECTOR_SIZE; 24487c478bd9Sstevel@tonic-gate 24497c478bd9Sstevel@tonic-gate /* Read the whole of Stage2 except for the first sector. */ 24507c478bd9Sstevel@tonic-gate grub_seek (SECTOR_SIZE); 24517c478bd9Sstevel@tonic-gate 24527c478bd9Sstevel@tonic-gate disk_read_hook = disk_read_blocklist_func; 24537c478bd9Sstevel@tonic-gate if (! grub_read (dummy, -1)) 24547c478bd9Sstevel@tonic-gate goto fail; 24557c478bd9Sstevel@tonic-gate 24567c478bd9Sstevel@tonic-gate disk_read_hook = 0; 24577c478bd9Sstevel@tonic-gate 24587c478bd9Sstevel@tonic-gate /* Find a string for the configuration filename. */ 24597c478bd9Sstevel@tonic-gate config_file_location = stage2_second_buffer + STAGE2_VER_STR_OFFS; 24607c478bd9Sstevel@tonic-gate while (*(config_file_location++)) 24617c478bd9Sstevel@tonic-gate ; 24627c478bd9Sstevel@tonic-gate 24637c478bd9Sstevel@tonic-gate /* Set the "force LBA" flag for Stage2. */ 24647c478bd9Sstevel@tonic-gate *((unsigned char *) (stage2_second_buffer + STAGE2_FORCE_LBA)) 24657c478bd9Sstevel@tonic-gate = is_force_lba; 24667c478bd9Sstevel@tonic-gate 24677c478bd9Sstevel@tonic-gate if (*ptr == 'p') 24687c478bd9Sstevel@tonic-gate { 24697c478bd9Sstevel@tonic-gate *((long *) (stage2_second_buffer + STAGE2_INSTALLPART)) 24707c478bd9Sstevel@tonic-gate = src_partition; 24717c478bd9Sstevel@tonic-gate if (is_stage1_5) 24727c478bd9Sstevel@tonic-gate { 24737c478bd9Sstevel@tonic-gate /* Reset the device information in FILE if it is a Stage 1.5. */ 24747c478bd9Sstevel@tonic-gate unsigned long device = 0xFFFFFFFF; 24757c478bd9Sstevel@tonic-gate 24767c478bd9Sstevel@tonic-gate grub_memmove (config_file_location, (char *) &device, 24777c478bd9Sstevel@tonic-gate sizeof (device)); 24787c478bd9Sstevel@tonic-gate } 24797c478bd9Sstevel@tonic-gate 24807c478bd9Sstevel@tonic-gate ptr = skip_to (0, ptr); 24817c478bd9Sstevel@tonic-gate } 24827c478bd9Sstevel@tonic-gate 24837c478bd9Sstevel@tonic-gate if (*ptr) 24847c478bd9Sstevel@tonic-gate { 24857c478bd9Sstevel@tonic-gate grub_strcpy (config_filename, ptr); 24867c478bd9Sstevel@tonic-gate nul_terminate (config_filename); 24877c478bd9Sstevel@tonic-gate 24887c478bd9Sstevel@tonic-gate if (! is_stage1_5) 24897c478bd9Sstevel@tonic-gate /* If it is a Stage 2, just copy PTR to CONFIG_FILE_LOCATION. */ 24907c478bd9Sstevel@tonic-gate grub_strcpy (config_file_location, ptr); 24917c478bd9Sstevel@tonic-gate else 24927c478bd9Sstevel@tonic-gate { 24937c478bd9Sstevel@tonic-gate char *real_config; 24947c478bd9Sstevel@tonic-gate unsigned long device; 24957c478bd9Sstevel@tonic-gate 24967c478bd9Sstevel@tonic-gate /* Translate the external device syntax to the internal device 24977c478bd9Sstevel@tonic-gate syntax. */ 24987c478bd9Sstevel@tonic-gate if (! (real_config = set_device (ptr))) 24997c478bd9Sstevel@tonic-gate { 25007c478bd9Sstevel@tonic-gate /* The Stage 2 PTR does not contain the device name, so 25017c478bd9Sstevel@tonic-gate use the root device instead. */ 25027c478bd9Sstevel@tonic-gate errnum = ERR_NONE; 25037c478bd9Sstevel@tonic-gate current_drive = saved_drive; 25047c478bd9Sstevel@tonic-gate current_partition = saved_partition; 25057c478bd9Sstevel@tonic-gate real_config = ptr; 25067c478bd9Sstevel@tonic-gate } 25077c478bd9Sstevel@tonic-gate 25087c478bd9Sstevel@tonic-gate if (current_drive == src_drive) 25097c478bd9Sstevel@tonic-gate { 25107c478bd9Sstevel@tonic-gate /* If the drive where the Stage 2 resides is the same as 25117c478bd9Sstevel@tonic-gate the one where the Stage 1.5 resides, do not embed the 25127c478bd9Sstevel@tonic-gate drive number. */ 25137c478bd9Sstevel@tonic-gate current_drive = GRUB_INVALID_DRIVE; 25147c478bd9Sstevel@tonic-gate } 25157c478bd9Sstevel@tonic-gate 25167c478bd9Sstevel@tonic-gate device = (current_drive << 24) | current_partition; 25177c478bd9Sstevel@tonic-gate grub_memmove (config_file_location, (char *) &device, 25187c478bd9Sstevel@tonic-gate sizeof (device)); 25197c478bd9Sstevel@tonic-gate grub_strcpy (config_file_location + sizeof (device), 25207c478bd9Sstevel@tonic-gate real_config); 25217c478bd9Sstevel@tonic-gate } 25227c478bd9Sstevel@tonic-gate 25237c478bd9Sstevel@tonic-gate /* If a Stage 1.5 is used, then we need to modify the Stage2. */ 25247c478bd9Sstevel@tonic-gate if (is_stage1_5) 25257c478bd9Sstevel@tonic-gate { 25267c478bd9Sstevel@tonic-gate char *real_config_filename = skip_to (0, ptr); 25277c478bd9Sstevel@tonic-gate 25287c478bd9Sstevel@tonic-gate is_open = grub_open (config_filename); 25297c478bd9Sstevel@tonic-gate if (! is_open) 25307c478bd9Sstevel@tonic-gate goto fail; 25317c478bd9Sstevel@tonic-gate 25327c478bd9Sstevel@tonic-gate /* Skip the first sector. */ 25337c478bd9Sstevel@tonic-gate grub_seek (SECTOR_SIZE); 25347c478bd9Sstevel@tonic-gate 25357c478bd9Sstevel@tonic-gate disk_read_hook = disk_read_savesect_func; 25367c478bd9Sstevel@tonic-gate if (grub_read (stage2_buffer, SECTOR_SIZE) != SECTOR_SIZE) 25377c478bd9Sstevel@tonic-gate goto fail; 25387c478bd9Sstevel@tonic-gate 25397c478bd9Sstevel@tonic-gate disk_read_hook = 0; 25407c478bd9Sstevel@tonic-gate grub_close (); 25417c478bd9Sstevel@tonic-gate is_open = 0; 25427c478bd9Sstevel@tonic-gate 25437c478bd9Sstevel@tonic-gate /* Sanity check. */ 25447c478bd9Sstevel@tonic-gate if (*(stage2_buffer + STAGE2_STAGE2_ID) != STAGE2_ID_STAGE2) 25457c478bd9Sstevel@tonic-gate { 25467c478bd9Sstevel@tonic-gate errnum = ERR_BAD_VERSION; 25477c478bd9Sstevel@tonic-gate goto fail; 25487c478bd9Sstevel@tonic-gate } 25497c478bd9Sstevel@tonic-gate 25507c478bd9Sstevel@tonic-gate /* Set the "force LBA" flag for Stage2. */ 25517c478bd9Sstevel@tonic-gate *(stage2_buffer + STAGE2_FORCE_LBA) = is_force_lba; 25527c478bd9Sstevel@tonic-gate 25537c478bd9Sstevel@tonic-gate /* If REAL_CONFIG_FILENAME is specified, copy it to the Stage2. */ 25547c478bd9Sstevel@tonic-gate if (*real_config_filename) 25557c478bd9Sstevel@tonic-gate { 25567c478bd9Sstevel@tonic-gate /* Specified */ 25577c478bd9Sstevel@tonic-gate char *location; 25587c478bd9Sstevel@tonic-gate 25597c478bd9Sstevel@tonic-gate /* Find a string for the configuration filename. */ 25607c478bd9Sstevel@tonic-gate location = stage2_buffer + STAGE2_VER_STR_OFFS; 25617c478bd9Sstevel@tonic-gate while (*(location++)) 25627c478bd9Sstevel@tonic-gate ; 25637c478bd9Sstevel@tonic-gate 25647c478bd9Sstevel@tonic-gate /* Copy the name. */ 25657c478bd9Sstevel@tonic-gate grub_strcpy (location, real_config_filename); 25667c478bd9Sstevel@tonic-gate } 25677c478bd9Sstevel@tonic-gate 25687c478bd9Sstevel@tonic-gate /* Write it to the disk. */ 2569342440ecSPrasad Singamsetty buf_track = BUF_CACHE_INVALID; 25707c478bd9Sstevel@tonic-gate 25717c478bd9Sstevel@tonic-gate #ifdef GRUB_UTIL 25727c478bd9Sstevel@tonic-gate /* In the grub shell, access the Stage 2 via the OS filesystem 25737c478bd9Sstevel@tonic-gate service, if possible. */ 25747c478bd9Sstevel@tonic-gate if (stage2_os_file) 25757c478bd9Sstevel@tonic-gate { 25767c478bd9Sstevel@tonic-gate FILE *fp; 25777c478bd9Sstevel@tonic-gate 25787c478bd9Sstevel@tonic-gate fp = fopen (stage2_os_file, "r+"); 25797c478bd9Sstevel@tonic-gate if (! fp) 25807c478bd9Sstevel@tonic-gate { 25817c478bd9Sstevel@tonic-gate errnum = ERR_FILE_NOT_FOUND; 25827c478bd9Sstevel@tonic-gate goto fail; 25837c478bd9Sstevel@tonic-gate } 25847c478bd9Sstevel@tonic-gate 25857c478bd9Sstevel@tonic-gate if (fseek (fp, SECTOR_SIZE, SEEK_SET) != 0) 25867c478bd9Sstevel@tonic-gate { 25877c478bd9Sstevel@tonic-gate fclose (fp); 25887c478bd9Sstevel@tonic-gate errnum = ERR_BAD_VERSION; 25897c478bd9Sstevel@tonic-gate goto fail; 25907c478bd9Sstevel@tonic-gate } 25917c478bd9Sstevel@tonic-gate 25927c478bd9Sstevel@tonic-gate if (fwrite (stage2_buffer, 1, SECTOR_SIZE, fp) 25937c478bd9Sstevel@tonic-gate != SECTOR_SIZE) 25947c478bd9Sstevel@tonic-gate { 25957c478bd9Sstevel@tonic-gate fclose (fp); 25967c478bd9Sstevel@tonic-gate errnum = ERR_WRITE; 25977c478bd9Sstevel@tonic-gate goto fail; 25987c478bd9Sstevel@tonic-gate } 25997c478bd9Sstevel@tonic-gate 26007c478bd9Sstevel@tonic-gate fclose (fp); 26017c478bd9Sstevel@tonic-gate } 26027c478bd9Sstevel@tonic-gate else 26037c478bd9Sstevel@tonic-gate #endif /* GRUB_UTIL */ 26047c478bd9Sstevel@tonic-gate { 26057c478bd9Sstevel@tonic-gate if (! devwrite (saved_sector - part_start, 1, stage2_buffer)) 26067c478bd9Sstevel@tonic-gate goto fail; 26077c478bd9Sstevel@tonic-gate } 26087c478bd9Sstevel@tonic-gate } 26097c478bd9Sstevel@tonic-gate } 26107c478bd9Sstevel@tonic-gate 26117c478bd9Sstevel@tonic-gate /* Clear the cache. */ 2612342440ecSPrasad Singamsetty buf_track = BUF_CACHE_INVALID; 26137c478bd9Sstevel@tonic-gate 26147c478bd9Sstevel@tonic-gate /* Write the modified sectors of Stage2 to the disk. */ 26157c478bd9Sstevel@tonic-gate #ifdef GRUB_UTIL 26167c478bd9Sstevel@tonic-gate if (! is_stage1_5 && stage2_os_file) 26177c478bd9Sstevel@tonic-gate { 26187c478bd9Sstevel@tonic-gate FILE *fp; 26197c478bd9Sstevel@tonic-gate 26207c478bd9Sstevel@tonic-gate fp = fopen (stage2_os_file, "r+"); 26217c478bd9Sstevel@tonic-gate if (! fp) 26227c478bd9Sstevel@tonic-gate { 26237c478bd9Sstevel@tonic-gate errnum = ERR_FILE_NOT_FOUND; 26247c478bd9Sstevel@tonic-gate goto fail; 26257c478bd9Sstevel@tonic-gate } 26267c478bd9Sstevel@tonic-gate 26277c478bd9Sstevel@tonic-gate if (fwrite (stage2_first_buffer, 1, SECTOR_SIZE, fp) != SECTOR_SIZE) 26287c478bd9Sstevel@tonic-gate { 26297c478bd9Sstevel@tonic-gate fclose (fp); 26307c478bd9Sstevel@tonic-gate errnum = ERR_WRITE; 26317c478bd9Sstevel@tonic-gate goto fail; 26327c478bd9Sstevel@tonic-gate } 26337c478bd9Sstevel@tonic-gate 26347c478bd9Sstevel@tonic-gate if (fwrite (stage2_second_buffer, 1, SECTOR_SIZE, fp) != SECTOR_SIZE) 26357c478bd9Sstevel@tonic-gate { 26367c478bd9Sstevel@tonic-gate fclose (fp); 26377c478bd9Sstevel@tonic-gate errnum = ERR_WRITE; 26387c478bd9Sstevel@tonic-gate goto fail; 26397c478bd9Sstevel@tonic-gate } 26407c478bd9Sstevel@tonic-gate 26417c478bd9Sstevel@tonic-gate fclose (fp); 26427c478bd9Sstevel@tonic-gate } 26437c478bd9Sstevel@tonic-gate else 26447c478bd9Sstevel@tonic-gate #endif /* GRUB_UTIL */ 26457c478bd9Sstevel@tonic-gate { 26467c478bd9Sstevel@tonic-gate /* The first. */ 26477c478bd9Sstevel@tonic-gate current_drive = src_drive; 26487c478bd9Sstevel@tonic-gate current_partition = src_partition; 26497c478bd9Sstevel@tonic-gate 26507c478bd9Sstevel@tonic-gate if (! open_partition ()) 26517c478bd9Sstevel@tonic-gate goto fail; 26527c478bd9Sstevel@tonic-gate 26537c478bd9Sstevel@tonic-gate if (! devwrite (stage2_first_sector - src_part_start, 1, 26547c478bd9Sstevel@tonic-gate stage2_first_buffer)) 26557c478bd9Sstevel@tonic-gate goto fail; 26567c478bd9Sstevel@tonic-gate 26577c478bd9Sstevel@tonic-gate if (! devwrite (stage2_second_sector - src_part_start, 1, 26587c478bd9Sstevel@tonic-gate stage2_second_buffer)) 26597c478bd9Sstevel@tonic-gate goto fail; 26607c478bd9Sstevel@tonic-gate } 26617c478bd9Sstevel@tonic-gate 26627c478bd9Sstevel@tonic-gate /* Write the modified sector of Stage 1 to the disk. */ 26637c478bd9Sstevel@tonic-gate current_drive = dest_drive; 26647c478bd9Sstevel@tonic-gate current_partition = dest_partition; 26657c478bd9Sstevel@tonic-gate if (! open_partition ()) 26667c478bd9Sstevel@tonic-gate goto fail; 26677c478bd9Sstevel@tonic-gate 26687c478bd9Sstevel@tonic-gate devwrite (0, 1, stage1_buffer); 26697c478bd9Sstevel@tonic-gate 26707c478bd9Sstevel@tonic-gate fail: 26717c478bd9Sstevel@tonic-gate if (is_open) 26727c478bd9Sstevel@tonic-gate grub_close (); 26737c478bd9Sstevel@tonic-gate 26747c478bd9Sstevel@tonic-gate disk_read_hook = 0; 26757c478bd9Sstevel@tonic-gate 26767c478bd9Sstevel@tonic-gate #ifndef NO_DECOMPRESSION 26777c478bd9Sstevel@tonic-gate no_decompression = 0; 26787c478bd9Sstevel@tonic-gate #endif 26797c478bd9Sstevel@tonic-gate 26807c478bd9Sstevel@tonic-gate return errnum; 26817c478bd9Sstevel@tonic-gate } 26827c478bd9Sstevel@tonic-gate 26837c478bd9Sstevel@tonic-gate static struct builtin builtin_install = 26847c478bd9Sstevel@tonic-gate { 26857c478bd9Sstevel@tonic-gate "install", 26867c478bd9Sstevel@tonic-gate install_func, 26877c478bd9Sstevel@tonic-gate BUILTIN_CMDLINE, 26887c478bd9Sstevel@tonic-gate "install [--stage2=STAGE2_FILE] [--force-lba] STAGE1 [d] DEVICE STAGE2 [ADDR] [p] [CONFIG_FILE] [REAL_CONFIG_FILE]", 26897c478bd9Sstevel@tonic-gate "Install STAGE1 on DEVICE, and install a blocklist for loading STAGE2" 26907c478bd9Sstevel@tonic-gate " as a Stage 2. If the option `d' is present, the Stage 1 will always" 26917c478bd9Sstevel@tonic-gate " look for the disk where STAGE2 was installed, rather than using" 26927c478bd9Sstevel@tonic-gate " the booting drive. The Stage 2 will be loaded at address ADDR, which" 26937c478bd9Sstevel@tonic-gate " will be determined automatically if you don't specify it. If" 26947c478bd9Sstevel@tonic-gate " the option `p' or CONFIG_FILE is present, then the first block" 26957c478bd9Sstevel@tonic-gate " of Stage 2 is patched with new values of the partition and name" 26967c478bd9Sstevel@tonic-gate " of the configuration file used by the true Stage 2 (for a Stage 1.5," 26977c478bd9Sstevel@tonic-gate " this is the name of the true Stage 2) at boot time. If STAGE2 is a Stage" 26987c478bd9Sstevel@tonic-gate " 1.5 and REAL_CONFIG_FILE is present, then the Stage 2 CONFIG_FILE is" 26997c478bd9Sstevel@tonic-gate " patched with the configuration filename REAL_CONFIG_FILE." 27007c478bd9Sstevel@tonic-gate " If the option `--force-lba' is specified, disable some sanity checks" 27017c478bd9Sstevel@tonic-gate " for LBA mode. If the option `--stage2' is specified, rewrite the Stage" 27027c478bd9Sstevel@tonic-gate " 2 via your OS's filesystem instead of the raw device." 27037c478bd9Sstevel@tonic-gate }; 27047c478bd9Sstevel@tonic-gate 27057c478bd9Sstevel@tonic-gate 27067c478bd9Sstevel@tonic-gate /* ioprobe */ 27077c478bd9Sstevel@tonic-gate static int 27087c478bd9Sstevel@tonic-gate ioprobe_func (char *arg, int flags) 27097c478bd9Sstevel@tonic-gate { 27107c478bd9Sstevel@tonic-gate #ifdef GRUB_UTIL 27117c478bd9Sstevel@tonic-gate 27127c478bd9Sstevel@tonic-gate errnum = ERR_UNRECOGNIZED; 27137c478bd9Sstevel@tonic-gate return 1; 27147c478bd9Sstevel@tonic-gate 27157c478bd9Sstevel@tonic-gate #else /* ! GRUB_UTIL */ 27167c478bd9Sstevel@tonic-gate 27177c478bd9Sstevel@tonic-gate unsigned short *port; 27187c478bd9Sstevel@tonic-gate 27197c478bd9Sstevel@tonic-gate /* Get the drive number. */ 27207c478bd9Sstevel@tonic-gate set_device (arg); 27217c478bd9Sstevel@tonic-gate if (errnum) 27227c478bd9Sstevel@tonic-gate return 1; 27237c478bd9Sstevel@tonic-gate 27247c478bd9Sstevel@tonic-gate /* Clean out IO_MAP. */ 27257c478bd9Sstevel@tonic-gate grub_memset ((char *) io_map, 0, IO_MAP_SIZE * sizeof (unsigned short)); 27267c478bd9Sstevel@tonic-gate 27277c478bd9Sstevel@tonic-gate /* Track the int13 handler. */ 27287c478bd9Sstevel@tonic-gate track_int13 (current_drive); 27297c478bd9Sstevel@tonic-gate 27307c478bd9Sstevel@tonic-gate /* Print out the result. */ 27317c478bd9Sstevel@tonic-gate for (port = io_map; *port != 0; port++) 27327c478bd9Sstevel@tonic-gate grub_printf (" 0x%x", (unsigned int) *port); 27337c478bd9Sstevel@tonic-gate 27347c478bd9Sstevel@tonic-gate return 0; 27357c478bd9Sstevel@tonic-gate 27367c478bd9Sstevel@tonic-gate #endif /* ! GRUB_UTIL */ 27377c478bd9Sstevel@tonic-gate } 27387c478bd9Sstevel@tonic-gate 27397c478bd9Sstevel@tonic-gate static struct builtin builtin_ioprobe = 27407c478bd9Sstevel@tonic-gate { 27417c478bd9Sstevel@tonic-gate "ioprobe", 27427c478bd9Sstevel@tonic-gate ioprobe_func, 27437c478bd9Sstevel@tonic-gate BUILTIN_CMDLINE, 27447c478bd9Sstevel@tonic-gate "ioprobe DRIVE", 27457c478bd9Sstevel@tonic-gate "Probe I/O ports used for the drive DRIVE." 27467c478bd9Sstevel@tonic-gate }; 27477c478bd9Sstevel@tonic-gate 27487c478bd9Sstevel@tonic-gate 2749b1b8ab34Slling /* 2750b1b8ab34Slling * To boot from a ZFS root filesystem, the kernel$ or module$ commands 2751ffb5616eSLin Ling * must include "-B $ZFS-BOOTFS" to expand to the zfs-bootfs, bootpath, 2752ffb5616eSLin Ling * and diskdevid boot property values for passing to the kernel: 2753b1b8ab34Slling * 2754b1b8ab34Slling * e.g. 2755b1b8ab34Slling * kernel$ /platform/i86pc/kernel/$ISADIR/unix -B $ZFS-BOOTFS,console=ttya 2756b1b8ab34Slling * 2757ffb5616eSLin Ling * $ZFS-BOOTFS is expanded to 2758ffb5616eSLin Ling * 2759ffb5616eSLin Ling * zfs-bootfs=<rootpool-name/zfs-rootfilesystem-object-num>, 2760ffb5616eSLin Ling * bootpath=<device phys path>, 2761ffb5616eSLin Ling * diskdevid=<device id> 2762ffb5616eSLin Ling * 2763ffb5616eSLin Ling * if both bootpath and diskdevid can be found. 2764ffb5616eSLin Ling * e.g 2765ffb5616eSLin Ling * zfs-bootfs=rpool/85, 2766ffb5616eSLin Ling * bootpath="/pci@0,0/pci1022,7450@a/pci17c2,10@4/sd@0,0:a", 2767ffb5616eSLin Ling * diskdevid="id1,sd@SSEAGATE_ST336607LC______3JA0LNHE0000741326W6/a" 2768b1b8ab34Slling */ 2769b1b8ab34Slling static int 2770b1b8ab34Slling expand_dollar_bootfs(char *in, char *out) 2771b1b8ab34Slling { 2772b1b8ab34Slling char *token, *tmpout = out; 2773b1b8ab34Slling int outlen, blen; 2774bf82a41bSeschrock int postcomma = 0; 2775b1b8ab34Slling 2776ffb5616eSLin Ling if (current_bootpath[0] == '\0' && current_devid[0] == '\0') { 2777ffb5616eSLin Ling errnum = ERR_NO_BOOTPATH; 2778ffb5616eSLin Ling return (1); 2779ffb5616eSLin Ling } 2780ffb5616eSLin Ling 2781b1b8ab34Slling outlen = strlen(in); 2782b1b8ab34Slling blen = current_bootfs_obj == 0 ? strlen(current_rootpool) : 2783b1b8ab34Slling strlen(current_rootpool) + 11; 2784b1b8ab34Slling 2785b1b8ab34Slling out[0] = '\0'; 2786b1b8ab34Slling while (token = strstr(in, "$ZFS-BOOTFS")) { 2787b1b8ab34Slling 2788ffb5616eSLin Ling if ((outlen += blen) >= MAX_CMDLINE) { 2789b1b8ab34Slling errnum = ERR_WONT_FIT; 2790b1b8ab34Slling return (1); 2791b1b8ab34Slling } 2792b1b8ab34Slling 2793b1b8ab34Slling token[0] = '\0'; 2794b1b8ab34Slling grub_sprintf(tmpout, "%s", in); 2795b1b8ab34Slling token[0] = '$'; 2796051aabe6Staylor in = token + 11; /* skip over $ZFS-BOOTFS */ 2797b1b8ab34Slling tmpout = out + strlen(out); 2798b1b8ab34Slling 2799b1b8ab34Slling /* Note: %u only fits 32 bit integer; */ 2800b1b8ab34Slling if (current_bootfs_obj > 0) 2801b1b8ab34Slling grub_sprintf(tmpout, "zfs-bootfs=%s/%u", 2802b1b8ab34Slling current_rootpool, current_bootfs_obj); 2803b1b8ab34Slling else 2804b1b8ab34Slling grub_sprintf(tmpout, "zfs-bootfs=%s", 2805b1b8ab34Slling current_rootpool); 2806b1b8ab34Slling tmpout = out + strlen(out); 2807b1b8ab34Slling } 2808b1b8ab34Slling 2809e7cbe64fSgw /* 2810bf82a41bSeschrock * Check to see if 'zfs-bootfs' was explicitly specified on the command 2811bf82a41bSeschrock * line so that we can insert the 'bootpath' property. 2812bf82a41bSeschrock */ 2813bf82a41bSeschrock if ((tmpout == out) && (token = strstr(in, "zfs-bootfs")) != NULL) { 2814bf82a41bSeschrock token[0] = '\0'; 2815bf82a41bSeschrock grub_strcpy(tmpout, in); 2816bf82a41bSeschrock token[0] = 'z'; 2817bf82a41bSeschrock in = token; 2818bf82a41bSeschrock 2819bf82a41bSeschrock tmpout = out + strlen(out); 2820bf82a41bSeschrock postcomma = 1; 2821bf82a41bSeschrock } 2822bf82a41bSeschrock 2823bf82a41bSeschrock /* 2824bf82a41bSeschrock * Set the 'bootpath' property if a ZFS dataset was specified, either 2825bf82a41bSeschrock * through '$ZFS-BOOTFS' or an explicit 'zfs-bootfs' setting. 2826e7cbe64fSgw */ 2827e7cbe64fSgw if (tmpout != out) { 2828ffb5616eSLin Ling if (current_bootpath[0] != '\0') { 2829ffb5616eSLin Ling if ((outlen += 12 + strlen(current_bootpath)) 2830ffb5616eSLin Ling >= MAX_CMDLINE) { 2831ffb5616eSLin Ling errnum = ERR_WONT_FIT; 2832ffb5616eSLin Ling return (1); 2833ffb5616eSLin Ling } 2834ffb5616eSLin Ling grub_sprintf(tmpout, 2835ffb5616eSLin Ling postcomma ? "bootpath=\"%s\"," : ",bootpath=\"%s\"", 2836ffb5616eSLin Ling current_bootpath); 2837ffb5616eSLin Ling tmpout = out + strlen(out); 2838e7cbe64fSgw } 2839ffb5616eSLin Ling 2840ffb5616eSLin Ling if (current_devid[0] != '\0') { 2841ffb5616eSLin Ling if ((outlen += 13 + strlen(current_devid)) 2842ffb5616eSLin Ling >= MAX_CMDLINE) { 2843ffb5616eSLin Ling errnum = ERR_WONT_FIT; 2844ffb5616eSLin Ling return (1); 2845ffb5616eSLin Ling } 2846ffb5616eSLin Ling grub_sprintf(tmpout, 2847ffb5616eSLin Ling postcomma ? "diskdevid=\"%s\"," : ",diskdevid=\"%s\"", 2848ffb5616eSLin Ling current_devid); 2849051aabe6Staylor } 2850e7cbe64fSgw } 2851e7cbe64fSgw 2852b1b8ab34Slling strncat(out, in, MAX_CMDLINE); 2853b1b8ab34Slling return (0); 2854b1b8ab34Slling } 2855b1b8ab34Slling 28567c478bd9Sstevel@tonic-gate /* kernel */ 28577c478bd9Sstevel@tonic-gate static int 28587c478bd9Sstevel@tonic-gate kernel_func (char *arg, int flags) 28597c478bd9Sstevel@tonic-gate { 28607c478bd9Sstevel@tonic-gate int len; 28617c478bd9Sstevel@tonic-gate kernel_t suggested_type = KERNEL_TYPE_NONE; 28627c478bd9Sstevel@tonic-gate unsigned long load_flags = 0; 28637c478bd9Sstevel@tonic-gate 28647c478bd9Sstevel@tonic-gate #ifndef AUTO_LINUX_MEM_OPT 28657c478bd9Sstevel@tonic-gate load_flags |= KERNEL_LOAD_NO_MEM_OPTION; 28667c478bd9Sstevel@tonic-gate #endif 28677c478bd9Sstevel@tonic-gate 28687c478bd9Sstevel@tonic-gate /* Deal with GNU-style long options. */ 28697c478bd9Sstevel@tonic-gate while (1) 28707c478bd9Sstevel@tonic-gate { 28717c478bd9Sstevel@tonic-gate /* If the option `--type=TYPE' is specified, convert the string to 28727c478bd9Sstevel@tonic-gate a kernel type. */ 28737c478bd9Sstevel@tonic-gate if (grub_memcmp (arg, "--type=", 7) == 0) 28747c478bd9Sstevel@tonic-gate { 28757c478bd9Sstevel@tonic-gate arg += 7; 28767c478bd9Sstevel@tonic-gate 28777c478bd9Sstevel@tonic-gate if (grub_memcmp (arg, "netbsd", 6) == 0) 28787c478bd9Sstevel@tonic-gate suggested_type = KERNEL_TYPE_NETBSD; 28797c478bd9Sstevel@tonic-gate else if (grub_memcmp (arg, "freebsd", 7) == 0) 28807c478bd9Sstevel@tonic-gate suggested_type = KERNEL_TYPE_FREEBSD; 28817c478bd9Sstevel@tonic-gate else if (grub_memcmp (arg, "openbsd", 7) == 0) 28827c478bd9Sstevel@tonic-gate /* XXX: For now, OpenBSD is identical to NetBSD, from GRUB's 28837c478bd9Sstevel@tonic-gate point of view. */ 28847c478bd9Sstevel@tonic-gate suggested_type = KERNEL_TYPE_NETBSD; 28857c478bd9Sstevel@tonic-gate else if (grub_memcmp (arg, "linux", 5) == 0) 28867c478bd9Sstevel@tonic-gate suggested_type = KERNEL_TYPE_LINUX; 28877c478bd9Sstevel@tonic-gate else if (grub_memcmp (arg, "biglinux", 8) == 0) 28887c478bd9Sstevel@tonic-gate suggested_type = KERNEL_TYPE_BIG_LINUX; 28897c478bd9Sstevel@tonic-gate else if (grub_memcmp (arg, "multiboot", 9) == 0) 28907c478bd9Sstevel@tonic-gate suggested_type = KERNEL_TYPE_MULTIBOOT; 28917c478bd9Sstevel@tonic-gate else 28927c478bd9Sstevel@tonic-gate { 28937c478bd9Sstevel@tonic-gate errnum = ERR_BAD_ARGUMENT; 28947c478bd9Sstevel@tonic-gate return 1; 28957c478bd9Sstevel@tonic-gate } 28967c478bd9Sstevel@tonic-gate } 28977c478bd9Sstevel@tonic-gate /* If the `--no-mem-option' is specified, don't pass a Linux's mem 28987c478bd9Sstevel@tonic-gate option automatically. If the kernel is another type, this flag 28997c478bd9Sstevel@tonic-gate has no effect. */ 29007c478bd9Sstevel@tonic-gate else if (grub_memcmp (arg, "--no-mem-option", 15) == 0) 29017c478bd9Sstevel@tonic-gate load_flags |= KERNEL_LOAD_NO_MEM_OPTION; 29027c478bd9Sstevel@tonic-gate else 29037c478bd9Sstevel@tonic-gate break; 29047c478bd9Sstevel@tonic-gate 29057c478bd9Sstevel@tonic-gate /* Try the next. */ 29067c478bd9Sstevel@tonic-gate arg = skip_to (0, arg); 29077c478bd9Sstevel@tonic-gate } 29087c478bd9Sstevel@tonic-gate 29097c478bd9Sstevel@tonic-gate len = grub_strlen (arg); 29107c478bd9Sstevel@tonic-gate 29117c478bd9Sstevel@tonic-gate /* Reset MB_CMDLINE. */ 29127c478bd9Sstevel@tonic-gate mb_cmdline = (char *) MB_CMDLINE_BUF; 29137c478bd9Sstevel@tonic-gate if (len + 1 > MB_CMDLINE_BUFLEN) 29147c478bd9Sstevel@tonic-gate { 29157c478bd9Sstevel@tonic-gate errnum = ERR_WONT_FIT; 29167c478bd9Sstevel@tonic-gate return 1; 29177c478bd9Sstevel@tonic-gate } 29187c478bd9Sstevel@tonic-gate 29197c478bd9Sstevel@tonic-gate /* Copy the command-line to MB_CMDLINE. */ 29207c478bd9Sstevel@tonic-gate grub_memmove (mb_cmdline, arg, len + 1); 29217c478bd9Sstevel@tonic-gate kernel_type = load_image (arg, mb_cmdline, suggested_type, load_flags); 29227c478bd9Sstevel@tonic-gate if (kernel_type == KERNEL_TYPE_NONE) 29237c478bd9Sstevel@tonic-gate return 1; 29247c478bd9Sstevel@tonic-gate 2925b1b8ab34Slling mb_cmdline += grub_strlen(mb_cmdline) + 1; 29267c478bd9Sstevel@tonic-gate return 0; 29277c478bd9Sstevel@tonic-gate } 29287c478bd9Sstevel@tonic-gate 29297c478bd9Sstevel@tonic-gate static struct builtin builtin_kernel = 29307c478bd9Sstevel@tonic-gate { 29317c478bd9Sstevel@tonic-gate "kernel", 29327c478bd9Sstevel@tonic-gate kernel_func, 29337c478bd9Sstevel@tonic-gate BUILTIN_CMDLINE | BUILTIN_HELP_LIST, 29347c478bd9Sstevel@tonic-gate "kernel [--no-mem-option] [--type=TYPE] FILE [ARG ...]", 29357c478bd9Sstevel@tonic-gate "Attempt to load the primary boot image from FILE. The rest of the" 29367c478bd9Sstevel@tonic-gate " line is passed verbatim as the \"kernel command line\". Any modules" 29377c478bd9Sstevel@tonic-gate " must be reloaded after using this command. The option --type is used" 29387c478bd9Sstevel@tonic-gate " to suggest what type of kernel to be loaded. TYPE must be either of" 29397c478bd9Sstevel@tonic-gate " \"netbsd\", \"freebsd\", \"openbsd\", \"linux\", \"biglinux\" and" 29407c478bd9Sstevel@tonic-gate " \"multiboot\". The option --no-mem-option tells GRUB not to pass a" 29417c478bd9Sstevel@tonic-gate " Linux's mem option automatically." 29427c478bd9Sstevel@tonic-gate }; 29437c478bd9Sstevel@tonic-gate 2944342440ecSPrasad Singamsetty int 2945342440ecSPrasad Singamsetty min_mem64_func(char *arg, int flags) 2946342440ecSPrasad Singamsetty { 2947342440ecSPrasad Singamsetty if (!safe_parse_maxint(&arg, &min_mem64)) 2948342440ecSPrasad Singamsetty return (1); 2949342440ecSPrasad Singamsetty } 2950342440ecSPrasad Singamsetty 2951342440ecSPrasad Singamsetty static struct builtin builtin_min_mem64 = 2952342440ecSPrasad Singamsetty { 2953342440ecSPrasad Singamsetty "min_mem64", 2954342440ecSPrasad Singamsetty min_mem64_func, 2955342440ecSPrasad Singamsetty BUILTIN_CMDLINE | BUILTIN_MENU | BUILTIN_SCRIPT | BUILTIN_HELP_LIST, 2956342440ecSPrasad Singamsetty "min_mem64 <memory in MB>", 2957342440ecSPrasad Singamsetty "Sets minimum memory (in MB) required for $ISADIR to expand to amd64, " 2958342440ecSPrasad Singamsetty "even on 64-bit capable hardware." 2959342440ecSPrasad Singamsetty }; 2960342440ecSPrasad Singamsetty 2961342440ecSPrasad Singamsetty int 2962342440ecSPrasad Singamsetty check_min_mem64() 2963342440ecSPrasad Singamsetty { 2964342440ecSPrasad Singamsetty if (min_mem64 == 0) 2965342440ecSPrasad Singamsetty return (1); 2966342440ecSPrasad Singamsetty 2967342440ecSPrasad Singamsetty if ((mbi.mem_upper / 10240) * 11 >= min_mem64) 2968342440ecSPrasad Singamsetty return (1); 2969342440ecSPrasad Singamsetty 2970342440ecSPrasad Singamsetty return (0); 2971342440ecSPrasad Singamsetty } 2972ae115bc7Smrj 2973ae115bc7Smrj static int detect_target_operating_mode(); 2974ae115bc7Smrj 2975ae115bc7Smrj int 2976ae115bc7Smrj amd64_config_cpu(void) 2977ae115bc7Smrj { 2978ae115bc7Smrj struct amd64_cpuid_regs __vcr, *vcr = &__vcr; 2979ae115bc7Smrj uint32_t maxeax; 2980ae115bc7Smrj uint32_t max_maxeax = 0x100; 2981ae115bc7Smrj char vendor[13]; 2982ae115bc7Smrj int isamd64 = 0; 2983ae115bc7Smrj uint32_t stdfeatures = 0, xtdfeatures = 0; 2984ae115bc7Smrj uint64_t efer; 2985ae115bc7Smrj 2986ae115bc7Smrj /* 2987ae115bc7Smrj * This check may seem silly, but if the C preprocesor symbol __amd64 2988ae115bc7Smrj * is #defined during compilation, something that may outwardly seem 2989ae115bc7Smrj * like a good idea, uts/common/sys/isa_defs.h will #define _LP64, 2990ae115bc7Smrj * which will cause uts/common/sys/int_types.h to typedef uint64_t as 2991ae115bc7Smrj * an unsigned long - which is only 4 bytes in size when using a 32-bit 2992ae115bc7Smrj * compiler. 2993ae115bc7Smrj * 2994ae115bc7Smrj * If that happens, all the page table translation routines will fail 2995ae115bc7Smrj * horribly, so check the size of uint64_t just to insure some degree 2996ae115bc7Smrj * of sanity in future operations. 2997ae115bc7Smrj */ 2998ae115bc7Smrj /*LINTED [sizeof result is invarient]*/ 2999ae115bc7Smrj if (sizeof (uint64_t) != 8) 3000ae115bc7Smrj prom_panic("grub compiled improperly, unable to boot " 3001ae115bc7Smrj "64-bit AMD64 executables"); 3002ae115bc7Smrj 3003ae115bc7Smrj /* 3004ae115bc7Smrj * If the CPU doesn't support the CPUID instruction, it's definitely 3005ae115bc7Smrj * not an AMD64. 3006ae115bc7Smrj */ 3007ae115bc7Smrj if (amd64_cpuid_supported() == 0) 3008ae115bc7Smrj return (0); 3009ae115bc7Smrj 3010ae115bc7Smrj amd64_cpuid_insn(0, vcr); 3011ae115bc7Smrj 3012ae115bc7Smrj maxeax = vcr->r_eax; 3013ae115bc7Smrj { 3014ae115bc7Smrj /*LINTED [vendor string from cpuid data]*/ 3015ae115bc7Smrj uint32_t *iptr = (uint32_t *)vendor; 3016ae115bc7Smrj 3017ae115bc7Smrj *iptr++ = vcr->r_ebx; 3018ae115bc7Smrj *iptr++ = vcr->r_edx; 3019ae115bc7Smrj *iptr++ = vcr->r_ecx; 3020ae115bc7Smrj 3021ae115bc7Smrj vendor[12] = '\0'; 3022ae115bc7Smrj } 3023ae115bc7Smrj 3024ae115bc7Smrj if (maxeax > max_maxeax) { 3025ae115bc7Smrj grub_printf("cpu: warning, maxeax was 0x%x -> 0x%x\n", 3026ae115bc7Smrj maxeax, max_maxeax); 3027ae115bc7Smrj maxeax = max_maxeax; 3028ae115bc7Smrj } 3029ae115bc7Smrj 3030ae115bc7Smrj if (maxeax < 1) 3031ae115bc7Smrj return (0); /* no additional functions, not an AMD64 */ 3032ae115bc7Smrj else { 3033ae115bc7Smrj uint_t family, model, step; 3034ae115bc7Smrj 3035ae115bc7Smrj amd64_cpuid_insn(1, vcr); 3036ae115bc7Smrj 3037ae115bc7Smrj /* 3038ae115bc7Smrj * All AMD64/IA32e processors technically SHOULD report 3039ae115bc7Smrj * themselves as being in family 0xf, but for some reason 3040ae115bc7Smrj * Simics doesn't, and this may change in the future, so 3041ae115bc7Smrj * don't error out if it's not true. 3042ae115bc7Smrj */ 3043ae115bc7Smrj if ((family = BITX(vcr->r_eax, 11, 8)) == 0xf) 3044ae115bc7Smrj family += BITX(vcr->r_eax, 27, 20); 3045ae115bc7Smrj 3046ae115bc7Smrj if ((model = BITX(vcr->r_eax, 7, 4)) == 0xf) 3047ae115bc7Smrj model += BITX(vcr->r_eax, 19, 16) << 4; 3048ae115bc7Smrj step = BITX(vcr->r_eax, 3, 0); 3049ae115bc7Smrj 3050ae115bc7Smrj grub_printf("cpu: '%s' family %d model %d step %d\n", 3051ae115bc7Smrj vendor, family, model, step); 3052ae115bc7Smrj stdfeatures = vcr->r_edx; 3053ae115bc7Smrj } 3054ae115bc7Smrj 3055ae115bc7Smrj amd64_cpuid_insn(0x80000000, vcr); 3056ae115bc7Smrj 3057ae115bc7Smrj if (vcr->r_eax & 0x80000000) { 3058ae115bc7Smrj uint32_t xmaxeax = vcr->r_eax; 3059ae115bc7Smrj const uint32_t max_xmaxeax = 0x80000100; 3060ae115bc7Smrj 3061ae115bc7Smrj if (xmaxeax > max_xmaxeax) { 3062ae115bc7Smrj grub_printf("amd64: warning, xmaxeax was " 3063ae115bc7Smrj "0x%x -> 0x%x\n", xmaxeax, max_xmaxeax); 3064ae115bc7Smrj xmaxeax = max_xmaxeax; 3065ae115bc7Smrj } 3066ae115bc7Smrj 3067ae115bc7Smrj if (xmaxeax >= 0x80000001) { 3068ae115bc7Smrj amd64_cpuid_insn(0x80000001, vcr); 3069ae115bc7Smrj xtdfeatures = vcr->r_edx; 3070ae115bc7Smrj } 3071ae115bc7Smrj } 3072ae115bc7Smrj 3073ae115bc7Smrj if (BITX(xtdfeatures, 29, 29)) /* long mode */ 3074ae115bc7Smrj isamd64++; 3075ae115bc7Smrj else 3076ae115bc7Smrj grub_printf("amd64: CPU does NOT support long mode\n"); 3077ae115bc7Smrj 3078ae115bc7Smrj if (!BITX(stdfeatures, 0, 0)) { 3079ae115bc7Smrj grub_printf("amd64: CPU does NOT support FPU\n"); 3080ae115bc7Smrj isamd64--; 3081ae115bc7Smrj } 3082ae115bc7Smrj 3083ae115bc7Smrj if (!BITX(stdfeatures, 4, 4)) { 3084ae115bc7Smrj grub_printf("amd64: CPU does NOT support TSC\n"); 3085ae115bc7Smrj isamd64--; 3086ae115bc7Smrj } 3087ae115bc7Smrj 3088ae115bc7Smrj if (!BITX(stdfeatures, 5, 5)) { 3089ae115bc7Smrj grub_printf("amd64: CPU does NOT support MSRs\n"); 3090ae115bc7Smrj isamd64--; 3091ae115bc7Smrj } 3092ae115bc7Smrj 3093ae115bc7Smrj if (!BITX(stdfeatures, 6, 6)) { 3094ae115bc7Smrj grub_printf("amd64: CPU does NOT support PAE\n"); 3095ae115bc7Smrj isamd64--; 3096ae115bc7Smrj } 3097ae115bc7Smrj 3098ae115bc7Smrj if (!BITX(stdfeatures, 8, 8)) { 3099ae115bc7Smrj grub_printf("amd64: CPU does NOT support CX8\n"); 3100ae115bc7Smrj isamd64--; 3101ae115bc7Smrj } 3102ae115bc7Smrj 3103ae115bc7Smrj if (!BITX(stdfeatures, 13, 13)) { 3104ae115bc7Smrj grub_printf("amd64: CPU does NOT support PGE\n"); 3105ae115bc7Smrj isamd64--; 3106ae115bc7Smrj } 3107ae115bc7Smrj 3108ae115bc7Smrj if (!BITX(stdfeatures, 19, 19)) { 3109ae115bc7Smrj grub_printf("amd64: CPU does NOT support CLFSH\n"); 3110ae115bc7Smrj isamd64--; 3111ae115bc7Smrj } 3112ae115bc7Smrj 3113ae115bc7Smrj if (!BITX(stdfeatures, 23, 23)) { 3114ae115bc7Smrj grub_printf("amd64: CPU does NOT support MMX\n"); 3115ae115bc7Smrj isamd64--; 3116ae115bc7Smrj } 3117ae115bc7Smrj 3118ae115bc7Smrj if (!BITX(stdfeatures, 24, 24)) { 3119ae115bc7Smrj grub_printf("amd64: CPU does NOT support FXSR\n"); 3120ae115bc7Smrj isamd64--; 3121ae115bc7Smrj } 3122ae115bc7Smrj 3123ae115bc7Smrj if (!BITX(stdfeatures, 25, 25)) { 3124ae115bc7Smrj grub_printf("amd64: CPU does NOT support SSE\n"); 3125ae115bc7Smrj isamd64--; 3126ae115bc7Smrj } 3127ae115bc7Smrj 3128ae115bc7Smrj if (!BITX(stdfeatures, 26, 26)) { 3129ae115bc7Smrj grub_printf("amd64: CPU does NOT support SSE2\n"); 3130ae115bc7Smrj isamd64--; 3131ae115bc7Smrj } 3132ae115bc7Smrj 3133ae115bc7Smrj if (isamd64 < 1) { 3134ae115bc7Smrj grub_printf("amd64: CPU does not support amd64 executables.\n"); 3135ae115bc7Smrj return (0); 3136ae115bc7Smrj } 3137ae115bc7Smrj 3138ae115bc7Smrj amd64_rdmsr(MSR_AMD_EFER, &efer); 3139ae115bc7Smrj if (efer & AMD_EFER_SCE) 3140ae115bc7Smrj grub_printf("amd64: EFER_SCE (syscall/sysret) already " 3141ae115bc7Smrj "enabled\n"); 3142ae115bc7Smrj if (efer & AMD_EFER_NXE) 3143ae115bc7Smrj grub_printf("amd64: EFER_NXE (no-exec prot) already enabled\n"); 3144ae115bc7Smrj if (efer & AMD_EFER_LME) 3145ae115bc7Smrj grub_printf("amd64: EFER_LME (long mode) already enabled\n"); 3146ae115bc7Smrj 3147ae115bc7Smrj return (detect_target_operating_mode()); 3148ae115bc7Smrj } 3149ae115bc7Smrj 3150ae115bc7Smrj static int 3151ae115bc7Smrj detect_target_operating_mode() 3152ae115bc7Smrj { 3153ae115bc7Smrj int ret, ah; 3154ae115bc7Smrj 3155ae115bc7Smrj ah = get_target_operating_mode(); 3156ae115bc7Smrj 3157ae115bc7Smrj ah = ah >> 8; 3158ae115bc7Smrj 3159ae115bc7Smrj /* XXX still need to pass back the return from the call */ 3160ae115bc7Smrj ret = 0; 3161ae115bc7Smrj 3162ae115bc7Smrj if (ah == 0x86 && (ret & CB) != 0) { 3163ae115bc7Smrj grub_printf("[BIOS 'Detect Target Operating Mode' " 3164ae115bc7Smrj "callback unsupported on this platform]\n"); 3165ae115bc7Smrj return (1); /* unsupported, ignore */ 3166ae115bc7Smrj } 3167ae115bc7Smrj 3168ae115bc7Smrj if (ah == 0x0 && (ret & CB) == 0) { 3169ae115bc7Smrj grub_printf("[BIOS accepted mixed-mode target setting!]\n"); 3170ae115bc7Smrj return (1); /* told the bios what we're up to */ 3171ae115bc7Smrj } 3172ae115bc7Smrj 3173ae115bc7Smrj if (ah == 0 && ret & CB) { 3174ae115bc7Smrj grub_printf("fatal: BIOS reports this machine CANNOT run in " 3175ae115bc7Smrj "mixed 32/64-bit mode!\n"); 3176ae115bc7Smrj return (0); 3177ae115bc7Smrj } 3178ae115bc7Smrj 3179ae115bc7Smrj grub_printf("warning: BIOS Detect Target Operating Mode callback " 3180ae115bc7Smrj "confused.\n %%ax >> 8 = 0x%x, carry = %d\n", ah, 3181ae115bc7Smrj ret & CB ? 1 : 0); 3182ae115bc7Smrj 3183ae115bc7Smrj return (1); 3184ae115bc7Smrj } 3185ae115bc7Smrj 3186ae115bc7Smrj 3187ae115bc7Smrj int 3188ae115bc7Smrj isamd64() 3189ae115bc7Smrj { 3190ae115bc7Smrj static int ret = -1; 3191ae115bc7Smrj 3192ae115bc7Smrj if (ret == -1) 3193ae115bc7Smrj ret = amd64_config_cpu(); 3194ae115bc7Smrj 3195ae115bc7Smrj return (ret); 3196ae115bc7Smrj } 3197ae115bc7Smrj 3198b1b8ab34Slling static void 3199b1b8ab34Slling expand_arch (char *arg, char *newarg) 3200ae115bc7Smrj { 3201ae115bc7Smrj char *index; 3202ae115bc7Smrj 3203ae115bc7Smrj newarg[0] = '\0'; 3204ae115bc7Smrj 3205ae115bc7Smrj while ((index = strstr(arg, "$ISADIR")) != NULL) { 3206ae115bc7Smrj 3207ae115bc7Smrj index[0] = '\0'; 3208ae115bc7Smrj strncat(newarg, arg, MAX_CMDLINE); 3209ae115bc7Smrj index[0] = '$'; 3210ae115bc7Smrj 3211342440ecSPrasad Singamsetty if (isamd64() && check_min_mem64()) 3212ae115bc7Smrj strncat(newarg, "amd64", MAX_CMDLINE); 3213ae115bc7Smrj 3214ae115bc7Smrj arg = index + 7; 3215ae115bc7Smrj } 3216ae115bc7Smrj 3217ae115bc7Smrj strncat(newarg, arg, MAX_CMDLINE); 3218b1b8ab34Slling return; 3219ae115bc7Smrj } 3220ae115bc7Smrj 3221ae115bc7Smrj /* kernel$ */ 3222ae115bc7Smrj static int 3223ae115bc7Smrj kernel_dollar_func (char *arg, int flags) 3224ae115bc7Smrj { 3225b1b8ab34Slling char newarg[MAX_CMDLINE]; /* everything boils down to MAX_CMDLINE */ 3226b1b8ab34Slling 3227b1b8ab34Slling grub_printf("loading '%s' ...\n", arg); 3228b1b8ab34Slling expand_arch(arg, newarg); 3229b1b8ab34Slling 3230b1b8ab34Slling if (kernel_func(newarg, flags)) 3231b1b8ab34Slling return (1); 3232b1b8ab34Slling 3233b1b8ab34Slling mb_cmdline = (char *)MB_CMDLINE_BUF; 3234ffb5616eSLin Ling if (expand_dollar_bootfs(newarg, mb_cmdline)) { 3235ffb5616eSLin Ling grub_printf("cannot expand $ZFS-BOOTFS for dataset %s\n", 3236ffb5616eSLin Ling current_bootfs); 3237b1b8ab34Slling return (1); 3238ffb5616eSLin Ling } 3239b1b8ab34Slling 3240b1b8ab34Slling grub_printf("'%s' is loaded\n", mb_cmdline); 3241b1b8ab34Slling mb_cmdline += grub_strlen(mb_cmdline) + 1; 3242b1b8ab34Slling 3243b1b8ab34Slling return (0); 3244ae115bc7Smrj } 3245ae115bc7Smrj 3246ae115bc7Smrj static struct builtin builtin_kernel_dollar = 3247ae115bc7Smrj { 3248ae115bc7Smrj "kernel$", 3249ae115bc7Smrj kernel_dollar_func, 3250ae115bc7Smrj BUILTIN_CMDLINE | BUILTIN_HELP_LIST, 3251ae115bc7Smrj "kernel$ [--no-mem-option] [--type=TYPE] FILE [ARG ...]", 3252ae115bc7Smrj " Just like kernel, but with $ISADIR expansion." 3253ae115bc7Smrj }; 3254ae115bc7Smrj 32557c478bd9Sstevel@tonic-gate 32567c478bd9Sstevel@tonic-gate /* lock */ 32577c478bd9Sstevel@tonic-gate static int 32587c478bd9Sstevel@tonic-gate lock_func (char *arg, int flags) 32597c478bd9Sstevel@tonic-gate { 32607c478bd9Sstevel@tonic-gate if (! auth && password) 32617c478bd9Sstevel@tonic-gate { 32627c478bd9Sstevel@tonic-gate errnum = ERR_PRIVILEGED; 32637c478bd9Sstevel@tonic-gate return 1; 32647c478bd9Sstevel@tonic-gate } 32657c478bd9Sstevel@tonic-gate 32667c478bd9Sstevel@tonic-gate return 0; 32677c478bd9Sstevel@tonic-gate } 32687c478bd9Sstevel@tonic-gate 32697c478bd9Sstevel@tonic-gate static struct builtin builtin_lock = 32707c478bd9Sstevel@tonic-gate { 32717c478bd9Sstevel@tonic-gate "lock", 32727c478bd9Sstevel@tonic-gate lock_func, 32737c478bd9Sstevel@tonic-gate BUILTIN_CMDLINE, 32747c478bd9Sstevel@tonic-gate "lock", 32757c478bd9Sstevel@tonic-gate "Break a command execution unless the user is authenticated." 32767c478bd9Sstevel@tonic-gate }; 32777c478bd9Sstevel@tonic-gate 32787c478bd9Sstevel@tonic-gate 32797c478bd9Sstevel@tonic-gate /* makeactive */ 32807c478bd9Sstevel@tonic-gate static int 32817c478bd9Sstevel@tonic-gate makeactive_func (char *arg, int flags) 32827c478bd9Sstevel@tonic-gate { 32837c478bd9Sstevel@tonic-gate if (! make_saved_active ()) 32847c478bd9Sstevel@tonic-gate return 1; 32857c478bd9Sstevel@tonic-gate 32867c478bd9Sstevel@tonic-gate return 0; 32877c478bd9Sstevel@tonic-gate } 32887c478bd9Sstevel@tonic-gate 32897c478bd9Sstevel@tonic-gate static struct builtin builtin_makeactive = 32907c478bd9Sstevel@tonic-gate { 32917c478bd9Sstevel@tonic-gate "makeactive", 32927c478bd9Sstevel@tonic-gate makeactive_func, 32937c478bd9Sstevel@tonic-gate BUILTIN_CMDLINE | BUILTIN_HELP_LIST, 32947c478bd9Sstevel@tonic-gate "makeactive", 32957c478bd9Sstevel@tonic-gate "Set the active partition on the root disk to GRUB's root device." 32967c478bd9Sstevel@tonic-gate " This command is limited to _primary_ PC partitions on a hard disk." 32977c478bd9Sstevel@tonic-gate }; 32987c478bd9Sstevel@tonic-gate 32997c478bd9Sstevel@tonic-gate 33007c478bd9Sstevel@tonic-gate /* map */ 33017c478bd9Sstevel@tonic-gate /* Map FROM_DRIVE to TO_DRIVE. */ 33027c478bd9Sstevel@tonic-gate static int 33037c478bd9Sstevel@tonic-gate map_func (char *arg, int flags) 33047c478bd9Sstevel@tonic-gate { 33057c478bd9Sstevel@tonic-gate char *to_drive; 33067c478bd9Sstevel@tonic-gate char *from_drive; 33077c478bd9Sstevel@tonic-gate unsigned long to, from; 33087c478bd9Sstevel@tonic-gate int i; 33097c478bd9Sstevel@tonic-gate 33107c478bd9Sstevel@tonic-gate to_drive = arg; 33117c478bd9Sstevel@tonic-gate from_drive = skip_to (0, arg); 33127c478bd9Sstevel@tonic-gate 33137c478bd9Sstevel@tonic-gate /* Get the drive number for TO_DRIVE. */ 33147c478bd9Sstevel@tonic-gate set_device (to_drive); 33157c478bd9Sstevel@tonic-gate if (errnum) 33167c478bd9Sstevel@tonic-gate return 1; 33177c478bd9Sstevel@tonic-gate to = current_drive; 33187c478bd9Sstevel@tonic-gate 33197c478bd9Sstevel@tonic-gate /* Get the drive number for FROM_DRIVE. */ 33207c478bd9Sstevel@tonic-gate set_device (from_drive); 33217c478bd9Sstevel@tonic-gate if (errnum) 33227c478bd9Sstevel@tonic-gate return 1; 33237c478bd9Sstevel@tonic-gate from = current_drive; 33247c478bd9Sstevel@tonic-gate 33257c478bd9Sstevel@tonic-gate /* Search for an empty slot in BIOS_DRIVE_MAP. */ 33267c478bd9Sstevel@tonic-gate for (i = 0; i < DRIVE_MAP_SIZE; i++) 33277c478bd9Sstevel@tonic-gate { 33287c478bd9Sstevel@tonic-gate /* Perhaps the user wants to override the map. */ 33297c478bd9Sstevel@tonic-gate if ((bios_drive_map[i] & 0xff) == from) 33307c478bd9Sstevel@tonic-gate break; 33317c478bd9Sstevel@tonic-gate 33327c478bd9Sstevel@tonic-gate if (! bios_drive_map[i]) 33337c478bd9Sstevel@tonic-gate break; 33347c478bd9Sstevel@tonic-gate } 33357c478bd9Sstevel@tonic-gate 33367c478bd9Sstevel@tonic-gate if (i == DRIVE_MAP_SIZE) 33377c478bd9Sstevel@tonic-gate { 33387c478bd9Sstevel@tonic-gate errnum = ERR_WONT_FIT; 33397c478bd9Sstevel@tonic-gate return 1; 33407c478bd9Sstevel@tonic-gate } 33417c478bd9Sstevel@tonic-gate 33427c478bd9Sstevel@tonic-gate if (to == from) 33437c478bd9Sstevel@tonic-gate /* If TO is equal to FROM, delete the entry. */ 33447c478bd9Sstevel@tonic-gate grub_memmove ((char *) &bios_drive_map[i], (char *) &bios_drive_map[i + 1], 33457c478bd9Sstevel@tonic-gate sizeof (unsigned short) * (DRIVE_MAP_SIZE - i)); 33467c478bd9Sstevel@tonic-gate else 33477c478bd9Sstevel@tonic-gate bios_drive_map[i] = from | (to << 8); 33487c478bd9Sstevel@tonic-gate 33497c478bd9Sstevel@tonic-gate return 0; 33507c478bd9Sstevel@tonic-gate } 33517c478bd9Sstevel@tonic-gate 33527c478bd9Sstevel@tonic-gate static struct builtin builtin_map = 33537c478bd9Sstevel@tonic-gate { 33547c478bd9Sstevel@tonic-gate "map", 33557c478bd9Sstevel@tonic-gate map_func, 33567c478bd9Sstevel@tonic-gate BUILTIN_CMDLINE | BUILTIN_HELP_LIST, 33577c478bd9Sstevel@tonic-gate "map TO_DRIVE FROM_DRIVE", 33587c478bd9Sstevel@tonic-gate "Map the drive FROM_DRIVE to the drive TO_DRIVE. This is necessary" 33597c478bd9Sstevel@tonic-gate " when you chain-load some operating systems, such as DOS, if such an" 33607c478bd9Sstevel@tonic-gate " OS resides at a non-first drive." 33617c478bd9Sstevel@tonic-gate }; 33627c478bd9Sstevel@tonic-gate 33637c478bd9Sstevel@tonic-gate 33647c478bd9Sstevel@tonic-gate #ifdef USE_MD5_PASSWORDS 33657c478bd9Sstevel@tonic-gate /* md5crypt */ 33667c478bd9Sstevel@tonic-gate static int 33677c478bd9Sstevel@tonic-gate md5crypt_func (char *arg, int flags) 33687c478bd9Sstevel@tonic-gate { 33697c478bd9Sstevel@tonic-gate char crypted[36]; 33707c478bd9Sstevel@tonic-gate char key[32]; 33717c478bd9Sstevel@tonic-gate unsigned int seed; 33727c478bd9Sstevel@tonic-gate int i; 33737c478bd9Sstevel@tonic-gate const char *const seedchars = 33747c478bd9Sstevel@tonic-gate "./0123456789ABCDEFGHIJKLMNOPQRST" 33757c478bd9Sstevel@tonic-gate "UVWXYZabcdefghijklmnopqrstuvwxyz"; 33767c478bd9Sstevel@tonic-gate 33777c478bd9Sstevel@tonic-gate /* First create a salt. */ 33787c478bd9Sstevel@tonic-gate 33797c478bd9Sstevel@tonic-gate /* The magical prefix. */ 33807c478bd9Sstevel@tonic-gate grub_memset (crypted, 0, sizeof (crypted)); 33817c478bd9Sstevel@tonic-gate grub_memmove (crypted, "$1$", 3); 33827c478bd9Sstevel@tonic-gate 33837c478bd9Sstevel@tonic-gate /* Create the length of a salt. */ 33847c478bd9Sstevel@tonic-gate seed = currticks (); 33857c478bd9Sstevel@tonic-gate 33867c478bd9Sstevel@tonic-gate /* Generate a salt. */ 33877c478bd9Sstevel@tonic-gate for (i = 0; i < 8 && seed; i++) 33887c478bd9Sstevel@tonic-gate { 33897c478bd9Sstevel@tonic-gate /* FIXME: This should be more random. */ 33907c478bd9Sstevel@tonic-gate crypted[3 + i] = seedchars[seed & 0x3f]; 33917c478bd9Sstevel@tonic-gate seed >>= 6; 33927c478bd9Sstevel@tonic-gate } 33937c478bd9Sstevel@tonic-gate 33947c478bd9Sstevel@tonic-gate /* A salt must be terminated with `$', if it is less than 8 chars. */ 33957c478bd9Sstevel@tonic-gate crypted[3 + i] = '$'; 33967c478bd9Sstevel@tonic-gate 33977c478bd9Sstevel@tonic-gate #ifdef DEBUG_MD5CRYPT 33987c478bd9Sstevel@tonic-gate grub_printf ("salt = %s\n", crypted); 33997c478bd9Sstevel@tonic-gate #endif 34007c478bd9Sstevel@tonic-gate 34017c478bd9Sstevel@tonic-gate /* Get a password. */ 34027c478bd9Sstevel@tonic-gate grub_memset (key, 0, sizeof (key)); 34037c478bd9Sstevel@tonic-gate get_cmdline ("Password: ", key, sizeof (key) - 1, '*', 0); 34047c478bd9Sstevel@tonic-gate 34057c478bd9Sstevel@tonic-gate /* Crypt the key. */ 34067c478bd9Sstevel@tonic-gate make_md5_password (key, crypted); 34077c478bd9Sstevel@tonic-gate 34087c478bd9Sstevel@tonic-gate grub_printf ("Encrypted: %s\n", crypted); 34097c478bd9Sstevel@tonic-gate return 0; 34107c478bd9Sstevel@tonic-gate } 34117c478bd9Sstevel@tonic-gate 34127c478bd9Sstevel@tonic-gate static struct builtin builtin_md5crypt = 34137c478bd9Sstevel@tonic-gate { 34147c478bd9Sstevel@tonic-gate "md5crypt", 34157c478bd9Sstevel@tonic-gate md5crypt_func, 34167c478bd9Sstevel@tonic-gate BUILTIN_CMDLINE | BUILTIN_HELP_LIST, 34177c478bd9Sstevel@tonic-gate "md5crypt", 34187c478bd9Sstevel@tonic-gate "Generate a password in MD5 format." 34197c478bd9Sstevel@tonic-gate }; 34207c478bd9Sstevel@tonic-gate #endif /* USE_MD5_PASSWORDS */ 34217c478bd9Sstevel@tonic-gate 34227c478bd9Sstevel@tonic-gate 34237c478bd9Sstevel@tonic-gate /* module */ 34247c478bd9Sstevel@tonic-gate static int 34257c478bd9Sstevel@tonic-gate module_func (char *arg, int flags) 34267c478bd9Sstevel@tonic-gate { 34277c478bd9Sstevel@tonic-gate int len = grub_strlen (arg); 34287c478bd9Sstevel@tonic-gate 34297c478bd9Sstevel@tonic-gate switch (kernel_type) 34307c478bd9Sstevel@tonic-gate { 34317c478bd9Sstevel@tonic-gate case KERNEL_TYPE_MULTIBOOT: 34327c478bd9Sstevel@tonic-gate if (mb_cmdline + len + 1 > (char *) MB_CMDLINE_BUF + MB_CMDLINE_BUFLEN) 34337c478bd9Sstevel@tonic-gate { 34347c478bd9Sstevel@tonic-gate errnum = ERR_WONT_FIT; 34357c478bd9Sstevel@tonic-gate return 1; 34367c478bd9Sstevel@tonic-gate } 34377c478bd9Sstevel@tonic-gate grub_memmove (mb_cmdline, arg, len + 1); 34387c478bd9Sstevel@tonic-gate if (! load_module (arg, mb_cmdline)) 34397c478bd9Sstevel@tonic-gate return 1; 3440b1b8ab34Slling 3441b1b8ab34Slling mb_cmdline += grub_strlen(mb_cmdline) + 1; 34427c478bd9Sstevel@tonic-gate break; 34437c478bd9Sstevel@tonic-gate 34447c478bd9Sstevel@tonic-gate case KERNEL_TYPE_LINUX: 34457c478bd9Sstevel@tonic-gate case KERNEL_TYPE_BIG_LINUX: 34467c478bd9Sstevel@tonic-gate if (! load_initrd (arg)) 34477c478bd9Sstevel@tonic-gate return 1; 34487c478bd9Sstevel@tonic-gate break; 34497c478bd9Sstevel@tonic-gate 34507c478bd9Sstevel@tonic-gate default: 34517c478bd9Sstevel@tonic-gate errnum = ERR_NEED_MB_KERNEL; 34527c478bd9Sstevel@tonic-gate return 1; 34537c478bd9Sstevel@tonic-gate } 34547c478bd9Sstevel@tonic-gate 34557c478bd9Sstevel@tonic-gate return 0; 34567c478bd9Sstevel@tonic-gate } 34577c478bd9Sstevel@tonic-gate 34587c478bd9Sstevel@tonic-gate static struct builtin builtin_module = 34597c478bd9Sstevel@tonic-gate { 34607c478bd9Sstevel@tonic-gate "module", 34617c478bd9Sstevel@tonic-gate module_func, 34627c478bd9Sstevel@tonic-gate BUILTIN_CMDLINE | BUILTIN_HELP_LIST, 34637c478bd9Sstevel@tonic-gate "module FILE [ARG ...]", 34647c478bd9Sstevel@tonic-gate "Load a boot module FILE for a Multiboot format boot image (no" 34657c478bd9Sstevel@tonic-gate " interpretation of the file contents is made, so users of this" 34667c478bd9Sstevel@tonic-gate " command must know what the kernel in question expects). The" 34677c478bd9Sstevel@tonic-gate " rest of the line is passed as the \"module command line\", like" 34687c478bd9Sstevel@tonic-gate " the `kernel' command." 34697c478bd9Sstevel@tonic-gate }; 34707c478bd9Sstevel@tonic-gate 3471ae115bc7Smrj /* module$ */ 3472ae115bc7Smrj static int 3473ae115bc7Smrj module_dollar_func (char *arg, int flags) 3474ae115bc7Smrj { 3475b1b8ab34Slling char newarg[MAX_CMDLINE]; /* everything boils down to MAX_CMDLINE */ 3476b1b8ab34Slling char *cmdline_sav; 3477b1b8ab34Slling 3478b1b8ab34Slling grub_printf("loading '%s' ...\n", arg); 3479b1b8ab34Slling expand_arch(arg, newarg); 3480b1b8ab34Slling 3481b1b8ab34Slling cmdline_sav = (char *)mb_cmdline; 3482b1b8ab34Slling if (module_func(newarg, flags)) 3483b1b8ab34Slling return (1); 3484b1b8ab34Slling 3485ffb5616eSLin Ling if (expand_dollar_bootfs(newarg, cmdline_sav)) { 3486ffb5616eSLin Ling grub_printf("cannot expand $ZFS-BOOTFS for dataset %s\n", 3487ffb5616eSLin Ling current_bootfs); 3488b1b8ab34Slling return (1); 3489ffb5616eSLin Ling } 3490b1b8ab34Slling 3491b1b8ab34Slling grub_printf("'%s' is loaded\n", (char *)cmdline_sav); 3492b1b8ab34Slling mb_cmdline += grub_strlen(cmdline_sav) + 1; 3493b1b8ab34Slling 3494b1b8ab34Slling return (0); 3495ae115bc7Smrj } 3496ae115bc7Smrj 3497ae115bc7Smrj static struct builtin builtin_module_dollar = 3498ae115bc7Smrj { 3499ae115bc7Smrj "module$", 3500ae115bc7Smrj module_dollar_func, 3501ae115bc7Smrj BUILTIN_CMDLINE | BUILTIN_HELP_LIST, 3502ae115bc7Smrj "module FILE [ARG ...]", 3503ae115bc7Smrj " Just like module, but with $ISADIR expansion." 3504ae115bc7Smrj }; 3505ae115bc7Smrj 35067c478bd9Sstevel@tonic-gate 35077c478bd9Sstevel@tonic-gate /* modulenounzip */ 35087c478bd9Sstevel@tonic-gate static int 35097c478bd9Sstevel@tonic-gate modulenounzip_func (char *arg, int flags) 35107c478bd9Sstevel@tonic-gate { 35117c478bd9Sstevel@tonic-gate int ret; 35127c478bd9Sstevel@tonic-gate 35137c478bd9Sstevel@tonic-gate #ifndef NO_DECOMPRESSION 35147c478bd9Sstevel@tonic-gate no_decompression = 1; 35157c478bd9Sstevel@tonic-gate #endif 35167c478bd9Sstevel@tonic-gate 35177c478bd9Sstevel@tonic-gate ret = module_func (arg, flags); 35187c478bd9Sstevel@tonic-gate 35197c478bd9Sstevel@tonic-gate #ifndef NO_DECOMPRESSION 35207c478bd9Sstevel@tonic-gate no_decompression = 0; 35217c478bd9Sstevel@tonic-gate #endif 35227c478bd9Sstevel@tonic-gate 35237c478bd9Sstevel@tonic-gate return ret; 35247c478bd9Sstevel@tonic-gate } 35257c478bd9Sstevel@tonic-gate 35267c478bd9Sstevel@tonic-gate static struct builtin builtin_modulenounzip = 35277c478bd9Sstevel@tonic-gate { 35287c478bd9Sstevel@tonic-gate "modulenounzip", 35297c478bd9Sstevel@tonic-gate modulenounzip_func, 35307c478bd9Sstevel@tonic-gate BUILTIN_CMDLINE | BUILTIN_HELP_LIST, 35317c478bd9Sstevel@tonic-gate "modulenounzip FILE [ARG ...]", 35327c478bd9Sstevel@tonic-gate "The same as `module', except that automatic decompression is" 35337c478bd9Sstevel@tonic-gate " disabled." 35347c478bd9Sstevel@tonic-gate }; 35357c478bd9Sstevel@tonic-gate 35367c478bd9Sstevel@tonic-gate 35377c478bd9Sstevel@tonic-gate /* pager [on|off] */ 35387c478bd9Sstevel@tonic-gate static int 35397c478bd9Sstevel@tonic-gate pager_func (char *arg, int flags) 35407c478bd9Sstevel@tonic-gate { 35417c478bd9Sstevel@tonic-gate /* If ARG is empty, toggle the flag. */ 35427c478bd9Sstevel@tonic-gate if (! *arg) 35437c478bd9Sstevel@tonic-gate use_pager = ! use_pager; 35447c478bd9Sstevel@tonic-gate else if (grub_memcmp (arg, "on", 2) == 0) 35457c478bd9Sstevel@tonic-gate use_pager = 1; 35467c478bd9Sstevel@tonic-gate else if (grub_memcmp (arg, "off", 3) == 0) 35477c478bd9Sstevel@tonic-gate use_pager = 0; 35487c478bd9Sstevel@tonic-gate else 35497c478bd9Sstevel@tonic-gate { 35507c478bd9Sstevel@tonic-gate errnum = ERR_BAD_ARGUMENT; 35517c478bd9Sstevel@tonic-gate return 1; 35527c478bd9Sstevel@tonic-gate } 35537c478bd9Sstevel@tonic-gate 35547c478bd9Sstevel@tonic-gate grub_printf (" Internal pager is now %s\n", use_pager ? "on" : "off"); 35557c478bd9Sstevel@tonic-gate return 0; 35567c478bd9Sstevel@tonic-gate } 35577c478bd9Sstevel@tonic-gate 35587c478bd9Sstevel@tonic-gate static struct builtin builtin_pager = 35597c478bd9Sstevel@tonic-gate { 35607c478bd9Sstevel@tonic-gate "pager", 35617c478bd9Sstevel@tonic-gate pager_func, 35627c478bd9Sstevel@tonic-gate BUILTIN_CMDLINE | BUILTIN_MENU | BUILTIN_HELP_LIST, 35637c478bd9Sstevel@tonic-gate "pager [FLAG]", 35647c478bd9Sstevel@tonic-gate "Toggle pager mode with no argument. If FLAG is given and its value" 35657c478bd9Sstevel@tonic-gate " is `on', turn on the mode. If FLAG is `off', turn off the mode." 35667c478bd9Sstevel@tonic-gate }; 35677c478bd9Sstevel@tonic-gate 35687c478bd9Sstevel@tonic-gate 35697c478bd9Sstevel@tonic-gate /* partnew PART TYPE START LEN */ 35707c478bd9Sstevel@tonic-gate static int 35717c478bd9Sstevel@tonic-gate partnew_func (char *arg, int flags) 35727c478bd9Sstevel@tonic-gate { 35737c478bd9Sstevel@tonic-gate int new_type, new_start, new_len; 35747c478bd9Sstevel@tonic-gate int start_cl, start_ch, start_dh; 35757c478bd9Sstevel@tonic-gate int end_cl, end_ch, end_dh; 35767c478bd9Sstevel@tonic-gate int entry; 35777c478bd9Sstevel@tonic-gate char mbr[512]; 35787c478bd9Sstevel@tonic-gate 35797c478bd9Sstevel@tonic-gate /* Convert a LBA address to a CHS address in the INT 13 format. */ 35807c478bd9Sstevel@tonic-gate auto void lba_to_chs (int lba, int *cl, int *ch, int *dh); 35817c478bd9Sstevel@tonic-gate void lba_to_chs (int lba, int *cl, int *ch, int *dh) 35827c478bd9Sstevel@tonic-gate { 35837c478bd9Sstevel@tonic-gate int cylinder, head, sector; 35847c478bd9Sstevel@tonic-gate 35857c478bd9Sstevel@tonic-gate sector = lba % buf_geom.sectors + 1; 35867c478bd9Sstevel@tonic-gate head = (lba / buf_geom.sectors) % buf_geom.heads; 35877c478bd9Sstevel@tonic-gate cylinder = lba / (buf_geom.sectors * buf_geom.heads); 35887c478bd9Sstevel@tonic-gate 35897c478bd9Sstevel@tonic-gate if (cylinder >= buf_geom.cylinders) 35907c478bd9Sstevel@tonic-gate cylinder = buf_geom.cylinders - 1; 35917c478bd9Sstevel@tonic-gate 35927c478bd9Sstevel@tonic-gate *cl = sector | ((cylinder & 0x300) >> 2); 35937c478bd9Sstevel@tonic-gate *ch = cylinder & 0xFF; 35947c478bd9Sstevel@tonic-gate *dh = head; 35957c478bd9Sstevel@tonic-gate } 35967c478bd9Sstevel@tonic-gate 35977c478bd9Sstevel@tonic-gate /* Get the drive and the partition. */ 35987c478bd9Sstevel@tonic-gate if (! set_device (arg)) 35997c478bd9Sstevel@tonic-gate return 1; 36007c478bd9Sstevel@tonic-gate 36017c478bd9Sstevel@tonic-gate /* The drive must be a hard disk. */ 36027c478bd9Sstevel@tonic-gate if (! (current_drive & 0x80)) 36037c478bd9Sstevel@tonic-gate { 36047c478bd9Sstevel@tonic-gate errnum = ERR_BAD_ARGUMENT; 36057c478bd9Sstevel@tonic-gate return 1; 36067c478bd9Sstevel@tonic-gate } 36077c478bd9Sstevel@tonic-gate 36087c478bd9Sstevel@tonic-gate /* The partition must a primary partition. */ 36097c478bd9Sstevel@tonic-gate if ((current_partition >> 16) > 3 36107c478bd9Sstevel@tonic-gate || (current_partition & 0xFFFF) != 0xFFFF) 36117c478bd9Sstevel@tonic-gate { 36127c478bd9Sstevel@tonic-gate errnum = ERR_BAD_ARGUMENT; 36137c478bd9Sstevel@tonic-gate return 1; 36147c478bd9Sstevel@tonic-gate } 36157c478bd9Sstevel@tonic-gate 36167c478bd9Sstevel@tonic-gate entry = current_partition >> 16; 36177c478bd9Sstevel@tonic-gate 36187c478bd9Sstevel@tonic-gate /* Get the new partition type. */ 36197c478bd9Sstevel@tonic-gate arg = skip_to (0, arg); 36207c478bd9Sstevel@tonic-gate if (! safe_parse_maxint (&arg, &new_type)) 36217c478bd9Sstevel@tonic-gate return 1; 36227c478bd9Sstevel@tonic-gate 36237c478bd9Sstevel@tonic-gate /* The partition type is unsigned char. */ 36247c478bd9Sstevel@tonic-gate if (new_type > 0xFF) 36257c478bd9Sstevel@tonic-gate { 36267c478bd9Sstevel@tonic-gate errnum = ERR_BAD_ARGUMENT; 36277c478bd9Sstevel@tonic-gate return 1; 36287c478bd9Sstevel@tonic-gate } 36297c478bd9Sstevel@tonic-gate 36307c478bd9Sstevel@tonic-gate /* Get the new partition start. */ 36317c478bd9Sstevel@tonic-gate arg = skip_to (0, arg); 36327c478bd9Sstevel@tonic-gate if (! safe_parse_maxint (&arg, &new_start)) 36337c478bd9Sstevel@tonic-gate return 1; 36347c478bd9Sstevel@tonic-gate 36357c478bd9Sstevel@tonic-gate /* Get the new partition length. */ 36367c478bd9Sstevel@tonic-gate arg = skip_to (0, arg); 36377c478bd9Sstevel@tonic-gate if (! safe_parse_maxint (&arg, &new_len)) 36387c478bd9Sstevel@tonic-gate return 1; 36397c478bd9Sstevel@tonic-gate 36407c478bd9Sstevel@tonic-gate /* Read the MBR. */ 36417c478bd9Sstevel@tonic-gate if (! rawread (current_drive, 0, 0, SECTOR_SIZE, mbr)) 36427c478bd9Sstevel@tonic-gate return 1; 36437c478bd9Sstevel@tonic-gate 36447c478bd9Sstevel@tonic-gate /* Check if the new partition will fit in the disk. */ 36457c478bd9Sstevel@tonic-gate if (new_start + new_len > buf_geom.total_sectors) 36467c478bd9Sstevel@tonic-gate { 36477c478bd9Sstevel@tonic-gate errnum = ERR_GEOM; 36487c478bd9Sstevel@tonic-gate return 1; 36497c478bd9Sstevel@tonic-gate } 36507c478bd9Sstevel@tonic-gate 36517c478bd9Sstevel@tonic-gate /* Store the partition information in the MBR. */ 36527c478bd9Sstevel@tonic-gate lba_to_chs (new_start, &start_cl, &start_ch, &start_dh); 36537c478bd9Sstevel@tonic-gate lba_to_chs (new_start + new_len - 1, &end_cl, &end_ch, &end_dh); 36547c478bd9Sstevel@tonic-gate 36557c478bd9Sstevel@tonic-gate PC_SLICE_FLAG (mbr, entry) = 0; 36567c478bd9Sstevel@tonic-gate PC_SLICE_HEAD (mbr, entry) = start_dh; 36577c478bd9Sstevel@tonic-gate PC_SLICE_SEC (mbr, entry) = start_cl; 36587c478bd9Sstevel@tonic-gate PC_SLICE_CYL (mbr, entry) = start_ch; 36597c478bd9Sstevel@tonic-gate PC_SLICE_TYPE (mbr, entry) = new_type; 36607c478bd9Sstevel@tonic-gate PC_SLICE_EHEAD (mbr, entry) = end_dh; 36617c478bd9Sstevel@tonic-gate PC_SLICE_ESEC (mbr, entry) = end_cl; 36627c478bd9Sstevel@tonic-gate PC_SLICE_ECYL (mbr, entry) = end_ch; 36637c478bd9Sstevel@tonic-gate PC_SLICE_START (mbr, entry) = new_start; 36647c478bd9Sstevel@tonic-gate PC_SLICE_LENGTH (mbr, entry) = new_len; 36657c478bd9Sstevel@tonic-gate 36667c478bd9Sstevel@tonic-gate /* Make sure that the MBR has a valid signature. */ 36677c478bd9Sstevel@tonic-gate PC_MBR_SIG (mbr) = PC_MBR_SIGNATURE; 36687c478bd9Sstevel@tonic-gate 36697c478bd9Sstevel@tonic-gate /* Write back the MBR to the disk. */ 3670342440ecSPrasad Singamsetty buf_track = BUF_CACHE_INVALID; 36717c478bd9Sstevel@tonic-gate if (! rawwrite (current_drive, 0, mbr)) 36727c478bd9Sstevel@tonic-gate return 1; 36737c478bd9Sstevel@tonic-gate 36747c478bd9Sstevel@tonic-gate return 0; 36757c478bd9Sstevel@tonic-gate } 36767c478bd9Sstevel@tonic-gate 36777c478bd9Sstevel@tonic-gate static struct builtin builtin_partnew = 36787c478bd9Sstevel@tonic-gate { 36797c478bd9Sstevel@tonic-gate "partnew", 36807c478bd9Sstevel@tonic-gate partnew_func, 36817c478bd9Sstevel@tonic-gate BUILTIN_CMDLINE | BUILTIN_MENU | BUILTIN_HELP_LIST, 36827c478bd9Sstevel@tonic-gate "partnew PART TYPE START LEN", 36837c478bd9Sstevel@tonic-gate "Create a primary partition at the starting address START with the" 36847c478bd9Sstevel@tonic-gate " length LEN, with the type TYPE. START and LEN are in sector units." 36857c478bd9Sstevel@tonic-gate }; 36867c478bd9Sstevel@tonic-gate 36877c478bd9Sstevel@tonic-gate 36887c478bd9Sstevel@tonic-gate /* parttype PART TYPE */ 36897c478bd9Sstevel@tonic-gate static int 36907c478bd9Sstevel@tonic-gate parttype_func (char *arg, int flags) 36917c478bd9Sstevel@tonic-gate { 36927c478bd9Sstevel@tonic-gate int new_type; 36937c478bd9Sstevel@tonic-gate unsigned long part = 0xFFFFFF; 36947c478bd9Sstevel@tonic-gate unsigned long start, len, offset, ext_offset; 36957c478bd9Sstevel@tonic-gate int entry, type; 36967c478bd9Sstevel@tonic-gate char mbr[512]; 36977c478bd9Sstevel@tonic-gate 36987c478bd9Sstevel@tonic-gate /* Get the drive and the partition. */ 36997c478bd9Sstevel@tonic-gate if (! set_device (arg)) 37007c478bd9Sstevel@tonic-gate return 1; 37017c478bd9Sstevel@tonic-gate 37027c478bd9Sstevel@tonic-gate /* The drive must be a hard disk. */ 37037c478bd9Sstevel@tonic-gate if (! (current_drive & 0x80)) 37047c478bd9Sstevel@tonic-gate { 37057c478bd9Sstevel@tonic-gate errnum = ERR_BAD_ARGUMENT; 37067c478bd9Sstevel@tonic-gate return 1; 37077c478bd9Sstevel@tonic-gate } 37087c478bd9Sstevel@tonic-gate 37097c478bd9Sstevel@tonic-gate /* The partition must be a PC slice. */ 37107c478bd9Sstevel@tonic-gate if ((current_partition >> 16) == 0xFF 37117c478bd9Sstevel@tonic-gate || (current_partition & 0xFFFF) != 0xFFFF) 37127c478bd9Sstevel@tonic-gate { 37137c478bd9Sstevel@tonic-gate errnum = ERR_BAD_ARGUMENT; 37147c478bd9Sstevel@tonic-gate return 1; 37157c478bd9Sstevel@tonic-gate } 37167c478bd9Sstevel@tonic-gate 37177c478bd9Sstevel@tonic-gate /* Get the new partition type. */ 37187c478bd9Sstevel@tonic-gate arg = skip_to (0, arg); 37197c478bd9Sstevel@tonic-gate if (! safe_parse_maxint (&arg, &new_type)) 37207c478bd9Sstevel@tonic-gate return 1; 37217c478bd9Sstevel@tonic-gate 37227c478bd9Sstevel@tonic-gate /* The partition type is unsigned char. */ 37237c478bd9Sstevel@tonic-gate if (new_type > 0xFF) 37247c478bd9Sstevel@tonic-gate { 37257c478bd9Sstevel@tonic-gate errnum = ERR_BAD_ARGUMENT; 37267c478bd9Sstevel@tonic-gate return 1; 37277c478bd9Sstevel@tonic-gate } 37287c478bd9Sstevel@tonic-gate 37297c478bd9Sstevel@tonic-gate /* Look for the partition. */ 37307c478bd9Sstevel@tonic-gate while (next_partition (current_drive, 0xFFFFFF, &part, &type, 37317c478bd9Sstevel@tonic-gate &start, &len, &offset, &entry, 37327c478bd9Sstevel@tonic-gate &ext_offset, mbr)) 37337c478bd9Sstevel@tonic-gate { 37347c478bd9Sstevel@tonic-gate if (part == current_partition) 37357c478bd9Sstevel@tonic-gate { 37367c478bd9Sstevel@tonic-gate /* Found. */ 37377c478bd9Sstevel@tonic-gate 37387c478bd9Sstevel@tonic-gate /* Set the type to NEW_TYPE. */ 37397c478bd9Sstevel@tonic-gate PC_SLICE_TYPE (mbr, entry) = new_type; 37407c478bd9Sstevel@tonic-gate 37417c478bd9Sstevel@tonic-gate /* Write back the MBR to the disk. */ 3742342440ecSPrasad Singamsetty buf_track = BUF_CACHE_INVALID; 37437c478bd9Sstevel@tonic-gate if (! rawwrite (current_drive, offset, mbr)) 37447c478bd9Sstevel@tonic-gate return 1; 37457c478bd9Sstevel@tonic-gate 37467c478bd9Sstevel@tonic-gate /* Succeed. */ 37477c478bd9Sstevel@tonic-gate return 0; 37487c478bd9Sstevel@tonic-gate } 37497c478bd9Sstevel@tonic-gate } 37507c478bd9Sstevel@tonic-gate 37517c478bd9Sstevel@tonic-gate /* The partition was not found. ERRNUM was set by next_partition. */ 37527c478bd9Sstevel@tonic-gate return 1; 37537c478bd9Sstevel@tonic-gate } 37547c478bd9Sstevel@tonic-gate 37557c478bd9Sstevel@tonic-gate static struct builtin builtin_parttype = 37567c478bd9Sstevel@tonic-gate { 37577c478bd9Sstevel@tonic-gate "parttype", 37587c478bd9Sstevel@tonic-gate parttype_func, 37597c478bd9Sstevel@tonic-gate BUILTIN_CMDLINE | BUILTIN_MENU | BUILTIN_HELP_LIST, 37607c478bd9Sstevel@tonic-gate "parttype PART TYPE", 37617c478bd9Sstevel@tonic-gate "Change the type of the partition PART to TYPE." 37627c478bd9Sstevel@tonic-gate }; 37637c478bd9Sstevel@tonic-gate 37647c478bd9Sstevel@tonic-gate 37657c478bd9Sstevel@tonic-gate /* password */ 37667c478bd9Sstevel@tonic-gate static int 37677c478bd9Sstevel@tonic-gate password_func (char *arg, int flags) 37687c478bd9Sstevel@tonic-gate { 37697c478bd9Sstevel@tonic-gate int len; 37707c478bd9Sstevel@tonic-gate password_t type = PASSWORD_PLAIN; 37717c478bd9Sstevel@tonic-gate 37727c478bd9Sstevel@tonic-gate #ifdef USE_MD5_PASSWORDS 37737c478bd9Sstevel@tonic-gate if (grub_memcmp (arg, "--md5", 5) == 0) 37747c478bd9Sstevel@tonic-gate { 37757c478bd9Sstevel@tonic-gate type = PASSWORD_MD5; 37767c478bd9Sstevel@tonic-gate arg = skip_to (0, arg); 37777c478bd9Sstevel@tonic-gate } 37787c478bd9Sstevel@tonic-gate #endif 37797c478bd9Sstevel@tonic-gate if (grub_memcmp (arg, "--", 2) == 0) 37807c478bd9Sstevel@tonic-gate { 37817c478bd9Sstevel@tonic-gate type = PASSWORD_UNSUPPORTED; 37827c478bd9Sstevel@tonic-gate arg = skip_to (0, arg); 37837c478bd9Sstevel@tonic-gate } 37847c478bd9Sstevel@tonic-gate 37857c478bd9Sstevel@tonic-gate if ((flags & (BUILTIN_CMDLINE | BUILTIN_SCRIPT)) != 0) 37867c478bd9Sstevel@tonic-gate { 37877c478bd9Sstevel@tonic-gate /* Do password check! */ 37887c478bd9Sstevel@tonic-gate char entered[32]; 37897c478bd9Sstevel@tonic-gate 37907c478bd9Sstevel@tonic-gate /* Wipe out any previously entered password */ 37917c478bd9Sstevel@tonic-gate entered[0] = 0; 37927c478bd9Sstevel@tonic-gate get_cmdline ("Password: ", entered, 31, '*', 0); 37937c478bd9Sstevel@tonic-gate 37947c478bd9Sstevel@tonic-gate nul_terminate (arg); 37957c478bd9Sstevel@tonic-gate if (check_password (entered, arg, type) != 0) 37967c478bd9Sstevel@tonic-gate { 37977c478bd9Sstevel@tonic-gate errnum = ERR_PRIVILEGED; 37987c478bd9Sstevel@tonic-gate return 1; 37997c478bd9Sstevel@tonic-gate } 38007c478bd9Sstevel@tonic-gate } 38017c478bd9Sstevel@tonic-gate else 38027c478bd9Sstevel@tonic-gate { 38037c478bd9Sstevel@tonic-gate len = grub_strlen (arg); 38047c478bd9Sstevel@tonic-gate 38057c478bd9Sstevel@tonic-gate /* PASSWORD NUL NUL ... */ 38067c478bd9Sstevel@tonic-gate if (len + 2 > PASSWORD_BUFLEN) 38077c478bd9Sstevel@tonic-gate { 38087c478bd9Sstevel@tonic-gate errnum = ERR_WONT_FIT; 38097c478bd9Sstevel@tonic-gate return 1; 38107c478bd9Sstevel@tonic-gate } 38117c478bd9Sstevel@tonic-gate 38127c478bd9Sstevel@tonic-gate /* Copy the password and clear the rest of the buffer. */ 38137c478bd9Sstevel@tonic-gate password = (char *) PASSWORD_BUF; 38147c478bd9Sstevel@tonic-gate grub_memmove (password, arg, len); 38157c478bd9Sstevel@tonic-gate grub_memset (password + len, 0, PASSWORD_BUFLEN - len); 38167c478bd9Sstevel@tonic-gate password_type = type; 38177c478bd9Sstevel@tonic-gate } 38187c478bd9Sstevel@tonic-gate return 0; 38197c478bd9Sstevel@tonic-gate } 38207c478bd9Sstevel@tonic-gate 38217c478bd9Sstevel@tonic-gate static struct builtin builtin_password = 38227c478bd9Sstevel@tonic-gate { 38237c478bd9Sstevel@tonic-gate "password", 38247c478bd9Sstevel@tonic-gate password_func, 38257c478bd9Sstevel@tonic-gate BUILTIN_MENU | BUILTIN_CMDLINE | BUILTIN_NO_ECHO, 38267c478bd9Sstevel@tonic-gate "password [--md5] PASSWD [FILE]", 38277c478bd9Sstevel@tonic-gate "If used in the first section of a menu file, disable all" 38287c478bd9Sstevel@tonic-gate " interactive editing control (menu entry editor and" 38297c478bd9Sstevel@tonic-gate " command line). If the password PASSWD is entered, it loads the" 38307c478bd9Sstevel@tonic-gate " FILE as a new config file and restarts the GRUB Stage 2. If you" 38317c478bd9Sstevel@tonic-gate " omit the argument FILE, then GRUB just unlocks privileged" 38327c478bd9Sstevel@tonic-gate " instructions. You can also use it in the script section, in" 38337c478bd9Sstevel@tonic-gate " which case it will ask for the password, before continueing." 38347c478bd9Sstevel@tonic-gate " The option --md5 tells GRUB that PASSWD is encrypted with" 38357c478bd9Sstevel@tonic-gate " md5crypt." 38367c478bd9Sstevel@tonic-gate }; 38377c478bd9Sstevel@tonic-gate 38387c478bd9Sstevel@tonic-gate 38397c478bd9Sstevel@tonic-gate /* pause */ 38407c478bd9Sstevel@tonic-gate static int 38417c478bd9Sstevel@tonic-gate pause_func (char *arg, int flags) 38427c478bd9Sstevel@tonic-gate { 38437c478bd9Sstevel@tonic-gate printf("%s\n", arg); 38447c478bd9Sstevel@tonic-gate 38457c478bd9Sstevel@tonic-gate /* If ESC is returned, then abort this entry. */ 38467c478bd9Sstevel@tonic-gate if (ASCII_CHAR (getkey ()) == 27) 38477c478bd9Sstevel@tonic-gate return 1; 38487c478bd9Sstevel@tonic-gate 38497c478bd9Sstevel@tonic-gate return 0; 38507c478bd9Sstevel@tonic-gate } 38517c478bd9Sstevel@tonic-gate 38527c478bd9Sstevel@tonic-gate static struct builtin builtin_pause = 38537c478bd9Sstevel@tonic-gate { 38547c478bd9Sstevel@tonic-gate "pause", 38557c478bd9Sstevel@tonic-gate pause_func, 38567c478bd9Sstevel@tonic-gate BUILTIN_CMDLINE | BUILTIN_NO_ECHO, 38577c478bd9Sstevel@tonic-gate "pause [MESSAGE ...]", 38587c478bd9Sstevel@tonic-gate "Print MESSAGE, then wait until a key is pressed." 38597c478bd9Sstevel@tonic-gate }; 38607c478bd9Sstevel@tonic-gate 38617c478bd9Sstevel@tonic-gate 38627c478bd9Sstevel@tonic-gate #ifdef GRUB_UTIL 38637c478bd9Sstevel@tonic-gate /* quit */ 38647c478bd9Sstevel@tonic-gate static int 38657c478bd9Sstevel@tonic-gate quit_func (char *arg, int flags) 38667c478bd9Sstevel@tonic-gate { 38677c478bd9Sstevel@tonic-gate stop (); 38687c478bd9Sstevel@tonic-gate 38697c478bd9Sstevel@tonic-gate /* Never reach here. */ 38707c478bd9Sstevel@tonic-gate return 0; 38717c478bd9Sstevel@tonic-gate } 38727c478bd9Sstevel@tonic-gate 38737c478bd9Sstevel@tonic-gate static struct builtin builtin_quit = 38747c478bd9Sstevel@tonic-gate { 38757c478bd9Sstevel@tonic-gate "quit", 38767c478bd9Sstevel@tonic-gate quit_func, 38777c478bd9Sstevel@tonic-gate BUILTIN_CMDLINE | BUILTIN_HELP_LIST, 38787c478bd9Sstevel@tonic-gate "quit", 38797c478bd9Sstevel@tonic-gate "Exit from the GRUB shell." 38807c478bd9Sstevel@tonic-gate }; 38817c478bd9Sstevel@tonic-gate #endif /* GRUB_UTIL */ 38827c478bd9Sstevel@tonic-gate 38837c478bd9Sstevel@tonic-gate 38847c478bd9Sstevel@tonic-gate #ifdef SUPPORT_NETBOOT 38857c478bd9Sstevel@tonic-gate /* rarp */ 38867c478bd9Sstevel@tonic-gate static int 38877c478bd9Sstevel@tonic-gate rarp_func (char *arg, int flags) 38887c478bd9Sstevel@tonic-gate { 38897c478bd9Sstevel@tonic-gate if (! rarp ()) 38907c478bd9Sstevel@tonic-gate { 38917c478bd9Sstevel@tonic-gate if (errnum == ERR_NONE) 38927c478bd9Sstevel@tonic-gate errnum = ERR_DEV_VALUES; 38937c478bd9Sstevel@tonic-gate 38947c478bd9Sstevel@tonic-gate return 1; 38957c478bd9Sstevel@tonic-gate } 38967c478bd9Sstevel@tonic-gate 38977c478bd9Sstevel@tonic-gate /* Notify the configuration. */ 38987c478bd9Sstevel@tonic-gate print_network_configuration (); 38997c478bd9Sstevel@tonic-gate return 0; 39007c478bd9Sstevel@tonic-gate } 39017c478bd9Sstevel@tonic-gate 39027c478bd9Sstevel@tonic-gate static struct builtin builtin_rarp = 39037c478bd9Sstevel@tonic-gate { 39047c478bd9Sstevel@tonic-gate "rarp", 39057c478bd9Sstevel@tonic-gate rarp_func, 39067c478bd9Sstevel@tonic-gate BUILTIN_CMDLINE | BUILTIN_MENU | BUILTIN_HELP_LIST, 39077c478bd9Sstevel@tonic-gate "rarp", 39087c478bd9Sstevel@tonic-gate "Initialize a network device via RARP." 39097c478bd9Sstevel@tonic-gate }; 39107c478bd9Sstevel@tonic-gate #endif /* SUPPORT_NETBOOT */ 39117c478bd9Sstevel@tonic-gate 39127c478bd9Sstevel@tonic-gate 39137c478bd9Sstevel@tonic-gate static int 39147c478bd9Sstevel@tonic-gate read_func (char *arg, int flags) 39157c478bd9Sstevel@tonic-gate { 39167c478bd9Sstevel@tonic-gate int addr; 39177c478bd9Sstevel@tonic-gate 39187c478bd9Sstevel@tonic-gate if (! safe_parse_maxint (&arg, &addr)) 39197c478bd9Sstevel@tonic-gate return 1; 39207c478bd9Sstevel@tonic-gate 39217c478bd9Sstevel@tonic-gate grub_printf ("Address 0x%x: Value 0x%x\n", 39227c478bd9Sstevel@tonic-gate addr, *((unsigned *) RAW_ADDR (addr))); 39237c478bd9Sstevel@tonic-gate return 0; 39247c478bd9Sstevel@tonic-gate } 39257c478bd9Sstevel@tonic-gate 39267c478bd9Sstevel@tonic-gate static struct builtin builtin_read = 39277c478bd9Sstevel@tonic-gate { 39287c478bd9Sstevel@tonic-gate "read", 39297c478bd9Sstevel@tonic-gate read_func, 39307c478bd9Sstevel@tonic-gate BUILTIN_CMDLINE, 39317c478bd9Sstevel@tonic-gate "read ADDR", 39327c478bd9Sstevel@tonic-gate "Read a 32-bit value from memory at address ADDR and" 39337c478bd9Sstevel@tonic-gate " display it in hex format." 39347c478bd9Sstevel@tonic-gate }; 39357c478bd9Sstevel@tonic-gate 39367c478bd9Sstevel@tonic-gate 39377c478bd9Sstevel@tonic-gate /* reboot */ 39387c478bd9Sstevel@tonic-gate static int 39397c478bd9Sstevel@tonic-gate reboot_func (char *arg, int flags) 39407c478bd9Sstevel@tonic-gate { 39417c478bd9Sstevel@tonic-gate grub_reboot (); 39427c478bd9Sstevel@tonic-gate 39437c478bd9Sstevel@tonic-gate /* Never reach here. */ 39447c478bd9Sstevel@tonic-gate return 1; 39457c478bd9Sstevel@tonic-gate } 39467c478bd9Sstevel@tonic-gate 39477c478bd9Sstevel@tonic-gate static struct builtin builtin_reboot = 39487c478bd9Sstevel@tonic-gate { 39497c478bd9Sstevel@tonic-gate "reboot", 39507c478bd9Sstevel@tonic-gate reboot_func, 39517c478bd9Sstevel@tonic-gate BUILTIN_CMDLINE | BUILTIN_HELP_LIST, 39527c478bd9Sstevel@tonic-gate "reboot", 39537c478bd9Sstevel@tonic-gate "Reboot your system." 39547c478bd9Sstevel@tonic-gate }; 39557c478bd9Sstevel@tonic-gate 39567c478bd9Sstevel@tonic-gate 39577c478bd9Sstevel@tonic-gate /* Print the root device information. */ 39587c478bd9Sstevel@tonic-gate static void 39597c478bd9Sstevel@tonic-gate print_root_device (void) 39607c478bd9Sstevel@tonic-gate { 39617c478bd9Sstevel@tonic-gate if (saved_drive == NETWORK_DRIVE) 39627c478bd9Sstevel@tonic-gate { 39637c478bd9Sstevel@tonic-gate /* Network drive. */ 39647c478bd9Sstevel@tonic-gate grub_printf (" (nd):"); 39657c478bd9Sstevel@tonic-gate } 39667c478bd9Sstevel@tonic-gate else if (saved_drive & 0x80) 39677c478bd9Sstevel@tonic-gate { 39687c478bd9Sstevel@tonic-gate /* Hard disk drive. */ 39697c478bd9Sstevel@tonic-gate grub_printf (" (hd%d", saved_drive - 0x80); 39707c478bd9Sstevel@tonic-gate 39717c478bd9Sstevel@tonic-gate if ((saved_partition & 0xFF0000) != 0xFF0000) 39727c478bd9Sstevel@tonic-gate grub_printf (",%d", saved_partition >> 16); 39737c478bd9Sstevel@tonic-gate 39747c478bd9Sstevel@tonic-gate if ((saved_partition & 0x00FF00) != 0x00FF00) 39757c478bd9Sstevel@tonic-gate grub_printf (",%c", ((saved_partition >> 8) & 0xFF) + 'a'); 39767c478bd9Sstevel@tonic-gate 39777c478bd9Sstevel@tonic-gate grub_printf ("):"); 39787c478bd9Sstevel@tonic-gate } 39797c478bd9Sstevel@tonic-gate else 39807c478bd9Sstevel@tonic-gate { 39817c478bd9Sstevel@tonic-gate /* Floppy disk drive. */ 39827c478bd9Sstevel@tonic-gate grub_printf (" (fd%d):", saved_drive); 39837c478bd9Sstevel@tonic-gate } 39847c478bd9Sstevel@tonic-gate 39857c478bd9Sstevel@tonic-gate /* Print the filesystem information. */ 39867c478bd9Sstevel@tonic-gate current_partition = saved_partition; 39877c478bd9Sstevel@tonic-gate current_drive = saved_drive; 39887c478bd9Sstevel@tonic-gate print_fsys_type (); 39897c478bd9Sstevel@tonic-gate } 39907c478bd9Sstevel@tonic-gate 39917c478bd9Sstevel@tonic-gate static int 39927c478bd9Sstevel@tonic-gate real_root_func (char *arg, int attempt_mount) 39937c478bd9Sstevel@tonic-gate { 39947c478bd9Sstevel@tonic-gate int hdbias = 0; 39957c478bd9Sstevel@tonic-gate char *biasptr; 39967c478bd9Sstevel@tonic-gate char *next; 39977c478bd9Sstevel@tonic-gate 39987c478bd9Sstevel@tonic-gate /* If ARG is empty, just print the current root device. */ 39997c478bd9Sstevel@tonic-gate if (! *arg) 40007c478bd9Sstevel@tonic-gate { 40017c478bd9Sstevel@tonic-gate print_root_device (); 40027c478bd9Sstevel@tonic-gate return 0; 40037c478bd9Sstevel@tonic-gate } 40047c478bd9Sstevel@tonic-gate 40057c478bd9Sstevel@tonic-gate /* Call set_device to get the drive and the partition in ARG. */ 40067c478bd9Sstevel@tonic-gate next = set_device (arg); 40077c478bd9Sstevel@tonic-gate if (! next) 40087c478bd9Sstevel@tonic-gate return 1; 40097c478bd9Sstevel@tonic-gate 40107c478bd9Sstevel@tonic-gate /* Ignore ERR_FSYS_MOUNT. */ 40117c478bd9Sstevel@tonic-gate if (attempt_mount) 40127c478bd9Sstevel@tonic-gate { 40137c478bd9Sstevel@tonic-gate if (! open_device () && errnum != ERR_FSYS_MOUNT) 40147c478bd9Sstevel@tonic-gate return 1; 40157c478bd9Sstevel@tonic-gate } 40167c478bd9Sstevel@tonic-gate else 40177c478bd9Sstevel@tonic-gate { 40187c478bd9Sstevel@tonic-gate /* This is necessary, because the location of a partition table 40197c478bd9Sstevel@tonic-gate must be set appropriately. */ 40207c478bd9Sstevel@tonic-gate if (open_partition ()) 40217c478bd9Sstevel@tonic-gate { 40227c478bd9Sstevel@tonic-gate set_bootdev (0); 40237c478bd9Sstevel@tonic-gate if (errnum) 40247c478bd9Sstevel@tonic-gate return 1; 40257c478bd9Sstevel@tonic-gate } 40267c478bd9Sstevel@tonic-gate } 40277c478bd9Sstevel@tonic-gate 40287c478bd9Sstevel@tonic-gate /* Clear ERRNUM. */ 40297c478bd9Sstevel@tonic-gate errnum = 0; 40307c478bd9Sstevel@tonic-gate saved_partition = current_partition; 40317c478bd9Sstevel@tonic-gate saved_drive = current_drive; 40327c478bd9Sstevel@tonic-gate 40337c478bd9Sstevel@tonic-gate if (attempt_mount) 40347c478bd9Sstevel@tonic-gate { 40357c478bd9Sstevel@tonic-gate /* BSD and chainloading evil hacks !! */ 40367c478bd9Sstevel@tonic-gate biasptr = skip_to (0, next); 40377c478bd9Sstevel@tonic-gate safe_parse_maxint (&biasptr, &hdbias); 40387c478bd9Sstevel@tonic-gate errnum = 0; 40397c478bd9Sstevel@tonic-gate bootdev = set_bootdev (hdbias); 40407c478bd9Sstevel@tonic-gate if (errnum) 40417c478bd9Sstevel@tonic-gate return 1; 40427c478bd9Sstevel@tonic-gate 40437c478bd9Sstevel@tonic-gate /* Print the type of the filesystem. */ 40447c478bd9Sstevel@tonic-gate print_fsys_type (); 40457c478bd9Sstevel@tonic-gate } 40467c478bd9Sstevel@tonic-gate 40477c478bd9Sstevel@tonic-gate return 0; 40487c478bd9Sstevel@tonic-gate } 40497c478bd9Sstevel@tonic-gate 40507c478bd9Sstevel@tonic-gate static int 40517c478bd9Sstevel@tonic-gate root_func (char *arg, int flags) 40527c478bd9Sstevel@tonic-gate { 4053b1b8ab34Slling is_zfs_mount = 0; 40547c478bd9Sstevel@tonic-gate return real_root_func (arg, 1); 40557c478bd9Sstevel@tonic-gate } 40567c478bd9Sstevel@tonic-gate 40577c478bd9Sstevel@tonic-gate static struct builtin builtin_root = 40587c478bd9Sstevel@tonic-gate { 40597c478bd9Sstevel@tonic-gate "root", 40607c478bd9Sstevel@tonic-gate root_func, 40617c478bd9Sstevel@tonic-gate BUILTIN_CMDLINE | BUILTIN_HELP_LIST, 40627c478bd9Sstevel@tonic-gate "root [DEVICE [HDBIAS]]", 40637c478bd9Sstevel@tonic-gate "Set the current \"root device\" to the device DEVICE, then" 40647c478bd9Sstevel@tonic-gate " attempt to mount it to get the partition size (for passing the" 40657c478bd9Sstevel@tonic-gate " partition descriptor in `ES:ESI', used by some chain-loaded" 40667c478bd9Sstevel@tonic-gate " bootloaders), the BSD drive-type (for booting BSD kernels using" 40677c478bd9Sstevel@tonic-gate " their native boot format), and correctly determine " 40687c478bd9Sstevel@tonic-gate " the PC partition where a BSD sub-partition is located. The" 40697c478bd9Sstevel@tonic-gate " optional HDBIAS parameter is a number to tell a BSD kernel" 40707c478bd9Sstevel@tonic-gate " how many BIOS drive numbers are on controllers before the current" 40717c478bd9Sstevel@tonic-gate " one. For example, if there is an IDE disk and a SCSI disk, and your" 40727c478bd9Sstevel@tonic-gate " FreeBSD root partition is on the SCSI disk, then use a `1' for HDBIAS." 40737c478bd9Sstevel@tonic-gate }; 40747c478bd9Sstevel@tonic-gate 4075eb2bd662Svikram 4076eb2bd662Svikram /* findroot */ 4077eb2bd662Svikram static int 4078eb2bd662Svikram findroot_func (char *arg, int flags) 4079eb2bd662Svikram { 4080eb2bd662Svikram int ret; 4081eb2bd662Svikram char root[32]; 4082eb2bd662Svikram 4083eb2bd662Svikram if (grub_strlen(arg) >= BOOTSIGN_ARGLEN) { 4084eb2bd662Svikram errnum = ERR_BAD_ARGUMENT; 4085eb2bd662Svikram return 1; 4086eb2bd662Svikram } 4087eb2bd662Svikram 4088eb2bd662Svikram if (arg[0] == '\0') { 4089eb2bd662Svikram errnum = ERR_BAD_ARGUMENT; 4090eb2bd662Svikram return 1; 4091eb2bd662Svikram } 4092eb2bd662Svikram 4093eb2bd662Svikram if (grub_strchr(arg, '/')) { 4094eb2bd662Svikram errnum = ERR_BAD_ARGUMENT; 4095eb2bd662Svikram return 1; 4096eb2bd662Svikram } 4097eb2bd662Svikram 4098051aabe6Staylor find_best_root = 1; 4099051aabe6Staylor best_drive = 0; 4100051aabe6Staylor best_part = 0; 4101eb2bd662Svikram ret = find_common(arg, root, 1, flags); 4102eb2bd662Svikram if (ret != 0) 4103eb2bd662Svikram return (ret); 4104051aabe6Staylor find_best_root = 0; 4105eb2bd662Svikram 4106eb2bd662Svikram return real_root_func (root, 1); 4107eb2bd662Svikram } 4108eb2bd662Svikram 4109eb2bd662Svikram static struct builtin builtin_findroot = 4110eb2bd662Svikram { 4111eb2bd662Svikram "findroot", 4112eb2bd662Svikram findroot_func, 4113eb2bd662Svikram BUILTIN_CMDLINE | BUILTIN_HELP_LIST, 4114963390b4Svikram "findroot <SIGNATURE | (SIGNATURE,partition[,slice])>", 4115963390b4Svikram "Searches across all partitions for the file name SIGNATURE." 4116963390b4Svikram " GRUB looks only in the directory /boot/grub/bootsign for the" 4117963390b4Svikram " filename and it stops as soon as it finds the first instance of" 4118963390b4Svikram " the file - so to be useful the name of the signature file must be" 4119963390b4Svikram " unique across all partitions. Once the signature file is found," 4120963390b4Svikram " GRUB invokes the \"root\" command on that partition." 4121eb2bd662Svikram " An optional partition and slice may be specified to optimize the search." 4122eb2bd662Svikram }; 4123eb2bd662Svikram 4124b1b8ab34Slling 4125b1b8ab34Slling /* 4126b1b8ab34Slling * COMMAND to override the default root filesystem for ZFS 4127b1b8ab34Slling * bootfs pool/fs 4128b1b8ab34Slling */ 4129b1b8ab34Slling static int 4130b1b8ab34Slling bootfs_func (char *arg, int flags) 4131b1b8ab34Slling { 4132b1b8ab34Slling int hdbias = 0; 4133b1b8ab34Slling char *biasptr; 4134b1b8ab34Slling char *next; 4135b1b8ab34Slling 4136b1b8ab34Slling if (! *arg) { 4137b1b8ab34Slling if (current_bootfs[0] != '\0') 4138b1b8ab34Slling grub_printf ("The zfs boot filesystem is set to '%s'.\n", 4139b1b8ab34Slling current_bootfs); 4140b1b8ab34Slling else if (current_rootpool[0] != 0 && current_bootfs_obj != 0) 4141b1b8ab34Slling grub_printf("The zfs boot filesystem is <default: %s/%u>.", 4142b1b8ab34Slling current_rootpool, current_bootfs_obj); 4143b1b8ab34Slling else 414411a41203Slling grub_printf ("The zfs boot filesystem will be derived from " 414511a41203Slling "the default bootfs pool property.\n"); 4146b1b8ab34Slling 4147b1b8ab34Slling return (1); 4148b1b8ab34Slling } 4149b1b8ab34Slling 4150b1b8ab34Slling /* Verify the zfs filesystem name */ 4151b1b8ab34Slling if (arg[0] == '/' || arg[0] == '\0') { 4152b1b8ab34Slling errnum = ERR_BAD_ARGUMENT; 4153b1b8ab34Slling return 0; 4154b1b8ab34Slling } 4155b35c6776Staylor if (current_rootpool[0] != 0 && grub_strncmp(arg, 4156b35c6776Staylor current_rootpool, strlen(current_rootpool))) { 4157b35c6776Staylor errnum = ERR_BAD_ARGUMENT; 4158b35c6776Staylor return 0; 4159b35c6776Staylor } 4160b1b8ab34Slling 4161b1b8ab34Slling if (set_bootfs(arg) == 0) { 4162b1b8ab34Slling errnum = ERR_BAD_ARGUMENT; 4163b1b8ab34Slling return 0; 4164b1b8ab34Slling } 4165b1b8ab34Slling 4166b1b8ab34Slling return (1); 4167b1b8ab34Slling } 4168b1b8ab34Slling 4169b1b8ab34Slling static struct builtin builtin_bootfs = 4170b1b8ab34Slling { 4171b1b8ab34Slling "bootfs", 4172b1b8ab34Slling bootfs_func, 4173b1b8ab34Slling BUILTIN_CMDLINE | BUILTIN_HELP_LIST, 4174b1b8ab34Slling "bootfs [ZFSBOOTFS]", 4175b1b8ab34Slling "Set the current zfs boot filesystem to ZFSBOOTFS (rootpool/rootfs)." 4176b1b8ab34Slling }; 4177b1b8ab34Slling 41787c478bd9Sstevel@tonic-gate 41797c478bd9Sstevel@tonic-gate /* rootnoverify */ 41807c478bd9Sstevel@tonic-gate static int 41817c478bd9Sstevel@tonic-gate rootnoverify_func (char *arg, int flags) 41827c478bd9Sstevel@tonic-gate { 41837c478bd9Sstevel@tonic-gate return real_root_func (arg, 0); 41847c478bd9Sstevel@tonic-gate } 41857c478bd9Sstevel@tonic-gate 41867c478bd9Sstevel@tonic-gate static struct builtin builtin_rootnoverify = 41877c478bd9Sstevel@tonic-gate { 41887c478bd9Sstevel@tonic-gate "rootnoverify", 41897c478bd9Sstevel@tonic-gate rootnoverify_func, 41907c478bd9Sstevel@tonic-gate BUILTIN_CMDLINE | BUILTIN_HELP_LIST, 41917c478bd9Sstevel@tonic-gate "rootnoverify [DEVICE [HDBIAS]]", 41927c478bd9Sstevel@tonic-gate "Similar to `root', but don't attempt to mount the partition. This" 41937c478bd9Sstevel@tonic-gate " is useful for when an OS is outside of the area of the disk that" 41947c478bd9Sstevel@tonic-gate " GRUB can read, but setting the correct root device is still" 41957c478bd9Sstevel@tonic-gate " desired. Note that the items mentioned in `root' which" 41967c478bd9Sstevel@tonic-gate " derived from attempting the mount will NOT work correctly." 41977c478bd9Sstevel@tonic-gate }; 41987c478bd9Sstevel@tonic-gate 41997c478bd9Sstevel@tonic-gate 42007c478bd9Sstevel@tonic-gate /* savedefault */ 42017c478bd9Sstevel@tonic-gate static int 42027c478bd9Sstevel@tonic-gate savedefault_func (char *arg, int flags) 42037c478bd9Sstevel@tonic-gate { 42047c478bd9Sstevel@tonic-gate #if !defined(SUPPORT_DISKLESS) && !defined(GRUB_UTIL) 42057c478bd9Sstevel@tonic-gate unsigned long tmp_drive = saved_drive; 42067c478bd9Sstevel@tonic-gate unsigned long tmp_partition = saved_partition; 42077c478bd9Sstevel@tonic-gate char *default_file = (char *) DEFAULT_FILE_BUF; 42087c478bd9Sstevel@tonic-gate char buf[10]; 42097c478bd9Sstevel@tonic-gate char sect[SECTOR_SIZE]; 42107c478bd9Sstevel@tonic-gate int entryno; 42117c478bd9Sstevel@tonic-gate int sector_count = 0; 4212342440ecSPrasad Singamsetty unsigned int saved_sectors[2]; 42137c478bd9Sstevel@tonic-gate int saved_offsets[2]; 42147c478bd9Sstevel@tonic-gate int saved_lengths[2]; 42157c478bd9Sstevel@tonic-gate 4216b1b8ab34Slling /* not supported for zfs root */ 4217b1b8ab34Slling if (is_zfs_mount == 1) { 4218b1b8ab34Slling return (0); /* no-op */ 4219b1b8ab34Slling } 4220b1b8ab34Slling 42217c478bd9Sstevel@tonic-gate /* Save sector information about at most two sectors. */ 42221b8adde7SWilliam Kucharski auto void disk_read_savesect_func (unsigned int sector, int offset, 42231b8adde7SWilliam Kucharski int length); 42241b8adde7SWilliam Kucharski void disk_read_savesect_func (unsigned int sector, int offset, int length) 42257c478bd9Sstevel@tonic-gate { 42267c478bd9Sstevel@tonic-gate if (sector_count < 2) 42277c478bd9Sstevel@tonic-gate { 42287c478bd9Sstevel@tonic-gate saved_sectors[sector_count] = sector; 42297c478bd9Sstevel@tonic-gate saved_offsets[sector_count] = offset; 42307c478bd9Sstevel@tonic-gate saved_lengths[sector_count] = length; 42317c478bd9Sstevel@tonic-gate } 42327c478bd9Sstevel@tonic-gate sector_count++; 42337c478bd9Sstevel@tonic-gate } 42347c478bd9Sstevel@tonic-gate 42357c478bd9Sstevel@tonic-gate /* This command is only useful when you boot an entry from the menu 42367c478bd9Sstevel@tonic-gate interface. */ 42377c478bd9Sstevel@tonic-gate if (! (flags & BUILTIN_SCRIPT)) 42387c478bd9Sstevel@tonic-gate { 42397c478bd9Sstevel@tonic-gate errnum = ERR_UNRECOGNIZED; 42407c478bd9Sstevel@tonic-gate return 1; 42417c478bd9Sstevel@tonic-gate } 42427c478bd9Sstevel@tonic-gate 42437c478bd9Sstevel@tonic-gate /* Determine a saved entry number. */ 42447c478bd9Sstevel@tonic-gate if (*arg) 42457c478bd9Sstevel@tonic-gate { 42467c478bd9Sstevel@tonic-gate if (grub_memcmp (arg, "fallback", sizeof ("fallback") - 1) == 0) 42477c478bd9Sstevel@tonic-gate { 42487c478bd9Sstevel@tonic-gate int i; 42497c478bd9Sstevel@tonic-gate int index = 0; 42507c478bd9Sstevel@tonic-gate 42517c478bd9Sstevel@tonic-gate for (i = 0; i < MAX_FALLBACK_ENTRIES; i++) 42527c478bd9Sstevel@tonic-gate { 42537c478bd9Sstevel@tonic-gate if (fallback_entries[i] < 0) 42547c478bd9Sstevel@tonic-gate break; 42557c478bd9Sstevel@tonic-gate if (fallback_entries[i] == current_entryno) 42567c478bd9Sstevel@tonic-gate { 42577c478bd9Sstevel@tonic-gate index = i + 1; 42587c478bd9Sstevel@tonic-gate break; 42597c478bd9Sstevel@tonic-gate } 42607c478bd9Sstevel@tonic-gate } 42617c478bd9Sstevel@tonic-gate 42627c478bd9Sstevel@tonic-gate if (index >= MAX_FALLBACK_ENTRIES || fallback_entries[index] < 0) 42637c478bd9Sstevel@tonic-gate { 42647c478bd9Sstevel@tonic-gate /* This is the last. */ 42657c478bd9Sstevel@tonic-gate errnum = ERR_BAD_ARGUMENT; 42667c478bd9Sstevel@tonic-gate return 1; 42677c478bd9Sstevel@tonic-gate } 42687c478bd9Sstevel@tonic-gate 42697c478bd9Sstevel@tonic-gate entryno = fallback_entries[index]; 42707c478bd9Sstevel@tonic-gate } 42717c478bd9Sstevel@tonic-gate else if (! safe_parse_maxint (&arg, &entryno)) 42727c478bd9Sstevel@tonic-gate return 1; 42737c478bd9Sstevel@tonic-gate } 42747c478bd9Sstevel@tonic-gate else 42757c478bd9Sstevel@tonic-gate entryno = current_entryno; 42767c478bd9Sstevel@tonic-gate 42777c478bd9Sstevel@tonic-gate /* Open the default file. */ 42787c478bd9Sstevel@tonic-gate saved_drive = boot_drive; 42797c478bd9Sstevel@tonic-gate saved_partition = install_partition; 42807c478bd9Sstevel@tonic-gate if (grub_open (default_file)) 42817c478bd9Sstevel@tonic-gate { 42827c478bd9Sstevel@tonic-gate int len; 42837c478bd9Sstevel@tonic-gate 42847c478bd9Sstevel@tonic-gate disk_read_hook = disk_read_savesect_func; 42857c478bd9Sstevel@tonic-gate len = grub_read (buf, sizeof (buf)); 42867c478bd9Sstevel@tonic-gate disk_read_hook = 0; 42877c478bd9Sstevel@tonic-gate grub_close (); 42887c478bd9Sstevel@tonic-gate 42897c478bd9Sstevel@tonic-gate if (len != sizeof (buf)) 42907c478bd9Sstevel@tonic-gate { 42917c478bd9Sstevel@tonic-gate /* This is too small. Do not modify the file manually, please! */ 42927c478bd9Sstevel@tonic-gate errnum = ERR_READ; 42937c478bd9Sstevel@tonic-gate goto fail; 42947c478bd9Sstevel@tonic-gate } 42957c478bd9Sstevel@tonic-gate 42967c478bd9Sstevel@tonic-gate if (sector_count > 2) 42977c478bd9Sstevel@tonic-gate { 42987c478bd9Sstevel@tonic-gate /* Is this possible?! Too fragmented! */ 42997c478bd9Sstevel@tonic-gate errnum = ERR_FSYS_CORRUPT; 43007c478bd9Sstevel@tonic-gate goto fail; 43017c478bd9Sstevel@tonic-gate } 43027c478bd9Sstevel@tonic-gate 43037c478bd9Sstevel@tonic-gate /* Set up a string to be written. */ 43047c478bd9Sstevel@tonic-gate grub_memset (buf, '\n', sizeof (buf)); 43057c478bd9Sstevel@tonic-gate grub_sprintf (buf, "%d", entryno); 43067c478bd9Sstevel@tonic-gate 43077c478bd9Sstevel@tonic-gate if (saved_lengths[0] < sizeof (buf)) 43087c478bd9Sstevel@tonic-gate { 43097c478bd9Sstevel@tonic-gate /* The file is anchored to another file and the first few bytes 43107c478bd9Sstevel@tonic-gate are spanned in two sectors. Uggh... */ 43117c478bd9Sstevel@tonic-gate if (! rawread (current_drive, saved_sectors[0], 0, SECTOR_SIZE, 43127c478bd9Sstevel@tonic-gate sect)) 43137c478bd9Sstevel@tonic-gate goto fail; 43147c478bd9Sstevel@tonic-gate grub_memmove (sect + saved_offsets[0], buf, saved_lengths[0]); 43157c478bd9Sstevel@tonic-gate if (! rawwrite (current_drive, saved_sectors[0], sect)) 43167c478bd9Sstevel@tonic-gate goto fail; 43177c478bd9Sstevel@tonic-gate 43187c478bd9Sstevel@tonic-gate if (! rawread (current_drive, saved_sectors[1], 0, SECTOR_SIZE, 43197c478bd9Sstevel@tonic-gate sect)) 43207c478bd9Sstevel@tonic-gate goto fail; 43217c478bd9Sstevel@tonic-gate grub_memmove (sect + saved_offsets[1], 43227c478bd9Sstevel@tonic-gate buf + saved_lengths[0], 43237c478bd9Sstevel@tonic-gate sizeof (buf) - saved_lengths[0]); 43247c478bd9Sstevel@tonic-gate if (! rawwrite (current_drive, saved_sectors[1], sect)) 43257c478bd9Sstevel@tonic-gate goto fail; 43267c478bd9Sstevel@tonic-gate } 43277c478bd9Sstevel@tonic-gate else 43287c478bd9Sstevel@tonic-gate { 43297c478bd9Sstevel@tonic-gate /* This is a simple case. It fits into a single sector. */ 43307c478bd9Sstevel@tonic-gate if (! rawread (current_drive, saved_sectors[0], 0, SECTOR_SIZE, 43317c478bd9Sstevel@tonic-gate sect)) 43327c478bd9Sstevel@tonic-gate goto fail; 43337c478bd9Sstevel@tonic-gate grub_memmove (sect + saved_offsets[0], buf, sizeof (buf)); 43347c478bd9Sstevel@tonic-gate if (! rawwrite (current_drive, saved_sectors[0], sect)) 43357c478bd9Sstevel@tonic-gate goto fail; 43367c478bd9Sstevel@tonic-gate } 43377c478bd9Sstevel@tonic-gate 43387c478bd9Sstevel@tonic-gate /* Clear the cache. */ 4339342440ecSPrasad Singamsetty buf_track = BUF_CACHE_INVALID; 43407c478bd9Sstevel@tonic-gate } 43417c478bd9Sstevel@tonic-gate 43427c478bd9Sstevel@tonic-gate fail: 43437c478bd9Sstevel@tonic-gate saved_drive = tmp_drive; 43447c478bd9Sstevel@tonic-gate saved_partition = tmp_partition; 43457c478bd9Sstevel@tonic-gate return errnum; 43467c478bd9Sstevel@tonic-gate #else /* ! SUPPORT_DISKLESS && ! GRUB_UTIL */ 43477c478bd9Sstevel@tonic-gate errnum = ERR_UNRECOGNIZED; 43487c478bd9Sstevel@tonic-gate return 1; 43497c478bd9Sstevel@tonic-gate #endif /* ! SUPPORT_DISKLESS && ! GRUB_UTIL */ 43507c478bd9Sstevel@tonic-gate } 43517c478bd9Sstevel@tonic-gate 43527c478bd9Sstevel@tonic-gate static struct builtin builtin_savedefault = 43537c478bd9Sstevel@tonic-gate { 43547c478bd9Sstevel@tonic-gate "savedefault", 43557c478bd9Sstevel@tonic-gate savedefault_func, 43567c478bd9Sstevel@tonic-gate BUILTIN_CMDLINE, 43577c478bd9Sstevel@tonic-gate "savedefault [NUM | `fallback']", 43587c478bd9Sstevel@tonic-gate "Save the current entry as the default boot entry if no argument is" 43597c478bd9Sstevel@tonic-gate " specified. If a number is specified, this number is saved. If" 43607c478bd9Sstevel@tonic-gate " `fallback' is used, next fallback entry is saved." 43617c478bd9Sstevel@tonic-gate }; 43627c478bd9Sstevel@tonic-gate 43637c478bd9Sstevel@tonic-gate 43647c478bd9Sstevel@tonic-gate #ifdef SUPPORT_SERIAL 43657c478bd9Sstevel@tonic-gate /* serial */ 43667c478bd9Sstevel@tonic-gate static int 43677c478bd9Sstevel@tonic-gate serial_func (char *arg, int flags) 43687c478bd9Sstevel@tonic-gate { 43697c478bd9Sstevel@tonic-gate unsigned short port = serial_hw_get_port (0); 43707c478bd9Sstevel@tonic-gate unsigned int speed = 9600; 43717c478bd9Sstevel@tonic-gate int word_len = UART_8BITS_WORD; 43727c478bd9Sstevel@tonic-gate int parity = UART_NO_PARITY; 43737c478bd9Sstevel@tonic-gate int stop_bit_len = UART_1_STOP_BIT; 43747c478bd9Sstevel@tonic-gate 43757c478bd9Sstevel@tonic-gate /* Process GNU-style long options. 43767c478bd9Sstevel@tonic-gate FIXME: We should implement a getopt-like function, to avoid 43777c478bd9Sstevel@tonic-gate duplications. */ 43787c478bd9Sstevel@tonic-gate while (1) 43797c478bd9Sstevel@tonic-gate { 43807c478bd9Sstevel@tonic-gate if (grub_memcmp (arg, "--unit=", sizeof ("--unit=") - 1) == 0) 43817c478bd9Sstevel@tonic-gate { 43827c478bd9Sstevel@tonic-gate char *p = arg + sizeof ("--unit=") - 1; 43837c478bd9Sstevel@tonic-gate int unit; 43847c478bd9Sstevel@tonic-gate 43857c478bd9Sstevel@tonic-gate if (! safe_parse_maxint (&p, &unit)) 43867c478bd9Sstevel@tonic-gate return 1; 43877c478bd9Sstevel@tonic-gate 43887c478bd9Sstevel@tonic-gate if (unit < 0 || unit > 3) 43897c478bd9Sstevel@tonic-gate { 43907c478bd9Sstevel@tonic-gate errnum = ERR_DEV_VALUES; 43917c478bd9Sstevel@tonic-gate return 1; 43927c478bd9Sstevel@tonic-gate } 43937c478bd9Sstevel@tonic-gate 43947c478bd9Sstevel@tonic-gate port = serial_hw_get_port (unit); 43957c478bd9Sstevel@tonic-gate } 43967c478bd9Sstevel@tonic-gate else if (grub_memcmp (arg, "--speed=", sizeof ("--speed=") - 1) == 0) 43977c478bd9Sstevel@tonic-gate { 43987c478bd9Sstevel@tonic-gate char *p = arg + sizeof ("--speed=") - 1; 43997c478bd9Sstevel@tonic-gate int num; 44007c478bd9Sstevel@tonic-gate 44017c478bd9Sstevel@tonic-gate if (! safe_parse_maxint (&p, &num)) 44027c478bd9Sstevel@tonic-gate return 1; 44037c478bd9Sstevel@tonic-gate 44047c478bd9Sstevel@tonic-gate speed = (unsigned int) num; 44057c478bd9Sstevel@tonic-gate } 44067c478bd9Sstevel@tonic-gate else if (grub_memcmp (arg, "--port=", sizeof ("--port=") - 1) == 0) 44077c478bd9Sstevel@tonic-gate { 44087c478bd9Sstevel@tonic-gate char *p = arg + sizeof ("--port=") - 1; 44097c478bd9Sstevel@tonic-gate int num; 44107c478bd9Sstevel@tonic-gate 44117c478bd9Sstevel@tonic-gate if (! safe_parse_maxint (&p, &num)) 44127c478bd9Sstevel@tonic-gate return 1; 44137c478bd9Sstevel@tonic-gate 44147c478bd9Sstevel@tonic-gate port = (unsigned short) num; 44157c478bd9Sstevel@tonic-gate } 44167c478bd9Sstevel@tonic-gate else if (grub_memcmp (arg, "--word=", sizeof ("--word=") - 1) == 0) 44177c478bd9Sstevel@tonic-gate { 44187c478bd9Sstevel@tonic-gate char *p = arg + sizeof ("--word=") - 1; 44197c478bd9Sstevel@tonic-gate int len; 44207c478bd9Sstevel@tonic-gate 44217c478bd9Sstevel@tonic-gate if (! safe_parse_maxint (&p, &len)) 44227c478bd9Sstevel@tonic-gate return 1; 44237c478bd9Sstevel@tonic-gate 44247c478bd9Sstevel@tonic-gate switch (len) 44257c478bd9Sstevel@tonic-gate { 44267c478bd9Sstevel@tonic-gate case 5: word_len = UART_5BITS_WORD; break; 44277c478bd9Sstevel@tonic-gate case 6: word_len = UART_6BITS_WORD; break; 44287c478bd9Sstevel@tonic-gate case 7: word_len = UART_7BITS_WORD; break; 44297c478bd9Sstevel@tonic-gate case 8: word_len = UART_8BITS_WORD; break; 44307c478bd9Sstevel@tonic-gate default: 44317c478bd9Sstevel@tonic-gate errnum = ERR_BAD_ARGUMENT; 44327c478bd9Sstevel@tonic-gate return 1; 44337c478bd9Sstevel@tonic-gate } 44347c478bd9Sstevel@tonic-gate } 44357c478bd9Sstevel@tonic-gate else if (grub_memcmp (arg, "--stop=", sizeof ("--stop=") - 1) == 0) 44367c478bd9Sstevel@tonic-gate { 44377c478bd9Sstevel@tonic-gate char *p = arg + sizeof ("--stop=") - 1; 44387c478bd9Sstevel@tonic-gate int len; 44397c478bd9Sstevel@tonic-gate 44407c478bd9Sstevel@tonic-gate if (! safe_parse_maxint (&p, &len)) 44417c478bd9Sstevel@tonic-gate return 1; 44427c478bd9Sstevel@tonic-gate 44437c478bd9Sstevel@tonic-gate switch (len) 44447c478bd9Sstevel@tonic-gate { 44457c478bd9Sstevel@tonic-gate case 1: stop_bit_len = UART_1_STOP_BIT; break; 44467c478bd9Sstevel@tonic-gate case 2: stop_bit_len = UART_2_STOP_BITS; break; 44477c478bd9Sstevel@tonic-gate default: 44487c478bd9Sstevel@tonic-gate errnum = ERR_BAD_ARGUMENT; 44497c478bd9Sstevel@tonic-gate return 1; 44507c478bd9Sstevel@tonic-gate } 44517c478bd9Sstevel@tonic-gate } 44527c478bd9Sstevel@tonic-gate else if (grub_memcmp (arg, "--parity=", sizeof ("--parity=") - 1) == 0) 44537c478bd9Sstevel@tonic-gate { 44547c478bd9Sstevel@tonic-gate char *p = arg + sizeof ("--parity=") - 1; 44557c478bd9Sstevel@tonic-gate 44567c478bd9Sstevel@tonic-gate if (grub_memcmp (p, "no", sizeof ("no") - 1) == 0) 44577c478bd9Sstevel@tonic-gate parity = UART_NO_PARITY; 44587c478bd9Sstevel@tonic-gate else if (grub_memcmp (p, "odd", sizeof ("odd") - 1) == 0) 44597c478bd9Sstevel@tonic-gate parity = UART_ODD_PARITY; 44607c478bd9Sstevel@tonic-gate else if (grub_memcmp (p, "even", sizeof ("even") - 1) == 0) 44617c478bd9Sstevel@tonic-gate parity = UART_EVEN_PARITY; 44627c478bd9Sstevel@tonic-gate else 44637c478bd9Sstevel@tonic-gate { 44647c478bd9Sstevel@tonic-gate errnum = ERR_BAD_ARGUMENT; 44657c478bd9Sstevel@tonic-gate return 1; 44667c478bd9Sstevel@tonic-gate } 44677c478bd9Sstevel@tonic-gate } 44687c478bd9Sstevel@tonic-gate # ifdef GRUB_UTIL 44697c478bd9Sstevel@tonic-gate /* In the grub shell, don't use any port number but open a tty 44707c478bd9Sstevel@tonic-gate device instead. */ 44717c478bd9Sstevel@tonic-gate else if (grub_memcmp (arg, "--device=", sizeof ("--device=") - 1) == 0) 44727c478bd9Sstevel@tonic-gate { 44737c478bd9Sstevel@tonic-gate char *p = arg + sizeof ("--device=") - 1; 44747c478bd9Sstevel@tonic-gate char dev[256]; /* XXX */ 44757c478bd9Sstevel@tonic-gate char *q = dev; 44767c478bd9Sstevel@tonic-gate 44777c478bd9Sstevel@tonic-gate while (*p && ! grub_isspace (*p)) 44787c478bd9Sstevel@tonic-gate *q++ = *p++; 44797c478bd9Sstevel@tonic-gate 44807c478bd9Sstevel@tonic-gate *q = 0; 44817c478bd9Sstevel@tonic-gate serial_set_device (dev); 44827c478bd9Sstevel@tonic-gate } 44837c478bd9Sstevel@tonic-gate # endif /* GRUB_UTIL */ 44847c478bd9Sstevel@tonic-gate else 44857c478bd9Sstevel@tonic-gate break; 44867c478bd9Sstevel@tonic-gate 44877c478bd9Sstevel@tonic-gate arg = skip_to (0, arg); 44887c478bd9Sstevel@tonic-gate } 44897c478bd9Sstevel@tonic-gate 44907c478bd9Sstevel@tonic-gate /* Initialize the serial unit. */ 44917c478bd9Sstevel@tonic-gate if (! serial_hw_init (port, speed, word_len, parity, stop_bit_len)) 44927c478bd9Sstevel@tonic-gate { 44937c478bd9Sstevel@tonic-gate errnum = ERR_BAD_ARGUMENT; 44947c478bd9Sstevel@tonic-gate return 1; 44957c478bd9Sstevel@tonic-gate } 44967c478bd9Sstevel@tonic-gate 44977c478bd9Sstevel@tonic-gate return 0; 44987c478bd9Sstevel@tonic-gate } 44997c478bd9Sstevel@tonic-gate 45007c478bd9Sstevel@tonic-gate static struct builtin builtin_serial = 45017c478bd9Sstevel@tonic-gate { 45027c478bd9Sstevel@tonic-gate "serial", 45037c478bd9Sstevel@tonic-gate serial_func, 45047c478bd9Sstevel@tonic-gate BUILTIN_MENU | BUILTIN_CMDLINE | BUILTIN_HELP_LIST, 45057c478bd9Sstevel@tonic-gate "serial [--unit=UNIT] [--port=PORT] [--speed=SPEED] [--word=WORD] [--parity=PARITY] [--stop=STOP] [--device=DEV]", 45067c478bd9Sstevel@tonic-gate "Initialize a serial device. UNIT is a digit that specifies which serial" 45077c478bd9Sstevel@tonic-gate " device is used (e.g. 0 == COM1). If you need to specify the port number," 45087c478bd9Sstevel@tonic-gate " set it by --port. SPEED is the DTE-DTE speed. WORD is the word length," 45097c478bd9Sstevel@tonic-gate " PARITY is the type of parity, which is one of `no', `odd' and `even'." 45107c478bd9Sstevel@tonic-gate " STOP is the length of stop bit(s). The option --device can be used only" 45117c478bd9Sstevel@tonic-gate " in the grub shell, which specifies the file name of a tty device. The" 45127c478bd9Sstevel@tonic-gate " default values are COM1, 9600, 8N1." 45137c478bd9Sstevel@tonic-gate }; 45147c478bd9Sstevel@tonic-gate #endif /* SUPPORT_SERIAL */ 45157c478bd9Sstevel@tonic-gate 45167c478bd9Sstevel@tonic-gate 45177c478bd9Sstevel@tonic-gate /* setkey */ 45187c478bd9Sstevel@tonic-gate struct keysym 45197c478bd9Sstevel@tonic-gate { 45207c478bd9Sstevel@tonic-gate char *unshifted_name; /* the name in unshifted state */ 45217c478bd9Sstevel@tonic-gate char *shifted_name; /* the name in shifted state */ 45227c478bd9Sstevel@tonic-gate unsigned char unshifted_ascii; /* the ascii code in unshifted state */ 45237c478bd9Sstevel@tonic-gate unsigned char shifted_ascii; /* the ascii code in shifted state */ 45247c478bd9Sstevel@tonic-gate unsigned char keycode; /* keyboard scancode */ 45257c478bd9Sstevel@tonic-gate }; 45267c478bd9Sstevel@tonic-gate 45277c478bd9Sstevel@tonic-gate /* The table for key symbols. If the "shifted" member of an entry is 45287c478bd9Sstevel@tonic-gate NULL, the entry does not have shifted state. */ 45297c478bd9Sstevel@tonic-gate static struct keysym keysym_table[] = 45307c478bd9Sstevel@tonic-gate { 45317c478bd9Sstevel@tonic-gate {"escape", 0, 0x1b, 0, 0x01}, 45327c478bd9Sstevel@tonic-gate {"1", "exclam", '1', '!', 0x02}, 45337c478bd9Sstevel@tonic-gate {"2", "at", '2', '@', 0x03}, 45347c478bd9Sstevel@tonic-gate {"3", "numbersign", '3', '#', 0x04}, 45357c478bd9Sstevel@tonic-gate {"4", "dollar", '4', '$', 0x05}, 45367c478bd9Sstevel@tonic-gate {"5", "percent", '5', '%', 0x06}, 45377c478bd9Sstevel@tonic-gate {"6", "caret", '6', '^', 0x07}, 45387c478bd9Sstevel@tonic-gate {"7", "ampersand", '7', '&', 0x08}, 45397c478bd9Sstevel@tonic-gate {"8", "asterisk", '8', '*', 0x09}, 45407c478bd9Sstevel@tonic-gate {"9", "parenleft", '9', '(', 0x0a}, 45417c478bd9Sstevel@tonic-gate {"0", "parenright", '0', ')', 0x0b}, 45427c478bd9Sstevel@tonic-gate {"minus", "underscore", '-', '_', 0x0c}, 45437c478bd9Sstevel@tonic-gate {"equal", "plus", '=', '+', 0x0d}, 45447c478bd9Sstevel@tonic-gate {"backspace", 0, '\b', 0, 0x0e}, 45457c478bd9Sstevel@tonic-gate {"tab", 0, '\t', 0, 0x0f}, 45467c478bd9Sstevel@tonic-gate {"q", "Q", 'q', 'Q', 0x10}, 45477c478bd9Sstevel@tonic-gate {"w", "W", 'w', 'W', 0x11}, 45487c478bd9Sstevel@tonic-gate {"e", "E", 'e', 'E', 0x12}, 45497c478bd9Sstevel@tonic-gate {"r", "R", 'r', 'R', 0x13}, 45507c478bd9Sstevel@tonic-gate {"t", "T", 't', 'T', 0x14}, 45517c478bd9Sstevel@tonic-gate {"y", "Y", 'y', 'Y', 0x15}, 45527c478bd9Sstevel@tonic-gate {"u", "U", 'u', 'U', 0x16}, 45537c478bd9Sstevel@tonic-gate {"i", "I", 'i', 'I', 0x17}, 45547c478bd9Sstevel@tonic-gate {"o", "O", 'o', 'O', 0x18}, 45557c478bd9Sstevel@tonic-gate {"p", "P", 'p', 'P', 0x19}, 45567c478bd9Sstevel@tonic-gate {"bracketleft", "braceleft", '[', '{', 0x1a}, 45577c478bd9Sstevel@tonic-gate {"bracketright", "braceright", ']', '}', 0x1b}, 45587c478bd9Sstevel@tonic-gate {"enter", 0, '\n', 0, 0x1c}, 45597c478bd9Sstevel@tonic-gate {"control", 0, 0, 0, 0x1d}, 45607c478bd9Sstevel@tonic-gate {"a", "A", 'a', 'A', 0x1e}, 45617c478bd9Sstevel@tonic-gate {"s", "S", 's', 'S', 0x1f}, 45627c478bd9Sstevel@tonic-gate {"d", "D", 'd', 'D', 0x20}, 45637c478bd9Sstevel@tonic-gate {"f", "F", 'f', 'F', 0x21}, 45647c478bd9Sstevel@tonic-gate {"g", "G", 'g', 'G', 0x22}, 45657c478bd9Sstevel@tonic-gate {"h", "H", 'h', 'H', 0x23}, 45667c478bd9Sstevel@tonic-gate {"j", "J", 'j', 'J', 0x24}, 45677c478bd9Sstevel@tonic-gate {"k", "K", 'k', 'K', 0x25}, 45687c478bd9Sstevel@tonic-gate {"l", "L", 'l', 'L', 0x26}, 45697c478bd9Sstevel@tonic-gate {"semicolon", "colon", ';', ':', 0x27}, 45707c478bd9Sstevel@tonic-gate {"quote", "doublequote", '\'', '"', 0x28}, 45717c478bd9Sstevel@tonic-gate {"backquote", "tilde", '`', '~', 0x29}, 45727c478bd9Sstevel@tonic-gate {"shift", 0, 0, 0, 0x2a}, 45737c478bd9Sstevel@tonic-gate {"backslash", "bar", '\\', '|', 0x2b}, 45747c478bd9Sstevel@tonic-gate {"z", "Z", 'z', 'Z', 0x2c}, 45757c478bd9Sstevel@tonic-gate {"x", "X", 'x', 'X', 0x2d}, 45767c478bd9Sstevel@tonic-gate {"c", "C", 'c', 'C', 0x2e}, 45777c478bd9Sstevel@tonic-gate {"v", "V", 'v', 'V', 0x2f}, 45787c478bd9Sstevel@tonic-gate {"b", "B", 'b', 'B', 0x30}, 45797c478bd9Sstevel@tonic-gate {"n", "N", 'n', 'N', 0x31}, 45807c478bd9Sstevel@tonic-gate {"m", "M", 'm', 'M', 0x32}, 45817c478bd9Sstevel@tonic-gate {"comma", "less", ',', '<', 0x33}, 45827c478bd9Sstevel@tonic-gate {"period", "greater", '.', '>', 0x34}, 45837c478bd9Sstevel@tonic-gate {"slash", "question", '/', '?', 0x35}, 45847c478bd9Sstevel@tonic-gate {"alt", 0, 0, 0, 0x38}, 45857c478bd9Sstevel@tonic-gate {"space", 0, ' ', 0, 0x39}, 45867c478bd9Sstevel@tonic-gate {"capslock", 0, 0, 0, 0x3a}, 45877c478bd9Sstevel@tonic-gate {"F1", 0, 0, 0, 0x3b}, 45887c478bd9Sstevel@tonic-gate {"F2", 0, 0, 0, 0x3c}, 45897c478bd9Sstevel@tonic-gate {"F3", 0, 0, 0, 0x3d}, 45907c478bd9Sstevel@tonic-gate {"F4", 0, 0, 0, 0x3e}, 45917c478bd9Sstevel@tonic-gate {"F5", 0, 0, 0, 0x3f}, 45927c478bd9Sstevel@tonic-gate {"F6", 0, 0, 0, 0x40}, 45937c478bd9Sstevel@tonic-gate {"F7", 0, 0, 0, 0x41}, 45947c478bd9Sstevel@tonic-gate {"F8", 0, 0, 0, 0x42}, 45957c478bd9Sstevel@tonic-gate {"F9", 0, 0, 0, 0x43}, 45967c478bd9Sstevel@tonic-gate {"F10", 0, 0, 0, 0x44}, 45977c478bd9Sstevel@tonic-gate /* Caution: do not add NumLock here! we cannot deal with it properly. */ 45987c478bd9Sstevel@tonic-gate {"delete", 0, 0x7f, 0, 0x53} 45997c478bd9Sstevel@tonic-gate }; 46007c478bd9Sstevel@tonic-gate 46017c478bd9Sstevel@tonic-gate static int 46027c478bd9Sstevel@tonic-gate setkey_func (char *arg, int flags) 46037c478bd9Sstevel@tonic-gate { 46047c478bd9Sstevel@tonic-gate char *to_key, *from_key; 46057c478bd9Sstevel@tonic-gate int to_code, from_code; 46067c478bd9Sstevel@tonic-gate int map_in_interrupt = 0; 46077c478bd9Sstevel@tonic-gate 46081b8adde7SWilliam Kucharski auto int find_key_code (char *key); 46091b8adde7SWilliam Kucharski auto int find_ascii_code (char *key); 46101b8adde7SWilliam Kucharski 46111b8adde7SWilliam Kucharski auto int find_key_code (char *key) 46127c478bd9Sstevel@tonic-gate { 46137c478bd9Sstevel@tonic-gate int i; 46147c478bd9Sstevel@tonic-gate 46157c478bd9Sstevel@tonic-gate for (i = 0; i < sizeof (keysym_table) / sizeof (keysym_table[0]); i++) 46167c478bd9Sstevel@tonic-gate { 46177c478bd9Sstevel@tonic-gate if (keysym_table[i].unshifted_name && 46187c478bd9Sstevel@tonic-gate grub_strcmp (key, keysym_table[i].unshifted_name) == 0) 46197c478bd9Sstevel@tonic-gate return keysym_table[i].keycode; 46207c478bd9Sstevel@tonic-gate else if (keysym_table[i].shifted_name && 46217c478bd9Sstevel@tonic-gate grub_strcmp (key, keysym_table[i].shifted_name) == 0) 46227c478bd9Sstevel@tonic-gate return keysym_table[i].keycode; 46237c478bd9Sstevel@tonic-gate } 46247c478bd9Sstevel@tonic-gate 46257c478bd9Sstevel@tonic-gate return 0; 46267c478bd9Sstevel@tonic-gate } 46277c478bd9Sstevel@tonic-gate 46281b8adde7SWilliam Kucharski auto int find_ascii_code (char *key) 46297c478bd9Sstevel@tonic-gate { 46307c478bd9Sstevel@tonic-gate int i; 46317c478bd9Sstevel@tonic-gate 46327c478bd9Sstevel@tonic-gate for (i = 0; i < sizeof (keysym_table) / sizeof (keysym_table[0]); i++) 46337c478bd9Sstevel@tonic-gate { 46347c478bd9Sstevel@tonic-gate if (keysym_table[i].unshifted_name && 46357c478bd9Sstevel@tonic-gate grub_strcmp (key, keysym_table[i].unshifted_name) == 0) 46367c478bd9Sstevel@tonic-gate return keysym_table[i].unshifted_ascii; 46377c478bd9Sstevel@tonic-gate else if (keysym_table[i].shifted_name && 46387c478bd9Sstevel@tonic-gate grub_strcmp (key, keysym_table[i].shifted_name) == 0) 46397c478bd9Sstevel@tonic-gate return keysym_table[i].shifted_ascii; 46407c478bd9Sstevel@tonic-gate } 46417c478bd9Sstevel@tonic-gate 46427c478bd9Sstevel@tonic-gate return 0; 46437c478bd9Sstevel@tonic-gate } 46447c478bd9Sstevel@tonic-gate 46457c478bd9Sstevel@tonic-gate to_key = arg; 46467c478bd9Sstevel@tonic-gate from_key = skip_to (0, to_key); 46477c478bd9Sstevel@tonic-gate 46487c478bd9Sstevel@tonic-gate if (! *to_key) 46497c478bd9Sstevel@tonic-gate { 46507c478bd9Sstevel@tonic-gate /* If the user specifies no argument, reset the key mappings. */ 46517c478bd9Sstevel@tonic-gate grub_memset (bios_key_map, 0, KEY_MAP_SIZE * sizeof (unsigned short)); 46527c478bd9Sstevel@tonic-gate grub_memset (ascii_key_map, 0, KEY_MAP_SIZE * sizeof (unsigned short)); 46537c478bd9Sstevel@tonic-gate 46547c478bd9Sstevel@tonic-gate return 0; 46557c478bd9Sstevel@tonic-gate } 46567c478bd9Sstevel@tonic-gate else if (! *from_key) 46577c478bd9Sstevel@tonic-gate { 46587c478bd9Sstevel@tonic-gate /* The user must specify two arguments or zero argument. */ 46597c478bd9Sstevel@tonic-gate errnum = ERR_BAD_ARGUMENT; 46607c478bd9Sstevel@tonic-gate return 1; 46617c478bd9Sstevel@tonic-gate } 46627c478bd9Sstevel@tonic-gate 46637c478bd9Sstevel@tonic-gate nul_terminate (to_key); 46647c478bd9Sstevel@tonic-gate nul_terminate (from_key); 46657c478bd9Sstevel@tonic-gate 46667c478bd9Sstevel@tonic-gate to_code = find_ascii_code (to_key); 46677c478bd9Sstevel@tonic-gate from_code = find_ascii_code (from_key); 46687c478bd9Sstevel@tonic-gate if (! to_code || ! from_code) 46697c478bd9Sstevel@tonic-gate { 46707c478bd9Sstevel@tonic-gate map_in_interrupt = 1; 46717c478bd9Sstevel@tonic-gate to_code = find_key_code (to_key); 46727c478bd9Sstevel@tonic-gate from_code = find_key_code (from_key); 46737c478bd9Sstevel@tonic-gate if (! to_code || ! from_code) 46747c478bd9Sstevel@tonic-gate { 46757c478bd9Sstevel@tonic-gate errnum = ERR_BAD_ARGUMENT; 46767c478bd9Sstevel@tonic-gate return 1; 46777c478bd9Sstevel@tonic-gate } 46787c478bd9Sstevel@tonic-gate } 46797c478bd9Sstevel@tonic-gate 46807c478bd9Sstevel@tonic-gate if (map_in_interrupt) 46817c478bd9Sstevel@tonic-gate { 46827c478bd9Sstevel@tonic-gate int i; 46837c478bd9Sstevel@tonic-gate 46847c478bd9Sstevel@tonic-gate /* Find an empty slot. */ 46857c478bd9Sstevel@tonic-gate for (i = 0; i < KEY_MAP_SIZE; i++) 46867c478bd9Sstevel@tonic-gate { 46877c478bd9Sstevel@tonic-gate if ((bios_key_map[i] & 0xff) == from_code) 46887c478bd9Sstevel@tonic-gate /* Perhaps the user wants to overwrite the map. */ 46897c478bd9Sstevel@tonic-gate break; 46907c478bd9Sstevel@tonic-gate 46917c478bd9Sstevel@tonic-gate if (! bios_key_map[i]) 46927c478bd9Sstevel@tonic-gate break; 46937c478bd9Sstevel@tonic-gate } 46947c478bd9Sstevel@tonic-gate 46957c478bd9Sstevel@tonic-gate if (i == KEY_MAP_SIZE) 46967c478bd9Sstevel@tonic-gate { 46977c478bd9Sstevel@tonic-gate errnum = ERR_WONT_FIT; 46987c478bd9Sstevel@tonic-gate return 1; 46997c478bd9Sstevel@tonic-gate } 47007c478bd9Sstevel@tonic-gate 47017c478bd9Sstevel@tonic-gate if (to_code == from_code) 47027c478bd9Sstevel@tonic-gate /* If TO is equal to FROM, delete the entry. */ 47037c478bd9Sstevel@tonic-gate grub_memmove ((char *) &bios_key_map[i], 47047c478bd9Sstevel@tonic-gate (char *) &bios_key_map[i + 1], 47057c478bd9Sstevel@tonic-gate sizeof (unsigned short) * (KEY_MAP_SIZE - i)); 47067c478bd9Sstevel@tonic-gate else 47077c478bd9Sstevel@tonic-gate bios_key_map[i] = (to_code << 8) | from_code; 47087c478bd9Sstevel@tonic-gate 47097c478bd9Sstevel@tonic-gate /* Ugly but should work. */ 47107c478bd9Sstevel@tonic-gate unset_int15_handler (); 47117c478bd9Sstevel@tonic-gate set_int15_handler (); 47127c478bd9Sstevel@tonic-gate } 47137c478bd9Sstevel@tonic-gate else 47147c478bd9Sstevel@tonic-gate { 47157c478bd9Sstevel@tonic-gate int i; 47167c478bd9Sstevel@tonic-gate 47177c478bd9Sstevel@tonic-gate /* Find an empty slot. */ 47187c478bd9Sstevel@tonic-gate for (i = 0; i < KEY_MAP_SIZE; i++) 47197c478bd9Sstevel@tonic-gate { 47207c478bd9Sstevel@tonic-gate if ((ascii_key_map[i] & 0xff) == from_code) 47217c478bd9Sstevel@tonic-gate /* Perhaps the user wants to overwrite the map. */ 47227c478bd9Sstevel@tonic-gate break; 47237c478bd9Sstevel@tonic-gate 47247c478bd9Sstevel@tonic-gate if (! ascii_key_map[i]) 47257c478bd9Sstevel@tonic-gate break; 47267c478bd9Sstevel@tonic-gate } 47277c478bd9Sstevel@tonic-gate 47287c478bd9Sstevel@tonic-gate if (i == KEY_MAP_SIZE) 47297c478bd9Sstevel@tonic-gate { 47307c478bd9Sstevel@tonic-gate errnum = ERR_WONT_FIT; 47317c478bd9Sstevel@tonic-gate return 1; 47327c478bd9Sstevel@tonic-gate } 47337c478bd9Sstevel@tonic-gate 47347c478bd9Sstevel@tonic-gate if (to_code == from_code) 47357c478bd9Sstevel@tonic-gate /* If TO is equal to FROM, delete the entry. */ 47367c478bd9Sstevel@tonic-gate grub_memmove ((char *) &ascii_key_map[i], 47377c478bd9Sstevel@tonic-gate (char *) &ascii_key_map[i + 1], 47387c478bd9Sstevel@tonic-gate sizeof (unsigned short) * (KEY_MAP_SIZE - i)); 47397c478bd9Sstevel@tonic-gate else 47407c478bd9Sstevel@tonic-gate ascii_key_map[i] = (to_code << 8) | from_code; 47417c478bd9Sstevel@tonic-gate } 47427c478bd9Sstevel@tonic-gate 47437c478bd9Sstevel@tonic-gate return 0; 47447c478bd9Sstevel@tonic-gate } 47457c478bd9Sstevel@tonic-gate 47467c478bd9Sstevel@tonic-gate static struct builtin builtin_setkey = 47477c478bd9Sstevel@tonic-gate { 47487c478bd9Sstevel@tonic-gate "setkey", 47497c478bd9Sstevel@tonic-gate setkey_func, 47507c478bd9Sstevel@tonic-gate BUILTIN_CMDLINE | BUILTIN_MENU | BUILTIN_HELP_LIST, 47517c478bd9Sstevel@tonic-gate "setkey [TO_KEY FROM_KEY]", 47527c478bd9Sstevel@tonic-gate "Change the keyboard map. The key FROM_KEY is mapped to the key TO_KEY." 47537c478bd9Sstevel@tonic-gate " A key must be an alphabet, a digit, or one of these: escape, exclam," 47547c478bd9Sstevel@tonic-gate " at, numbersign, dollar, percent, caret, ampersand, asterisk, parenleft," 47557c478bd9Sstevel@tonic-gate " parenright, minus, underscore, equal, plus, backspace, tab, bracketleft," 47567c478bd9Sstevel@tonic-gate " braceleft, bracketright, braceright, enter, control, semicolon, colon," 47577c478bd9Sstevel@tonic-gate " quote, doublequote, backquote, tilde, shift, backslash, bar, comma," 47587c478bd9Sstevel@tonic-gate " less, period, greater, slash, question, alt, space, capslock, FX (X" 47597c478bd9Sstevel@tonic-gate " is a digit), and delete. If no argument is specified, reset key" 47607c478bd9Sstevel@tonic-gate " mappings." 47617c478bd9Sstevel@tonic-gate }; 47627c478bd9Sstevel@tonic-gate 47637c478bd9Sstevel@tonic-gate 47647c478bd9Sstevel@tonic-gate /* setup */ 47657c478bd9Sstevel@tonic-gate static int 47667c478bd9Sstevel@tonic-gate setup_func (char *arg, int flags) 47677c478bd9Sstevel@tonic-gate { 47687c478bd9Sstevel@tonic-gate /* Point to the string of the installed drive/partition. */ 47697c478bd9Sstevel@tonic-gate char *install_ptr; 47707c478bd9Sstevel@tonic-gate /* Point to the string of the drive/parition where the GRUB images 47717c478bd9Sstevel@tonic-gate reside. */ 47727c478bd9Sstevel@tonic-gate char *image_ptr; 47737c478bd9Sstevel@tonic-gate unsigned long installed_drive, installed_partition; 47747c478bd9Sstevel@tonic-gate unsigned long image_drive, image_partition; 47757c478bd9Sstevel@tonic-gate unsigned long tmp_drive, tmp_partition; 47767c478bd9Sstevel@tonic-gate char stage1[64]; 47777c478bd9Sstevel@tonic-gate char stage2[64]; 47787c478bd9Sstevel@tonic-gate char config_filename[64]; 47797c478bd9Sstevel@tonic-gate char real_config_filename[64]; 47807c478bd9Sstevel@tonic-gate char cmd_arg[256]; 47817c478bd9Sstevel@tonic-gate char device[16]; 47827c478bd9Sstevel@tonic-gate char *buffer = (char *) RAW_ADDR (0x100000); 47837c478bd9Sstevel@tonic-gate int is_force_lba = 0; 47847c478bd9Sstevel@tonic-gate char *stage2_arg = 0; 47857c478bd9Sstevel@tonic-gate char *prefix = 0; 47867c478bd9Sstevel@tonic-gate 47877c478bd9Sstevel@tonic-gate auto int check_file (char *file); 47887c478bd9Sstevel@tonic-gate auto void sprint_device (int drive, int partition); 47897c478bd9Sstevel@tonic-gate auto int embed_stage1_5 (char * stage1_5, int drive, int partition); 47907c478bd9Sstevel@tonic-gate 47917c478bd9Sstevel@tonic-gate /* Check if the file FILE exists like Autoconf. */ 47927c478bd9Sstevel@tonic-gate int check_file (char *file) 47937c478bd9Sstevel@tonic-gate { 47947c478bd9Sstevel@tonic-gate int ret; 47957c478bd9Sstevel@tonic-gate 47967c478bd9Sstevel@tonic-gate grub_printf (" Checking if \"%s\" exists... ", file); 47977c478bd9Sstevel@tonic-gate ret = grub_open (file); 47987c478bd9Sstevel@tonic-gate if (ret) 47997c478bd9Sstevel@tonic-gate { 48007c478bd9Sstevel@tonic-gate grub_close (); 48017c478bd9Sstevel@tonic-gate grub_printf ("yes\n"); 48027c478bd9Sstevel@tonic-gate } 48037c478bd9Sstevel@tonic-gate else 48047c478bd9Sstevel@tonic-gate grub_printf ("no\n"); 48057c478bd9Sstevel@tonic-gate 48067c478bd9Sstevel@tonic-gate return ret; 48077c478bd9Sstevel@tonic-gate } 48087c478bd9Sstevel@tonic-gate 48097c478bd9Sstevel@tonic-gate /* Construct a device name in DEVICE. */ 48107c478bd9Sstevel@tonic-gate void sprint_device (int drive, int partition) 48117c478bd9Sstevel@tonic-gate { 48127c478bd9Sstevel@tonic-gate grub_sprintf (device, "(%cd%d", 48137c478bd9Sstevel@tonic-gate (drive & 0x80) ? 'h' : 'f', 48147c478bd9Sstevel@tonic-gate drive & ~0x80); 48157c478bd9Sstevel@tonic-gate if ((partition & 0xFF0000) != 0xFF0000) 48167c478bd9Sstevel@tonic-gate { 48177c478bd9Sstevel@tonic-gate char tmp[16]; 48187c478bd9Sstevel@tonic-gate grub_sprintf (tmp, ",%d", (partition >> 16) & 0xFF); 48197c478bd9Sstevel@tonic-gate grub_strncat (device, tmp, 256); 48207c478bd9Sstevel@tonic-gate } 48217c478bd9Sstevel@tonic-gate if ((partition & 0x00FF00) != 0x00FF00) 48227c478bd9Sstevel@tonic-gate { 48237c478bd9Sstevel@tonic-gate char tmp[16]; 48247c478bd9Sstevel@tonic-gate grub_sprintf (tmp, ",%c", 'a' + ((partition >> 8) & 0xFF)); 48257c478bd9Sstevel@tonic-gate grub_strncat (device, tmp, 256); 48267c478bd9Sstevel@tonic-gate } 48277c478bd9Sstevel@tonic-gate grub_strncat (device, ")", 256); 48287c478bd9Sstevel@tonic-gate } 48297c478bd9Sstevel@tonic-gate 48307c478bd9Sstevel@tonic-gate int embed_stage1_5 (char *stage1_5, int drive, int partition) 48317c478bd9Sstevel@tonic-gate { 48327c478bd9Sstevel@tonic-gate /* We install GRUB into the MBR, so try to embed the 48337c478bd9Sstevel@tonic-gate Stage 1.5 in the sectors right after the MBR. */ 48347c478bd9Sstevel@tonic-gate sprint_device (drive, partition); 48357c478bd9Sstevel@tonic-gate grub_sprintf (cmd_arg, "%s %s", stage1_5, device); 48367c478bd9Sstevel@tonic-gate 48377c478bd9Sstevel@tonic-gate /* Notify what will be run. */ 48387c478bd9Sstevel@tonic-gate grub_printf (" Running \"embed %s\"... ", cmd_arg); 48397c478bd9Sstevel@tonic-gate 48407c478bd9Sstevel@tonic-gate embed_func (cmd_arg, flags); 48417c478bd9Sstevel@tonic-gate if (! errnum) 48427c478bd9Sstevel@tonic-gate { 48437c478bd9Sstevel@tonic-gate /* Construct the blocklist representation. */ 48447c478bd9Sstevel@tonic-gate grub_sprintf (buffer, "%s%s", device, embed_info); 48457c478bd9Sstevel@tonic-gate grub_printf ("succeeded\n"); 48467c478bd9Sstevel@tonic-gate return 1; 48477c478bd9Sstevel@tonic-gate } 48487c478bd9Sstevel@tonic-gate else 48497c478bd9Sstevel@tonic-gate { 48507c478bd9Sstevel@tonic-gate grub_printf ("failed (this is not fatal)\n"); 48517c478bd9Sstevel@tonic-gate return 0; 48527c478bd9Sstevel@tonic-gate } 48537c478bd9Sstevel@tonic-gate } 48547c478bd9Sstevel@tonic-gate 48557c478bd9Sstevel@tonic-gate struct stage1_5_map { 48567c478bd9Sstevel@tonic-gate char *fsys; 48577c478bd9Sstevel@tonic-gate char *name; 48587c478bd9Sstevel@tonic-gate }; 48597c478bd9Sstevel@tonic-gate struct stage1_5_map stage1_5_map[] = 48607c478bd9Sstevel@tonic-gate { 48617c478bd9Sstevel@tonic-gate {"ext2fs", "/e2fs_stage1_5"}, 48627c478bd9Sstevel@tonic-gate {"fat", "/fat_stage1_5"}, 48637c478bd9Sstevel@tonic-gate {"ufs2", "/ufs2_stage1_5"}, 48647c478bd9Sstevel@tonic-gate {"ffs", "/ffs_stage1_5"}, 48657c478bd9Sstevel@tonic-gate {"iso9660", "/iso9660_stage1_5"}, 48667c478bd9Sstevel@tonic-gate {"jfs", "/jfs_stage1_5"}, 48677c478bd9Sstevel@tonic-gate {"minix", "/minix_stage1_5"}, 48687c478bd9Sstevel@tonic-gate {"reiserfs", "/reiserfs_stage1_5"}, 48697c478bd9Sstevel@tonic-gate {"vstafs", "/vstafs_stage1_5"}, 48707c478bd9Sstevel@tonic-gate {"xfs", "/xfs_stage1_5"}, 48717c478bd9Sstevel@tonic-gate {"ufs", "/ufs_stage1_5"} 48727c478bd9Sstevel@tonic-gate }; 48737c478bd9Sstevel@tonic-gate 48747c478bd9Sstevel@tonic-gate tmp_drive = saved_drive; 48757c478bd9Sstevel@tonic-gate tmp_partition = saved_partition; 48767c478bd9Sstevel@tonic-gate 48777c478bd9Sstevel@tonic-gate /* Check if the user specifies --force-lba. */ 48787c478bd9Sstevel@tonic-gate while (1) 48797c478bd9Sstevel@tonic-gate { 48807c478bd9Sstevel@tonic-gate if (grub_memcmp ("--force-lba", arg, sizeof ("--force-lba") - 1) == 0) 48817c478bd9Sstevel@tonic-gate { 48827c478bd9Sstevel@tonic-gate is_force_lba = 1; 48837c478bd9Sstevel@tonic-gate arg = skip_to (0, arg); 48847c478bd9Sstevel@tonic-gate } 48857c478bd9Sstevel@tonic-gate else if (grub_memcmp ("--prefix=", arg, sizeof ("--prefix=") - 1) == 0) 48867c478bd9Sstevel@tonic-gate { 48877c478bd9Sstevel@tonic-gate prefix = arg + sizeof ("--prefix=") - 1; 48887c478bd9Sstevel@tonic-gate arg = skip_to (0, arg); 48897c478bd9Sstevel@tonic-gate nul_terminate (prefix); 48907c478bd9Sstevel@tonic-gate } 48917c478bd9Sstevel@tonic-gate #ifdef GRUB_UTIL 48927c478bd9Sstevel@tonic-gate else if (grub_memcmp ("--stage2=", arg, sizeof ("--stage2=") - 1) == 0) 48937c478bd9Sstevel@tonic-gate { 48947c478bd9Sstevel@tonic-gate stage2_arg = arg; 48957c478bd9Sstevel@tonic-gate arg = skip_to (0, arg); 48967c478bd9Sstevel@tonic-gate nul_terminate (stage2_arg); 48977c478bd9Sstevel@tonic-gate } 48987c478bd9Sstevel@tonic-gate #endif /* GRUB_UTIL */ 48997c478bd9Sstevel@tonic-gate else 49007c478bd9Sstevel@tonic-gate break; 49017c478bd9Sstevel@tonic-gate } 49027c478bd9Sstevel@tonic-gate 49037c478bd9Sstevel@tonic-gate install_ptr = arg; 49047c478bd9Sstevel@tonic-gate image_ptr = skip_to (0, install_ptr); 49057c478bd9Sstevel@tonic-gate 49067c478bd9Sstevel@tonic-gate /* Make sure that INSTALL_PTR is valid. */ 49077c478bd9Sstevel@tonic-gate set_device (install_ptr); 49087c478bd9Sstevel@tonic-gate if (errnum) 49097c478bd9Sstevel@tonic-gate return 1; 49107c478bd9Sstevel@tonic-gate 49117c478bd9Sstevel@tonic-gate installed_drive = current_drive; 49127c478bd9Sstevel@tonic-gate installed_partition = current_partition; 49137c478bd9Sstevel@tonic-gate 49147c478bd9Sstevel@tonic-gate /* Mount the drive pointed by IMAGE_PTR. */ 49157c478bd9Sstevel@tonic-gate if (*image_ptr) 49167c478bd9Sstevel@tonic-gate { 49177c478bd9Sstevel@tonic-gate /* If the drive/partition where the images reside is specified, 49187c478bd9Sstevel@tonic-gate get the drive and the partition. */ 49197c478bd9Sstevel@tonic-gate set_device (image_ptr); 49207c478bd9Sstevel@tonic-gate if (errnum) 49217c478bd9Sstevel@tonic-gate return 1; 49227c478bd9Sstevel@tonic-gate } 49237c478bd9Sstevel@tonic-gate else 49247c478bd9Sstevel@tonic-gate { 49257c478bd9Sstevel@tonic-gate /* If omitted, use SAVED_PARTITION and SAVED_DRIVE. */ 49267c478bd9Sstevel@tonic-gate current_drive = saved_drive; 49277c478bd9Sstevel@tonic-gate current_partition = saved_partition; 49287c478bd9Sstevel@tonic-gate } 49297c478bd9Sstevel@tonic-gate 49307c478bd9Sstevel@tonic-gate image_drive = saved_drive = current_drive; 49317c478bd9Sstevel@tonic-gate image_partition = saved_partition = current_partition; 49327c478bd9Sstevel@tonic-gate 49337c478bd9Sstevel@tonic-gate /* Open it. */ 49347c478bd9Sstevel@tonic-gate if (! open_device ()) 49357c478bd9Sstevel@tonic-gate goto fail; 49367c478bd9Sstevel@tonic-gate 49377c478bd9Sstevel@tonic-gate /* Check if stage1 exists. If the user doesn't specify the option 49387c478bd9Sstevel@tonic-gate `--prefix', attempt /boot/grub and /grub. */ 49397c478bd9Sstevel@tonic-gate /* NOTE: It is dangerous to run this command without `--prefix' in the 49407c478bd9Sstevel@tonic-gate grub shell, since that affects `--stage2'. */ 49417c478bd9Sstevel@tonic-gate if (! prefix) 49427c478bd9Sstevel@tonic-gate { 49437c478bd9Sstevel@tonic-gate prefix = "/boot/grub"; 49447c478bd9Sstevel@tonic-gate grub_sprintf (stage1, "%s%s", prefix, "/stage1"); 49457c478bd9Sstevel@tonic-gate if (! check_file (stage1)) 49467c478bd9Sstevel@tonic-gate { 49477c478bd9Sstevel@tonic-gate errnum = ERR_NONE; 49487c478bd9Sstevel@tonic-gate prefix = "/grub"; 49497c478bd9Sstevel@tonic-gate grub_sprintf (stage1, "%s%s", prefix, "/stage1"); 49507c478bd9Sstevel@tonic-gate if (! check_file (stage1)) 49517c478bd9Sstevel@tonic-gate goto fail; 49527c478bd9Sstevel@tonic-gate } 49537c478bd9Sstevel@tonic-gate } 49547c478bd9Sstevel@tonic-gate else 49557c478bd9Sstevel@tonic-gate { 49567c478bd9Sstevel@tonic-gate grub_sprintf (stage1, "%s%s", prefix, "/stage1"); 49577c478bd9Sstevel@tonic-gate if (! check_file (stage1)) 49587c478bd9Sstevel@tonic-gate goto fail; 49597c478bd9Sstevel@tonic-gate } 49607c478bd9Sstevel@tonic-gate 49617c478bd9Sstevel@tonic-gate /* The prefix was determined. */ 49627c478bd9Sstevel@tonic-gate grub_sprintf (stage2, "%s%s", prefix, "/stage2"); 49637c478bd9Sstevel@tonic-gate grub_sprintf (config_filename, "%s%s", prefix, "/menu.lst"); 49647c478bd9Sstevel@tonic-gate *real_config_filename = 0; 49657c478bd9Sstevel@tonic-gate 49667c478bd9Sstevel@tonic-gate /* Check if stage2 exists. */ 49677c478bd9Sstevel@tonic-gate if (! check_file (stage2)) 49687c478bd9Sstevel@tonic-gate goto fail; 49697c478bd9Sstevel@tonic-gate 49707c478bd9Sstevel@tonic-gate { 49717c478bd9Sstevel@tonic-gate char *fsys = fsys_table[fsys_type].name; 49727c478bd9Sstevel@tonic-gate int i; 49737c478bd9Sstevel@tonic-gate int size = sizeof (stage1_5_map) / sizeof (stage1_5_map[0]); 49747c478bd9Sstevel@tonic-gate 49757c478bd9Sstevel@tonic-gate /* Iterate finding the same filesystem name as FSYS. */ 49767c478bd9Sstevel@tonic-gate for (i = 0; i < size; i++) 49777c478bd9Sstevel@tonic-gate if (grub_strcmp (fsys, stage1_5_map[i].fsys) == 0) 49787c478bd9Sstevel@tonic-gate { 49797c478bd9Sstevel@tonic-gate /* OK, check if the Stage 1.5 exists. */ 49807c478bd9Sstevel@tonic-gate char stage1_5[64]; 49817c478bd9Sstevel@tonic-gate 49827c478bd9Sstevel@tonic-gate grub_sprintf (stage1_5, "%s%s", prefix, stage1_5_map[i].name); 49837c478bd9Sstevel@tonic-gate if (check_file (stage1_5)) 49847c478bd9Sstevel@tonic-gate { 49857c478bd9Sstevel@tonic-gate if (embed_stage1_5 (stage1_5, 49867c478bd9Sstevel@tonic-gate installed_drive, installed_partition) 49877c478bd9Sstevel@tonic-gate || embed_stage1_5 (stage1_5, 49887c478bd9Sstevel@tonic-gate image_drive, image_partition)) 49897c478bd9Sstevel@tonic-gate { 49907c478bd9Sstevel@tonic-gate grub_strcpy (real_config_filename, config_filename); 49917c478bd9Sstevel@tonic-gate sprint_device (image_drive, image_partition); 49927c478bd9Sstevel@tonic-gate grub_sprintf (config_filename, "%s%s", device, stage2); 49937c478bd9Sstevel@tonic-gate grub_strcpy (stage2, buffer); 49947c478bd9Sstevel@tonic-gate } 49957c478bd9Sstevel@tonic-gate } 49967c478bd9Sstevel@tonic-gate errnum = 0; 49977c478bd9Sstevel@tonic-gate break; 49987c478bd9Sstevel@tonic-gate } 49997c478bd9Sstevel@tonic-gate } 50007c478bd9Sstevel@tonic-gate 50017c478bd9Sstevel@tonic-gate /* Construct a string that is used by the command "install" as its 50027c478bd9Sstevel@tonic-gate arguments. */ 50037c478bd9Sstevel@tonic-gate sprint_device (installed_drive, installed_partition); 50047c478bd9Sstevel@tonic-gate 50057c478bd9Sstevel@tonic-gate #if 1 50067c478bd9Sstevel@tonic-gate /* Don't embed a drive number unnecessarily. */ 50077c478bd9Sstevel@tonic-gate grub_sprintf (cmd_arg, "%s%s%s%s %s%s %s p %s %s", 50087c478bd9Sstevel@tonic-gate is_force_lba? "--force-lba " : "", 50097c478bd9Sstevel@tonic-gate stage2_arg? stage2_arg : "", 50107c478bd9Sstevel@tonic-gate stage2_arg? " " : "", 50117c478bd9Sstevel@tonic-gate stage1, 50127c478bd9Sstevel@tonic-gate (installed_drive != image_drive) ? "d " : "", 50137c478bd9Sstevel@tonic-gate device, 50147c478bd9Sstevel@tonic-gate stage2, 50157c478bd9Sstevel@tonic-gate config_filename, 50167c478bd9Sstevel@tonic-gate real_config_filename); 50177c478bd9Sstevel@tonic-gate #else /* NOT USED */ 50187c478bd9Sstevel@tonic-gate /* This code was used, because we belived some BIOSes had a problem 50197c478bd9Sstevel@tonic-gate that they didn't pass a booting drive correctly. It turned out, 50207c478bd9Sstevel@tonic-gate however, stage1 could trash a booting drive when checking LBA support, 50217c478bd9Sstevel@tonic-gate because some BIOSes modified the register %dx in INT 13H, AH=48H. 50227c478bd9Sstevel@tonic-gate So it becamed unclear whether GRUB should use a pre-defined booting 50237c478bd9Sstevel@tonic-gate drive or not. If the problem still exists, it would be necessary to 50247c478bd9Sstevel@tonic-gate switch back to this code. */ 50257c478bd9Sstevel@tonic-gate grub_sprintf (cmd_arg, "%s%s%s%s d %s %s p %s %s", 50267c478bd9Sstevel@tonic-gate is_force_lba? "--force-lba " : "", 50277c478bd9Sstevel@tonic-gate stage2_arg? stage2_arg : "", 50287c478bd9Sstevel@tonic-gate stage2_arg? " " : "", 50297c478bd9Sstevel@tonic-gate stage1, 50307c478bd9Sstevel@tonic-gate device, 50317c478bd9Sstevel@tonic-gate stage2, 50327c478bd9Sstevel@tonic-gate config_filename, 50337c478bd9Sstevel@tonic-gate real_config_filename); 50347c478bd9Sstevel@tonic-gate #endif /* NOT USED */ 50357c478bd9Sstevel@tonic-gate 50367c478bd9Sstevel@tonic-gate /* Notify what will be run. */ 50377c478bd9Sstevel@tonic-gate grub_printf (" Running \"install %s\"... ", cmd_arg); 50387c478bd9Sstevel@tonic-gate 50397c478bd9Sstevel@tonic-gate /* Make sure that SAVED_DRIVE and SAVED_PARTITION are identical 50407c478bd9Sstevel@tonic-gate with IMAGE_DRIVE and IMAGE_PARTITION, respectively. */ 50417c478bd9Sstevel@tonic-gate saved_drive = image_drive; 50427c478bd9Sstevel@tonic-gate saved_partition = image_partition; 50437c478bd9Sstevel@tonic-gate 50447c478bd9Sstevel@tonic-gate /* Run the command. */ 50457c478bd9Sstevel@tonic-gate if (! install_func (cmd_arg, flags)) 50467c478bd9Sstevel@tonic-gate grub_printf ("succeeded\nDone.\n"); 50477c478bd9Sstevel@tonic-gate else 50487c478bd9Sstevel@tonic-gate grub_printf ("failed\n"); 50497c478bd9Sstevel@tonic-gate 50507c478bd9Sstevel@tonic-gate fail: 50517c478bd9Sstevel@tonic-gate saved_drive = tmp_drive; 50527c478bd9Sstevel@tonic-gate saved_partition = tmp_partition; 50537c478bd9Sstevel@tonic-gate return errnum; 50547c478bd9Sstevel@tonic-gate } 50557c478bd9Sstevel@tonic-gate 50567c478bd9Sstevel@tonic-gate static struct builtin builtin_setup = 50577c478bd9Sstevel@tonic-gate { 50587c478bd9Sstevel@tonic-gate "setup", 50597c478bd9Sstevel@tonic-gate setup_func, 50607c478bd9Sstevel@tonic-gate BUILTIN_CMDLINE | BUILTIN_HELP_LIST, 50617c478bd9Sstevel@tonic-gate "setup [--prefix=DIR] [--stage2=STAGE2_FILE] [--force-lba] INSTALL_DEVICE [IMAGE_DEVICE]", 50627c478bd9Sstevel@tonic-gate "Set up the installation of GRUB automatically. This command uses" 50637c478bd9Sstevel@tonic-gate " the more flexible command \"install\" in the backend and installs" 50647c478bd9Sstevel@tonic-gate " GRUB into the device INSTALL_DEVICE. If IMAGE_DEVICE is specified," 50657c478bd9Sstevel@tonic-gate " then find the GRUB images in the device IMAGE_DEVICE, otherwise" 50667c478bd9Sstevel@tonic-gate " use the current \"root device\", which can be set by the command" 50677c478bd9Sstevel@tonic-gate " \"root\". If you know that your BIOS should support LBA but GRUB" 50687c478bd9Sstevel@tonic-gate " doesn't work in LBA mode, specify the option `--force-lba'." 50697c478bd9Sstevel@tonic-gate " If you install GRUB under the grub shell and you cannot unmount the" 50707c478bd9Sstevel@tonic-gate " partition where GRUB images reside, specify the option `--stage2'" 50717c478bd9Sstevel@tonic-gate " to tell GRUB the file name under your OS." 50727c478bd9Sstevel@tonic-gate }; 50737c478bd9Sstevel@tonic-gate 50747c478bd9Sstevel@tonic-gate 50757c478bd9Sstevel@tonic-gate #if defined(SUPPORT_SERIAL) || defined(SUPPORT_HERCULES) || defined(SUPPORT_GRAPHICS) 50767c478bd9Sstevel@tonic-gate /* terminal */ 50777c478bd9Sstevel@tonic-gate static int 50787c478bd9Sstevel@tonic-gate terminal_func (char *arg, int flags) 50797c478bd9Sstevel@tonic-gate { 50807c478bd9Sstevel@tonic-gate /* The index of the default terminal in TERM_TABLE. */ 50817c478bd9Sstevel@tonic-gate int default_term = -1; 50827c478bd9Sstevel@tonic-gate struct term_entry *prev_term = current_term; 50837c478bd9Sstevel@tonic-gate int to = -1; 50847c478bd9Sstevel@tonic-gate int lines = 0; 50857c478bd9Sstevel@tonic-gate int no_message = 0; 50867c478bd9Sstevel@tonic-gate unsigned long term_flags = 0; 50877c478bd9Sstevel@tonic-gate /* XXX: Assume less than 32 terminals. */ 50887c478bd9Sstevel@tonic-gate unsigned long term_bitmap = 0; 50897c478bd9Sstevel@tonic-gate 50907c478bd9Sstevel@tonic-gate /* Get GNU-style long options. */ 50917c478bd9Sstevel@tonic-gate while (1) 50927c478bd9Sstevel@tonic-gate { 50937c478bd9Sstevel@tonic-gate if (grub_memcmp (arg, "--dumb", sizeof ("--dumb") - 1) == 0) 50947c478bd9Sstevel@tonic-gate term_flags |= TERM_DUMB; 50957c478bd9Sstevel@tonic-gate else if (grub_memcmp (arg, "--no-echo", sizeof ("--no-echo") - 1) == 0) 50967c478bd9Sstevel@tonic-gate /* ``--no-echo'' implies ``--no-edit''. */ 50977c478bd9Sstevel@tonic-gate term_flags |= (TERM_NO_ECHO | TERM_NO_EDIT); 50987c478bd9Sstevel@tonic-gate else if (grub_memcmp (arg, "--no-edit", sizeof ("--no-edit") - 1) == 0) 50997c478bd9Sstevel@tonic-gate term_flags |= TERM_NO_EDIT; 51007c478bd9Sstevel@tonic-gate else if (grub_memcmp (arg, "--timeout=", sizeof ("--timeout=") - 1) == 0) 51017c478bd9Sstevel@tonic-gate { 51027c478bd9Sstevel@tonic-gate char *val = arg + sizeof ("--timeout=") - 1; 51037c478bd9Sstevel@tonic-gate 51047c478bd9Sstevel@tonic-gate if (! safe_parse_maxint (&val, &to)) 51057c478bd9Sstevel@tonic-gate return 1; 51067c478bd9Sstevel@tonic-gate } 51077c478bd9Sstevel@tonic-gate else if (grub_memcmp (arg, "--lines=", sizeof ("--lines=") - 1) == 0) 51087c478bd9Sstevel@tonic-gate { 51097c478bd9Sstevel@tonic-gate char *val = arg + sizeof ("--lines=") - 1; 51107c478bd9Sstevel@tonic-gate 51117c478bd9Sstevel@tonic-gate if (! safe_parse_maxint (&val, &lines)) 51127c478bd9Sstevel@tonic-gate return 1; 51137c478bd9Sstevel@tonic-gate 51147c478bd9Sstevel@tonic-gate /* Probably less than four is meaningless.... */ 51157c478bd9Sstevel@tonic-gate if (lines < 4) 51167c478bd9Sstevel@tonic-gate { 51177c478bd9Sstevel@tonic-gate errnum = ERR_BAD_ARGUMENT; 51187c478bd9Sstevel@tonic-gate return 1; 51197c478bd9Sstevel@tonic-gate } 51207c478bd9Sstevel@tonic-gate } 51217c478bd9Sstevel@tonic-gate else if (grub_memcmp (arg, "--silent", sizeof ("--silent") - 1) == 0) 51227c478bd9Sstevel@tonic-gate no_message = 1; 51237c478bd9Sstevel@tonic-gate else 51247c478bd9Sstevel@tonic-gate break; 51257c478bd9Sstevel@tonic-gate 51267c478bd9Sstevel@tonic-gate arg = skip_to (0, arg); 51277c478bd9Sstevel@tonic-gate } 51287c478bd9Sstevel@tonic-gate 51297c478bd9Sstevel@tonic-gate /* If no argument is specified, show current setting. */ 51307c478bd9Sstevel@tonic-gate if (! *arg) 51317c478bd9Sstevel@tonic-gate { 51327c478bd9Sstevel@tonic-gate grub_printf ("%s%s%s%s\n", 51337c478bd9Sstevel@tonic-gate current_term->name, 51347c478bd9Sstevel@tonic-gate current_term->flags & TERM_DUMB ? " (dumb)" : "", 51357c478bd9Sstevel@tonic-gate current_term->flags & TERM_NO_EDIT ? " (no edit)" : "", 51367c478bd9Sstevel@tonic-gate current_term->flags & TERM_NO_ECHO ? " (no echo)" : ""); 51377c478bd9Sstevel@tonic-gate return 0; 51387c478bd9Sstevel@tonic-gate } 51397c478bd9Sstevel@tonic-gate 51407c478bd9Sstevel@tonic-gate while (*arg) 51417c478bd9Sstevel@tonic-gate { 51427c478bd9Sstevel@tonic-gate int i; 51437c478bd9Sstevel@tonic-gate char *next = skip_to (0, arg); 51447c478bd9Sstevel@tonic-gate 51457c478bd9Sstevel@tonic-gate nul_terminate (arg); 51467c478bd9Sstevel@tonic-gate 51477c478bd9Sstevel@tonic-gate for (i = 0; term_table[i].name; i++) 51487c478bd9Sstevel@tonic-gate { 51497c478bd9Sstevel@tonic-gate if (grub_strcmp (arg, term_table[i].name) == 0) 51507c478bd9Sstevel@tonic-gate { 51517c478bd9Sstevel@tonic-gate if (term_table[i].flags & TERM_NEED_INIT) 51527c478bd9Sstevel@tonic-gate { 51537c478bd9Sstevel@tonic-gate errnum = ERR_DEV_NEED_INIT; 51547c478bd9Sstevel@tonic-gate return 1; 51557c478bd9Sstevel@tonic-gate } 51567c478bd9Sstevel@tonic-gate 51577c478bd9Sstevel@tonic-gate if (default_term < 0) 51587c478bd9Sstevel@tonic-gate default_term = i; 51597c478bd9Sstevel@tonic-gate 51607c478bd9Sstevel@tonic-gate term_bitmap |= (1 << i); 51617c478bd9Sstevel@tonic-gate break; 51627c478bd9Sstevel@tonic-gate } 51637c478bd9Sstevel@tonic-gate } 51647c478bd9Sstevel@tonic-gate 51657c478bd9Sstevel@tonic-gate if (! term_table[i].name) 51667c478bd9Sstevel@tonic-gate { 51677c478bd9Sstevel@tonic-gate errnum = ERR_BAD_ARGUMENT; 51687c478bd9Sstevel@tonic-gate return 1; 51697c478bd9Sstevel@tonic-gate } 51707c478bd9Sstevel@tonic-gate 51717c478bd9Sstevel@tonic-gate arg = next; 51727c478bd9Sstevel@tonic-gate } 51737c478bd9Sstevel@tonic-gate 51747c478bd9Sstevel@tonic-gate /* If multiple terminals are specified, wait until the user pushes any 51757c478bd9Sstevel@tonic-gate key on one of the terminals. */ 51767c478bd9Sstevel@tonic-gate if (term_bitmap & ~(1 << default_term)) 51777c478bd9Sstevel@tonic-gate { 51787c478bd9Sstevel@tonic-gate int time1, time2 = -1; 51797c478bd9Sstevel@tonic-gate 51807c478bd9Sstevel@tonic-gate /* XXX: Disable the pager. */ 51817c478bd9Sstevel@tonic-gate count_lines = -1; 51827c478bd9Sstevel@tonic-gate 51837c478bd9Sstevel@tonic-gate /* Get current time. */ 51847c478bd9Sstevel@tonic-gate while ((time1 = getrtsecs ()) == 0xFF) 51857c478bd9Sstevel@tonic-gate ; 51867c478bd9Sstevel@tonic-gate 51877c478bd9Sstevel@tonic-gate /* Wait for a key input. */ 51887c478bd9Sstevel@tonic-gate while (to) 51897c478bd9Sstevel@tonic-gate { 51907c478bd9Sstevel@tonic-gate int i; 51917c478bd9Sstevel@tonic-gate 51927c478bd9Sstevel@tonic-gate for (i = 0; term_table[i].name; i++) 51937c478bd9Sstevel@tonic-gate { 51947c478bd9Sstevel@tonic-gate if (term_bitmap & (1 << i)) 51957c478bd9Sstevel@tonic-gate { 51967c478bd9Sstevel@tonic-gate if (term_table[i].checkkey () >= 0) 51977c478bd9Sstevel@tonic-gate { 51987c478bd9Sstevel@tonic-gate (void) term_table[i].getkey (); 51997c478bd9Sstevel@tonic-gate default_term = i; 52007c478bd9Sstevel@tonic-gate 52017c478bd9Sstevel@tonic-gate goto end; 52027c478bd9Sstevel@tonic-gate } 52037c478bd9Sstevel@tonic-gate } 52047c478bd9Sstevel@tonic-gate } 52057c478bd9Sstevel@tonic-gate 52067c478bd9Sstevel@tonic-gate /* Prompt the user, once per sec. */ 52077c478bd9Sstevel@tonic-gate if ((time1 = getrtsecs ()) != time2 && time1 != 0xFF) 52087c478bd9Sstevel@tonic-gate { 52097c478bd9Sstevel@tonic-gate if (! no_message) 52107c478bd9Sstevel@tonic-gate { 52117c478bd9Sstevel@tonic-gate /* Need to set CURRENT_TERM to each of selected 52127c478bd9Sstevel@tonic-gate terminals. */ 52137c478bd9Sstevel@tonic-gate for (i = 0; term_table[i].name; i++) 52147c478bd9Sstevel@tonic-gate if (term_bitmap & (1 << i)) 52157c478bd9Sstevel@tonic-gate { 52167c478bd9Sstevel@tonic-gate current_term = term_table + i; 52177c478bd9Sstevel@tonic-gate grub_printf ("\rPress any key to continue.\n"); 52187c478bd9Sstevel@tonic-gate } 52197c478bd9Sstevel@tonic-gate 52207c478bd9Sstevel@tonic-gate /* Restore CURRENT_TERM. */ 52217c478bd9Sstevel@tonic-gate current_term = prev_term; 52227c478bd9Sstevel@tonic-gate } 52237c478bd9Sstevel@tonic-gate 52247c478bd9Sstevel@tonic-gate time2 = time1; 52257c478bd9Sstevel@tonic-gate if (to > 0) 52267c478bd9Sstevel@tonic-gate to--; 52277c478bd9Sstevel@tonic-gate } 52287c478bd9Sstevel@tonic-gate } 52297c478bd9Sstevel@tonic-gate } 52307c478bd9Sstevel@tonic-gate 52317c478bd9Sstevel@tonic-gate end: 52327c478bd9Sstevel@tonic-gate current_term = term_table + default_term; 52337c478bd9Sstevel@tonic-gate current_term->flags = term_flags; 52347c478bd9Sstevel@tonic-gate 52357c478bd9Sstevel@tonic-gate if (lines) 52367c478bd9Sstevel@tonic-gate max_lines = lines; 52377c478bd9Sstevel@tonic-gate else 52387c478bd9Sstevel@tonic-gate max_lines = current_term->max_lines; 52397c478bd9Sstevel@tonic-gate 52407c478bd9Sstevel@tonic-gate /* If the interface is currently the command-line, 52417c478bd9Sstevel@tonic-gate restart it to repaint the screen. */ 52427c478bd9Sstevel@tonic-gate if ((current_term != prev_term) && (flags & BUILTIN_CMDLINE)){ 52437c478bd9Sstevel@tonic-gate if (prev_term->shutdown) 52447c478bd9Sstevel@tonic-gate prev_term->shutdown(); 52457c478bd9Sstevel@tonic-gate if (current_term->startup) 52467c478bd9Sstevel@tonic-gate current_term->startup(); 52477c478bd9Sstevel@tonic-gate grub_longjmp (restart_cmdline_env, 0); 52487c478bd9Sstevel@tonic-gate } 52497c478bd9Sstevel@tonic-gate 52507c478bd9Sstevel@tonic-gate return 0; 52517c478bd9Sstevel@tonic-gate } 52527c478bd9Sstevel@tonic-gate 52537c478bd9Sstevel@tonic-gate static struct builtin builtin_terminal = 52547c478bd9Sstevel@tonic-gate { 52557c478bd9Sstevel@tonic-gate "terminal", 52567c478bd9Sstevel@tonic-gate terminal_func, 52577c478bd9Sstevel@tonic-gate BUILTIN_MENU | BUILTIN_CMDLINE | BUILTIN_HELP_LIST, 52587c478bd9Sstevel@tonic-gate "terminal [--dumb] [--no-echo] [--no-edit] [--timeout=SECS] [--lines=LINES] [--silent] [console] [serial] [hercules] [graphics]", 52597c478bd9Sstevel@tonic-gate "Select a terminal. When multiple terminals are specified, wait until" 52607c478bd9Sstevel@tonic-gate " you push any key to continue. If both console and serial are specified," 52617c478bd9Sstevel@tonic-gate " the terminal to which you input a key first will be selected. If no" 52627c478bd9Sstevel@tonic-gate " argument is specified, print current setting. The option --dumb" 52637c478bd9Sstevel@tonic-gate " specifies that your terminal is dumb, otherwise, vt100-compatibility" 52647c478bd9Sstevel@tonic-gate " is assumed. If you specify --no-echo, input characters won't be echoed." 52657c478bd9Sstevel@tonic-gate " If you specify --no-edit, the BASH-like editing feature will be disabled." 52667c478bd9Sstevel@tonic-gate " If --timeout is present, this command will wait at most for SECS" 52677c478bd9Sstevel@tonic-gate " seconds. The option --lines specifies the maximum number of lines." 52687c478bd9Sstevel@tonic-gate " The option --silent is used to suppress messages." 52697c478bd9Sstevel@tonic-gate }; 52707c478bd9Sstevel@tonic-gate #endif /* SUPPORT_SERIAL || SUPPORT_HERCULES || SUPPORT_GRAPHICS */ 52717c478bd9Sstevel@tonic-gate 52727c478bd9Sstevel@tonic-gate 52737c478bd9Sstevel@tonic-gate #ifdef SUPPORT_SERIAL 52747c478bd9Sstevel@tonic-gate static int 52757c478bd9Sstevel@tonic-gate terminfo_func (char *arg, int flags) 52767c478bd9Sstevel@tonic-gate { 52777c478bd9Sstevel@tonic-gate struct terminfo term; 52787c478bd9Sstevel@tonic-gate 52797c478bd9Sstevel@tonic-gate if (*arg) 52807c478bd9Sstevel@tonic-gate { 52817c478bd9Sstevel@tonic-gate struct 52827c478bd9Sstevel@tonic-gate { 52837c478bd9Sstevel@tonic-gate const char *name; 52847c478bd9Sstevel@tonic-gate char *var; 52857c478bd9Sstevel@tonic-gate } 52867c478bd9Sstevel@tonic-gate options[] = 52877c478bd9Sstevel@tonic-gate { 52887c478bd9Sstevel@tonic-gate {"--name=", term.name}, 52897c478bd9Sstevel@tonic-gate {"--cursor-address=", term.cursor_address}, 52907c478bd9Sstevel@tonic-gate {"--clear-screen=", term.clear_screen}, 52917c478bd9Sstevel@tonic-gate {"--enter-standout-mode=", term.enter_standout_mode}, 52927c478bd9Sstevel@tonic-gate {"--exit-standout-mode=", term.exit_standout_mode} 52937c478bd9Sstevel@tonic-gate }; 52947c478bd9Sstevel@tonic-gate 52957c478bd9Sstevel@tonic-gate grub_memset (&term, 0, sizeof (term)); 52967c478bd9Sstevel@tonic-gate 52977c478bd9Sstevel@tonic-gate while (*arg) 52987c478bd9Sstevel@tonic-gate { 52997c478bd9Sstevel@tonic-gate int i; 53007c478bd9Sstevel@tonic-gate char *next = skip_to (0, arg); 53017c478bd9Sstevel@tonic-gate 53027c478bd9Sstevel@tonic-gate nul_terminate (arg); 53037c478bd9Sstevel@tonic-gate 53047c478bd9Sstevel@tonic-gate for (i = 0; i < sizeof (options) / sizeof (options[0]); i++) 53057c478bd9Sstevel@tonic-gate { 53067c478bd9Sstevel@tonic-gate const char *name = options[i].name; 53077c478bd9Sstevel@tonic-gate int len = grub_strlen (name); 53087c478bd9Sstevel@tonic-gate 53097c478bd9Sstevel@tonic-gate if (! grub_memcmp (arg, name, len)) 53107c478bd9Sstevel@tonic-gate { 53117c478bd9Sstevel@tonic-gate grub_strcpy (options[i].var, ti_unescape_string (arg + len)); 53127c478bd9Sstevel@tonic-gate break; 53137c478bd9Sstevel@tonic-gate } 53147c478bd9Sstevel@tonic-gate } 53157c478bd9Sstevel@tonic-gate 53167c478bd9Sstevel@tonic-gate if (i == sizeof (options) / sizeof (options[0])) 53177c478bd9Sstevel@tonic-gate { 53187c478bd9Sstevel@tonic-gate errnum = ERR_BAD_ARGUMENT; 53197c478bd9Sstevel@tonic-gate return errnum; 53207c478bd9Sstevel@tonic-gate } 53217c478bd9Sstevel@tonic-gate 53227c478bd9Sstevel@tonic-gate arg = next; 53237c478bd9Sstevel@tonic-gate } 53247c478bd9Sstevel@tonic-gate 53257c478bd9Sstevel@tonic-gate if (term.name[0] == 0 || term.cursor_address[0] == 0) 53267c478bd9Sstevel@tonic-gate { 53277c478bd9Sstevel@tonic-gate errnum = ERR_BAD_ARGUMENT; 53287c478bd9Sstevel@tonic-gate return errnum; 53297c478bd9Sstevel@tonic-gate } 53307c478bd9Sstevel@tonic-gate 53317c478bd9Sstevel@tonic-gate ti_set_term (&term); 53327c478bd9Sstevel@tonic-gate } 53337c478bd9Sstevel@tonic-gate else 53347c478bd9Sstevel@tonic-gate { 53357c478bd9Sstevel@tonic-gate /* No option specifies printing out current settings. */ 53367c478bd9Sstevel@tonic-gate ti_get_term (&term); 53377c478bd9Sstevel@tonic-gate 53387c478bd9Sstevel@tonic-gate grub_printf ("name=%s\n", 53397c478bd9Sstevel@tonic-gate ti_escape_string (term.name)); 53407c478bd9Sstevel@tonic-gate grub_printf ("cursor_address=%s\n", 53417c478bd9Sstevel@tonic-gate ti_escape_string (term.cursor_address)); 53427c478bd9Sstevel@tonic-gate grub_printf ("clear_screen=%s\n", 53437c478bd9Sstevel@tonic-gate ti_escape_string (term.clear_screen)); 53447c478bd9Sstevel@tonic-gate grub_printf ("enter_standout_mode=%s\n", 53457c478bd9Sstevel@tonic-gate ti_escape_string (term.enter_standout_mode)); 53467c478bd9Sstevel@tonic-gate grub_printf ("exit_standout_mode=%s\n", 53477c478bd9Sstevel@tonic-gate ti_escape_string (term.exit_standout_mode)); 53487c478bd9Sstevel@tonic-gate } 53497c478bd9Sstevel@tonic-gate 53507c478bd9Sstevel@tonic-gate return 0; 53517c478bd9Sstevel@tonic-gate } 53527c478bd9Sstevel@tonic-gate 53537c478bd9Sstevel@tonic-gate static struct builtin builtin_terminfo = 53547c478bd9Sstevel@tonic-gate { 53557c478bd9Sstevel@tonic-gate "terminfo", 53567c478bd9Sstevel@tonic-gate terminfo_func, 53577c478bd9Sstevel@tonic-gate BUILTIN_MENU | BUILTIN_CMDLINE | BUILTIN_HELP_LIST, 53587c478bd9Sstevel@tonic-gate "terminfo [--name=NAME --cursor-address=SEQ [--clear-screen=SEQ]" 53597c478bd9Sstevel@tonic-gate " [--enter-standout-mode=SEQ] [--exit-standout-mode=SEQ]]", 53607c478bd9Sstevel@tonic-gate 53617c478bd9Sstevel@tonic-gate "Define the capabilities of your terminal. Use this command to" 53627c478bd9Sstevel@tonic-gate " define escape sequences, if it is not vt100-compatible." 53637c478bd9Sstevel@tonic-gate " You may use \\e for ESC and ^X for a control character." 53647c478bd9Sstevel@tonic-gate " If no option is specified, the current settings are printed." 53657c478bd9Sstevel@tonic-gate }; 53667c478bd9Sstevel@tonic-gate #endif /* SUPPORT_SERIAL */ 53677c478bd9Sstevel@tonic-gate 53687c478bd9Sstevel@tonic-gate 53697c478bd9Sstevel@tonic-gate /* testload */ 53707c478bd9Sstevel@tonic-gate static int 53717c478bd9Sstevel@tonic-gate testload_func (char *arg, int flags) 53727c478bd9Sstevel@tonic-gate { 53737c478bd9Sstevel@tonic-gate int i; 53747c478bd9Sstevel@tonic-gate 53757c478bd9Sstevel@tonic-gate kernel_type = KERNEL_TYPE_NONE; 53767c478bd9Sstevel@tonic-gate 53777c478bd9Sstevel@tonic-gate if (! grub_open (arg)) 53787c478bd9Sstevel@tonic-gate return 1; 53797c478bd9Sstevel@tonic-gate 53807c478bd9Sstevel@tonic-gate disk_read_hook = disk_read_print_func; 53817c478bd9Sstevel@tonic-gate 53827c478bd9Sstevel@tonic-gate /* Perform filesystem test on the specified file. */ 53837c478bd9Sstevel@tonic-gate /* Read whole file first. */ 53847c478bd9Sstevel@tonic-gate grub_printf ("Whole file: "); 53857c478bd9Sstevel@tonic-gate 53867c478bd9Sstevel@tonic-gate grub_read ((char *) RAW_ADDR (0x100000), -1); 53877c478bd9Sstevel@tonic-gate 53887c478bd9Sstevel@tonic-gate /* Now compare two sections of the file read differently. */ 53897c478bd9Sstevel@tonic-gate 53907c478bd9Sstevel@tonic-gate for (i = 0; i < 0x10ac0; i++) 53917c478bd9Sstevel@tonic-gate { 53927c478bd9Sstevel@tonic-gate *((unsigned char *) RAW_ADDR (0x200000 + i)) = 0; 53937c478bd9Sstevel@tonic-gate *((unsigned char *) RAW_ADDR (0x300000 + i)) = 1; 53947c478bd9Sstevel@tonic-gate } 53957c478bd9Sstevel@tonic-gate 53967c478bd9Sstevel@tonic-gate /* First partial read. */ 53977c478bd9Sstevel@tonic-gate grub_printf ("\nPartial read 1: "); 53987c478bd9Sstevel@tonic-gate 53997c478bd9Sstevel@tonic-gate grub_seek (0); 54007c478bd9Sstevel@tonic-gate grub_read ((char *) RAW_ADDR (0x200000), 0x7); 54017c478bd9Sstevel@tonic-gate grub_read ((char *) RAW_ADDR (0x200007), 0x100); 54027c478bd9Sstevel@tonic-gate grub_read ((char *) RAW_ADDR (0x200107), 0x10); 54037c478bd9Sstevel@tonic-gate grub_read ((char *) RAW_ADDR (0x200117), 0x999); 54047c478bd9Sstevel@tonic-gate grub_read ((char *) RAW_ADDR (0x200ab0), 0x10); 54057c478bd9Sstevel@tonic-gate grub_read ((char *) RAW_ADDR (0x200ac0), 0x10000); 54067c478bd9Sstevel@tonic-gate 54077c478bd9Sstevel@tonic-gate /* Second partial read. */ 54087c478bd9Sstevel@tonic-gate grub_printf ("\nPartial read 2: "); 54097c478bd9Sstevel@tonic-gate 54107c478bd9Sstevel@tonic-gate grub_seek (0); 54117c478bd9Sstevel@tonic-gate grub_read ((char *) RAW_ADDR (0x300000), 0x10000); 54127c478bd9Sstevel@tonic-gate grub_read ((char *) RAW_ADDR (0x310000), 0x10); 54137c478bd9Sstevel@tonic-gate grub_read ((char *) RAW_ADDR (0x310010), 0x7); 54147c478bd9Sstevel@tonic-gate grub_read ((char *) RAW_ADDR (0x310017), 0x10); 54157c478bd9Sstevel@tonic-gate grub_read ((char *) RAW_ADDR (0x310027), 0x999); 54167c478bd9Sstevel@tonic-gate grub_read ((char *) RAW_ADDR (0x3109c0), 0x100); 54177c478bd9Sstevel@tonic-gate 54187c478bd9Sstevel@tonic-gate grub_printf ("\nHeader1 = 0x%x, next = 0x%x, next = 0x%x, next = 0x%x\n", 54197c478bd9Sstevel@tonic-gate *((int *) RAW_ADDR (0x200000)), 54207c478bd9Sstevel@tonic-gate *((int *) RAW_ADDR (0x200004)), 54217c478bd9Sstevel@tonic-gate *((int *) RAW_ADDR (0x200008)), 54227c478bd9Sstevel@tonic-gate *((int *) RAW_ADDR (0x20000c))); 54237c478bd9Sstevel@tonic-gate 54247c478bd9Sstevel@tonic-gate grub_printf ("Header2 = 0x%x, next = 0x%x, next = 0x%x, next = 0x%x\n", 54257c478bd9Sstevel@tonic-gate *((int *) RAW_ADDR (0x300000)), 54267c478bd9Sstevel@tonic-gate *((int *) RAW_ADDR (0x300004)), 54277c478bd9Sstevel@tonic-gate *((int *) RAW_ADDR (0x300008)), 54287c478bd9Sstevel@tonic-gate *((int *) RAW_ADDR (0x30000c))); 54297c478bd9Sstevel@tonic-gate 54307c478bd9Sstevel@tonic-gate for (i = 0; i < 0x10ac0; i++) 54317c478bd9Sstevel@tonic-gate if (*((unsigned char *) RAW_ADDR (0x200000 + i)) 54327c478bd9Sstevel@tonic-gate != *((unsigned char *) RAW_ADDR (0x300000 + i))) 54337c478bd9Sstevel@tonic-gate break; 54347c478bd9Sstevel@tonic-gate 54357c478bd9Sstevel@tonic-gate grub_printf ("Max is 0x10ac0: i=0x%x, filepos=0x%x\n", i, filepos); 54367c478bd9Sstevel@tonic-gate disk_read_hook = 0; 54377c478bd9Sstevel@tonic-gate grub_close (); 54387c478bd9Sstevel@tonic-gate return 0; 54397c478bd9Sstevel@tonic-gate } 54407c478bd9Sstevel@tonic-gate 54417c478bd9Sstevel@tonic-gate static struct builtin builtin_testload = 54427c478bd9Sstevel@tonic-gate { 54437c478bd9Sstevel@tonic-gate "testload", 54447c478bd9Sstevel@tonic-gate testload_func, 54457c478bd9Sstevel@tonic-gate BUILTIN_CMDLINE, 54467c478bd9Sstevel@tonic-gate "testload FILE", 54477c478bd9Sstevel@tonic-gate "Read the entire contents of FILE in several different ways and" 54487c478bd9Sstevel@tonic-gate " compares them, to test the filesystem code. The output is somewhat" 54497c478bd9Sstevel@tonic-gate " cryptic, but if no errors are reported and the final `i=X," 54507c478bd9Sstevel@tonic-gate " filepos=Y' reading has X and Y equal, then it is definitely" 54517c478bd9Sstevel@tonic-gate " consistent, and very likely works correctly subject to a" 54527c478bd9Sstevel@tonic-gate " consistent offset error. If this test succeeds, then a good next" 54537c478bd9Sstevel@tonic-gate " step is to try loading a kernel." 54547c478bd9Sstevel@tonic-gate }; 54557c478bd9Sstevel@tonic-gate 54567c478bd9Sstevel@tonic-gate 54577c478bd9Sstevel@tonic-gate /* testvbe MODE */ 54587c478bd9Sstevel@tonic-gate static int 54597c478bd9Sstevel@tonic-gate testvbe_func (char *arg, int flags) 54607c478bd9Sstevel@tonic-gate { 54617c478bd9Sstevel@tonic-gate int mode_number; 54627c478bd9Sstevel@tonic-gate struct vbe_controller controller; 54637c478bd9Sstevel@tonic-gate struct vbe_mode mode; 54647c478bd9Sstevel@tonic-gate 54657c478bd9Sstevel@tonic-gate if (! *arg) 54667c478bd9Sstevel@tonic-gate { 54677c478bd9Sstevel@tonic-gate errnum = ERR_BAD_ARGUMENT; 54687c478bd9Sstevel@tonic-gate return 1; 54697c478bd9Sstevel@tonic-gate } 54707c478bd9Sstevel@tonic-gate 54717c478bd9Sstevel@tonic-gate if (! safe_parse_maxint (&arg, &mode_number)) 54727c478bd9Sstevel@tonic-gate return 1; 54737c478bd9Sstevel@tonic-gate 54747c478bd9Sstevel@tonic-gate /* Preset `VBE2'. */ 54757c478bd9Sstevel@tonic-gate grub_memmove (controller.signature, "VBE2", 4); 54767c478bd9Sstevel@tonic-gate 54777c478bd9Sstevel@tonic-gate /* Detect VBE BIOS. */ 54787c478bd9Sstevel@tonic-gate if (get_vbe_controller_info (&controller) != 0x004F) 54797c478bd9Sstevel@tonic-gate { 54807c478bd9Sstevel@tonic-gate grub_printf (" VBE BIOS is not present.\n"); 54817c478bd9Sstevel@tonic-gate return 0; 54827c478bd9Sstevel@tonic-gate } 54837c478bd9Sstevel@tonic-gate 54847c478bd9Sstevel@tonic-gate if (controller.version < 0x0200) 54857c478bd9Sstevel@tonic-gate { 54867c478bd9Sstevel@tonic-gate grub_printf (" VBE version %d.%d is not supported.\n", 54877c478bd9Sstevel@tonic-gate (int) (controller.version >> 8), 54887c478bd9Sstevel@tonic-gate (int) (controller.version & 0xFF)); 54897c478bd9Sstevel@tonic-gate return 0; 54907c478bd9Sstevel@tonic-gate } 54917c478bd9Sstevel@tonic-gate 54927c478bd9Sstevel@tonic-gate if (get_vbe_mode_info (mode_number, &mode) != 0x004F 54937c478bd9Sstevel@tonic-gate || (mode.mode_attributes & 0x0091) != 0x0091) 54947c478bd9Sstevel@tonic-gate { 54957c478bd9Sstevel@tonic-gate grub_printf (" Mode 0x%x is not supported.\n", mode_number); 54967c478bd9Sstevel@tonic-gate return 0; 54977c478bd9Sstevel@tonic-gate } 54987c478bd9Sstevel@tonic-gate 54997c478bd9Sstevel@tonic-gate /* Now trip to the graphics mode. */ 55007c478bd9Sstevel@tonic-gate if (set_vbe_mode (mode_number | (1 << 14)) != 0x004F) 55017c478bd9Sstevel@tonic-gate { 55027c478bd9Sstevel@tonic-gate grub_printf (" Switching to Mode 0x%x failed.\n", mode_number); 55037c478bd9Sstevel@tonic-gate return 0; 55047c478bd9Sstevel@tonic-gate } 55057c478bd9Sstevel@tonic-gate 55067c478bd9Sstevel@tonic-gate /* Draw something on the screen... */ 55077c478bd9Sstevel@tonic-gate { 55087c478bd9Sstevel@tonic-gate unsigned char *base_buf = (unsigned char *) mode.phys_base; 55097c478bd9Sstevel@tonic-gate int scanline = controller.version >= 0x0300 55107c478bd9Sstevel@tonic-gate ? mode.linear_bytes_per_scanline : mode.bytes_per_scanline; 55117c478bd9Sstevel@tonic-gate /* FIXME: this assumes that any depth is a modulo of 8. */ 55127c478bd9Sstevel@tonic-gate int bpp = mode.bits_per_pixel / 8; 55137c478bd9Sstevel@tonic-gate int width = mode.x_resolution; 55147c478bd9Sstevel@tonic-gate int height = mode.y_resolution; 55157c478bd9Sstevel@tonic-gate int x, y; 55167c478bd9Sstevel@tonic-gate unsigned color = 0; 55177c478bd9Sstevel@tonic-gate 55187c478bd9Sstevel@tonic-gate /* Iterate drawing on the screen, until the user hits any key. */ 55197c478bd9Sstevel@tonic-gate while (checkkey () == -1) 55207c478bd9Sstevel@tonic-gate { 55217c478bd9Sstevel@tonic-gate for (y = 0; y < height; y++) 55227c478bd9Sstevel@tonic-gate { 55237c478bd9Sstevel@tonic-gate unsigned char *line_buf = base_buf + scanline * y; 55247c478bd9Sstevel@tonic-gate 55257c478bd9Sstevel@tonic-gate for (x = 0; x < width; x++) 55267c478bd9Sstevel@tonic-gate { 55277c478bd9Sstevel@tonic-gate unsigned char *buf = line_buf + bpp * x; 55287c478bd9Sstevel@tonic-gate int i; 55297c478bd9Sstevel@tonic-gate 55307c478bd9Sstevel@tonic-gate for (i = 0; i < bpp; i++, buf++) 55317c478bd9Sstevel@tonic-gate *buf = (color >> (i * 8)) & 0xff; 55327c478bd9Sstevel@tonic-gate } 55337c478bd9Sstevel@tonic-gate 55347c478bd9Sstevel@tonic-gate color++; 55357c478bd9Sstevel@tonic-gate } 55367c478bd9Sstevel@tonic-gate } 55377c478bd9Sstevel@tonic-gate 55387c478bd9Sstevel@tonic-gate /* Discard the input. */ 55397c478bd9Sstevel@tonic-gate getkey (); 55407c478bd9Sstevel@tonic-gate } 55417c478bd9Sstevel@tonic-gate 55427c478bd9Sstevel@tonic-gate /* Back to the default text mode. */ 55437c478bd9Sstevel@tonic-gate if (set_vbe_mode (0x03) != 0x004F) 55447c478bd9Sstevel@tonic-gate { 55457c478bd9Sstevel@tonic-gate /* Why?! */ 55467c478bd9Sstevel@tonic-gate grub_reboot (); 55477c478bd9Sstevel@tonic-gate } 55487c478bd9Sstevel@tonic-gate 55497c478bd9Sstevel@tonic-gate return 0; 55507c478bd9Sstevel@tonic-gate } 55517c478bd9Sstevel@tonic-gate 55527c478bd9Sstevel@tonic-gate static struct builtin builtin_testvbe = 55537c478bd9Sstevel@tonic-gate { 55547c478bd9Sstevel@tonic-gate "testvbe", 55557c478bd9Sstevel@tonic-gate testvbe_func, 55567c478bd9Sstevel@tonic-gate BUILTIN_CMDLINE | BUILTIN_HELP_LIST, 55577c478bd9Sstevel@tonic-gate "testvbe MODE", 55587c478bd9Sstevel@tonic-gate "Test the VBE mode MODE. Hit any key to return." 55597c478bd9Sstevel@tonic-gate }; 55607c478bd9Sstevel@tonic-gate 55617c478bd9Sstevel@tonic-gate 55627c478bd9Sstevel@tonic-gate #ifdef SUPPORT_NETBOOT 55637c478bd9Sstevel@tonic-gate /* tftpserver */ 55647c478bd9Sstevel@tonic-gate static int 55657c478bd9Sstevel@tonic-gate tftpserver_func (char *arg, int flags) 55667c478bd9Sstevel@tonic-gate { 55677c478bd9Sstevel@tonic-gate if (! *arg || ! ifconfig (0, 0, 0, arg)) 55687c478bd9Sstevel@tonic-gate { 55697c478bd9Sstevel@tonic-gate errnum = ERR_BAD_ARGUMENT; 55707c478bd9Sstevel@tonic-gate return 1; 55717c478bd9Sstevel@tonic-gate } 55727c478bd9Sstevel@tonic-gate 55737c478bd9Sstevel@tonic-gate print_network_configuration (); 55747c478bd9Sstevel@tonic-gate return 0; 55757c478bd9Sstevel@tonic-gate } 55767c478bd9Sstevel@tonic-gate 55777c478bd9Sstevel@tonic-gate static struct builtin builtin_tftpserver = 55787c478bd9Sstevel@tonic-gate { 55797c478bd9Sstevel@tonic-gate "tftpserver", 55807c478bd9Sstevel@tonic-gate tftpserver_func, 55817c478bd9Sstevel@tonic-gate BUILTIN_CMDLINE | BUILTIN_MENU | BUILTIN_HELP_LIST, 55827c478bd9Sstevel@tonic-gate "tftpserver IPADDR", 55837c478bd9Sstevel@tonic-gate "Override the TFTP server address." 55847c478bd9Sstevel@tonic-gate }; 55857c478bd9Sstevel@tonic-gate #endif /* SUPPORT_NETBOOT */ 55867c478bd9Sstevel@tonic-gate 55877c478bd9Sstevel@tonic-gate 55887c478bd9Sstevel@tonic-gate /* timeout */ 55897c478bd9Sstevel@tonic-gate static int 55907c478bd9Sstevel@tonic-gate timeout_func (char *arg, int flags) 55917c478bd9Sstevel@tonic-gate { 55927c478bd9Sstevel@tonic-gate if (! safe_parse_maxint (&arg, &grub_timeout)) 55937c478bd9Sstevel@tonic-gate return 1; 55947c478bd9Sstevel@tonic-gate 55957c478bd9Sstevel@tonic-gate return 0; 55967c478bd9Sstevel@tonic-gate } 55977c478bd9Sstevel@tonic-gate 55987c478bd9Sstevel@tonic-gate static struct builtin builtin_timeout = 55997c478bd9Sstevel@tonic-gate { 56007c478bd9Sstevel@tonic-gate "timeout", 56017c478bd9Sstevel@tonic-gate timeout_func, 56027c478bd9Sstevel@tonic-gate BUILTIN_MENU, 56037c478bd9Sstevel@tonic-gate #if 0 56047c478bd9Sstevel@tonic-gate "timeout SEC", 56057c478bd9Sstevel@tonic-gate "Set a timeout, in SEC seconds, before automatically booting the" 56067c478bd9Sstevel@tonic-gate " default entry (normally the first entry defined)." 56077c478bd9Sstevel@tonic-gate #endif 56087c478bd9Sstevel@tonic-gate }; 56097c478bd9Sstevel@tonic-gate 56107c478bd9Sstevel@tonic-gate 56117c478bd9Sstevel@tonic-gate /* title */ 56127c478bd9Sstevel@tonic-gate static int 56137c478bd9Sstevel@tonic-gate title_func (char *arg, int flags) 56147c478bd9Sstevel@tonic-gate { 56157c478bd9Sstevel@tonic-gate /* This function is not actually used at least currently. */ 56167c478bd9Sstevel@tonic-gate return 0; 56177c478bd9Sstevel@tonic-gate } 56187c478bd9Sstevel@tonic-gate 56197c478bd9Sstevel@tonic-gate static struct builtin builtin_title = 56207c478bd9Sstevel@tonic-gate { 56217c478bd9Sstevel@tonic-gate "title", 56227c478bd9Sstevel@tonic-gate title_func, 56237c478bd9Sstevel@tonic-gate BUILTIN_TITLE, 56247c478bd9Sstevel@tonic-gate #if 0 56257c478bd9Sstevel@tonic-gate "title [NAME ...]", 56267c478bd9Sstevel@tonic-gate "Start a new boot entry, and set its name to the contents of the" 56277c478bd9Sstevel@tonic-gate " rest of the line, starting with the first non-space character." 56287c478bd9Sstevel@tonic-gate #endif 56297c478bd9Sstevel@tonic-gate }; 56307c478bd9Sstevel@tonic-gate 56317c478bd9Sstevel@tonic-gate 56327c478bd9Sstevel@tonic-gate /* unhide */ 56337c478bd9Sstevel@tonic-gate static int 56347c478bd9Sstevel@tonic-gate unhide_func (char *arg, int flags) 56357c478bd9Sstevel@tonic-gate { 56367c478bd9Sstevel@tonic-gate if (! set_device (arg)) 56377c478bd9Sstevel@tonic-gate return 1; 56387c478bd9Sstevel@tonic-gate 56397c478bd9Sstevel@tonic-gate if (! set_partition_hidden_flag (0)) 56407c478bd9Sstevel@tonic-gate return 1; 56417c478bd9Sstevel@tonic-gate 56427c478bd9Sstevel@tonic-gate return 0; 56437c478bd9Sstevel@tonic-gate } 56447c478bd9Sstevel@tonic-gate 56457c478bd9Sstevel@tonic-gate static struct builtin builtin_unhide = 56467c478bd9Sstevel@tonic-gate { 56477c478bd9Sstevel@tonic-gate "unhide", 56487c478bd9Sstevel@tonic-gate unhide_func, 56497c478bd9Sstevel@tonic-gate BUILTIN_CMDLINE | BUILTIN_MENU | BUILTIN_HELP_LIST, 56507c478bd9Sstevel@tonic-gate "unhide PARTITION", 56517c478bd9Sstevel@tonic-gate "Unhide PARTITION by clearing the \"hidden\" bit in its" 56527c478bd9Sstevel@tonic-gate " partition type code." 56537c478bd9Sstevel@tonic-gate }; 56547c478bd9Sstevel@tonic-gate 56557c478bd9Sstevel@tonic-gate 56567c478bd9Sstevel@tonic-gate /* uppermem */ 56577c478bd9Sstevel@tonic-gate static int 56587c478bd9Sstevel@tonic-gate uppermem_func (char *arg, int flags) 56597c478bd9Sstevel@tonic-gate { 56607c478bd9Sstevel@tonic-gate if (! safe_parse_maxint (&arg, (int *) &mbi.mem_upper)) 56617c478bd9Sstevel@tonic-gate return 1; 56627c478bd9Sstevel@tonic-gate 56637c478bd9Sstevel@tonic-gate mbi.flags &= ~MB_INFO_MEM_MAP; 56647c478bd9Sstevel@tonic-gate return 0; 56657c478bd9Sstevel@tonic-gate } 56667c478bd9Sstevel@tonic-gate 56677c478bd9Sstevel@tonic-gate static struct builtin builtin_uppermem = 56687c478bd9Sstevel@tonic-gate { 56697c478bd9Sstevel@tonic-gate "uppermem", 56707c478bd9Sstevel@tonic-gate uppermem_func, 56717c478bd9Sstevel@tonic-gate BUILTIN_CMDLINE | BUILTIN_HELP_LIST, 56727c478bd9Sstevel@tonic-gate "uppermem KBYTES", 56737c478bd9Sstevel@tonic-gate "Force GRUB to assume that only KBYTES kilobytes of upper memory are" 56747c478bd9Sstevel@tonic-gate " installed. Any system address range maps are discarded." 56757c478bd9Sstevel@tonic-gate }; 56767c478bd9Sstevel@tonic-gate 56777c478bd9Sstevel@tonic-gate 56787c478bd9Sstevel@tonic-gate /* vbeprobe */ 56797c478bd9Sstevel@tonic-gate static int 56807c478bd9Sstevel@tonic-gate vbeprobe_func (char *arg, int flags) 56817c478bd9Sstevel@tonic-gate { 56827c478bd9Sstevel@tonic-gate struct vbe_controller controller; 56837c478bd9Sstevel@tonic-gate unsigned short *mode_list; 56847c478bd9Sstevel@tonic-gate int mode_number = -1; 56857c478bd9Sstevel@tonic-gate 56867c478bd9Sstevel@tonic-gate auto unsigned long vbe_far_ptr_to_linear (unsigned long); 56877c478bd9Sstevel@tonic-gate 56887c478bd9Sstevel@tonic-gate unsigned long vbe_far_ptr_to_linear (unsigned long ptr) 56897c478bd9Sstevel@tonic-gate { 56907c478bd9Sstevel@tonic-gate unsigned short seg = (ptr >> 16); 56917c478bd9Sstevel@tonic-gate unsigned short off = (ptr & 0xFFFF); 56927c478bd9Sstevel@tonic-gate 56937c478bd9Sstevel@tonic-gate return (seg << 4) + off; 56947c478bd9Sstevel@tonic-gate } 56957c478bd9Sstevel@tonic-gate 56967c478bd9Sstevel@tonic-gate if (*arg) 56977c478bd9Sstevel@tonic-gate { 56987c478bd9Sstevel@tonic-gate if (! safe_parse_maxint (&arg, &mode_number)) 56997c478bd9Sstevel@tonic-gate return 1; 57007c478bd9Sstevel@tonic-gate } 57017c478bd9Sstevel@tonic-gate 57027c478bd9Sstevel@tonic-gate /* Set the signature to `VBE2', to obtain VBE 3.0 information. */ 57037c478bd9Sstevel@tonic-gate grub_memmove (controller.signature, "VBE2", 4); 57047c478bd9Sstevel@tonic-gate 57057c478bd9Sstevel@tonic-gate if (get_vbe_controller_info (&controller) != 0x004F) 57067c478bd9Sstevel@tonic-gate { 57077c478bd9Sstevel@tonic-gate grub_printf (" VBE BIOS is not present.\n"); 57087c478bd9Sstevel@tonic-gate return 0; 57097c478bd9Sstevel@tonic-gate } 57107c478bd9Sstevel@tonic-gate 57117c478bd9Sstevel@tonic-gate /* Check the version. */ 57127c478bd9Sstevel@tonic-gate if (controller.version < 0x0200) 57137c478bd9Sstevel@tonic-gate { 57147c478bd9Sstevel@tonic-gate grub_printf (" VBE version %d.%d is not supported.\n", 57157c478bd9Sstevel@tonic-gate (int) (controller.version >> 8), 57167c478bd9Sstevel@tonic-gate (int) (controller.version & 0xFF)); 57177c478bd9Sstevel@tonic-gate return 0; 57187c478bd9Sstevel@tonic-gate } 57197c478bd9Sstevel@tonic-gate 57207c478bd9Sstevel@tonic-gate /* Print some information. */ 57217c478bd9Sstevel@tonic-gate grub_printf (" VBE version %d.%d\n", 57227c478bd9Sstevel@tonic-gate (int) (controller.version >> 8), 57237c478bd9Sstevel@tonic-gate (int) (controller.version & 0xFF)); 57247c478bd9Sstevel@tonic-gate 57257c478bd9Sstevel@tonic-gate /* Iterate probing modes. */ 57267c478bd9Sstevel@tonic-gate for (mode_list 57277c478bd9Sstevel@tonic-gate = (unsigned short *) vbe_far_ptr_to_linear (controller.video_mode); 57287c478bd9Sstevel@tonic-gate *mode_list != 0xFFFF; 57297c478bd9Sstevel@tonic-gate mode_list++) 57307c478bd9Sstevel@tonic-gate { 57317c478bd9Sstevel@tonic-gate struct vbe_mode mode; 57327c478bd9Sstevel@tonic-gate 57337c478bd9Sstevel@tonic-gate if (get_vbe_mode_info (*mode_list, &mode) != 0x004F) 57347c478bd9Sstevel@tonic-gate continue; 57357c478bd9Sstevel@tonic-gate 57367c478bd9Sstevel@tonic-gate /* Skip this, if this is not supported or linear frame buffer 57377c478bd9Sstevel@tonic-gate mode is not support. */ 57387c478bd9Sstevel@tonic-gate if ((mode.mode_attributes & 0x0081) != 0x0081) 57397c478bd9Sstevel@tonic-gate continue; 57407c478bd9Sstevel@tonic-gate 57417c478bd9Sstevel@tonic-gate if (mode_number == -1 || mode_number == *mode_list) 57427c478bd9Sstevel@tonic-gate { 57437c478bd9Sstevel@tonic-gate char *model; 57447c478bd9Sstevel@tonic-gate switch (mode.memory_model) 57457c478bd9Sstevel@tonic-gate { 57467c478bd9Sstevel@tonic-gate case 0x00: model = "Text"; break; 57477c478bd9Sstevel@tonic-gate case 0x01: model = "CGA graphics"; break; 57487c478bd9Sstevel@tonic-gate case 0x02: model = "Hercules graphics"; break; 57497c478bd9Sstevel@tonic-gate case 0x03: model = "Planar"; break; 57507c478bd9Sstevel@tonic-gate case 0x04: model = "Packed pixel"; break; 57517c478bd9Sstevel@tonic-gate case 0x05: model = "Non-chain 4, 256 color"; break; 57527c478bd9Sstevel@tonic-gate case 0x06: model = "Direct Color"; break; 57537c478bd9Sstevel@tonic-gate case 0x07: model = "YUV"; break; 57547c478bd9Sstevel@tonic-gate default: model = "Unknown"; break; 57557c478bd9Sstevel@tonic-gate } 57567c478bd9Sstevel@tonic-gate 57577c478bd9Sstevel@tonic-gate grub_printf (" 0x%x: %s, %ux%ux%u\n", 57587c478bd9Sstevel@tonic-gate (unsigned) *mode_list, 57597c478bd9Sstevel@tonic-gate model, 57607c478bd9Sstevel@tonic-gate (unsigned) mode.x_resolution, 57617c478bd9Sstevel@tonic-gate (unsigned) mode.y_resolution, 57627c478bd9Sstevel@tonic-gate (unsigned) mode.bits_per_pixel); 57637c478bd9Sstevel@tonic-gate 57647c478bd9Sstevel@tonic-gate if (mode_number != -1) 57657c478bd9Sstevel@tonic-gate break; 57667c478bd9Sstevel@tonic-gate } 57677c478bd9Sstevel@tonic-gate } 57687c478bd9Sstevel@tonic-gate 57697c478bd9Sstevel@tonic-gate if (mode_number != -1 && mode_number != *mode_list) 57707c478bd9Sstevel@tonic-gate grub_printf (" Mode 0x%x is not found or supported.\n", mode_number); 57717c478bd9Sstevel@tonic-gate 57727c478bd9Sstevel@tonic-gate return 0; 57737c478bd9Sstevel@tonic-gate } 57747c478bd9Sstevel@tonic-gate 57757c478bd9Sstevel@tonic-gate static struct builtin builtin_vbeprobe = 57767c478bd9Sstevel@tonic-gate { 57777c478bd9Sstevel@tonic-gate "vbeprobe", 57787c478bd9Sstevel@tonic-gate vbeprobe_func, 57797c478bd9Sstevel@tonic-gate BUILTIN_CMDLINE | BUILTIN_HELP_LIST, 57807c478bd9Sstevel@tonic-gate "vbeprobe [MODE]", 57817c478bd9Sstevel@tonic-gate "Probe VBE information. If the mode number MODE is specified, show only" 57827c478bd9Sstevel@tonic-gate " the information about only the mode." 57837c478bd9Sstevel@tonic-gate }; 57847c478bd9Sstevel@tonic-gate 57857c478bd9Sstevel@tonic-gate 57867c478bd9Sstevel@tonic-gate /* The table of builtin commands. Sorted in dictionary order. */ 57877c478bd9Sstevel@tonic-gate struct builtin *builtin_table[] = 57887c478bd9Sstevel@tonic-gate { 57897c478bd9Sstevel@tonic-gate #ifdef SUPPORT_GRAPHICS 57907c478bd9Sstevel@tonic-gate &builtin_background, 57917c478bd9Sstevel@tonic-gate #endif 57927c478bd9Sstevel@tonic-gate &builtin_blocklist, 57937c478bd9Sstevel@tonic-gate &builtin_boot, 5794b1b8ab34Slling &builtin_bootfs, 57957c478bd9Sstevel@tonic-gate #ifdef SUPPORT_NETBOOT 57967c478bd9Sstevel@tonic-gate &builtin_bootp, 57977c478bd9Sstevel@tonic-gate #endif /* SUPPORT_NETBOOT */ 57987c478bd9Sstevel@tonic-gate &builtin_cat, 57997c478bd9Sstevel@tonic-gate &builtin_chainloader, 58007c478bd9Sstevel@tonic-gate &builtin_clear, 58017c478bd9Sstevel@tonic-gate &builtin_cmp, 58027c478bd9Sstevel@tonic-gate &builtin_color, 58037c478bd9Sstevel@tonic-gate &builtin_configfile, 58047c478bd9Sstevel@tonic-gate &builtin_debug, 58057c478bd9Sstevel@tonic-gate &builtin_default, 58067c478bd9Sstevel@tonic-gate #ifdef GRUB_UTIL 58077c478bd9Sstevel@tonic-gate &builtin_device, 58087c478bd9Sstevel@tonic-gate #endif /* GRUB_UTIL */ 58097c478bd9Sstevel@tonic-gate #ifdef SUPPORT_NETBOOT 58107c478bd9Sstevel@tonic-gate &builtin_dhcp, 58117c478bd9Sstevel@tonic-gate #endif /* SUPPORT_NETBOOT */ 58127c478bd9Sstevel@tonic-gate &builtin_displayapm, 58137c478bd9Sstevel@tonic-gate &builtin_displaymem, 58147c478bd9Sstevel@tonic-gate #ifdef GRUB_UTIL 58157c478bd9Sstevel@tonic-gate &builtin_dump, 58167c478bd9Sstevel@tonic-gate #endif /* GRUB_UTIL */ 58177c478bd9Sstevel@tonic-gate &builtin_embed, 58187c478bd9Sstevel@tonic-gate &builtin_fallback, 58197c478bd9Sstevel@tonic-gate &builtin_find, 5820eb2bd662Svikram &builtin_findroot, 58217c478bd9Sstevel@tonic-gate #ifdef SUPPORT_GRAPHICS 58227c478bd9Sstevel@tonic-gate &builtin_foreground, 58237c478bd9Sstevel@tonic-gate #endif 58247c478bd9Sstevel@tonic-gate &builtin_fstest, 58257c478bd9Sstevel@tonic-gate &builtin_geometry, 58267c478bd9Sstevel@tonic-gate &builtin_halt, 58277c478bd9Sstevel@tonic-gate &builtin_help, 58287c478bd9Sstevel@tonic-gate &builtin_hiddenmenu, 58297c478bd9Sstevel@tonic-gate &builtin_hide, 58307c478bd9Sstevel@tonic-gate #ifdef SUPPORT_NETBOOT 58317c478bd9Sstevel@tonic-gate &builtin_ifconfig, 58327c478bd9Sstevel@tonic-gate #endif /* SUPPORT_NETBOOT */ 58337c478bd9Sstevel@tonic-gate &builtin_impsprobe, 58347c478bd9Sstevel@tonic-gate &builtin_initrd, 58357c478bd9Sstevel@tonic-gate &builtin_install, 58367c478bd9Sstevel@tonic-gate &builtin_ioprobe, 58377c478bd9Sstevel@tonic-gate &builtin_kernel, 5838ae115bc7Smrj &builtin_kernel_dollar, 58397c478bd9Sstevel@tonic-gate &builtin_lock, 58407c478bd9Sstevel@tonic-gate &builtin_makeactive, 58417c478bd9Sstevel@tonic-gate &builtin_map, 58427c478bd9Sstevel@tonic-gate #ifdef USE_MD5_PASSWORDS 58437c478bd9Sstevel@tonic-gate &builtin_md5crypt, 58447c478bd9Sstevel@tonic-gate #endif /* USE_MD5_PASSWORDS */ 5845342440ecSPrasad Singamsetty &builtin_min_mem64, 58467c478bd9Sstevel@tonic-gate &builtin_module, 5847ae115bc7Smrj &builtin_module_dollar, 58487c478bd9Sstevel@tonic-gate &builtin_modulenounzip, 58497c478bd9Sstevel@tonic-gate &builtin_pager, 58507c478bd9Sstevel@tonic-gate &builtin_partnew, 58517c478bd9Sstevel@tonic-gate &builtin_parttype, 58527c478bd9Sstevel@tonic-gate &builtin_password, 58537c478bd9Sstevel@tonic-gate &builtin_pause, 58547c478bd9Sstevel@tonic-gate #if defined(RPC_DEBUG) && defined(SUPPORT_NETBOOT) 58557c478bd9Sstevel@tonic-gate &builtin_portmap, 58567c478bd9Sstevel@tonic-gate #endif /* RPC_DEBUG && SUPPORT_NETBOOT */ 58577c478bd9Sstevel@tonic-gate #ifdef GRUB_UTIL 58587c478bd9Sstevel@tonic-gate &builtin_quit, 58597c478bd9Sstevel@tonic-gate #endif /* GRUB_UTIL */ 58607c478bd9Sstevel@tonic-gate #ifdef SUPPORT_NETBOOT 58617c478bd9Sstevel@tonic-gate &builtin_rarp, 58627c478bd9Sstevel@tonic-gate #endif /* SUPPORT_NETBOOT */ 58637c478bd9Sstevel@tonic-gate &builtin_read, 58647c478bd9Sstevel@tonic-gate &builtin_reboot, 58657c478bd9Sstevel@tonic-gate &builtin_root, 58667c478bd9Sstevel@tonic-gate &builtin_rootnoverify, 58677c478bd9Sstevel@tonic-gate &builtin_savedefault, 58687c478bd9Sstevel@tonic-gate #ifdef SUPPORT_SERIAL 58697c478bd9Sstevel@tonic-gate &builtin_serial, 58707c478bd9Sstevel@tonic-gate #endif /* SUPPORT_SERIAL */ 58717c478bd9Sstevel@tonic-gate &builtin_setkey, 58727c478bd9Sstevel@tonic-gate &builtin_setup, 58737c478bd9Sstevel@tonic-gate #ifdef SUPPORT_GRAPHICS 58747c478bd9Sstevel@tonic-gate &builtin_splashimage, 58757c478bd9Sstevel@tonic-gate #endif /* SUPPORT_GRAPHICS */ 58767c478bd9Sstevel@tonic-gate #if defined(SUPPORT_SERIAL) || defined(SUPPORT_HERCULES) || defined(SUPPORT_GRAPHICS) 58777c478bd9Sstevel@tonic-gate &builtin_terminal, 58787c478bd9Sstevel@tonic-gate #endif /* SUPPORT_SERIAL || SUPPORT_HERCULES || SUPPORT_GRAPHICS */ 58797c478bd9Sstevel@tonic-gate #ifdef SUPPORT_SERIAL 58807c478bd9Sstevel@tonic-gate &builtin_terminfo, 58817c478bd9Sstevel@tonic-gate #endif /* SUPPORT_SERIAL */ 58827c478bd9Sstevel@tonic-gate &builtin_testload, 58837c478bd9Sstevel@tonic-gate &builtin_testvbe, 58847c478bd9Sstevel@tonic-gate #ifdef SUPPORT_NETBOOT 58857c478bd9Sstevel@tonic-gate &builtin_tftpserver, 58867c478bd9Sstevel@tonic-gate #endif /* SUPPORT_NETBOOT */ 58877c478bd9Sstevel@tonic-gate &builtin_timeout, 58887c478bd9Sstevel@tonic-gate &builtin_title, 58897c478bd9Sstevel@tonic-gate &builtin_unhide, 58907c478bd9Sstevel@tonic-gate &builtin_uppermem, 58917c478bd9Sstevel@tonic-gate &builtin_vbeprobe, 58921fac5a60Ssetje &builtin_verbose, 58937c478bd9Sstevel@tonic-gate 0 58947c478bd9Sstevel@tonic-gate }; 5895