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