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); 164*1b8adde7SWilliam 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 169*1b8adde7SWilliam Kucharski auto void disk_read_blocklist_func (unsigned int sector, int offset, 170*1b8adde7SWilliam Kucharski int length); 171*1b8adde7SWilliam 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. */ 174*1b8adde7SWilliam Kucharski auto void disk_read_blocklist_func (unsigned int sector, int offset, 175*1b8adde7SWilliam 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 { 206*1b8adde7SWilliam 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 635*1b8adde7SWilliam Kucharski auto int color_number (char *str); 636*1b8adde7SWilliam Kucharski 6377c478bd9Sstevel@tonic-gate /* Convert the color name STR into the magical number. */ 638*1b8adde7SWilliam Kucharski auto int color_number (char *str) 6397c478bd9Sstevel@tonic-gate { 6407c478bd9Sstevel@tonic-gate char *ptr; 6417c478bd9Sstevel@tonic-gate int i; 6427c478bd9Sstevel@tonic-gate int color = 0; 6437c478bd9Sstevel@tonic-gate 6447c478bd9Sstevel@tonic-gate /* Find the separator. */ 6457c478bd9Sstevel@tonic-gate for (ptr = str; *ptr && *ptr != '/'; ptr++) 6467c478bd9Sstevel@tonic-gate ; 6477c478bd9Sstevel@tonic-gate 6487c478bd9Sstevel@tonic-gate /* If not found, return -1. */ 6497c478bd9Sstevel@tonic-gate if (! *ptr) 6507c478bd9Sstevel@tonic-gate return -1; 6517c478bd9Sstevel@tonic-gate 6527c478bd9Sstevel@tonic-gate /* Terminate the string STR. */ 6537c478bd9Sstevel@tonic-gate *ptr++ = 0; 6547c478bd9Sstevel@tonic-gate 6557c478bd9Sstevel@tonic-gate /* If STR contains the prefix "blink-", then set the `blink' bit 6567c478bd9Sstevel@tonic-gate in COLOR. */ 6577c478bd9Sstevel@tonic-gate if (substring ("blink-", str) <= 0) 6587c478bd9Sstevel@tonic-gate { 6597c478bd9Sstevel@tonic-gate color = 0x80; 6607c478bd9Sstevel@tonic-gate str += 6; 6617c478bd9Sstevel@tonic-gate } 6627c478bd9Sstevel@tonic-gate 6637c478bd9Sstevel@tonic-gate /* Search for the color name. */ 6647c478bd9Sstevel@tonic-gate for (i = 0; i < 16; i++) 6657c478bd9Sstevel@tonic-gate if (grub_strcmp (color_list[i], str) == 0) 6667c478bd9Sstevel@tonic-gate { 6677c478bd9Sstevel@tonic-gate color |= i; 6687c478bd9Sstevel@tonic-gate break; 6697c478bd9Sstevel@tonic-gate } 6707c478bd9Sstevel@tonic-gate 6717c478bd9Sstevel@tonic-gate if (i == 16) 6727c478bd9Sstevel@tonic-gate return -1; 6737c478bd9Sstevel@tonic-gate 6747c478bd9Sstevel@tonic-gate str = ptr; 6757c478bd9Sstevel@tonic-gate nul_terminate (str); 6767c478bd9Sstevel@tonic-gate 6777c478bd9Sstevel@tonic-gate /* Search for the color name. */ 6787c478bd9Sstevel@tonic-gate for (i = 0; i < 8; i++) 6797c478bd9Sstevel@tonic-gate if (grub_strcmp (color_list[i], str) == 0) 6807c478bd9Sstevel@tonic-gate { 6817c478bd9Sstevel@tonic-gate color |= i << 4; 6827c478bd9Sstevel@tonic-gate break; 6837c478bd9Sstevel@tonic-gate } 6847c478bd9Sstevel@tonic-gate 6857c478bd9Sstevel@tonic-gate if (i == 8) 6867c478bd9Sstevel@tonic-gate return -1; 6877c478bd9Sstevel@tonic-gate 6887c478bd9Sstevel@tonic-gate return color; 6897c478bd9Sstevel@tonic-gate } 6907c478bd9Sstevel@tonic-gate 6917c478bd9Sstevel@tonic-gate normal = arg; 6927c478bd9Sstevel@tonic-gate highlight = skip_to (0, arg); 6937c478bd9Sstevel@tonic-gate 6947c478bd9Sstevel@tonic-gate new_normal_color = color_number (normal); 6957c478bd9Sstevel@tonic-gate if (new_normal_color < 0 && ! safe_parse_maxint (&normal, &new_normal_color)) 6967c478bd9Sstevel@tonic-gate return 1; 6977c478bd9Sstevel@tonic-gate 6987c478bd9Sstevel@tonic-gate /* The second argument is optional, so set highlight_color 6997c478bd9Sstevel@tonic-gate to inverted NORMAL_COLOR. */ 7007c478bd9Sstevel@tonic-gate if (! *highlight) 7017c478bd9Sstevel@tonic-gate new_highlight_color = ((new_normal_color >> 4) 7027c478bd9Sstevel@tonic-gate | ((new_normal_color & 0xf) << 4)); 7037c478bd9Sstevel@tonic-gate else 7047c478bd9Sstevel@tonic-gate { 7057c478bd9Sstevel@tonic-gate new_highlight_color = color_number (highlight); 7067c478bd9Sstevel@tonic-gate if (new_highlight_color < 0 7077c478bd9Sstevel@tonic-gate && ! safe_parse_maxint (&highlight, &new_highlight_color)) 7087c478bd9Sstevel@tonic-gate return 1; 7097c478bd9Sstevel@tonic-gate } 7107c478bd9Sstevel@tonic-gate 7117c478bd9Sstevel@tonic-gate if (current_term->setcolor) 7127c478bd9Sstevel@tonic-gate current_term->setcolor (new_normal_color, new_highlight_color); 7137c478bd9Sstevel@tonic-gate 7147c478bd9Sstevel@tonic-gate return 0; 7157c478bd9Sstevel@tonic-gate } 7167c478bd9Sstevel@tonic-gate 7177c478bd9Sstevel@tonic-gate static struct builtin builtin_color = 7187c478bd9Sstevel@tonic-gate { 7197c478bd9Sstevel@tonic-gate "color", 7207c478bd9Sstevel@tonic-gate color_func, 7217c478bd9Sstevel@tonic-gate BUILTIN_CMDLINE | BUILTIN_MENU | BUILTIN_HELP_LIST, 7227c478bd9Sstevel@tonic-gate "color NORMAL [HIGHLIGHT]", 7237c478bd9Sstevel@tonic-gate "Change the menu colors. The color NORMAL is used for most" 7247c478bd9Sstevel@tonic-gate " lines in the menu, and the color HIGHLIGHT is used to highlight the" 7257c478bd9Sstevel@tonic-gate " line where the cursor points. If you omit HIGHLIGHT, then the" 7267c478bd9Sstevel@tonic-gate " inverted color of NORMAL is used for the highlighted line." 7277c478bd9Sstevel@tonic-gate " The format of a color is \"FG/BG\". FG and BG are symbolic color names." 7287c478bd9Sstevel@tonic-gate " A symbolic color name must be one of these: black, blue, green," 7297c478bd9Sstevel@tonic-gate " cyan, red, magenta, brown, light-gray, dark-gray, light-blue," 7307c478bd9Sstevel@tonic-gate " light-green, light-cyan, light-red, light-magenta, yellow and white." 7317c478bd9Sstevel@tonic-gate " But only the first eight names can be used for BG. You can prefix" 7327c478bd9Sstevel@tonic-gate " \"blink-\" to FG if you want a blinking foreground color." 7337c478bd9Sstevel@tonic-gate }; 7347c478bd9Sstevel@tonic-gate 7357c478bd9Sstevel@tonic-gate 7367c478bd9Sstevel@tonic-gate /* configfile */ 7377c478bd9Sstevel@tonic-gate static int 7387c478bd9Sstevel@tonic-gate configfile_func (char *arg, int flags) 7397c478bd9Sstevel@tonic-gate { 7407c478bd9Sstevel@tonic-gate char *new_config = config_file; 7417c478bd9Sstevel@tonic-gate 7427c478bd9Sstevel@tonic-gate /* Check if the file ARG is present. */ 7437c478bd9Sstevel@tonic-gate if (! grub_open (arg)) 7447c478bd9Sstevel@tonic-gate return 1; 7457c478bd9Sstevel@tonic-gate 7467c478bd9Sstevel@tonic-gate grub_close (); 7477c478bd9Sstevel@tonic-gate 7487c478bd9Sstevel@tonic-gate /* Copy ARG to CONFIG_FILE. */ 7497c478bd9Sstevel@tonic-gate while ((*new_config++ = *arg++) != 0) 7507c478bd9Sstevel@tonic-gate ; 7517c478bd9Sstevel@tonic-gate 7527c478bd9Sstevel@tonic-gate #ifdef GRUB_UTIL 7537c478bd9Sstevel@tonic-gate /* Force to load the configuration file. */ 7547c478bd9Sstevel@tonic-gate use_config_file = 1; 7557c478bd9Sstevel@tonic-gate #endif 7567c478bd9Sstevel@tonic-gate 7577c478bd9Sstevel@tonic-gate /* Make sure that the user will not be authoritative. */ 7587c478bd9Sstevel@tonic-gate auth = 0; 7597c478bd9Sstevel@tonic-gate 7607c478bd9Sstevel@tonic-gate /* Restart cmain. */ 7617c478bd9Sstevel@tonic-gate grub_longjmp (restart_env, 0); 7627c478bd9Sstevel@tonic-gate 7637c478bd9Sstevel@tonic-gate /* Never reach here. */ 7647c478bd9Sstevel@tonic-gate return 0; 7657c478bd9Sstevel@tonic-gate } 7667c478bd9Sstevel@tonic-gate 7677c478bd9Sstevel@tonic-gate static struct builtin builtin_configfile = 7687c478bd9Sstevel@tonic-gate { 7697c478bd9Sstevel@tonic-gate "configfile", 7707c478bd9Sstevel@tonic-gate configfile_func, 7717c478bd9Sstevel@tonic-gate BUILTIN_CMDLINE | BUILTIN_HELP_LIST, 7727c478bd9Sstevel@tonic-gate "configfile FILE", 7737c478bd9Sstevel@tonic-gate "Load FILE as the configuration file." 7747c478bd9Sstevel@tonic-gate }; 7757c478bd9Sstevel@tonic-gate 7767c478bd9Sstevel@tonic-gate 7777c478bd9Sstevel@tonic-gate /* debug */ 7787c478bd9Sstevel@tonic-gate static int 7797c478bd9Sstevel@tonic-gate debug_func (char *arg, int flags) 7807c478bd9Sstevel@tonic-gate { 7817c478bd9Sstevel@tonic-gate if (debug) 7827c478bd9Sstevel@tonic-gate { 7837c478bd9Sstevel@tonic-gate debug = 0; 7847c478bd9Sstevel@tonic-gate grub_printf (" Debug mode is turned off\n"); 7857c478bd9Sstevel@tonic-gate } 7867c478bd9Sstevel@tonic-gate else 7877c478bd9Sstevel@tonic-gate { 7887c478bd9Sstevel@tonic-gate debug = 1; 7897c478bd9Sstevel@tonic-gate grub_printf (" Debug mode is turned on\n"); 7907c478bd9Sstevel@tonic-gate } 7917c478bd9Sstevel@tonic-gate 7927c478bd9Sstevel@tonic-gate return 0; 7937c478bd9Sstevel@tonic-gate } 7947c478bd9Sstevel@tonic-gate 7957c478bd9Sstevel@tonic-gate static struct builtin builtin_debug = 7967c478bd9Sstevel@tonic-gate { 7977c478bd9Sstevel@tonic-gate "debug", 7987c478bd9Sstevel@tonic-gate debug_func, 7997c478bd9Sstevel@tonic-gate BUILTIN_CMDLINE, 8007c478bd9Sstevel@tonic-gate "debug", 8017c478bd9Sstevel@tonic-gate "Turn on/off the debug mode." 8027c478bd9Sstevel@tonic-gate }; 8037c478bd9Sstevel@tonic-gate 8047c478bd9Sstevel@tonic-gate 8057c478bd9Sstevel@tonic-gate /* default */ 8067c478bd9Sstevel@tonic-gate static int 8077c478bd9Sstevel@tonic-gate default_func (char *arg, int flags) 8087c478bd9Sstevel@tonic-gate { 8097c478bd9Sstevel@tonic-gate #ifndef SUPPORT_DISKLESS 8107c478bd9Sstevel@tonic-gate if (grub_strcmp (arg, "saved") == 0) 8117c478bd9Sstevel@tonic-gate { 8127c478bd9Sstevel@tonic-gate default_entry = saved_entryno; 8137c478bd9Sstevel@tonic-gate return 0; 8147c478bd9Sstevel@tonic-gate } 8157c478bd9Sstevel@tonic-gate #endif /* SUPPORT_DISKLESS */ 8167c478bd9Sstevel@tonic-gate 8177c478bd9Sstevel@tonic-gate if (! safe_parse_maxint (&arg, &default_entry)) 8187c478bd9Sstevel@tonic-gate return 1; 8197c478bd9Sstevel@tonic-gate 8207c478bd9Sstevel@tonic-gate return 0; 8217c478bd9Sstevel@tonic-gate } 8227c478bd9Sstevel@tonic-gate 8237c478bd9Sstevel@tonic-gate static struct builtin builtin_default = 8247c478bd9Sstevel@tonic-gate { 8257c478bd9Sstevel@tonic-gate "default", 8267c478bd9Sstevel@tonic-gate default_func, 8277c478bd9Sstevel@tonic-gate BUILTIN_MENU, 8287c478bd9Sstevel@tonic-gate #if 0 8297c478bd9Sstevel@tonic-gate "default [NUM | `saved']", 8307c478bd9Sstevel@tonic-gate "Set the default entry to entry number NUM (if not specified, it is" 8317c478bd9Sstevel@tonic-gate " 0, the first entry) or the entry number saved by savedefault." 8327c478bd9Sstevel@tonic-gate #endif 8337c478bd9Sstevel@tonic-gate }; 8347c478bd9Sstevel@tonic-gate 8357c478bd9Sstevel@tonic-gate 8367c478bd9Sstevel@tonic-gate #ifdef GRUB_UTIL 8377c478bd9Sstevel@tonic-gate /* device */ 8387c478bd9Sstevel@tonic-gate static int 8397c478bd9Sstevel@tonic-gate device_func (char *arg, int flags) 8407c478bd9Sstevel@tonic-gate { 8417c478bd9Sstevel@tonic-gate char *drive = arg; 8427c478bd9Sstevel@tonic-gate char *device; 8437c478bd9Sstevel@tonic-gate 8447c478bd9Sstevel@tonic-gate /* Get the drive number from DRIVE. */ 8457c478bd9Sstevel@tonic-gate if (! set_device (drive)) 8467c478bd9Sstevel@tonic-gate return 1; 8477c478bd9Sstevel@tonic-gate 8487c478bd9Sstevel@tonic-gate /* Get the device argument. */ 8497c478bd9Sstevel@tonic-gate device = skip_to (0, drive); 8507c478bd9Sstevel@tonic-gate 8517c478bd9Sstevel@tonic-gate /* Terminate DEVICE. */ 8527c478bd9Sstevel@tonic-gate nul_terminate (device); 8537c478bd9Sstevel@tonic-gate 8547c478bd9Sstevel@tonic-gate if (! *device || ! check_device (device)) 8557c478bd9Sstevel@tonic-gate { 8567c478bd9Sstevel@tonic-gate errnum = ERR_FILE_NOT_FOUND; 8577c478bd9Sstevel@tonic-gate return 1; 8587c478bd9Sstevel@tonic-gate } 8597c478bd9Sstevel@tonic-gate 8607c478bd9Sstevel@tonic-gate assign_device_name (current_drive, device); 8617c478bd9Sstevel@tonic-gate 8627c478bd9Sstevel@tonic-gate return 0; 8637c478bd9Sstevel@tonic-gate } 8647c478bd9Sstevel@tonic-gate 8657c478bd9Sstevel@tonic-gate static struct builtin builtin_device = 8667c478bd9Sstevel@tonic-gate { 8677c478bd9Sstevel@tonic-gate "device", 8687c478bd9Sstevel@tonic-gate device_func, 8697c478bd9Sstevel@tonic-gate BUILTIN_MENU | BUILTIN_CMDLINE | BUILTIN_HELP_LIST, 8707c478bd9Sstevel@tonic-gate "device DRIVE DEVICE", 8717c478bd9Sstevel@tonic-gate "Specify DEVICE as the actual drive for a BIOS drive DRIVE. This command" 8727c478bd9Sstevel@tonic-gate " can be used only in the grub shell." 8737c478bd9Sstevel@tonic-gate }; 8747c478bd9Sstevel@tonic-gate #endif /* GRUB_UTIL */ 8757c478bd9Sstevel@tonic-gate 8767c478bd9Sstevel@tonic-gate #ifdef SUPPORT_NETBOOT 8777c478bd9Sstevel@tonic-gate /* Debug Function for RPC */ 8787c478bd9Sstevel@tonic-gate #ifdef RPC_DEBUG 8797c478bd9Sstevel@tonic-gate /* portmap */ 8807c478bd9Sstevel@tonic-gate static int 8817c478bd9Sstevel@tonic-gate portmap_func (char *arg, int flags) 8827c478bd9Sstevel@tonic-gate { 8837c478bd9Sstevel@tonic-gate int port, prog, ver; 8847c478bd9Sstevel@tonic-gate if (! grub_eth_probe ()){ 8857c478bd9Sstevel@tonic-gate grub_printf ("No ethernet card found.\n"); 8867c478bd9Sstevel@tonic-gate errnum = ERR_DEV_VALUES; 8877c478bd9Sstevel@tonic-gate return 1; 8887c478bd9Sstevel@tonic-gate } 8897c478bd9Sstevel@tonic-gate if ((prog = getdec(&arg)) == -1){ 8907c478bd9Sstevel@tonic-gate grub_printf("Error prog number\n"); 8917c478bd9Sstevel@tonic-gate return 1; 8927c478bd9Sstevel@tonic-gate } 8937c478bd9Sstevel@tonic-gate arg = skip_to (0, arg); 8947c478bd9Sstevel@tonic-gate if ((ver = getdec(&arg)) == -1){ 8957c478bd9Sstevel@tonic-gate grub_printf("Error ver number\n"); 8967c478bd9Sstevel@tonic-gate return 1; 8977c478bd9Sstevel@tonic-gate } 8987c478bd9Sstevel@tonic-gate port = __pmapudp_getport(ARP_SERVER, prog, ver); 8997c478bd9Sstevel@tonic-gate printf("portmap getport %d", port); 9007c478bd9Sstevel@tonic-gate return 0; 9017c478bd9Sstevel@tonic-gate } 9027c478bd9Sstevel@tonic-gate 9037c478bd9Sstevel@tonic-gate static struct builtin builtin_portmap = 9047c478bd9Sstevel@tonic-gate { 9057c478bd9Sstevel@tonic-gate "portmap", 9067c478bd9Sstevel@tonic-gate portmap_func, 9077c478bd9Sstevel@tonic-gate BUILTIN_CMDLINE | BUILTIN_HELP_LIST, 9087c478bd9Sstevel@tonic-gate "portmap prog_number vers_number", 9097c478bd9Sstevel@tonic-gate "Do portmap with the prog_number and vers_number" 9107c478bd9Sstevel@tonic-gate }; 9117c478bd9Sstevel@tonic-gate #endif /* RPC_DEBUG */ 9127c478bd9Sstevel@tonic-gate 9137c478bd9Sstevel@tonic-gate /* dhcp */ 9147c478bd9Sstevel@tonic-gate static int 9157c478bd9Sstevel@tonic-gate dhcp_func (char *arg, int flags) 9167c478bd9Sstevel@tonic-gate { 9177c478bd9Sstevel@tonic-gate int with_configfile = 0; 9187c478bd9Sstevel@tonic-gate 9197c478bd9Sstevel@tonic-gate if (grub_memcmp (arg, "--with-configfile", sizeof ("--with-configfile") - 1) 9207c478bd9Sstevel@tonic-gate == 0) 9217c478bd9Sstevel@tonic-gate { 9227c478bd9Sstevel@tonic-gate with_configfile = 1; 9237c478bd9Sstevel@tonic-gate arg = skip_to (0, arg); 9247c478bd9Sstevel@tonic-gate } 9257c478bd9Sstevel@tonic-gate 9267c478bd9Sstevel@tonic-gate if (! dhcp ()) 9277c478bd9Sstevel@tonic-gate { 9287c478bd9Sstevel@tonic-gate if (errnum == ERR_NONE) 9297c478bd9Sstevel@tonic-gate errnum = ERR_DEV_VALUES; 9307c478bd9Sstevel@tonic-gate 9317c478bd9Sstevel@tonic-gate return 1; 9327c478bd9Sstevel@tonic-gate } 9337c478bd9Sstevel@tonic-gate 9347c478bd9Sstevel@tonic-gate /* Notify the configuration. */ 9357c478bd9Sstevel@tonic-gate print_network_configuration (); 9367c478bd9Sstevel@tonic-gate 9377c478bd9Sstevel@tonic-gate /* XXX: this can cause an endless loop, but there is no easy way to 9387c478bd9Sstevel@tonic-gate detect such a loop unfortunately. */ 9397c478bd9Sstevel@tonic-gate if (with_configfile) 9407c478bd9Sstevel@tonic-gate configfile_func (config_file, flags); 9417c478bd9Sstevel@tonic-gate else 9427c478bd9Sstevel@tonic-gate solaris_config_file(); 9437c478bd9Sstevel@tonic-gate 9447c478bd9Sstevel@tonic-gate return 0; 9457c478bd9Sstevel@tonic-gate } 9467c478bd9Sstevel@tonic-gate 9477c478bd9Sstevel@tonic-gate static void solaris_config_file (void) 9487c478bd9Sstevel@tonic-gate { 9497c478bd9Sstevel@tonic-gate static char menufile[64]; 9507c478bd9Sstevel@tonic-gate static char hexdigit[] = "0123456789ABCDEF"; 9517c478bd9Sstevel@tonic-gate char *c = menufile; 9527c478bd9Sstevel@tonic-gate int i; 9536759d08fScasper int err; 9547c478bd9Sstevel@tonic-gate 9557c478bd9Sstevel@tonic-gate /* if config_file is from DHCP option 150, keep the setting */ 9567c478bd9Sstevel@tonic-gate if (grub_strcmp(config_file, "/boot/grub/menu.lst") != 0) 9577c478bd9Sstevel@tonic-gate return; 9587c478bd9Sstevel@tonic-gate 9592269adc8Sszhou /* default solaris configfile name menu.lst.01<ether_addr> */ 9602269adc8Sszhou grub_strcpy(c, "menu.lst.01"); 9617c478bd9Sstevel@tonic-gate c += grub_strlen(c); 9627c478bd9Sstevel@tonic-gate for (i = 0; i < ETH_ALEN; i++) { 9637c478bd9Sstevel@tonic-gate unsigned char b = arptable[ARP_CLIENT].node[i]; 9647c478bd9Sstevel@tonic-gate *c++ = hexdigit[b >> 4]; 9657c478bd9Sstevel@tonic-gate *c++ = hexdigit[b & 0xf]; 9667c478bd9Sstevel@tonic-gate } 9677c478bd9Sstevel@tonic-gate *c = 0; 9687c478bd9Sstevel@tonic-gate 9696759d08fScasper /* 9706759d08fScasper * If the file exists, make it the default. Else, fallback 9716759d08fScasper * to what it was. Make sure we don't change errnum in the 9726759d08fScasper * process. 9737c478bd9Sstevel@tonic-gate */ 9746759d08fScasper err = errnum; 9757c478bd9Sstevel@tonic-gate if (grub_open(menufile)) { 9767c478bd9Sstevel@tonic-gate grub_strcpy(config_file, menufile); 9777c478bd9Sstevel@tonic-gate grub_close(); 9782269adc8Sszhou } else { 9792269adc8Sszhou char *cp = config_file; 9802269adc8Sszhou /* skip leading slashes for tftp */ 981266095caSszhou while (*cp == '/') 982266095caSszhou ++cp; 9832269adc8Sszhou grub_memmove (config_file, cp, strlen(cp) + 1); 9847c478bd9Sstevel@tonic-gate } 9856759d08fScasper errnum = err; 9867c478bd9Sstevel@tonic-gate } 9877c478bd9Sstevel@tonic-gate 9887c478bd9Sstevel@tonic-gate static struct builtin builtin_dhcp = 9897c478bd9Sstevel@tonic-gate { 9907c478bd9Sstevel@tonic-gate "dhcp", 9917c478bd9Sstevel@tonic-gate dhcp_func, 9927c478bd9Sstevel@tonic-gate BUILTIN_CMDLINE | BUILTIN_MENU | BUILTIN_HELP_LIST, 9937c478bd9Sstevel@tonic-gate "dhcp", 9947c478bd9Sstevel@tonic-gate "Initialize a network device via DHCP." 9957c478bd9Sstevel@tonic-gate }; 9967c478bd9Sstevel@tonic-gate #endif /* SUPPORT_NETBOOT */ 9977c478bd9Sstevel@tonic-gate 9987c478bd9Sstevel@tonic-gate static int terminal_func (char *arg, int flags); 9997c478bd9Sstevel@tonic-gate 10001fac5a60Ssetje static int verbose_func(char *arg, int flags) { 10011fac5a60Ssetje 10021fac5a60Ssetje if (grub_strcmp(arg, "off") == 0) { 10031fac5a60Ssetje silent.status = DEFER_SILENT; 10041fac5a60Ssetje return; 10051fac5a60Ssetje } else 10061fac5a60Ssetje if (flags == BUILTIN_CMDLINE) { 10071fac5a60Ssetje silent.status = DEFER_VERBOSE; 10081fac5a60Ssetje return; 10091fac5a60Ssetje } 10101fac5a60Ssetje 10111fac5a60Ssetje silent.status = VERBOSE; 10121fac5a60Ssetje 1013ae115bc7Smrj /* get back to text console */ 10141fac5a60Ssetje if (current_term->shutdown) { 10151fac5a60Ssetje (*current_term->shutdown)(); 10161fac5a60Ssetje current_term = term_table; /* assumption: console is first */ 10171fac5a60Ssetje } 10181fac5a60Ssetje 10191fac5a60Ssetje /* dump the buffer */ 10201fac5a60Ssetje if (!silent.looped) { 10211fac5a60Ssetje /* if the buffer hasn't looped, just print it */ 10221fac5a60Ssetje printf("%s", silent.buffer); 10231fac5a60Ssetje } else { 10241fac5a60Ssetje /* 10251fac5a60Ssetje * If the buffer has looped, first print the oldest part of the buffer, 10261fac5a60Ssetje * which is one past the current null. Then print the newer part which 10271fac5a60Ssetje * starts at the beginning of the buffer. 10281fac5a60Ssetje */ 10291fac5a60Ssetje printf("%s", silent.buffer_start + 1); 10301fac5a60Ssetje printf("%s", silent.buffer); 10311fac5a60Ssetje } 10321fac5a60Ssetje 10331fac5a60Ssetje return 0; 10341fac5a60Ssetje } 10351fac5a60Ssetje 10361fac5a60Ssetje static struct builtin builtin_verbose = 10371fac5a60Ssetje { 10381fac5a60Ssetje "verbose", 10391fac5a60Ssetje verbose_func, 10401fac5a60Ssetje BUILTIN_CMDLINE | BUILTIN_MENU | BUILTIN_SCRIPT | BUILTIN_HELP_LIST, 10411fac5a60Ssetje "verbose", 10421fac5a60Ssetje "Verbose output during menu entry (script) execution." 10431fac5a60Ssetje }; 10441fac5a60Ssetje 10457c478bd9Sstevel@tonic-gate #ifdef SUPPORT_GRAPHICS 10467c478bd9Sstevel@tonic-gate 10477c478bd9Sstevel@tonic-gate static int splashimage_func(char *arg, int flags) { 10487c478bd9Sstevel@tonic-gate char splashimage[64]; 10497c478bd9Sstevel@tonic-gate int i; 10501fac5a60Ssetje 10517c478bd9Sstevel@tonic-gate /* filename can only be 64 characters due to our buffer size */ 10527c478bd9Sstevel@tonic-gate if (strlen(arg) > 63) 10537c478bd9Sstevel@tonic-gate return 1; 10547c478bd9Sstevel@tonic-gate 10551fac5a60Ssetje if (flags == BUILTIN_SCRIPT) 10561fac5a60Ssetje flags = BUILTIN_CMDLINE; 10571fac5a60Ssetje 10587c478bd9Sstevel@tonic-gate if (flags == BUILTIN_CMDLINE) { 10597c478bd9Sstevel@tonic-gate if (!grub_open(arg)) 10607c478bd9Sstevel@tonic-gate return 1; 10617c478bd9Sstevel@tonic-gate grub_close(); 10627c478bd9Sstevel@tonic-gate } 10637c478bd9Sstevel@tonic-gate 10647c478bd9Sstevel@tonic-gate strcpy(splashimage, arg); 10657c478bd9Sstevel@tonic-gate 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 10747c478bd9Sstevel@tonic-gate graphics_set_splash(splashimage); 10757c478bd9Sstevel@tonic-gate 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 2204*1b8adde7SWilliam Kucharski auto void disk_read_savesect_func (unsigned int sector, int offset, 2205*1b8adde7SWilliam Kucharski int length); 2206*1b8adde7SWilliam Kucharski auto void disk_read_blocklist_func (unsigned int sector, int offset, 2207*1b8adde7SWilliam Kucharski int length); 2208*1b8adde7SWilliam Kucharski 22097c478bd9Sstevel@tonic-gate /* Save the first sector of Stage2 in STAGE2_SECT. */ 2210*1b8adde7SWilliam Kucharski auto void disk_read_savesect_func (unsigned int sector, int offset, 2211*1b8adde7SWilliam 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. */ 2227*1b8adde7SWilliam Kucharski auto void disk_read_blocklist_func (unsigned int sector, int offset, 2228*1b8adde7SWilliam 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 2382*1b8adde7SWilliam Kucharski /* If DEST_DRIVE is a hard disk, enable the workaround, which is 2383*1b8adde7SWilliam Kucharski for buggy BIOSes which don't pass boot drive correctly. Instead, 2384*1b8adde7SWilliam Kucharski they pass 0x00 or 0x01 even when booted from 0x80. */ 2385*1b8adde7SWilliam Kucharski if (dest_drive & BIOS_FLAG_FIXED_DISK) 2386*1b8adde7SWilliam Kucharski /* Replace the jmp (2 bytes) with double nop's. */ 2387*1b8adde7SWilliam Kucharski *((unsigned short *) (stage1_buffer + STAGE1_BOOT_DRIVE_CHECK)) 2388*1b8adde7SWilliam Kucharski = 0x9090; 2389*1b8adde7SWilliam 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 2756b1b8ab34Slling * must include "-B $ZFS-BOOTFS" to pass to the kernel: 2757b1b8ab34Slling * 2758b1b8ab34Slling * e.g. 2759b1b8ab34Slling * kernel$ /platform/i86pc/kernel/$ISADIR/unix -B $ZFS-BOOTFS,console=ttya 2760b1b8ab34Slling * 2761b1b8ab34Slling * The expand_dollar_bootfs routine expands $ZFS-BOOTFS to 2762b1b8ab34Slling * "pool-name/zfs-rootfilesystem-object-num", e.g. "rootpool/85" 2763b1b8ab34Slling * so that in the kernel zfs_mountroot would know which zfs root 2764b1b8ab34Slling * filesystem to be mounted. 2765b1b8ab34Slling */ 2766b1b8ab34Slling static int 2767b1b8ab34Slling expand_dollar_bootfs(char *in, char *out) 2768b1b8ab34Slling { 2769b1b8ab34Slling char *token, *tmpout = out; 2770b1b8ab34Slling int outlen, blen; 2771bf82a41bSeschrock int postcomma = 0; 2772b1b8ab34Slling 2773b1b8ab34Slling outlen = strlen(in); 2774b1b8ab34Slling blen = current_bootfs_obj == 0 ? strlen(current_rootpool) : 2775b1b8ab34Slling strlen(current_rootpool) + 11; 2776b1b8ab34Slling 2777b1b8ab34Slling out[0] = '\0'; 2778b1b8ab34Slling while (token = strstr(in, "$ZFS-BOOTFS")) { 2779b1b8ab34Slling 2780b1b8ab34Slling if ((outlen += blen) > MAX_CMDLINE) { 2781b1b8ab34Slling errnum = ERR_WONT_FIT; 2782b1b8ab34Slling return (1); 2783b1b8ab34Slling } 2784b1b8ab34Slling 2785b1b8ab34Slling token[0] = '\0'; 2786b1b8ab34Slling grub_sprintf(tmpout, "%s", in); 2787b1b8ab34Slling token[0] = '$'; 2788051aabe6Staylor in = token + 11; /* skip over $ZFS-BOOTFS */ 2789b1b8ab34Slling tmpout = out + strlen(out); 2790b1b8ab34Slling 2791b1b8ab34Slling /* Note: %u only fits 32 bit integer; */ 2792b1b8ab34Slling if (current_bootfs_obj > 0) 2793b1b8ab34Slling grub_sprintf(tmpout, "zfs-bootfs=%s/%u", 2794b1b8ab34Slling current_rootpool, current_bootfs_obj); 2795b1b8ab34Slling else 2796b1b8ab34Slling grub_sprintf(tmpout, "zfs-bootfs=%s", 2797b1b8ab34Slling current_rootpool); 2798b1b8ab34Slling tmpout = out + strlen(out); 2799b1b8ab34Slling } 2800b1b8ab34Slling 2801e7cbe64fSgw /* 2802bf82a41bSeschrock * Check to see if 'zfs-bootfs' was explicitly specified on the command 2803bf82a41bSeschrock * line so that we can insert the 'bootpath' property. 2804bf82a41bSeschrock */ 2805bf82a41bSeschrock if ((tmpout == out) && (token = strstr(in, "zfs-bootfs")) != NULL) { 2806bf82a41bSeschrock token[0] = '\0'; 2807bf82a41bSeschrock grub_strcpy(tmpout, in); 2808bf82a41bSeschrock token[0] = 'z'; 2809bf82a41bSeschrock in = token; 2810bf82a41bSeschrock 2811bf82a41bSeschrock tmpout = out + strlen(out); 2812bf82a41bSeschrock postcomma = 1; 2813bf82a41bSeschrock } 2814bf82a41bSeschrock 2815bf82a41bSeschrock /* 2816bf82a41bSeschrock * Set the 'bootpath' property if a ZFS dataset was specified, either 2817bf82a41bSeschrock * through '$ZFS-BOOTFS' or an explicit 'zfs-bootfs' setting. 2818e7cbe64fSgw */ 2819e7cbe64fSgw if (tmpout != out) { 2820e7cbe64fSgw if ((outlen += 12 + strlen(current_bootpath)) > MAX_CMDLINE) { 2821e7cbe64fSgw errnum = ERR_WONT_FIT; 2822e7cbe64fSgw return (1); 2823e7cbe64fSgw } 2824bf82a41bSeschrock grub_sprintf(tmpout, 2825bf82a41bSeschrock postcomma ? "bootpath=\"%s\"," : ",bootpath=\"%s\"", 2826bf82a41bSeschrock current_bootpath); 2827051aabe6Staylor tmpout = out + strlen(out); 2828051aabe6Staylor } 2829051aabe6Staylor if (strlen(current_devid)) { 2830051aabe6Staylor if ((outlen += 13 + strlen(current_devid)) > MAX_CMDLINE) { 2831051aabe6Staylor errnum = ERR_WONT_FIT; 2832051aabe6Staylor return (1); 2833051aabe6Staylor } 2834051aabe6Staylor grub_sprintf(tmpout, 2835051aabe6Staylor postcomma ? "diskdevid=\"%s\"," : ",diskdevid=\"%s\"", 2836051aabe6Staylor current_devid); 2837e7cbe64fSgw } 2838e7cbe64fSgw 2839b1b8ab34Slling strncat(out, in, MAX_CMDLINE); 2840b1b8ab34Slling return (0); 2841b1b8ab34Slling } 2842b1b8ab34Slling 28437c478bd9Sstevel@tonic-gate /* kernel */ 28447c478bd9Sstevel@tonic-gate static int 28457c478bd9Sstevel@tonic-gate kernel_func (char *arg, int flags) 28467c478bd9Sstevel@tonic-gate { 28477c478bd9Sstevel@tonic-gate int len; 28487c478bd9Sstevel@tonic-gate kernel_t suggested_type = KERNEL_TYPE_NONE; 28497c478bd9Sstevel@tonic-gate unsigned long load_flags = 0; 28507c478bd9Sstevel@tonic-gate 28517c478bd9Sstevel@tonic-gate #ifndef AUTO_LINUX_MEM_OPT 28527c478bd9Sstevel@tonic-gate load_flags |= KERNEL_LOAD_NO_MEM_OPTION; 28537c478bd9Sstevel@tonic-gate #endif 28547c478bd9Sstevel@tonic-gate 28557c478bd9Sstevel@tonic-gate /* Deal with GNU-style long options. */ 28567c478bd9Sstevel@tonic-gate while (1) 28577c478bd9Sstevel@tonic-gate { 28587c478bd9Sstevel@tonic-gate /* If the option `--type=TYPE' is specified, convert the string to 28597c478bd9Sstevel@tonic-gate a kernel type. */ 28607c478bd9Sstevel@tonic-gate if (grub_memcmp (arg, "--type=", 7) == 0) 28617c478bd9Sstevel@tonic-gate { 28627c478bd9Sstevel@tonic-gate arg += 7; 28637c478bd9Sstevel@tonic-gate 28647c478bd9Sstevel@tonic-gate if (grub_memcmp (arg, "netbsd", 6) == 0) 28657c478bd9Sstevel@tonic-gate suggested_type = KERNEL_TYPE_NETBSD; 28667c478bd9Sstevel@tonic-gate else if (grub_memcmp (arg, "freebsd", 7) == 0) 28677c478bd9Sstevel@tonic-gate suggested_type = KERNEL_TYPE_FREEBSD; 28687c478bd9Sstevel@tonic-gate else if (grub_memcmp (arg, "openbsd", 7) == 0) 28697c478bd9Sstevel@tonic-gate /* XXX: For now, OpenBSD is identical to NetBSD, from GRUB's 28707c478bd9Sstevel@tonic-gate point of view. */ 28717c478bd9Sstevel@tonic-gate suggested_type = KERNEL_TYPE_NETBSD; 28727c478bd9Sstevel@tonic-gate else if (grub_memcmp (arg, "linux", 5) == 0) 28737c478bd9Sstevel@tonic-gate suggested_type = KERNEL_TYPE_LINUX; 28747c478bd9Sstevel@tonic-gate else if (grub_memcmp (arg, "biglinux", 8) == 0) 28757c478bd9Sstevel@tonic-gate suggested_type = KERNEL_TYPE_BIG_LINUX; 28767c478bd9Sstevel@tonic-gate else if (grub_memcmp (arg, "multiboot", 9) == 0) 28777c478bd9Sstevel@tonic-gate suggested_type = KERNEL_TYPE_MULTIBOOT; 28787c478bd9Sstevel@tonic-gate else 28797c478bd9Sstevel@tonic-gate { 28807c478bd9Sstevel@tonic-gate errnum = ERR_BAD_ARGUMENT; 28817c478bd9Sstevel@tonic-gate return 1; 28827c478bd9Sstevel@tonic-gate } 28837c478bd9Sstevel@tonic-gate } 28847c478bd9Sstevel@tonic-gate /* If the `--no-mem-option' is specified, don't pass a Linux's mem 28857c478bd9Sstevel@tonic-gate option automatically. If the kernel is another type, this flag 28867c478bd9Sstevel@tonic-gate has no effect. */ 28877c478bd9Sstevel@tonic-gate else if (grub_memcmp (arg, "--no-mem-option", 15) == 0) 28887c478bd9Sstevel@tonic-gate load_flags |= KERNEL_LOAD_NO_MEM_OPTION; 28897c478bd9Sstevel@tonic-gate else 28907c478bd9Sstevel@tonic-gate break; 28917c478bd9Sstevel@tonic-gate 28927c478bd9Sstevel@tonic-gate /* Try the next. */ 28937c478bd9Sstevel@tonic-gate arg = skip_to (0, arg); 28947c478bd9Sstevel@tonic-gate } 28957c478bd9Sstevel@tonic-gate 28967c478bd9Sstevel@tonic-gate len = grub_strlen (arg); 28977c478bd9Sstevel@tonic-gate 28987c478bd9Sstevel@tonic-gate /* Reset MB_CMDLINE. */ 28997c478bd9Sstevel@tonic-gate mb_cmdline = (char *) MB_CMDLINE_BUF; 29007c478bd9Sstevel@tonic-gate if (len + 1 > MB_CMDLINE_BUFLEN) 29017c478bd9Sstevel@tonic-gate { 29027c478bd9Sstevel@tonic-gate errnum = ERR_WONT_FIT; 29037c478bd9Sstevel@tonic-gate return 1; 29047c478bd9Sstevel@tonic-gate } 29057c478bd9Sstevel@tonic-gate 29067c478bd9Sstevel@tonic-gate /* Copy the command-line to MB_CMDLINE. */ 29077c478bd9Sstevel@tonic-gate grub_memmove (mb_cmdline, arg, len + 1); 29087c478bd9Sstevel@tonic-gate kernel_type = load_image (arg, mb_cmdline, suggested_type, load_flags); 29097c478bd9Sstevel@tonic-gate if (kernel_type == KERNEL_TYPE_NONE) 29107c478bd9Sstevel@tonic-gate return 1; 29117c478bd9Sstevel@tonic-gate 2912b1b8ab34Slling mb_cmdline += grub_strlen(mb_cmdline) + 1; 29137c478bd9Sstevel@tonic-gate return 0; 29147c478bd9Sstevel@tonic-gate } 29157c478bd9Sstevel@tonic-gate 29167c478bd9Sstevel@tonic-gate static struct builtin builtin_kernel = 29177c478bd9Sstevel@tonic-gate { 29187c478bd9Sstevel@tonic-gate "kernel", 29197c478bd9Sstevel@tonic-gate kernel_func, 29207c478bd9Sstevel@tonic-gate BUILTIN_CMDLINE | BUILTIN_HELP_LIST, 29217c478bd9Sstevel@tonic-gate "kernel [--no-mem-option] [--type=TYPE] FILE [ARG ...]", 29227c478bd9Sstevel@tonic-gate "Attempt to load the primary boot image from FILE. The rest of the" 29237c478bd9Sstevel@tonic-gate " line is passed verbatim as the \"kernel command line\". Any modules" 29247c478bd9Sstevel@tonic-gate " must be reloaded after using this command. The option --type is used" 29257c478bd9Sstevel@tonic-gate " to suggest what type of kernel to be loaded. TYPE must be either of" 29267c478bd9Sstevel@tonic-gate " \"netbsd\", \"freebsd\", \"openbsd\", \"linux\", \"biglinux\" and" 29277c478bd9Sstevel@tonic-gate " \"multiboot\". The option --no-mem-option tells GRUB not to pass a" 29287c478bd9Sstevel@tonic-gate " Linux's mem option automatically." 29297c478bd9Sstevel@tonic-gate }; 29307c478bd9Sstevel@tonic-gate 2931342440ecSPrasad Singamsetty int 2932342440ecSPrasad Singamsetty min_mem64_func(char *arg, int flags) 2933342440ecSPrasad Singamsetty { 2934342440ecSPrasad Singamsetty if (!safe_parse_maxint(&arg, &min_mem64)) 2935342440ecSPrasad Singamsetty return (1); 2936342440ecSPrasad Singamsetty } 2937342440ecSPrasad Singamsetty 2938342440ecSPrasad Singamsetty static struct builtin builtin_min_mem64 = 2939342440ecSPrasad Singamsetty { 2940342440ecSPrasad Singamsetty "min_mem64", 2941342440ecSPrasad Singamsetty min_mem64_func, 2942342440ecSPrasad Singamsetty BUILTIN_CMDLINE | BUILTIN_MENU | BUILTIN_SCRIPT | BUILTIN_HELP_LIST, 2943342440ecSPrasad Singamsetty "min_mem64 <memory in MB>", 2944342440ecSPrasad Singamsetty "Sets minimum memory (in MB) required for $ISADIR to expand to amd64, " 2945342440ecSPrasad Singamsetty "even on 64-bit capable hardware." 2946342440ecSPrasad Singamsetty }; 2947342440ecSPrasad Singamsetty 2948342440ecSPrasad Singamsetty int 2949342440ecSPrasad Singamsetty check_min_mem64() 2950342440ecSPrasad Singamsetty { 2951342440ecSPrasad Singamsetty if (min_mem64 == 0) 2952342440ecSPrasad Singamsetty return (1); 2953342440ecSPrasad Singamsetty 2954342440ecSPrasad Singamsetty if ((mbi.mem_upper / 10240) * 11 >= min_mem64) 2955342440ecSPrasad Singamsetty return (1); 2956342440ecSPrasad Singamsetty 2957342440ecSPrasad Singamsetty return (0); 2958342440ecSPrasad Singamsetty } 2959ae115bc7Smrj 2960ae115bc7Smrj static int detect_target_operating_mode(); 2961ae115bc7Smrj 2962ae115bc7Smrj int 2963ae115bc7Smrj amd64_config_cpu(void) 2964ae115bc7Smrj { 2965ae115bc7Smrj struct amd64_cpuid_regs __vcr, *vcr = &__vcr; 2966ae115bc7Smrj uint32_t maxeax; 2967ae115bc7Smrj uint32_t max_maxeax = 0x100; 2968ae115bc7Smrj char vendor[13]; 2969ae115bc7Smrj int isamd64 = 0; 2970ae115bc7Smrj uint32_t stdfeatures = 0, xtdfeatures = 0; 2971ae115bc7Smrj uint64_t efer; 2972ae115bc7Smrj 2973ae115bc7Smrj /* 2974ae115bc7Smrj * This check may seem silly, but if the C preprocesor symbol __amd64 2975ae115bc7Smrj * is #defined during compilation, something that may outwardly seem 2976ae115bc7Smrj * like a good idea, uts/common/sys/isa_defs.h will #define _LP64, 2977ae115bc7Smrj * which will cause uts/common/sys/int_types.h to typedef uint64_t as 2978ae115bc7Smrj * an unsigned long - which is only 4 bytes in size when using a 32-bit 2979ae115bc7Smrj * compiler. 2980ae115bc7Smrj * 2981ae115bc7Smrj * If that happens, all the page table translation routines will fail 2982ae115bc7Smrj * horribly, so check the size of uint64_t just to insure some degree 2983ae115bc7Smrj * of sanity in future operations. 2984ae115bc7Smrj */ 2985ae115bc7Smrj /*LINTED [sizeof result is invarient]*/ 2986ae115bc7Smrj if (sizeof (uint64_t) != 8) 2987ae115bc7Smrj prom_panic("grub compiled improperly, unable to boot " 2988ae115bc7Smrj "64-bit AMD64 executables"); 2989ae115bc7Smrj 2990ae115bc7Smrj /* 2991ae115bc7Smrj * If the CPU doesn't support the CPUID instruction, it's definitely 2992ae115bc7Smrj * not an AMD64. 2993ae115bc7Smrj */ 2994ae115bc7Smrj if (amd64_cpuid_supported() == 0) 2995ae115bc7Smrj return (0); 2996ae115bc7Smrj 2997ae115bc7Smrj amd64_cpuid_insn(0, vcr); 2998ae115bc7Smrj 2999ae115bc7Smrj maxeax = vcr->r_eax; 3000ae115bc7Smrj { 3001ae115bc7Smrj /*LINTED [vendor string from cpuid data]*/ 3002ae115bc7Smrj uint32_t *iptr = (uint32_t *)vendor; 3003ae115bc7Smrj 3004ae115bc7Smrj *iptr++ = vcr->r_ebx; 3005ae115bc7Smrj *iptr++ = vcr->r_edx; 3006ae115bc7Smrj *iptr++ = vcr->r_ecx; 3007ae115bc7Smrj 3008ae115bc7Smrj vendor[12] = '\0'; 3009ae115bc7Smrj } 3010ae115bc7Smrj 3011ae115bc7Smrj if (maxeax > max_maxeax) { 3012ae115bc7Smrj grub_printf("cpu: warning, maxeax was 0x%x -> 0x%x\n", 3013ae115bc7Smrj maxeax, max_maxeax); 3014ae115bc7Smrj maxeax = max_maxeax; 3015ae115bc7Smrj } 3016ae115bc7Smrj 3017ae115bc7Smrj if (maxeax < 1) 3018ae115bc7Smrj return (0); /* no additional functions, not an AMD64 */ 3019ae115bc7Smrj else { 3020ae115bc7Smrj uint_t family, model, step; 3021ae115bc7Smrj 3022ae115bc7Smrj amd64_cpuid_insn(1, vcr); 3023ae115bc7Smrj 3024ae115bc7Smrj /* 3025ae115bc7Smrj * All AMD64/IA32e processors technically SHOULD report 3026ae115bc7Smrj * themselves as being in family 0xf, but for some reason 3027ae115bc7Smrj * Simics doesn't, and this may change in the future, so 3028ae115bc7Smrj * don't error out if it's not true. 3029ae115bc7Smrj */ 3030ae115bc7Smrj if ((family = BITX(vcr->r_eax, 11, 8)) == 0xf) 3031ae115bc7Smrj family += BITX(vcr->r_eax, 27, 20); 3032ae115bc7Smrj 3033ae115bc7Smrj if ((model = BITX(vcr->r_eax, 7, 4)) == 0xf) 3034ae115bc7Smrj model += BITX(vcr->r_eax, 19, 16) << 4; 3035ae115bc7Smrj step = BITX(vcr->r_eax, 3, 0); 3036ae115bc7Smrj 3037ae115bc7Smrj grub_printf("cpu: '%s' family %d model %d step %d\n", 3038ae115bc7Smrj vendor, family, model, step); 3039ae115bc7Smrj stdfeatures = vcr->r_edx; 3040ae115bc7Smrj } 3041ae115bc7Smrj 3042ae115bc7Smrj amd64_cpuid_insn(0x80000000, vcr); 3043ae115bc7Smrj 3044ae115bc7Smrj if (vcr->r_eax & 0x80000000) { 3045ae115bc7Smrj uint32_t xmaxeax = vcr->r_eax; 3046ae115bc7Smrj const uint32_t max_xmaxeax = 0x80000100; 3047ae115bc7Smrj 3048ae115bc7Smrj if (xmaxeax > max_xmaxeax) { 3049ae115bc7Smrj grub_printf("amd64: warning, xmaxeax was " 3050ae115bc7Smrj "0x%x -> 0x%x\n", xmaxeax, max_xmaxeax); 3051ae115bc7Smrj xmaxeax = max_xmaxeax; 3052ae115bc7Smrj } 3053ae115bc7Smrj 3054ae115bc7Smrj if (xmaxeax >= 0x80000001) { 3055ae115bc7Smrj amd64_cpuid_insn(0x80000001, vcr); 3056ae115bc7Smrj xtdfeatures = vcr->r_edx; 3057ae115bc7Smrj } 3058ae115bc7Smrj } 3059ae115bc7Smrj 3060ae115bc7Smrj if (BITX(xtdfeatures, 29, 29)) /* long mode */ 3061ae115bc7Smrj isamd64++; 3062ae115bc7Smrj else 3063ae115bc7Smrj grub_printf("amd64: CPU does NOT support long mode\n"); 3064ae115bc7Smrj 3065ae115bc7Smrj if (!BITX(stdfeatures, 0, 0)) { 3066ae115bc7Smrj grub_printf("amd64: CPU does NOT support FPU\n"); 3067ae115bc7Smrj isamd64--; 3068ae115bc7Smrj } 3069ae115bc7Smrj 3070ae115bc7Smrj if (!BITX(stdfeatures, 4, 4)) { 3071ae115bc7Smrj grub_printf("amd64: CPU does NOT support TSC\n"); 3072ae115bc7Smrj isamd64--; 3073ae115bc7Smrj } 3074ae115bc7Smrj 3075ae115bc7Smrj if (!BITX(stdfeatures, 5, 5)) { 3076ae115bc7Smrj grub_printf("amd64: CPU does NOT support MSRs\n"); 3077ae115bc7Smrj isamd64--; 3078ae115bc7Smrj } 3079ae115bc7Smrj 3080ae115bc7Smrj if (!BITX(stdfeatures, 6, 6)) { 3081ae115bc7Smrj grub_printf("amd64: CPU does NOT support PAE\n"); 3082ae115bc7Smrj isamd64--; 3083ae115bc7Smrj } 3084ae115bc7Smrj 3085ae115bc7Smrj if (!BITX(stdfeatures, 8, 8)) { 3086ae115bc7Smrj grub_printf("amd64: CPU does NOT support CX8\n"); 3087ae115bc7Smrj isamd64--; 3088ae115bc7Smrj } 3089ae115bc7Smrj 3090ae115bc7Smrj if (!BITX(stdfeatures, 13, 13)) { 3091ae115bc7Smrj grub_printf("amd64: CPU does NOT support PGE\n"); 3092ae115bc7Smrj isamd64--; 3093ae115bc7Smrj } 3094ae115bc7Smrj 3095ae115bc7Smrj if (!BITX(stdfeatures, 19, 19)) { 3096ae115bc7Smrj grub_printf("amd64: CPU does NOT support CLFSH\n"); 3097ae115bc7Smrj isamd64--; 3098ae115bc7Smrj } 3099ae115bc7Smrj 3100ae115bc7Smrj if (!BITX(stdfeatures, 23, 23)) { 3101ae115bc7Smrj grub_printf("amd64: CPU does NOT support MMX\n"); 3102ae115bc7Smrj isamd64--; 3103ae115bc7Smrj } 3104ae115bc7Smrj 3105ae115bc7Smrj if (!BITX(stdfeatures, 24, 24)) { 3106ae115bc7Smrj grub_printf("amd64: CPU does NOT support FXSR\n"); 3107ae115bc7Smrj isamd64--; 3108ae115bc7Smrj } 3109ae115bc7Smrj 3110ae115bc7Smrj if (!BITX(stdfeatures, 25, 25)) { 3111ae115bc7Smrj grub_printf("amd64: CPU does NOT support SSE\n"); 3112ae115bc7Smrj isamd64--; 3113ae115bc7Smrj } 3114ae115bc7Smrj 3115ae115bc7Smrj if (!BITX(stdfeatures, 26, 26)) { 3116ae115bc7Smrj grub_printf("amd64: CPU does NOT support SSE2\n"); 3117ae115bc7Smrj isamd64--; 3118ae115bc7Smrj } 3119ae115bc7Smrj 3120ae115bc7Smrj if (isamd64 < 1) { 3121ae115bc7Smrj grub_printf("amd64: CPU does not support amd64 executables.\n"); 3122ae115bc7Smrj return (0); 3123ae115bc7Smrj } 3124ae115bc7Smrj 3125ae115bc7Smrj amd64_rdmsr(MSR_AMD_EFER, &efer); 3126ae115bc7Smrj if (efer & AMD_EFER_SCE) 3127ae115bc7Smrj grub_printf("amd64: EFER_SCE (syscall/sysret) already " 3128ae115bc7Smrj "enabled\n"); 3129ae115bc7Smrj if (efer & AMD_EFER_NXE) 3130ae115bc7Smrj grub_printf("amd64: EFER_NXE (no-exec prot) already enabled\n"); 3131ae115bc7Smrj if (efer & AMD_EFER_LME) 3132ae115bc7Smrj grub_printf("amd64: EFER_LME (long mode) already enabled\n"); 3133ae115bc7Smrj 3134ae115bc7Smrj return (detect_target_operating_mode()); 3135ae115bc7Smrj } 3136ae115bc7Smrj 3137ae115bc7Smrj static int 3138ae115bc7Smrj detect_target_operating_mode() 3139ae115bc7Smrj { 3140ae115bc7Smrj int ret, ah; 3141ae115bc7Smrj 3142ae115bc7Smrj ah = get_target_operating_mode(); 3143ae115bc7Smrj 3144ae115bc7Smrj ah = ah >> 8; 3145ae115bc7Smrj 3146ae115bc7Smrj /* XXX still need to pass back the return from the call */ 3147ae115bc7Smrj ret = 0; 3148ae115bc7Smrj 3149ae115bc7Smrj if (ah == 0x86 && (ret & CB) != 0) { 3150ae115bc7Smrj grub_printf("[BIOS 'Detect Target Operating Mode' " 3151ae115bc7Smrj "callback unsupported on this platform]\n"); 3152ae115bc7Smrj return (1); /* unsupported, ignore */ 3153ae115bc7Smrj } 3154ae115bc7Smrj 3155ae115bc7Smrj if (ah == 0x0 && (ret & CB) == 0) { 3156ae115bc7Smrj grub_printf("[BIOS accepted mixed-mode target setting!]\n"); 3157ae115bc7Smrj return (1); /* told the bios what we're up to */ 3158ae115bc7Smrj } 3159ae115bc7Smrj 3160ae115bc7Smrj if (ah == 0 && ret & CB) { 3161ae115bc7Smrj grub_printf("fatal: BIOS reports this machine CANNOT run in " 3162ae115bc7Smrj "mixed 32/64-bit mode!\n"); 3163ae115bc7Smrj return (0); 3164ae115bc7Smrj } 3165ae115bc7Smrj 3166ae115bc7Smrj grub_printf("warning: BIOS Detect Target Operating Mode callback " 3167ae115bc7Smrj "confused.\n %%ax >> 8 = 0x%x, carry = %d\n", ah, 3168ae115bc7Smrj ret & CB ? 1 : 0); 3169ae115bc7Smrj 3170ae115bc7Smrj return (1); 3171ae115bc7Smrj } 3172ae115bc7Smrj 3173ae115bc7Smrj 3174ae115bc7Smrj int 3175ae115bc7Smrj isamd64() 3176ae115bc7Smrj { 3177ae115bc7Smrj static int ret = -1; 3178ae115bc7Smrj 3179ae115bc7Smrj if (ret == -1) 3180ae115bc7Smrj ret = amd64_config_cpu(); 3181ae115bc7Smrj 3182ae115bc7Smrj return (ret); 3183ae115bc7Smrj } 3184ae115bc7Smrj 3185b1b8ab34Slling static void 3186b1b8ab34Slling expand_arch (char *arg, char *newarg) 3187ae115bc7Smrj { 3188ae115bc7Smrj char *index; 3189ae115bc7Smrj 3190ae115bc7Smrj newarg[0] = '\0'; 3191ae115bc7Smrj 3192ae115bc7Smrj while ((index = strstr(arg, "$ISADIR")) != NULL) { 3193ae115bc7Smrj 3194ae115bc7Smrj index[0] = '\0'; 3195ae115bc7Smrj strncat(newarg, arg, MAX_CMDLINE); 3196ae115bc7Smrj index[0] = '$'; 3197ae115bc7Smrj 3198342440ecSPrasad Singamsetty if (isamd64() && check_min_mem64()) 3199ae115bc7Smrj strncat(newarg, "amd64", MAX_CMDLINE); 3200ae115bc7Smrj 3201ae115bc7Smrj arg = index + 7; 3202ae115bc7Smrj } 3203ae115bc7Smrj 3204ae115bc7Smrj strncat(newarg, arg, MAX_CMDLINE); 3205b1b8ab34Slling return; 3206ae115bc7Smrj } 3207ae115bc7Smrj 3208ae115bc7Smrj /* kernel$ */ 3209ae115bc7Smrj static int 3210ae115bc7Smrj kernel_dollar_func (char *arg, int flags) 3211ae115bc7Smrj { 3212b1b8ab34Slling char newarg[MAX_CMDLINE]; /* everything boils down to MAX_CMDLINE */ 3213b1b8ab34Slling 3214b1b8ab34Slling grub_printf("loading '%s' ...\n", arg); 3215b1b8ab34Slling expand_arch(arg, newarg); 3216b1b8ab34Slling 3217b1b8ab34Slling if (kernel_func(newarg, flags)) 3218b1b8ab34Slling return (1); 3219b1b8ab34Slling 3220b1b8ab34Slling mb_cmdline = (char *)MB_CMDLINE_BUF; 3221b1b8ab34Slling if (expand_dollar_bootfs(newarg, mb_cmdline)) 3222b1b8ab34Slling return (1); 3223b1b8ab34Slling 3224b1b8ab34Slling grub_printf("'%s' is loaded\n", mb_cmdline); 3225b1b8ab34Slling mb_cmdline += grub_strlen(mb_cmdline) + 1; 3226b1b8ab34Slling 3227b1b8ab34Slling return (0); 3228ae115bc7Smrj } 3229ae115bc7Smrj 3230ae115bc7Smrj static struct builtin builtin_kernel_dollar = 3231ae115bc7Smrj { 3232ae115bc7Smrj "kernel$", 3233ae115bc7Smrj kernel_dollar_func, 3234ae115bc7Smrj BUILTIN_CMDLINE | BUILTIN_HELP_LIST, 3235ae115bc7Smrj "kernel$ [--no-mem-option] [--type=TYPE] FILE [ARG ...]", 3236ae115bc7Smrj " Just like kernel, but with $ISADIR expansion." 3237ae115bc7Smrj }; 3238ae115bc7Smrj 32397c478bd9Sstevel@tonic-gate 32407c478bd9Sstevel@tonic-gate /* lock */ 32417c478bd9Sstevel@tonic-gate static int 32427c478bd9Sstevel@tonic-gate lock_func (char *arg, int flags) 32437c478bd9Sstevel@tonic-gate { 32447c478bd9Sstevel@tonic-gate if (! auth && password) 32457c478bd9Sstevel@tonic-gate { 32467c478bd9Sstevel@tonic-gate errnum = ERR_PRIVILEGED; 32477c478bd9Sstevel@tonic-gate return 1; 32487c478bd9Sstevel@tonic-gate } 32497c478bd9Sstevel@tonic-gate 32507c478bd9Sstevel@tonic-gate return 0; 32517c478bd9Sstevel@tonic-gate } 32527c478bd9Sstevel@tonic-gate 32537c478bd9Sstevel@tonic-gate static struct builtin builtin_lock = 32547c478bd9Sstevel@tonic-gate { 32557c478bd9Sstevel@tonic-gate "lock", 32567c478bd9Sstevel@tonic-gate lock_func, 32577c478bd9Sstevel@tonic-gate BUILTIN_CMDLINE, 32587c478bd9Sstevel@tonic-gate "lock", 32597c478bd9Sstevel@tonic-gate "Break a command execution unless the user is authenticated." 32607c478bd9Sstevel@tonic-gate }; 32617c478bd9Sstevel@tonic-gate 32627c478bd9Sstevel@tonic-gate 32637c478bd9Sstevel@tonic-gate /* makeactive */ 32647c478bd9Sstevel@tonic-gate static int 32657c478bd9Sstevel@tonic-gate makeactive_func (char *arg, int flags) 32667c478bd9Sstevel@tonic-gate { 32677c478bd9Sstevel@tonic-gate if (! make_saved_active ()) 32687c478bd9Sstevel@tonic-gate return 1; 32697c478bd9Sstevel@tonic-gate 32707c478bd9Sstevel@tonic-gate return 0; 32717c478bd9Sstevel@tonic-gate } 32727c478bd9Sstevel@tonic-gate 32737c478bd9Sstevel@tonic-gate static struct builtin builtin_makeactive = 32747c478bd9Sstevel@tonic-gate { 32757c478bd9Sstevel@tonic-gate "makeactive", 32767c478bd9Sstevel@tonic-gate makeactive_func, 32777c478bd9Sstevel@tonic-gate BUILTIN_CMDLINE | BUILTIN_HELP_LIST, 32787c478bd9Sstevel@tonic-gate "makeactive", 32797c478bd9Sstevel@tonic-gate "Set the active partition on the root disk to GRUB's root device." 32807c478bd9Sstevel@tonic-gate " This command is limited to _primary_ PC partitions on a hard disk." 32817c478bd9Sstevel@tonic-gate }; 32827c478bd9Sstevel@tonic-gate 32837c478bd9Sstevel@tonic-gate 32847c478bd9Sstevel@tonic-gate /* map */ 32857c478bd9Sstevel@tonic-gate /* Map FROM_DRIVE to TO_DRIVE. */ 32867c478bd9Sstevel@tonic-gate static int 32877c478bd9Sstevel@tonic-gate map_func (char *arg, int flags) 32887c478bd9Sstevel@tonic-gate { 32897c478bd9Sstevel@tonic-gate char *to_drive; 32907c478bd9Sstevel@tonic-gate char *from_drive; 32917c478bd9Sstevel@tonic-gate unsigned long to, from; 32927c478bd9Sstevel@tonic-gate int i; 32937c478bd9Sstevel@tonic-gate 32947c478bd9Sstevel@tonic-gate to_drive = arg; 32957c478bd9Sstevel@tonic-gate from_drive = skip_to (0, arg); 32967c478bd9Sstevel@tonic-gate 32977c478bd9Sstevel@tonic-gate /* Get the drive number for TO_DRIVE. */ 32987c478bd9Sstevel@tonic-gate set_device (to_drive); 32997c478bd9Sstevel@tonic-gate if (errnum) 33007c478bd9Sstevel@tonic-gate return 1; 33017c478bd9Sstevel@tonic-gate to = current_drive; 33027c478bd9Sstevel@tonic-gate 33037c478bd9Sstevel@tonic-gate /* Get the drive number for FROM_DRIVE. */ 33047c478bd9Sstevel@tonic-gate set_device (from_drive); 33057c478bd9Sstevel@tonic-gate if (errnum) 33067c478bd9Sstevel@tonic-gate return 1; 33077c478bd9Sstevel@tonic-gate from = current_drive; 33087c478bd9Sstevel@tonic-gate 33097c478bd9Sstevel@tonic-gate /* Search for an empty slot in BIOS_DRIVE_MAP. */ 33107c478bd9Sstevel@tonic-gate for (i = 0; i < DRIVE_MAP_SIZE; i++) 33117c478bd9Sstevel@tonic-gate { 33127c478bd9Sstevel@tonic-gate /* Perhaps the user wants to override the map. */ 33137c478bd9Sstevel@tonic-gate if ((bios_drive_map[i] & 0xff) == from) 33147c478bd9Sstevel@tonic-gate break; 33157c478bd9Sstevel@tonic-gate 33167c478bd9Sstevel@tonic-gate if (! bios_drive_map[i]) 33177c478bd9Sstevel@tonic-gate break; 33187c478bd9Sstevel@tonic-gate } 33197c478bd9Sstevel@tonic-gate 33207c478bd9Sstevel@tonic-gate if (i == DRIVE_MAP_SIZE) 33217c478bd9Sstevel@tonic-gate { 33227c478bd9Sstevel@tonic-gate errnum = ERR_WONT_FIT; 33237c478bd9Sstevel@tonic-gate return 1; 33247c478bd9Sstevel@tonic-gate } 33257c478bd9Sstevel@tonic-gate 33267c478bd9Sstevel@tonic-gate if (to == from) 33277c478bd9Sstevel@tonic-gate /* If TO is equal to FROM, delete the entry. */ 33287c478bd9Sstevel@tonic-gate grub_memmove ((char *) &bios_drive_map[i], (char *) &bios_drive_map[i + 1], 33297c478bd9Sstevel@tonic-gate sizeof (unsigned short) * (DRIVE_MAP_SIZE - i)); 33307c478bd9Sstevel@tonic-gate else 33317c478bd9Sstevel@tonic-gate bios_drive_map[i] = from | (to << 8); 33327c478bd9Sstevel@tonic-gate 33337c478bd9Sstevel@tonic-gate return 0; 33347c478bd9Sstevel@tonic-gate } 33357c478bd9Sstevel@tonic-gate 33367c478bd9Sstevel@tonic-gate static struct builtin builtin_map = 33377c478bd9Sstevel@tonic-gate { 33387c478bd9Sstevel@tonic-gate "map", 33397c478bd9Sstevel@tonic-gate map_func, 33407c478bd9Sstevel@tonic-gate BUILTIN_CMDLINE | BUILTIN_HELP_LIST, 33417c478bd9Sstevel@tonic-gate "map TO_DRIVE FROM_DRIVE", 33427c478bd9Sstevel@tonic-gate "Map the drive FROM_DRIVE to the drive TO_DRIVE. This is necessary" 33437c478bd9Sstevel@tonic-gate " when you chain-load some operating systems, such as DOS, if such an" 33447c478bd9Sstevel@tonic-gate " OS resides at a non-first drive." 33457c478bd9Sstevel@tonic-gate }; 33467c478bd9Sstevel@tonic-gate 33477c478bd9Sstevel@tonic-gate 33487c478bd9Sstevel@tonic-gate #ifdef USE_MD5_PASSWORDS 33497c478bd9Sstevel@tonic-gate /* md5crypt */ 33507c478bd9Sstevel@tonic-gate static int 33517c478bd9Sstevel@tonic-gate md5crypt_func (char *arg, int flags) 33527c478bd9Sstevel@tonic-gate { 33537c478bd9Sstevel@tonic-gate char crypted[36]; 33547c478bd9Sstevel@tonic-gate char key[32]; 33557c478bd9Sstevel@tonic-gate unsigned int seed; 33567c478bd9Sstevel@tonic-gate int i; 33577c478bd9Sstevel@tonic-gate const char *const seedchars = 33587c478bd9Sstevel@tonic-gate "./0123456789ABCDEFGHIJKLMNOPQRST" 33597c478bd9Sstevel@tonic-gate "UVWXYZabcdefghijklmnopqrstuvwxyz"; 33607c478bd9Sstevel@tonic-gate 33617c478bd9Sstevel@tonic-gate /* First create a salt. */ 33627c478bd9Sstevel@tonic-gate 33637c478bd9Sstevel@tonic-gate /* The magical prefix. */ 33647c478bd9Sstevel@tonic-gate grub_memset (crypted, 0, sizeof (crypted)); 33657c478bd9Sstevel@tonic-gate grub_memmove (crypted, "$1$", 3); 33667c478bd9Sstevel@tonic-gate 33677c478bd9Sstevel@tonic-gate /* Create the length of a salt. */ 33687c478bd9Sstevel@tonic-gate seed = currticks (); 33697c478bd9Sstevel@tonic-gate 33707c478bd9Sstevel@tonic-gate /* Generate a salt. */ 33717c478bd9Sstevel@tonic-gate for (i = 0; i < 8 && seed; i++) 33727c478bd9Sstevel@tonic-gate { 33737c478bd9Sstevel@tonic-gate /* FIXME: This should be more random. */ 33747c478bd9Sstevel@tonic-gate crypted[3 + i] = seedchars[seed & 0x3f]; 33757c478bd9Sstevel@tonic-gate seed >>= 6; 33767c478bd9Sstevel@tonic-gate } 33777c478bd9Sstevel@tonic-gate 33787c478bd9Sstevel@tonic-gate /* A salt must be terminated with `$', if it is less than 8 chars. */ 33797c478bd9Sstevel@tonic-gate crypted[3 + i] = '$'; 33807c478bd9Sstevel@tonic-gate 33817c478bd9Sstevel@tonic-gate #ifdef DEBUG_MD5CRYPT 33827c478bd9Sstevel@tonic-gate grub_printf ("salt = %s\n", crypted); 33837c478bd9Sstevel@tonic-gate #endif 33847c478bd9Sstevel@tonic-gate 33857c478bd9Sstevel@tonic-gate /* Get a password. */ 33867c478bd9Sstevel@tonic-gate grub_memset (key, 0, sizeof (key)); 33877c478bd9Sstevel@tonic-gate get_cmdline ("Password: ", key, sizeof (key) - 1, '*', 0); 33887c478bd9Sstevel@tonic-gate 33897c478bd9Sstevel@tonic-gate /* Crypt the key. */ 33907c478bd9Sstevel@tonic-gate make_md5_password (key, crypted); 33917c478bd9Sstevel@tonic-gate 33927c478bd9Sstevel@tonic-gate grub_printf ("Encrypted: %s\n", crypted); 33937c478bd9Sstevel@tonic-gate return 0; 33947c478bd9Sstevel@tonic-gate } 33957c478bd9Sstevel@tonic-gate 33967c478bd9Sstevel@tonic-gate static struct builtin builtin_md5crypt = 33977c478bd9Sstevel@tonic-gate { 33987c478bd9Sstevel@tonic-gate "md5crypt", 33997c478bd9Sstevel@tonic-gate md5crypt_func, 34007c478bd9Sstevel@tonic-gate BUILTIN_CMDLINE | BUILTIN_HELP_LIST, 34017c478bd9Sstevel@tonic-gate "md5crypt", 34027c478bd9Sstevel@tonic-gate "Generate a password in MD5 format." 34037c478bd9Sstevel@tonic-gate }; 34047c478bd9Sstevel@tonic-gate #endif /* USE_MD5_PASSWORDS */ 34057c478bd9Sstevel@tonic-gate 34067c478bd9Sstevel@tonic-gate 34077c478bd9Sstevel@tonic-gate /* module */ 34087c478bd9Sstevel@tonic-gate static int 34097c478bd9Sstevel@tonic-gate module_func (char *arg, int flags) 34107c478bd9Sstevel@tonic-gate { 34117c478bd9Sstevel@tonic-gate int len = grub_strlen (arg); 34127c478bd9Sstevel@tonic-gate 34137c478bd9Sstevel@tonic-gate switch (kernel_type) 34147c478bd9Sstevel@tonic-gate { 34157c478bd9Sstevel@tonic-gate case KERNEL_TYPE_MULTIBOOT: 34167c478bd9Sstevel@tonic-gate if (mb_cmdline + len + 1 > (char *) MB_CMDLINE_BUF + MB_CMDLINE_BUFLEN) 34177c478bd9Sstevel@tonic-gate { 34187c478bd9Sstevel@tonic-gate errnum = ERR_WONT_FIT; 34197c478bd9Sstevel@tonic-gate return 1; 34207c478bd9Sstevel@tonic-gate } 34217c478bd9Sstevel@tonic-gate grub_memmove (mb_cmdline, arg, len + 1); 34227c478bd9Sstevel@tonic-gate if (! load_module (arg, mb_cmdline)) 34237c478bd9Sstevel@tonic-gate return 1; 3424b1b8ab34Slling 3425b1b8ab34Slling mb_cmdline += grub_strlen(mb_cmdline) + 1; 34267c478bd9Sstevel@tonic-gate break; 34277c478bd9Sstevel@tonic-gate 34287c478bd9Sstevel@tonic-gate case KERNEL_TYPE_LINUX: 34297c478bd9Sstevel@tonic-gate case KERNEL_TYPE_BIG_LINUX: 34307c478bd9Sstevel@tonic-gate if (! load_initrd (arg)) 34317c478bd9Sstevel@tonic-gate return 1; 34327c478bd9Sstevel@tonic-gate break; 34337c478bd9Sstevel@tonic-gate 34347c478bd9Sstevel@tonic-gate default: 34357c478bd9Sstevel@tonic-gate errnum = ERR_NEED_MB_KERNEL; 34367c478bd9Sstevel@tonic-gate return 1; 34377c478bd9Sstevel@tonic-gate } 34387c478bd9Sstevel@tonic-gate 34397c478bd9Sstevel@tonic-gate return 0; 34407c478bd9Sstevel@tonic-gate } 34417c478bd9Sstevel@tonic-gate 34427c478bd9Sstevel@tonic-gate static struct builtin builtin_module = 34437c478bd9Sstevel@tonic-gate { 34447c478bd9Sstevel@tonic-gate "module", 34457c478bd9Sstevel@tonic-gate module_func, 34467c478bd9Sstevel@tonic-gate BUILTIN_CMDLINE | BUILTIN_HELP_LIST, 34477c478bd9Sstevel@tonic-gate "module FILE [ARG ...]", 34487c478bd9Sstevel@tonic-gate "Load a boot module FILE for a Multiboot format boot image (no" 34497c478bd9Sstevel@tonic-gate " interpretation of the file contents is made, so users of this" 34507c478bd9Sstevel@tonic-gate " command must know what the kernel in question expects). The" 34517c478bd9Sstevel@tonic-gate " rest of the line is passed as the \"module command line\", like" 34527c478bd9Sstevel@tonic-gate " the `kernel' command." 34537c478bd9Sstevel@tonic-gate }; 34547c478bd9Sstevel@tonic-gate 3455ae115bc7Smrj /* module$ */ 3456ae115bc7Smrj static int 3457ae115bc7Smrj module_dollar_func (char *arg, int flags) 3458ae115bc7Smrj { 3459b1b8ab34Slling char newarg[MAX_CMDLINE]; /* everything boils down to MAX_CMDLINE */ 3460b1b8ab34Slling char *cmdline_sav; 3461b1b8ab34Slling 3462b1b8ab34Slling grub_printf("loading '%s' ...\n", arg); 3463b1b8ab34Slling expand_arch(arg, newarg); 3464b1b8ab34Slling 3465b1b8ab34Slling cmdline_sav = (char *)mb_cmdline; 3466b1b8ab34Slling if (module_func(newarg, flags)) 3467b1b8ab34Slling return (1); 3468b1b8ab34Slling 3469b1b8ab34Slling if (expand_dollar_bootfs(newarg, cmdline_sav)) 3470b1b8ab34Slling return (1); 3471b1b8ab34Slling 3472b1b8ab34Slling grub_printf("'%s' is loaded\n", (char *)cmdline_sav); 3473b1b8ab34Slling mb_cmdline += grub_strlen(cmdline_sav) + 1; 3474b1b8ab34Slling 3475b1b8ab34Slling return (0); 3476ae115bc7Smrj } 3477ae115bc7Smrj 3478ae115bc7Smrj static struct builtin builtin_module_dollar = 3479ae115bc7Smrj { 3480ae115bc7Smrj "module$", 3481ae115bc7Smrj module_dollar_func, 3482ae115bc7Smrj BUILTIN_CMDLINE | BUILTIN_HELP_LIST, 3483ae115bc7Smrj "module FILE [ARG ...]", 3484ae115bc7Smrj " Just like module, but with $ISADIR expansion." 3485ae115bc7Smrj }; 3486ae115bc7Smrj 34877c478bd9Sstevel@tonic-gate 34887c478bd9Sstevel@tonic-gate /* modulenounzip */ 34897c478bd9Sstevel@tonic-gate static int 34907c478bd9Sstevel@tonic-gate modulenounzip_func (char *arg, int flags) 34917c478bd9Sstevel@tonic-gate { 34927c478bd9Sstevel@tonic-gate int ret; 34937c478bd9Sstevel@tonic-gate 34947c478bd9Sstevel@tonic-gate #ifndef NO_DECOMPRESSION 34957c478bd9Sstevel@tonic-gate no_decompression = 1; 34967c478bd9Sstevel@tonic-gate #endif 34977c478bd9Sstevel@tonic-gate 34987c478bd9Sstevel@tonic-gate ret = module_func (arg, flags); 34997c478bd9Sstevel@tonic-gate 35007c478bd9Sstevel@tonic-gate #ifndef NO_DECOMPRESSION 35017c478bd9Sstevel@tonic-gate no_decompression = 0; 35027c478bd9Sstevel@tonic-gate #endif 35037c478bd9Sstevel@tonic-gate 35047c478bd9Sstevel@tonic-gate return ret; 35057c478bd9Sstevel@tonic-gate } 35067c478bd9Sstevel@tonic-gate 35077c478bd9Sstevel@tonic-gate static struct builtin builtin_modulenounzip = 35087c478bd9Sstevel@tonic-gate { 35097c478bd9Sstevel@tonic-gate "modulenounzip", 35107c478bd9Sstevel@tonic-gate modulenounzip_func, 35117c478bd9Sstevel@tonic-gate BUILTIN_CMDLINE | BUILTIN_HELP_LIST, 35127c478bd9Sstevel@tonic-gate "modulenounzip FILE [ARG ...]", 35137c478bd9Sstevel@tonic-gate "The same as `module', except that automatic decompression is" 35147c478bd9Sstevel@tonic-gate " disabled." 35157c478bd9Sstevel@tonic-gate }; 35167c478bd9Sstevel@tonic-gate 35177c478bd9Sstevel@tonic-gate 35187c478bd9Sstevel@tonic-gate /* pager [on|off] */ 35197c478bd9Sstevel@tonic-gate static int 35207c478bd9Sstevel@tonic-gate pager_func (char *arg, int flags) 35217c478bd9Sstevel@tonic-gate { 35227c478bd9Sstevel@tonic-gate /* If ARG is empty, toggle the flag. */ 35237c478bd9Sstevel@tonic-gate if (! *arg) 35247c478bd9Sstevel@tonic-gate use_pager = ! use_pager; 35257c478bd9Sstevel@tonic-gate else if (grub_memcmp (arg, "on", 2) == 0) 35267c478bd9Sstevel@tonic-gate use_pager = 1; 35277c478bd9Sstevel@tonic-gate else if (grub_memcmp (arg, "off", 3) == 0) 35287c478bd9Sstevel@tonic-gate use_pager = 0; 35297c478bd9Sstevel@tonic-gate else 35307c478bd9Sstevel@tonic-gate { 35317c478bd9Sstevel@tonic-gate errnum = ERR_BAD_ARGUMENT; 35327c478bd9Sstevel@tonic-gate return 1; 35337c478bd9Sstevel@tonic-gate } 35347c478bd9Sstevel@tonic-gate 35357c478bd9Sstevel@tonic-gate grub_printf (" Internal pager is now %s\n", use_pager ? "on" : "off"); 35367c478bd9Sstevel@tonic-gate return 0; 35377c478bd9Sstevel@tonic-gate } 35387c478bd9Sstevel@tonic-gate 35397c478bd9Sstevel@tonic-gate static struct builtin builtin_pager = 35407c478bd9Sstevel@tonic-gate { 35417c478bd9Sstevel@tonic-gate "pager", 35427c478bd9Sstevel@tonic-gate pager_func, 35437c478bd9Sstevel@tonic-gate BUILTIN_CMDLINE | BUILTIN_MENU | BUILTIN_HELP_LIST, 35447c478bd9Sstevel@tonic-gate "pager [FLAG]", 35457c478bd9Sstevel@tonic-gate "Toggle pager mode with no argument. If FLAG is given and its value" 35467c478bd9Sstevel@tonic-gate " is `on', turn on the mode. If FLAG is `off', turn off the mode." 35477c478bd9Sstevel@tonic-gate }; 35487c478bd9Sstevel@tonic-gate 35497c478bd9Sstevel@tonic-gate 35507c478bd9Sstevel@tonic-gate /* partnew PART TYPE START LEN */ 35517c478bd9Sstevel@tonic-gate static int 35527c478bd9Sstevel@tonic-gate partnew_func (char *arg, int flags) 35537c478bd9Sstevel@tonic-gate { 35547c478bd9Sstevel@tonic-gate int new_type, new_start, new_len; 35557c478bd9Sstevel@tonic-gate int start_cl, start_ch, start_dh; 35567c478bd9Sstevel@tonic-gate int end_cl, end_ch, end_dh; 35577c478bd9Sstevel@tonic-gate int entry; 35587c478bd9Sstevel@tonic-gate char mbr[512]; 35597c478bd9Sstevel@tonic-gate 35607c478bd9Sstevel@tonic-gate /* Convert a LBA address to a CHS address in the INT 13 format. */ 35617c478bd9Sstevel@tonic-gate auto void lba_to_chs (int lba, int *cl, int *ch, int *dh); 35627c478bd9Sstevel@tonic-gate void lba_to_chs (int lba, int *cl, int *ch, int *dh) 35637c478bd9Sstevel@tonic-gate { 35647c478bd9Sstevel@tonic-gate int cylinder, head, sector; 35657c478bd9Sstevel@tonic-gate 35667c478bd9Sstevel@tonic-gate sector = lba % buf_geom.sectors + 1; 35677c478bd9Sstevel@tonic-gate head = (lba / buf_geom.sectors) % buf_geom.heads; 35687c478bd9Sstevel@tonic-gate cylinder = lba / (buf_geom.sectors * buf_geom.heads); 35697c478bd9Sstevel@tonic-gate 35707c478bd9Sstevel@tonic-gate if (cylinder >= buf_geom.cylinders) 35717c478bd9Sstevel@tonic-gate cylinder = buf_geom.cylinders - 1; 35727c478bd9Sstevel@tonic-gate 35737c478bd9Sstevel@tonic-gate *cl = sector | ((cylinder & 0x300) >> 2); 35747c478bd9Sstevel@tonic-gate *ch = cylinder & 0xFF; 35757c478bd9Sstevel@tonic-gate *dh = head; 35767c478bd9Sstevel@tonic-gate } 35777c478bd9Sstevel@tonic-gate 35787c478bd9Sstevel@tonic-gate /* Get the drive and the partition. */ 35797c478bd9Sstevel@tonic-gate if (! set_device (arg)) 35807c478bd9Sstevel@tonic-gate return 1; 35817c478bd9Sstevel@tonic-gate 35827c478bd9Sstevel@tonic-gate /* The drive must be a hard disk. */ 35837c478bd9Sstevel@tonic-gate if (! (current_drive & 0x80)) 35847c478bd9Sstevel@tonic-gate { 35857c478bd9Sstevel@tonic-gate errnum = ERR_BAD_ARGUMENT; 35867c478bd9Sstevel@tonic-gate return 1; 35877c478bd9Sstevel@tonic-gate } 35887c478bd9Sstevel@tonic-gate 35897c478bd9Sstevel@tonic-gate /* The partition must a primary partition. */ 35907c478bd9Sstevel@tonic-gate if ((current_partition >> 16) > 3 35917c478bd9Sstevel@tonic-gate || (current_partition & 0xFFFF) != 0xFFFF) 35927c478bd9Sstevel@tonic-gate { 35937c478bd9Sstevel@tonic-gate errnum = ERR_BAD_ARGUMENT; 35947c478bd9Sstevel@tonic-gate return 1; 35957c478bd9Sstevel@tonic-gate } 35967c478bd9Sstevel@tonic-gate 35977c478bd9Sstevel@tonic-gate entry = current_partition >> 16; 35987c478bd9Sstevel@tonic-gate 35997c478bd9Sstevel@tonic-gate /* Get the new partition type. */ 36007c478bd9Sstevel@tonic-gate arg = skip_to (0, arg); 36017c478bd9Sstevel@tonic-gate if (! safe_parse_maxint (&arg, &new_type)) 36027c478bd9Sstevel@tonic-gate return 1; 36037c478bd9Sstevel@tonic-gate 36047c478bd9Sstevel@tonic-gate /* The partition type is unsigned char. */ 36057c478bd9Sstevel@tonic-gate if (new_type > 0xFF) 36067c478bd9Sstevel@tonic-gate { 36077c478bd9Sstevel@tonic-gate errnum = ERR_BAD_ARGUMENT; 36087c478bd9Sstevel@tonic-gate return 1; 36097c478bd9Sstevel@tonic-gate } 36107c478bd9Sstevel@tonic-gate 36117c478bd9Sstevel@tonic-gate /* Get the new partition start. */ 36127c478bd9Sstevel@tonic-gate arg = skip_to (0, arg); 36137c478bd9Sstevel@tonic-gate if (! safe_parse_maxint (&arg, &new_start)) 36147c478bd9Sstevel@tonic-gate return 1; 36157c478bd9Sstevel@tonic-gate 36167c478bd9Sstevel@tonic-gate /* Get the new partition length. */ 36177c478bd9Sstevel@tonic-gate arg = skip_to (0, arg); 36187c478bd9Sstevel@tonic-gate if (! safe_parse_maxint (&arg, &new_len)) 36197c478bd9Sstevel@tonic-gate return 1; 36207c478bd9Sstevel@tonic-gate 36217c478bd9Sstevel@tonic-gate /* Read the MBR. */ 36227c478bd9Sstevel@tonic-gate if (! rawread (current_drive, 0, 0, SECTOR_SIZE, mbr)) 36237c478bd9Sstevel@tonic-gate return 1; 36247c478bd9Sstevel@tonic-gate 36257c478bd9Sstevel@tonic-gate /* Check if the new partition will fit in the disk. */ 36267c478bd9Sstevel@tonic-gate if (new_start + new_len > buf_geom.total_sectors) 36277c478bd9Sstevel@tonic-gate { 36287c478bd9Sstevel@tonic-gate errnum = ERR_GEOM; 36297c478bd9Sstevel@tonic-gate return 1; 36307c478bd9Sstevel@tonic-gate } 36317c478bd9Sstevel@tonic-gate 36327c478bd9Sstevel@tonic-gate /* Store the partition information in the MBR. */ 36337c478bd9Sstevel@tonic-gate lba_to_chs (new_start, &start_cl, &start_ch, &start_dh); 36347c478bd9Sstevel@tonic-gate lba_to_chs (new_start + new_len - 1, &end_cl, &end_ch, &end_dh); 36357c478bd9Sstevel@tonic-gate 36367c478bd9Sstevel@tonic-gate PC_SLICE_FLAG (mbr, entry) = 0; 36377c478bd9Sstevel@tonic-gate PC_SLICE_HEAD (mbr, entry) = start_dh; 36387c478bd9Sstevel@tonic-gate PC_SLICE_SEC (mbr, entry) = start_cl; 36397c478bd9Sstevel@tonic-gate PC_SLICE_CYL (mbr, entry) = start_ch; 36407c478bd9Sstevel@tonic-gate PC_SLICE_TYPE (mbr, entry) = new_type; 36417c478bd9Sstevel@tonic-gate PC_SLICE_EHEAD (mbr, entry) = end_dh; 36427c478bd9Sstevel@tonic-gate PC_SLICE_ESEC (mbr, entry) = end_cl; 36437c478bd9Sstevel@tonic-gate PC_SLICE_ECYL (mbr, entry) = end_ch; 36447c478bd9Sstevel@tonic-gate PC_SLICE_START (mbr, entry) = new_start; 36457c478bd9Sstevel@tonic-gate PC_SLICE_LENGTH (mbr, entry) = new_len; 36467c478bd9Sstevel@tonic-gate 36477c478bd9Sstevel@tonic-gate /* Make sure that the MBR has a valid signature. */ 36487c478bd9Sstevel@tonic-gate PC_MBR_SIG (mbr) = PC_MBR_SIGNATURE; 36497c478bd9Sstevel@tonic-gate 36507c478bd9Sstevel@tonic-gate /* Write back the MBR to the disk. */ 3651342440ecSPrasad Singamsetty buf_track = BUF_CACHE_INVALID; 36527c478bd9Sstevel@tonic-gate if (! rawwrite (current_drive, 0, mbr)) 36537c478bd9Sstevel@tonic-gate return 1; 36547c478bd9Sstevel@tonic-gate 36557c478bd9Sstevel@tonic-gate return 0; 36567c478bd9Sstevel@tonic-gate } 36577c478bd9Sstevel@tonic-gate 36587c478bd9Sstevel@tonic-gate static struct builtin builtin_partnew = 36597c478bd9Sstevel@tonic-gate { 36607c478bd9Sstevel@tonic-gate "partnew", 36617c478bd9Sstevel@tonic-gate partnew_func, 36627c478bd9Sstevel@tonic-gate BUILTIN_CMDLINE | BUILTIN_MENU | BUILTIN_HELP_LIST, 36637c478bd9Sstevel@tonic-gate "partnew PART TYPE START LEN", 36647c478bd9Sstevel@tonic-gate "Create a primary partition at the starting address START with the" 36657c478bd9Sstevel@tonic-gate " length LEN, with the type TYPE. START and LEN are in sector units." 36667c478bd9Sstevel@tonic-gate }; 36677c478bd9Sstevel@tonic-gate 36687c478bd9Sstevel@tonic-gate 36697c478bd9Sstevel@tonic-gate /* parttype PART TYPE */ 36707c478bd9Sstevel@tonic-gate static int 36717c478bd9Sstevel@tonic-gate parttype_func (char *arg, int flags) 36727c478bd9Sstevel@tonic-gate { 36737c478bd9Sstevel@tonic-gate int new_type; 36747c478bd9Sstevel@tonic-gate unsigned long part = 0xFFFFFF; 36757c478bd9Sstevel@tonic-gate unsigned long start, len, offset, ext_offset; 36767c478bd9Sstevel@tonic-gate int entry, type; 36777c478bd9Sstevel@tonic-gate char mbr[512]; 36787c478bd9Sstevel@tonic-gate 36797c478bd9Sstevel@tonic-gate /* Get the drive and the partition. */ 36807c478bd9Sstevel@tonic-gate if (! set_device (arg)) 36817c478bd9Sstevel@tonic-gate return 1; 36827c478bd9Sstevel@tonic-gate 36837c478bd9Sstevel@tonic-gate /* The drive must be a hard disk. */ 36847c478bd9Sstevel@tonic-gate if (! (current_drive & 0x80)) 36857c478bd9Sstevel@tonic-gate { 36867c478bd9Sstevel@tonic-gate errnum = ERR_BAD_ARGUMENT; 36877c478bd9Sstevel@tonic-gate return 1; 36887c478bd9Sstevel@tonic-gate } 36897c478bd9Sstevel@tonic-gate 36907c478bd9Sstevel@tonic-gate /* The partition must be a PC slice. */ 36917c478bd9Sstevel@tonic-gate if ((current_partition >> 16) == 0xFF 36927c478bd9Sstevel@tonic-gate || (current_partition & 0xFFFF) != 0xFFFF) 36937c478bd9Sstevel@tonic-gate { 36947c478bd9Sstevel@tonic-gate errnum = ERR_BAD_ARGUMENT; 36957c478bd9Sstevel@tonic-gate return 1; 36967c478bd9Sstevel@tonic-gate } 36977c478bd9Sstevel@tonic-gate 36987c478bd9Sstevel@tonic-gate /* Get the new partition type. */ 36997c478bd9Sstevel@tonic-gate arg = skip_to (0, arg); 37007c478bd9Sstevel@tonic-gate if (! safe_parse_maxint (&arg, &new_type)) 37017c478bd9Sstevel@tonic-gate return 1; 37027c478bd9Sstevel@tonic-gate 37037c478bd9Sstevel@tonic-gate /* The partition type is unsigned char. */ 37047c478bd9Sstevel@tonic-gate if (new_type > 0xFF) 37057c478bd9Sstevel@tonic-gate { 37067c478bd9Sstevel@tonic-gate errnum = ERR_BAD_ARGUMENT; 37077c478bd9Sstevel@tonic-gate return 1; 37087c478bd9Sstevel@tonic-gate } 37097c478bd9Sstevel@tonic-gate 37107c478bd9Sstevel@tonic-gate /* Look for the partition. */ 37117c478bd9Sstevel@tonic-gate while (next_partition (current_drive, 0xFFFFFF, &part, &type, 37127c478bd9Sstevel@tonic-gate &start, &len, &offset, &entry, 37137c478bd9Sstevel@tonic-gate &ext_offset, mbr)) 37147c478bd9Sstevel@tonic-gate { 37157c478bd9Sstevel@tonic-gate if (part == current_partition) 37167c478bd9Sstevel@tonic-gate { 37177c478bd9Sstevel@tonic-gate /* Found. */ 37187c478bd9Sstevel@tonic-gate 37197c478bd9Sstevel@tonic-gate /* Set the type to NEW_TYPE. */ 37207c478bd9Sstevel@tonic-gate PC_SLICE_TYPE (mbr, entry) = new_type; 37217c478bd9Sstevel@tonic-gate 37227c478bd9Sstevel@tonic-gate /* Write back the MBR to the disk. */ 3723342440ecSPrasad Singamsetty buf_track = BUF_CACHE_INVALID; 37247c478bd9Sstevel@tonic-gate if (! rawwrite (current_drive, offset, mbr)) 37257c478bd9Sstevel@tonic-gate return 1; 37267c478bd9Sstevel@tonic-gate 37277c478bd9Sstevel@tonic-gate /* Succeed. */ 37287c478bd9Sstevel@tonic-gate return 0; 37297c478bd9Sstevel@tonic-gate } 37307c478bd9Sstevel@tonic-gate } 37317c478bd9Sstevel@tonic-gate 37327c478bd9Sstevel@tonic-gate /* The partition was not found. ERRNUM was set by next_partition. */ 37337c478bd9Sstevel@tonic-gate return 1; 37347c478bd9Sstevel@tonic-gate } 37357c478bd9Sstevel@tonic-gate 37367c478bd9Sstevel@tonic-gate static struct builtin builtin_parttype = 37377c478bd9Sstevel@tonic-gate { 37387c478bd9Sstevel@tonic-gate "parttype", 37397c478bd9Sstevel@tonic-gate parttype_func, 37407c478bd9Sstevel@tonic-gate BUILTIN_CMDLINE | BUILTIN_MENU | BUILTIN_HELP_LIST, 37417c478bd9Sstevel@tonic-gate "parttype PART TYPE", 37427c478bd9Sstevel@tonic-gate "Change the type of the partition PART to TYPE." 37437c478bd9Sstevel@tonic-gate }; 37447c478bd9Sstevel@tonic-gate 37457c478bd9Sstevel@tonic-gate 37467c478bd9Sstevel@tonic-gate /* password */ 37477c478bd9Sstevel@tonic-gate static int 37487c478bd9Sstevel@tonic-gate password_func (char *arg, int flags) 37497c478bd9Sstevel@tonic-gate { 37507c478bd9Sstevel@tonic-gate int len; 37517c478bd9Sstevel@tonic-gate password_t type = PASSWORD_PLAIN; 37527c478bd9Sstevel@tonic-gate 37537c478bd9Sstevel@tonic-gate #ifdef USE_MD5_PASSWORDS 37547c478bd9Sstevel@tonic-gate if (grub_memcmp (arg, "--md5", 5) == 0) 37557c478bd9Sstevel@tonic-gate { 37567c478bd9Sstevel@tonic-gate type = PASSWORD_MD5; 37577c478bd9Sstevel@tonic-gate arg = skip_to (0, arg); 37587c478bd9Sstevel@tonic-gate } 37597c478bd9Sstevel@tonic-gate #endif 37607c478bd9Sstevel@tonic-gate if (grub_memcmp (arg, "--", 2) == 0) 37617c478bd9Sstevel@tonic-gate { 37627c478bd9Sstevel@tonic-gate type = PASSWORD_UNSUPPORTED; 37637c478bd9Sstevel@tonic-gate arg = skip_to (0, arg); 37647c478bd9Sstevel@tonic-gate } 37657c478bd9Sstevel@tonic-gate 37667c478bd9Sstevel@tonic-gate if ((flags & (BUILTIN_CMDLINE | BUILTIN_SCRIPT)) != 0) 37677c478bd9Sstevel@tonic-gate { 37687c478bd9Sstevel@tonic-gate /* Do password check! */ 37697c478bd9Sstevel@tonic-gate char entered[32]; 37707c478bd9Sstevel@tonic-gate 37717c478bd9Sstevel@tonic-gate /* Wipe out any previously entered password */ 37727c478bd9Sstevel@tonic-gate entered[0] = 0; 37737c478bd9Sstevel@tonic-gate get_cmdline ("Password: ", entered, 31, '*', 0); 37747c478bd9Sstevel@tonic-gate 37757c478bd9Sstevel@tonic-gate nul_terminate (arg); 37767c478bd9Sstevel@tonic-gate if (check_password (entered, arg, type) != 0) 37777c478bd9Sstevel@tonic-gate { 37787c478bd9Sstevel@tonic-gate errnum = ERR_PRIVILEGED; 37797c478bd9Sstevel@tonic-gate return 1; 37807c478bd9Sstevel@tonic-gate } 37817c478bd9Sstevel@tonic-gate } 37827c478bd9Sstevel@tonic-gate else 37837c478bd9Sstevel@tonic-gate { 37847c478bd9Sstevel@tonic-gate len = grub_strlen (arg); 37857c478bd9Sstevel@tonic-gate 37867c478bd9Sstevel@tonic-gate /* PASSWORD NUL NUL ... */ 37877c478bd9Sstevel@tonic-gate if (len + 2 > PASSWORD_BUFLEN) 37887c478bd9Sstevel@tonic-gate { 37897c478bd9Sstevel@tonic-gate errnum = ERR_WONT_FIT; 37907c478bd9Sstevel@tonic-gate return 1; 37917c478bd9Sstevel@tonic-gate } 37927c478bd9Sstevel@tonic-gate 37937c478bd9Sstevel@tonic-gate /* Copy the password and clear the rest of the buffer. */ 37947c478bd9Sstevel@tonic-gate password = (char *) PASSWORD_BUF; 37957c478bd9Sstevel@tonic-gate grub_memmove (password, arg, len); 37967c478bd9Sstevel@tonic-gate grub_memset (password + len, 0, PASSWORD_BUFLEN - len); 37977c478bd9Sstevel@tonic-gate password_type = type; 37987c478bd9Sstevel@tonic-gate } 37997c478bd9Sstevel@tonic-gate return 0; 38007c478bd9Sstevel@tonic-gate } 38017c478bd9Sstevel@tonic-gate 38027c478bd9Sstevel@tonic-gate static struct builtin builtin_password = 38037c478bd9Sstevel@tonic-gate { 38047c478bd9Sstevel@tonic-gate "password", 38057c478bd9Sstevel@tonic-gate password_func, 38067c478bd9Sstevel@tonic-gate BUILTIN_MENU | BUILTIN_CMDLINE | BUILTIN_NO_ECHO, 38077c478bd9Sstevel@tonic-gate "password [--md5] PASSWD [FILE]", 38087c478bd9Sstevel@tonic-gate "If used in the first section of a menu file, disable all" 38097c478bd9Sstevel@tonic-gate " interactive editing control (menu entry editor and" 38107c478bd9Sstevel@tonic-gate " command line). If the password PASSWD is entered, it loads the" 38117c478bd9Sstevel@tonic-gate " FILE as a new config file and restarts the GRUB Stage 2. If you" 38127c478bd9Sstevel@tonic-gate " omit the argument FILE, then GRUB just unlocks privileged" 38137c478bd9Sstevel@tonic-gate " instructions. You can also use it in the script section, in" 38147c478bd9Sstevel@tonic-gate " which case it will ask for the password, before continueing." 38157c478bd9Sstevel@tonic-gate " The option --md5 tells GRUB that PASSWD is encrypted with" 38167c478bd9Sstevel@tonic-gate " md5crypt." 38177c478bd9Sstevel@tonic-gate }; 38187c478bd9Sstevel@tonic-gate 38197c478bd9Sstevel@tonic-gate 38207c478bd9Sstevel@tonic-gate /* pause */ 38217c478bd9Sstevel@tonic-gate static int 38227c478bd9Sstevel@tonic-gate pause_func (char *arg, int flags) 38237c478bd9Sstevel@tonic-gate { 38247c478bd9Sstevel@tonic-gate printf("%s\n", arg); 38257c478bd9Sstevel@tonic-gate 38267c478bd9Sstevel@tonic-gate /* If ESC is returned, then abort this entry. */ 38277c478bd9Sstevel@tonic-gate if (ASCII_CHAR (getkey ()) == 27) 38287c478bd9Sstevel@tonic-gate return 1; 38297c478bd9Sstevel@tonic-gate 38307c478bd9Sstevel@tonic-gate return 0; 38317c478bd9Sstevel@tonic-gate } 38327c478bd9Sstevel@tonic-gate 38337c478bd9Sstevel@tonic-gate static struct builtin builtin_pause = 38347c478bd9Sstevel@tonic-gate { 38357c478bd9Sstevel@tonic-gate "pause", 38367c478bd9Sstevel@tonic-gate pause_func, 38377c478bd9Sstevel@tonic-gate BUILTIN_CMDLINE | BUILTIN_NO_ECHO, 38387c478bd9Sstevel@tonic-gate "pause [MESSAGE ...]", 38397c478bd9Sstevel@tonic-gate "Print MESSAGE, then wait until a key is pressed." 38407c478bd9Sstevel@tonic-gate }; 38417c478bd9Sstevel@tonic-gate 38427c478bd9Sstevel@tonic-gate 38437c478bd9Sstevel@tonic-gate #ifdef GRUB_UTIL 38447c478bd9Sstevel@tonic-gate /* quit */ 38457c478bd9Sstevel@tonic-gate static int 38467c478bd9Sstevel@tonic-gate quit_func (char *arg, int flags) 38477c478bd9Sstevel@tonic-gate { 38487c478bd9Sstevel@tonic-gate stop (); 38497c478bd9Sstevel@tonic-gate 38507c478bd9Sstevel@tonic-gate /* Never reach here. */ 38517c478bd9Sstevel@tonic-gate return 0; 38527c478bd9Sstevel@tonic-gate } 38537c478bd9Sstevel@tonic-gate 38547c478bd9Sstevel@tonic-gate static struct builtin builtin_quit = 38557c478bd9Sstevel@tonic-gate { 38567c478bd9Sstevel@tonic-gate "quit", 38577c478bd9Sstevel@tonic-gate quit_func, 38587c478bd9Sstevel@tonic-gate BUILTIN_CMDLINE | BUILTIN_HELP_LIST, 38597c478bd9Sstevel@tonic-gate "quit", 38607c478bd9Sstevel@tonic-gate "Exit from the GRUB shell." 38617c478bd9Sstevel@tonic-gate }; 38627c478bd9Sstevel@tonic-gate #endif /* GRUB_UTIL */ 38637c478bd9Sstevel@tonic-gate 38647c478bd9Sstevel@tonic-gate 38657c478bd9Sstevel@tonic-gate #ifdef SUPPORT_NETBOOT 38667c478bd9Sstevel@tonic-gate /* rarp */ 38677c478bd9Sstevel@tonic-gate static int 38687c478bd9Sstevel@tonic-gate rarp_func (char *arg, int flags) 38697c478bd9Sstevel@tonic-gate { 38707c478bd9Sstevel@tonic-gate if (! rarp ()) 38717c478bd9Sstevel@tonic-gate { 38727c478bd9Sstevel@tonic-gate if (errnum == ERR_NONE) 38737c478bd9Sstevel@tonic-gate errnum = ERR_DEV_VALUES; 38747c478bd9Sstevel@tonic-gate 38757c478bd9Sstevel@tonic-gate return 1; 38767c478bd9Sstevel@tonic-gate } 38777c478bd9Sstevel@tonic-gate 38787c478bd9Sstevel@tonic-gate /* Notify the configuration. */ 38797c478bd9Sstevel@tonic-gate print_network_configuration (); 38807c478bd9Sstevel@tonic-gate return 0; 38817c478bd9Sstevel@tonic-gate } 38827c478bd9Sstevel@tonic-gate 38837c478bd9Sstevel@tonic-gate static struct builtin builtin_rarp = 38847c478bd9Sstevel@tonic-gate { 38857c478bd9Sstevel@tonic-gate "rarp", 38867c478bd9Sstevel@tonic-gate rarp_func, 38877c478bd9Sstevel@tonic-gate BUILTIN_CMDLINE | BUILTIN_MENU | BUILTIN_HELP_LIST, 38887c478bd9Sstevel@tonic-gate "rarp", 38897c478bd9Sstevel@tonic-gate "Initialize a network device via RARP." 38907c478bd9Sstevel@tonic-gate }; 38917c478bd9Sstevel@tonic-gate #endif /* SUPPORT_NETBOOT */ 38927c478bd9Sstevel@tonic-gate 38937c478bd9Sstevel@tonic-gate 38947c478bd9Sstevel@tonic-gate static int 38957c478bd9Sstevel@tonic-gate read_func (char *arg, int flags) 38967c478bd9Sstevel@tonic-gate { 38977c478bd9Sstevel@tonic-gate int addr; 38987c478bd9Sstevel@tonic-gate 38997c478bd9Sstevel@tonic-gate if (! safe_parse_maxint (&arg, &addr)) 39007c478bd9Sstevel@tonic-gate return 1; 39017c478bd9Sstevel@tonic-gate 39027c478bd9Sstevel@tonic-gate grub_printf ("Address 0x%x: Value 0x%x\n", 39037c478bd9Sstevel@tonic-gate addr, *((unsigned *) RAW_ADDR (addr))); 39047c478bd9Sstevel@tonic-gate return 0; 39057c478bd9Sstevel@tonic-gate } 39067c478bd9Sstevel@tonic-gate 39077c478bd9Sstevel@tonic-gate static struct builtin builtin_read = 39087c478bd9Sstevel@tonic-gate { 39097c478bd9Sstevel@tonic-gate "read", 39107c478bd9Sstevel@tonic-gate read_func, 39117c478bd9Sstevel@tonic-gate BUILTIN_CMDLINE, 39127c478bd9Sstevel@tonic-gate "read ADDR", 39137c478bd9Sstevel@tonic-gate "Read a 32-bit value from memory at address ADDR and" 39147c478bd9Sstevel@tonic-gate " display it in hex format." 39157c478bd9Sstevel@tonic-gate }; 39167c478bd9Sstevel@tonic-gate 39177c478bd9Sstevel@tonic-gate 39187c478bd9Sstevel@tonic-gate /* reboot */ 39197c478bd9Sstevel@tonic-gate static int 39207c478bd9Sstevel@tonic-gate reboot_func (char *arg, int flags) 39217c478bd9Sstevel@tonic-gate { 39227c478bd9Sstevel@tonic-gate grub_reboot (); 39237c478bd9Sstevel@tonic-gate 39247c478bd9Sstevel@tonic-gate /* Never reach here. */ 39257c478bd9Sstevel@tonic-gate return 1; 39267c478bd9Sstevel@tonic-gate } 39277c478bd9Sstevel@tonic-gate 39287c478bd9Sstevel@tonic-gate static struct builtin builtin_reboot = 39297c478bd9Sstevel@tonic-gate { 39307c478bd9Sstevel@tonic-gate "reboot", 39317c478bd9Sstevel@tonic-gate reboot_func, 39327c478bd9Sstevel@tonic-gate BUILTIN_CMDLINE | BUILTIN_HELP_LIST, 39337c478bd9Sstevel@tonic-gate "reboot", 39347c478bd9Sstevel@tonic-gate "Reboot your system." 39357c478bd9Sstevel@tonic-gate }; 39367c478bd9Sstevel@tonic-gate 39377c478bd9Sstevel@tonic-gate 39387c478bd9Sstevel@tonic-gate /* Print the root device information. */ 39397c478bd9Sstevel@tonic-gate static void 39407c478bd9Sstevel@tonic-gate print_root_device (void) 39417c478bd9Sstevel@tonic-gate { 39427c478bd9Sstevel@tonic-gate if (saved_drive == NETWORK_DRIVE) 39437c478bd9Sstevel@tonic-gate { 39447c478bd9Sstevel@tonic-gate /* Network drive. */ 39457c478bd9Sstevel@tonic-gate grub_printf (" (nd):"); 39467c478bd9Sstevel@tonic-gate } 39477c478bd9Sstevel@tonic-gate else if (saved_drive & 0x80) 39487c478bd9Sstevel@tonic-gate { 39497c478bd9Sstevel@tonic-gate /* Hard disk drive. */ 39507c478bd9Sstevel@tonic-gate grub_printf (" (hd%d", saved_drive - 0x80); 39517c478bd9Sstevel@tonic-gate 39527c478bd9Sstevel@tonic-gate if ((saved_partition & 0xFF0000) != 0xFF0000) 39537c478bd9Sstevel@tonic-gate grub_printf (",%d", saved_partition >> 16); 39547c478bd9Sstevel@tonic-gate 39557c478bd9Sstevel@tonic-gate if ((saved_partition & 0x00FF00) != 0x00FF00) 39567c478bd9Sstevel@tonic-gate grub_printf (",%c", ((saved_partition >> 8) & 0xFF) + 'a'); 39577c478bd9Sstevel@tonic-gate 39587c478bd9Sstevel@tonic-gate grub_printf ("):"); 39597c478bd9Sstevel@tonic-gate } 39607c478bd9Sstevel@tonic-gate else 39617c478bd9Sstevel@tonic-gate { 39627c478bd9Sstevel@tonic-gate /* Floppy disk drive. */ 39637c478bd9Sstevel@tonic-gate grub_printf (" (fd%d):", saved_drive); 39647c478bd9Sstevel@tonic-gate } 39657c478bd9Sstevel@tonic-gate 39667c478bd9Sstevel@tonic-gate /* Print the filesystem information. */ 39677c478bd9Sstevel@tonic-gate current_partition = saved_partition; 39687c478bd9Sstevel@tonic-gate current_drive = saved_drive; 39697c478bd9Sstevel@tonic-gate print_fsys_type (); 39707c478bd9Sstevel@tonic-gate } 39717c478bd9Sstevel@tonic-gate 39727c478bd9Sstevel@tonic-gate static int 39737c478bd9Sstevel@tonic-gate real_root_func (char *arg, int attempt_mount) 39747c478bd9Sstevel@tonic-gate { 39757c478bd9Sstevel@tonic-gate int hdbias = 0; 39767c478bd9Sstevel@tonic-gate char *biasptr; 39777c478bd9Sstevel@tonic-gate char *next; 39787c478bd9Sstevel@tonic-gate 39797c478bd9Sstevel@tonic-gate /* If ARG is empty, just print the current root device. */ 39807c478bd9Sstevel@tonic-gate if (! *arg) 39817c478bd9Sstevel@tonic-gate { 39827c478bd9Sstevel@tonic-gate print_root_device (); 39837c478bd9Sstevel@tonic-gate return 0; 39847c478bd9Sstevel@tonic-gate } 39857c478bd9Sstevel@tonic-gate 39867c478bd9Sstevel@tonic-gate /* Call set_device to get the drive and the partition in ARG. */ 39877c478bd9Sstevel@tonic-gate next = set_device (arg); 39887c478bd9Sstevel@tonic-gate if (! next) 39897c478bd9Sstevel@tonic-gate return 1; 39907c478bd9Sstevel@tonic-gate 39917c478bd9Sstevel@tonic-gate /* Ignore ERR_FSYS_MOUNT. */ 39927c478bd9Sstevel@tonic-gate if (attempt_mount) 39937c478bd9Sstevel@tonic-gate { 39947c478bd9Sstevel@tonic-gate if (! open_device () && errnum != ERR_FSYS_MOUNT) 39957c478bd9Sstevel@tonic-gate return 1; 39967c478bd9Sstevel@tonic-gate } 39977c478bd9Sstevel@tonic-gate else 39987c478bd9Sstevel@tonic-gate { 39997c478bd9Sstevel@tonic-gate /* This is necessary, because the location of a partition table 40007c478bd9Sstevel@tonic-gate must be set appropriately. */ 40017c478bd9Sstevel@tonic-gate if (open_partition ()) 40027c478bd9Sstevel@tonic-gate { 40037c478bd9Sstevel@tonic-gate set_bootdev (0); 40047c478bd9Sstevel@tonic-gate if (errnum) 40057c478bd9Sstevel@tonic-gate return 1; 40067c478bd9Sstevel@tonic-gate } 40077c478bd9Sstevel@tonic-gate } 40087c478bd9Sstevel@tonic-gate 40097c478bd9Sstevel@tonic-gate /* Clear ERRNUM. */ 40107c478bd9Sstevel@tonic-gate errnum = 0; 40117c478bd9Sstevel@tonic-gate saved_partition = current_partition; 40127c478bd9Sstevel@tonic-gate saved_drive = current_drive; 40137c478bd9Sstevel@tonic-gate 40147c478bd9Sstevel@tonic-gate if (attempt_mount) 40157c478bd9Sstevel@tonic-gate { 40167c478bd9Sstevel@tonic-gate /* BSD and chainloading evil hacks !! */ 40177c478bd9Sstevel@tonic-gate biasptr = skip_to (0, next); 40187c478bd9Sstevel@tonic-gate safe_parse_maxint (&biasptr, &hdbias); 40197c478bd9Sstevel@tonic-gate errnum = 0; 40207c478bd9Sstevel@tonic-gate bootdev = set_bootdev (hdbias); 40217c478bd9Sstevel@tonic-gate if (errnum) 40227c478bd9Sstevel@tonic-gate return 1; 40237c478bd9Sstevel@tonic-gate 40247c478bd9Sstevel@tonic-gate /* Print the type of the filesystem. */ 40257c478bd9Sstevel@tonic-gate print_fsys_type (); 40267c478bd9Sstevel@tonic-gate } 40277c478bd9Sstevel@tonic-gate 40287c478bd9Sstevel@tonic-gate return 0; 40297c478bd9Sstevel@tonic-gate } 40307c478bd9Sstevel@tonic-gate 40317c478bd9Sstevel@tonic-gate static int 40327c478bd9Sstevel@tonic-gate root_func (char *arg, int flags) 40337c478bd9Sstevel@tonic-gate { 4034b1b8ab34Slling is_zfs_mount = 0; 40357c478bd9Sstevel@tonic-gate return real_root_func (arg, 1); 40367c478bd9Sstevel@tonic-gate } 40377c478bd9Sstevel@tonic-gate 40387c478bd9Sstevel@tonic-gate static struct builtin builtin_root = 40397c478bd9Sstevel@tonic-gate { 40407c478bd9Sstevel@tonic-gate "root", 40417c478bd9Sstevel@tonic-gate root_func, 40427c478bd9Sstevel@tonic-gate BUILTIN_CMDLINE | BUILTIN_HELP_LIST, 40437c478bd9Sstevel@tonic-gate "root [DEVICE [HDBIAS]]", 40447c478bd9Sstevel@tonic-gate "Set the current \"root device\" to the device DEVICE, then" 40457c478bd9Sstevel@tonic-gate " attempt to mount it to get the partition size (for passing the" 40467c478bd9Sstevel@tonic-gate " partition descriptor in `ES:ESI', used by some chain-loaded" 40477c478bd9Sstevel@tonic-gate " bootloaders), the BSD drive-type (for booting BSD kernels using" 40487c478bd9Sstevel@tonic-gate " their native boot format), and correctly determine " 40497c478bd9Sstevel@tonic-gate " the PC partition where a BSD sub-partition is located. The" 40507c478bd9Sstevel@tonic-gate " optional HDBIAS parameter is a number to tell a BSD kernel" 40517c478bd9Sstevel@tonic-gate " how many BIOS drive numbers are on controllers before the current" 40527c478bd9Sstevel@tonic-gate " one. For example, if there is an IDE disk and a SCSI disk, and your" 40537c478bd9Sstevel@tonic-gate " FreeBSD root partition is on the SCSI disk, then use a `1' for HDBIAS." 40547c478bd9Sstevel@tonic-gate }; 40557c478bd9Sstevel@tonic-gate 4056eb2bd662Svikram 4057eb2bd662Svikram /* findroot */ 4058eb2bd662Svikram static int 4059eb2bd662Svikram findroot_func (char *arg, int flags) 4060eb2bd662Svikram { 4061eb2bd662Svikram int ret; 4062eb2bd662Svikram char root[32]; 4063eb2bd662Svikram 4064eb2bd662Svikram if (grub_strlen(arg) >= BOOTSIGN_ARGLEN) { 4065eb2bd662Svikram errnum = ERR_BAD_ARGUMENT; 4066eb2bd662Svikram return 1; 4067eb2bd662Svikram } 4068eb2bd662Svikram 4069eb2bd662Svikram if (arg[0] == '\0') { 4070eb2bd662Svikram errnum = ERR_BAD_ARGUMENT; 4071eb2bd662Svikram return 1; 4072eb2bd662Svikram } 4073eb2bd662Svikram 4074eb2bd662Svikram if (grub_strchr(arg, '/')) { 4075eb2bd662Svikram errnum = ERR_BAD_ARGUMENT; 4076eb2bd662Svikram return 1; 4077eb2bd662Svikram } 4078eb2bd662Svikram 4079051aabe6Staylor find_best_root = 1; 4080051aabe6Staylor best_drive = 0; 4081051aabe6Staylor best_part = 0; 4082eb2bd662Svikram ret = find_common(arg, root, 1, flags); 4083eb2bd662Svikram if (ret != 0) 4084eb2bd662Svikram return (ret); 4085051aabe6Staylor find_best_root = 0; 4086eb2bd662Svikram 4087eb2bd662Svikram return real_root_func (root, 1); 4088eb2bd662Svikram } 4089eb2bd662Svikram 4090eb2bd662Svikram static struct builtin builtin_findroot = 4091eb2bd662Svikram { 4092eb2bd662Svikram "findroot", 4093eb2bd662Svikram findroot_func, 4094eb2bd662Svikram BUILTIN_CMDLINE | BUILTIN_HELP_LIST, 4095963390b4Svikram "findroot <SIGNATURE | (SIGNATURE,partition[,slice])>", 4096963390b4Svikram "Searches across all partitions for the file name SIGNATURE." 4097963390b4Svikram " GRUB looks only in the directory /boot/grub/bootsign for the" 4098963390b4Svikram " filename and it stops as soon as it finds the first instance of" 4099963390b4Svikram " the file - so to be useful the name of the signature file must be" 4100963390b4Svikram " unique across all partitions. Once the signature file is found," 4101963390b4Svikram " GRUB invokes the \"root\" command on that partition." 4102eb2bd662Svikram " An optional partition and slice may be specified to optimize the search." 4103eb2bd662Svikram }; 4104eb2bd662Svikram 4105b1b8ab34Slling 4106b1b8ab34Slling /* 4107b1b8ab34Slling * COMMAND to override the default root filesystem for ZFS 4108b1b8ab34Slling * bootfs pool/fs 4109b1b8ab34Slling */ 4110b1b8ab34Slling static int 4111b1b8ab34Slling bootfs_func (char *arg, int flags) 4112b1b8ab34Slling { 4113b1b8ab34Slling int hdbias = 0; 4114b1b8ab34Slling char *biasptr; 4115b1b8ab34Slling char *next; 4116b1b8ab34Slling 4117b1b8ab34Slling if (! *arg) { 4118b1b8ab34Slling if (current_bootfs[0] != '\0') 4119b1b8ab34Slling grub_printf ("The zfs boot filesystem is set to '%s'.\n", 4120b1b8ab34Slling current_bootfs); 4121b1b8ab34Slling else if (current_rootpool[0] != 0 && current_bootfs_obj != 0) 4122b1b8ab34Slling grub_printf("The zfs boot filesystem is <default: %s/%u>.", 4123b1b8ab34Slling current_rootpool, current_bootfs_obj); 4124b1b8ab34Slling else 412511a41203Slling grub_printf ("The zfs boot filesystem will be derived from " 412611a41203Slling "the default bootfs pool property.\n"); 4127b1b8ab34Slling 4128b1b8ab34Slling return (1); 4129b1b8ab34Slling } 4130b1b8ab34Slling 4131b1b8ab34Slling /* Verify the zfs filesystem name */ 4132b1b8ab34Slling if (arg[0] == '/' || arg[0] == '\0') { 4133b1b8ab34Slling errnum = ERR_BAD_ARGUMENT; 4134b1b8ab34Slling return 0; 4135b1b8ab34Slling } 4136b35c6776Staylor if (current_rootpool[0] != 0 && grub_strncmp(arg, 4137b35c6776Staylor current_rootpool, strlen(current_rootpool))) { 4138b35c6776Staylor errnum = ERR_BAD_ARGUMENT; 4139b35c6776Staylor return 0; 4140b35c6776Staylor } 4141b1b8ab34Slling 4142b1b8ab34Slling if (set_bootfs(arg) == 0) { 4143b1b8ab34Slling errnum = ERR_BAD_ARGUMENT; 4144b1b8ab34Slling return 0; 4145b1b8ab34Slling } 4146b1b8ab34Slling 4147b1b8ab34Slling return (1); 4148b1b8ab34Slling } 4149b1b8ab34Slling 4150b1b8ab34Slling static struct builtin builtin_bootfs = 4151b1b8ab34Slling { 4152b1b8ab34Slling "bootfs", 4153b1b8ab34Slling bootfs_func, 4154b1b8ab34Slling BUILTIN_CMDLINE | BUILTIN_HELP_LIST, 4155b1b8ab34Slling "bootfs [ZFSBOOTFS]", 4156b1b8ab34Slling "Set the current zfs boot filesystem to ZFSBOOTFS (rootpool/rootfs)." 4157b1b8ab34Slling }; 4158b1b8ab34Slling 41597c478bd9Sstevel@tonic-gate 41607c478bd9Sstevel@tonic-gate /* rootnoverify */ 41617c478bd9Sstevel@tonic-gate static int 41627c478bd9Sstevel@tonic-gate rootnoverify_func (char *arg, int flags) 41637c478bd9Sstevel@tonic-gate { 41647c478bd9Sstevel@tonic-gate return real_root_func (arg, 0); 41657c478bd9Sstevel@tonic-gate } 41667c478bd9Sstevel@tonic-gate 41677c478bd9Sstevel@tonic-gate static struct builtin builtin_rootnoverify = 41687c478bd9Sstevel@tonic-gate { 41697c478bd9Sstevel@tonic-gate "rootnoverify", 41707c478bd9Sstevel@tonic-gate rootnoverify_func, 41717c478bd9Sstevel@tonic-gate BUILTIN_CMDLINE | BUILTIN_HELP_LIST, 41727c478bd9Sstevel@tonic-gate "rootnoverify [DEVICE [HDBIAS]]", 41737c478bd9Sstevel@tonic-gate "Similar to `root', but don't attempt to mount the partition. This" 41747c478bd9Sstevel@tonic-gate " is useful for when an OS is outside of the area of the disk that" 41757c478bd9Sstevel@tonic-gate " GRUB can read, but setting the correct root device is still" 41767c478bd9Sstevel@tonic-gate " desired. Note that the items mentioned in `root' which" 41777c478bd9Sstevel@tonic-gate " derived from attempting the mount will NOT work correctly." 41787c478bd9Sstevel@tonic-gate }; 41797c478bd9Sstevel@tonic-gate 41807c478bd9Sstevel@tonic-gate 41817c478bd9Sstevel@tonic-gate /* savedefault */ 41827c478bd9Sstevel@tonic-gate static int 41837c478bd9Sstevel@tonic-gate savedefault_func (char *arg, int flags) 41847c478bd9Sstevel@tonic-gate { 41857c478bd9Sstevel@tonic-gate #if !defined(SUPPORT_DISKLESS) && !defined(GRUB_UTIL) 41867c478bd9Sstevel@tonic-gate unsigned long tmp_drive = saved_drive; 41877c478bd9Sstevel@tonic-gate unsigned long tmp_partition = saved_partition; 41887c478bd9Sstevel@tonic-gate char *default_file = (char *) DEFAULT_FILE_BUF; 41897c478bd9Sstevel@tonic-gate char buf[10]; 41907c478bd9Sstevel@tonic-gate char sect[SECTOR_SIZE]; 41917c478bd9Sstevel@tonic-gate int entryno; 41927c478bd9Sstevel@tonic-gate int sector_count = 0; 4193342440ecSPrasad Singamsetty unsigned int saved_sectors[2]; 41947c478bd9Sstevel@tonic-gate int saved_offsets[2]; 41957c478bd9Sstevel@tonic-gate int saved_lengths[2]; 41967c478bd9Sstevel@tonic-gate 4197b1b8ab34Slling /* not supported for zfs root */ 4198b1b8ab34Slling if (is_zfs_mount == 1) { 4199b1b8ab34Slling return (0); /* no-op */ 4200b1b8ab34Slling } 4201b1b8ab34Slling 42027c478bd9Sstevel@tonic-gate /* Save sector information about at most two sectors. */ 4203*1b8adde7SWilliam Kucharski auto void disk_read_savesect_func (unsigned int sector, int offset, 4204*1b8adde7SWilliam Kucharski int length); 4205*1b8adde7SWilliam Kucharski void disk_read_savesect_func (unsigned int sector, int offset, int length) 42067c478bd9Sstevel@tonic-gate { 42077c478bd9Sstevel@tonic-gate if (sector_count < 2) 42087c478bd9Sstevel@tonic-gate { 42097c478bd9Sstevel@tonic-gate saved_sectors[sector_count] = sector; 42107c478bd9Sstevel@tonic-gate saved_offsets[sector_count] = offset; 42117c478bd9Sstevel@tonic-gate saved_lengths[sector_count] = length; 42127c478bd9Sstevel@tonic-gate } 42137c478bd9Sstevel@tonic-gate sector_count++; 42147c478bd9Sstevel@tonic-gate } 42157c478bd9Sstevel@tonic-gate 42167c478bd9Sstevel@tonic-gate /* This command is only useful when you boot an entry from the menu 42177c478bd9Sstevel@tonic-gate interface. */ 42187c478bd9Sstevel@tonic-gate if (! (flags & BUILTIN_SCRIPT)) 42197c478bd9Sstevel@tonic-gate { 42207c478bd9Sstevel@tonic-gate errnum = ERR_UNRECOGNIZED; 42217c478bd9Sstevel@tonic-gate return 1; 42227c478bd9Sstevel@tonic-gate } 42237c478bd9Sstevel@tonic-gate 42247c478bd9Sstevel@tonic-gate /* Determine a saved entry number. */ 42257c478bd9Sstevel@tonic-gate if (*arg) 42267c478bd9Sstevel@tonic-gate { 42277c478bd9Sstevel@tonic-gate if (grub_memcmp (arg, "fallback", sizeof ("fallback") - 1) == 0) 42287c478bd9Sstevel@tonic-gate { 42297c478bd9Sstevel@tonic-gate int i; 42307c478bd9Sstevel@tonic-gate int index = 0; 42317c478bd9Sstevel@tonic-gate 42327c478bd9Sstevel@tonic-gate for (i = 0; i < MAX_FALLBACK_ENTRIES; i++) 42337c478bd9Sstevel@tonic-gate { 42347c478bd9Sstevel@tonic-gate if (fallback_entries[i] < 0) 42357c478bd9Sstevel@tonic-gate break; 42367c478bd9Sstevel@tonic-gate if (fallback_entries[i] == current_entryno) 42377c478bd9Sstevel@tonic-gate { 42387c478bd9Sstevel@tonic-gate index = i + 1; 42397c478bd9Sstevel@tonic-gate break; 42407c478bd9Sstevel@tonic-gate } 42417c478bd9Sstevel@tonic-gate } 42427c478bd9Sstevel@tonic-gate 42437c478bd9Sstevel@tonic-gate if (index >= MAX_FALLBACK_ENTRIES || fallback_entries[index] < 0) 42447c478bd9Sstevel@tonic-gate { 42457c478bd9Sstevel@tonic-gate /* This is the last. */ 42467c478bd9Sstevel@tonic-gate errnum = ERR_BAD_ARGUMENT; 42477c478bd9Sstevel@tonic-gate return 1; 42487c478bd9Sstevel@tonic-gate } 42497c478bd9Sstevel@tonic-gate 42507c478bd9Sstevel@tonic-gate entryno = fallback_entries[index]; 42517c478bd9Sstevel@tonic-gate } 42527c478bd9Sstevel@tonic-gate else if (! safe_parse_maxint (&arg, &entryno)) 42537c478bd9Sstevel@tonic-gate return 1; 42547c478bd9Sstevel@tonic-gate } 42557c478bd9Sstevel@tonic-gate else 42567c478bd9Sstevel@tonic-gate entryno = current_entryno; 42577c478bd9Sstevel@tonic-gate 42587c478bd9Sstevel@tonic-gate /* Open the default file. */ 42597c478bd9Sstevel@tonic-gate saved_drive = boot_drive; 42607c478bd9Sstevel@tonic-gate saved_partition = install_partition; 42617c478bd9Sstevel@tonic-gate if (grub_open (default_file)) 42627c478bd9Sstevel@tonic-gate { 42637c478bd9Sstevel@tonic-gate int len; 42647c478bd9Sstevel@tonic-gate 42657c478bd9Sstevel@tonic-gate disk_read_hook = disk_read_savesect_func; 42667c478bd9Sstevel@tonic-gate len = grub_read (buf, sizeof (buf)); 42677c478bd9Sstevel@tonic-gate disk_read_hook = 0; 42687c478bd9Sstevel@tonic-gate grub_close (); 42697c478bd9Sstevel@tonic-gate 42707c478bd9Sstevel@tonic-gate if (len != sizeof (buf)) 42717c478bd9Sstevel@tonic-gate { 42727c478bd9Sstevel@tonic-gate /* This is too small. Do not modify the file manually, please! */ 42737c478bd9Sstevel@tonic-gate errnum = ERR_READ; 42747c478bd9Sstevel@tonic-gate goto fail; 42757c478bd9Sstevel@tonic-gate } 42767c478bd9Sstevel@tonic-gate 42777c478bd9Sstevel@tonic-gate if (sector_count > 2) 42787c478bd9Sstevel@tonic-gate { 42797c478bd9Sstevel@tonic-gate /* Is this possible?! Too fragmented! */ 42807c478bd9Sstevel@tonic-gate errnum = ERR_FSYS_CORRUPT; 42817c478bd9Sstevel@tonic-gate goto fail; 42827c478bd9Sstevel@tonic-gate } 42837c478bd9Sstevel@tonic-gate 42847c478bd9Sstevel@tonic-gate /* Set up a string to be written. */ 42857c478bd9Sstevel@tonic-gate grub_memset (buf, '\n', sizeof (buf)); 42867c478bd9Sstevel@tonic-gate grub_sprintf (buf, "%d", entryno); 42877c478bd9Sstevel@tonic-gate 42887c478bd9Sstevel@tonic-gate if (saved_lengths[0] < sizeof (buf)) 42897c478bd9Sstevel@tonic-gate { 42907c478bd9Sstevel@tonic-gate /* The file is anchored to another file and the first few bytes 42917c478bd9Sstevel@tonic-gate are spanned in two sectors. Uggh... */ 42927c478bd9Sstevel@tonic-gate if (! rawread (current_drive, saved_sectors[0], 0, SECTOR_SIZE, 42937c478bd9Sstevel@tonic-gate sect)) 42947c478bd9Sstevel@tonic-gate goto fail; 42957c478bd9Sstevel@tonic-gate grub_memmove (sect + saved_offsets[0], buf, saved_lengths[0]); 42967c478bd9Sstevel@tonic-gate if (! rawwrite (current_drive, saved_sectors[0], sect)) 42977c478bd9Sstevel@tonic-gate goto fail; 42987c478bd9Sstevel@tonic-gate 42997c478bd9Sstevel@tonic-gate if (! rawread (current_drive, saved_sectors[1], 0, SECTOR_SIZE, 43007c478bd9Sstevel@tonic-gate sect)) 43017c478bd9Sstevel@tonic-gate goto fail; 43027c478bd9Sstevel@tonic-gate grub_memmove (sect + saved_offsets[1], 43037c478bd9Sstevel@tonic-gate buf + saved_lengths[0], 43047c478bd9Sstevel@tonic-gate sizeof (buf) - saved_lengths[0]); 43057c478bd9Sstevel@tonic-gate if (! rawwrite (current_drive, saved_sectors[1], sect)) 43067c478bd9Sstevel@tonic-gate goto fail; 43077c478bd9Sstevel@tonic-gate } 43087c478bd9Sstevel@tonic-gate else 43097c478bd9Sstevel@tonic-gate { 43107c478bd9Sstevel@tonic-gate /* This is a simple case. It fits into a single sector. */ 43117c478bd9Sstevel@tonic-gate if (! rawread (current_drive, saved_sectors[0], 0, SECTOR_SIZE, 43127c478bd9Sstevel@tonic-gate sect)) 43137c478bd9Sstevel@tonic-gate goto fail; 43147c478bd9Sstevel@tonic-gate grub_memmove (sect + saved_offsets[0], buf, sizeof (buf)); 43157c478bd9Sstevel@tonic-gate if (! rawwrite (current_drive, saved_sectors[0], sect)) 43167c478bd9Sstevel@tonic-gate goto fail; 43177c478bd9Sstevel@tonic-gate } 43187c478bd9Sstevel@tonic-gate 43197c478bd9Sstevel@tonic-gate /* Clear the cache. */ 4320342440ecSPrasad Singamsetty buf_track = BUF_CACHE_INVALID; 43217c478bd9Sstevel@tonic-gate } 43227c478bd9Sstevel@tonic-gate 43237c478bd9Sstevel@tonic-gate fail: 43247c478bd9Sstevel@tonic-gate saved_drive = tmp_drive; 43257c478bd9Sstevel@tonic-gate saved_partition = tmp_partition; 43267c478bd9Sstevel@tonic-gate return errnum; 43277c478bd9Sstevel@tonic-gate #else /* ! SUPPORT_DISKLESS && ! GRUB_UTIL */ 43287c478bd9Sstevel@tonic-gate errnum = ERR_UNRECOGNIZED; 43297c478bd9Sstevel@tonic-gate return 1; 43307c478bd9Sstevel@tonic-gate #endif /* ! SUPPORT_DISKLESS && ! GRUB_UTIL */ 43317c478bd9Sstevel@tonic-gate } 43327c478bd9Sstevel@tonic-gate 43337c478bd9Sstevel@tonic-gate static struct builtin builtin_savedefault = 43347c478bd9Sstevel@tonic-gate { 43357c478bd9Sstevel@tonic-gate "savedefault", 43367c478bd9Sstevel@tonic-gate savedefault_func, 43377c478bd9Sstevel@tonic-gate BUILTIN_CMDLINE, 43387c478bd9Sstevel@tonic-gate "savedefault [NUM | `fallback']", 43397c478bd9Sstevel@tonic-gate "Save the current entry as the default boot entry if no argument is" 43407c478bd9Sstevel@tonic-gate " specified. If a number is specified, this number is saved. If" 43417c478bd9Sstevel@tonic-gate " `fallback' is used, next fallback entry is saved." 43427c478bd9Sstevel@tonic-gate }; 43437c478bd9Sstevel@tonic-gate 43447c478bd9Sstevel@tonic-gate 43457c478bd9Sstevel@tonic-gate #ifdef SUPPORT_SERIAL 43467c478bd9Sstevel@tonic-gate /* serial */ 43477c478bd9Sstevel@tonic-gate static int 43487c478bd9Sstevel@tonic-gate serial_func (char *arg, int flags) 43497c478bd9Sstevel@tonic-gate { 43507c478bd9Sstevel@tonic-gate unsigned short port = serial_hw_get_port (0); 43517c478bd9Sstevel@tonic-gate unsigned int speed = 9600; 43527c478bd9Sstevel@tonic-gate int word_len = UART_8BITS_WORD; 43537c478bd9Sstevel@tonic-gate int parity = UART_NO_PARITY; 43547c478bd9Sstevel@tonic-gate int stop_bit_len = UART_1_STOP_BIT; 43557c478bd9Sstevel@tonic-gate 43567c478bd9Sstevel@tonic-gate /* Process GNU-style long options. 43577c478bd9Sstevel@tonic-gate FIXME: We should implement a getopt-like function, to avoid 43587c478bd9Sstevel@tonic-gate duplications. */ 43597c478bd9Sstevel@tonic-gate while (1) 43607c478bd9Sstevel@tonic-gate { 43617c478bd9Sstevel@tonic-gate if (grub_memcmp (arg, "--unit=", sizeof ("--unit=") - 1) == 0) 43627c478bd9Sstevel@tonic-gate { 43637c478bd9Sstevel@tonic-gate char *p = arg + sizeof ("--unit=") - 1; 43647c478bd9Sstevel@tonic-gate int unit; 43657c478bd9Sstevel@tonic-gate 43667c478bd9Sstevel@tonic-gate if (! safe_parse_maxint (&p, &unit)) 43677c478bd9Sstevel@tonic-gate return 1; 43687c478bd9Sstevel@tonic-gate 43697c478bd9Sstevel@tonic-gate if (unit < 0 || unit > 3) 43707c478bd9Sstevel@tonic-gate { 43717c478bd9Sstevel@tonic-gate errnum = ERR_DEV_VALUES; 43727c478bd9Sstevel@tonic-gate return 1; 43737c478bd9Sstevel@tonic-gate } 43747c478bd9Sstevel@tonic-gate 43757c478bd9Sstevel@tonic-gate port = serial_hw_get_port (unit); 43767c478bd9Sstevel@tonic-gate } 43777c478bd9Sstevel@tonic-gate else if (grub_memcmp (arg, "--speed=", sizeof ("--speed=") - 1) == 0) 43787c478bd9Sstevel@tonic-gate { 43797c478bd9Sstevel@tonic-gate char *p = arg + sizeof ("--speed=") - 1; 43807c478bd9Sstevel@tonic-gate int num; 43817c478bd9Sstevel@tonic-gate 43827c478bd9Sstevel@tonic-gate if (! safe_parse_maxint (&p, &num)) 43837c478bd9Sstevel@tonic-gate return 1; 43847c478bd9Sstevel@tonic-gate 43857c478bd9Sstevel@tonic-gate speed = (unsigned int) num; 43867c478bd9Sstevel@tonic-gate } 43877c478bd9Sstevel@tonic-gate else if (grub_memcmp (arg, "--port=", sizeof ("--port=") - 1) == 0) 43887c478bd9Sstevel@tonic-gate { 43897c478bd9Sstevel@tonic-gate char *p = arg + sizeof ("--port=") - 1; 43907c478bd9Sstevel@tonic-gate int num; 43917c478bd9Sstevel@tonic-gate 43927c478bd9Sstevel@tonic-gate if (! safe_parse_maxint (&p, &num)) 43937c478bd9Sstevel@tonic-gate return 1; 43947c478bd9Sstevel@tonic-gate 43957c478bd9Sstevel@tonic-gate port = (unsigned short) num; 43967c478bd9Sstevel@tonic-gate } 43977c478bd9Sstevel@tonic-gate else if (grub_memcmp (arg, "--word=", sizeof ("--word=") - 1) == 0) 43987c478bd9Sstevel@tonic-gate { 43997c478bd9Sstevel@tonic-gate char *p = arg + sizeof ("--word=") - 1; 44007c478bd9Sstevel@tonic-gate int len; 44017c478bd9Sstevel@tonic-gate 44027c478bd9Sstevel@tonic-gate if (! safe_parse_maxint (&p, &len)) 44037c478bd9Sstevel@tonic-gate return 1; 44047c478bd9Sstevel@tonic-gate 44057c478bd9Sstevel@tonic-gate switch (len) 44067c478bd9Sstevel@tonic-gate { 44077c478bd9Sstevel@tonic-gate case 5: word_len = UART_5BITS_WORD; break; 44087c478bd9Sstevel@tonic-gate case 6: word_len = UART_6BITS_WORD; break; 44097c478bd9Sstevel@tonic-gate case 7: word_len = UART_7BITS_WORD; break; 44107c478bd9Sstevel@tonic-gate case 8: word_len = UART_8BITS_WORD; break; 44117c478bd9Sstevel@tonic-gate default: 44127c478bd9Sstevel@tonic-gate errnum = ERR_BAD_ARGUMENT; 44137c478bd9Sstevel@tonic-gate return 1; 44147c478bd9Sstevel@tonic-gate } 44157c478bd9Sstevel@tonic-gate } 44167c478bd9Sstevel@tonic-gate else if (grub_memcmp (arg, "--stop=", sizeof ("--stop=") - 1) == 0) 44177c478bd9Sstevel@tonic-gate { 44187c478bd9Sstevel@tonic-gate char *p = arg + sizeof ("--stop=") - 1; 44197c478bd9Sstevel@tonic-gate int len; 44207c478bd9Sstevel@tonic-gate 44217c478bd9Sstevel@tonic-gate if (! safe_parse_maxint (&p, &len)) 44227c478bd9Sstevel@tonic-gate return 1; 44237c478bd9Sstevel@tonic-gate 44247c478bd9Sstevel@tonic-gate switch (len) 44257c478bd9Sstevel@tonic-gate { 44267c478bd9Sstevel@tonic-gate case 1: stop_bit_len = UART_1_STOP_BIT; break; 44277c478bd9Sstevel@tonic-gate case 2: stop_bit_len = UART_2_STOP_BITS; break; 44287c478bd9Sstevel@tonic-gate default: 44297c478bd9Sstevel@tonic-gate errnum = ERR_BAD_ARGUMENT; 44307c478bd9Sstevel@tonic-gate return 1; 44317c478bd9Sstevel@tonic-gate } 44327c478bd9Sstevel@tonic-gate } 44337c478bd9Sstevel@tonic-gate else if (grub_memcmp (arg, "--parity=", sizeof ("--parity=") - 1) == 0) 44347c478bd9Sstevel@tonic-gate { 44357c478bd9Sstevel@tonic-gate char *p = arg + sizeof ("--parity=") - 1; 44367c478bd9Sstevel@tonic-gate 44377c478bd9Sstevel@tonic-gate if (grub_memcmp (p, "no", sizeof ("no") - 1) == 0) 44387c478bd9Sstevel@tonic-gate parity = UART_NO_PARITY; 44397c478bd9Sstevel@tonic-gate else if (grub_memcmp (p, "odd", sizeof ("odd") - 1) == 0) 44407c478bd9Sstevel@tonic-gate parity = UART_ODD_PARITY; 44417c478bd9Sstevel@tonic-gate else if (grub_memcmp (p, "even", sizeof ("even") - 1) == 0) 44427c478bd9Sstevel@tonic-gate parity = UART_EVEN_PARITY; 44437c478bd9Sstevel@tonic-gate else 44447c478bd9Sstevel@tonic-gate { 44457c478bd9Sstevel@tonic-gate errnum = ERR_BAD_ARGUMENT; 44467c478bd9Sstevel@tonic-gate return 1; 44477c478bd9Sstevel@tonic-gate } 44487c478bd9Sstevel@tonic-gate } 44497c478bd9Sstevel@tonic-gate # ifdef GRUB_UTIL 44507c478bd9Sstevel@tonic-gate /* In the grub shell, don't use any port number but open a tty 44517c478bd9Sstevel@tonic-gate device instead. */ 44527c478bd9Sstevel@tonic-gate else if (grub_memcmp (arg, "--device=", sizeof ("--device=") - 1) == 0) 44537c478bd9Sstevel@tonic-gate { 44547c478bd9Sstevel@tonic-gate char *p = arg + sizeof ("--device=") - 1; 44557c478bd9Sstevel@tonic-gate char dev[256]; /* XXX */ 44567c478bd9Sstevel@tonic-gate char *q = dev; 44577c478bd9Sstevel@tonic-gate 44587c478bd9Sstevel@tonic-gate while (*p && ! grub_isspace (*p)) 44597c478bd9Sstevel@tonic-gate *q++ = *p++; 44607c478bd9Sstevel@tonic-gate 44617c478bd9Sstevel@tonic-gate *q = 0; 44627c478bd9Sstevel@tonic-gate serial_set_device (dev); 44637c478bd9Sstevel@tonic-gate } 44647c478bd9Sstevel@tonic-gate # endif /* GRUB_UTIL */ 44657c478bd9Sstevel@tonic-gate else 44667c478bd9Sstevel@tonic-gate break; 44677c478bd9Sstevel@tonic-gate 44687c478bd9Sstevel@tonic-gate arg = skip_to (0, arg); 44697c478bd9Sstevel@tonic-gate } 44707c478bd9Sstevel@tonic-gate 44717c478bd9Sstevel@tonic-gate /* Initialize the serial unit. */ 44727c478bd9Sstevel@tonic-gate if (! serial_hw_init (port, speed, word_len, parity, stop_bit_len)) 44737c478bd9Sstevel@tonic-gate { 44747c478bd9Sstevel@tonic-gate errnum = ERR_BAD_ARGUMENT; 44757c478bd9Sstevel@tonic-gate return 1; 44767c478bd9Sstevel@tonic-gate } 44777c478bd9Sstevel@tonic-gate 44787c478bd9Sstevel@tonic-gate return 0; 44797c478bd9Sstevel@tonic-gate } 44807c478bd9Sstevel@tonic-gate 44817c478bd9Sstevel@tonic-gate static struct builtin builtin_serial = 44827c478bd9Sstevel@tonic-gate { 44837c478bd9Sstevel@tonic-gate "serial", 44847c478bd9Sstevel@tonic-gate serial_func, 44857c478bd9Sstevel@tonic-gate BUILTIN_MENU | BUILTIN_CMDLINE | BUILTIN_HELP_LIST, 44867c478bd9Sstevel@tonic-gate "serial [--unit=UNIT] [--port=PORT] [--speed=SPEED] [--word=WORD] [--parity=PARITY] [--stop=STOP] [--device=DEV]", 44877c478bd9Sstevel@tonic-gate "Initialize a serial device. UNIT is a digit that specifies which serial" 44887c478bd9Sstevel@tonic-gate " device is used (e.g. 0 == COM1). If you need to specify the port number," 44897c478bd9Sstevel@tonic-gate " set it by --port. SPEED is the DTE-DTE speed. WORD is the word length," 44907c478bd9Sstevel@tonic-gate " PARITY is the type of parity, which is one of `no', `odd' and `even'." 44917c478bd9Sstevel@tonic-gate " STOP is the length of stop bit(s). The option --device can be used only" 44927c478bd9Sstevel@tonic-gate " in the grub shell, which specifies the file name of a tty device. The" 44937c478bd9Sstevel@tonic-gate " default values are COM1, 9600, 8N1." 44947c478bd9Sstevel@tonic-gate }; 44957c478bd9Sstevel@tonic-gate #endif /* SUPPORT_SERIAL */ 44967c478bd9Sstevel@tonic-gate 44977c478bd9Sstevel@tonic-gate 44987c478bd9Sstevel@tonic-gate /* setkey */ 44997c478bd9Sstevel@tonic-gate struct keysym 45007c478bd9Sstevel@tonic-gate { 45017c478bd9Sstevel@tonic-gate char *unshifted_name; /* the name in unshifted state */ 45027c478bd9Sstevel@tonic-gate char *shifted_name; /* the name in shifted state */ 45037c478bd9Sstevel@tonic-gate unsigned char unshifted_ascii; /* the ascii code in unshifted state */ 45047c478bd9Sstevel@tonic-gate unsigned char shifted_ascii; /* the ascii code in shifted state */ 45057c478bd9Sstevel@tonic-gate unsigned char keycode; /* keyboard scancode */ 45067c478bd9Sstevel@tonic-gate }; 45077c478bd9Sstevel@tonic-gate 45087c478bd9Sstevel@tonic-gate /* The table for key symbols. If the "shifted" member of an entry is 45097c478bd9Sstevel@tonic-gate NULL, the entry does not have shifted state. */ 45107c478bd9Sstevel@tonic-gate static struct keysym keysym_table[] = 45117c478bd9Sstevel@tonic-gate { 45127c478bd9Sstevel@tonic-gate {"escape", 0, 0x1b, 0, 0x01}, 45137c478bd9Sstevel@tonic-gate {"1", "exclam", '1', '!', 0x02}, 45147c478bd9Sstevel@tonic-gate {"2", "at", '2', '@', 0x03}, 45157c478bd9Sstevel@tonic-gate {"3", "numbersign", '3', '#', 0x04}, 45167c478bd9Sstevel@tonic-gate {"4", "dollar", '4', '$', 0x05}, 45177c478bd9Sstevel@tonic-gate {"5", "percent", '5', '%', 0x06}, 45187c478bd9Sstevel@tonic-gate {"6", "caret", '6', '^', 0x07}, 45197c478bd9Sstevel@tonic-gate {"7", "ampersand", '7', '&', 0x08}, 45207c478bd9Sstevel@tonic-gate {"8", "asterisk", '8', '*', 0x09}, 45217c478bd9Sstevel@tonic-gate {"9", "parenleft", '9', '(', 0x0a}, 45227c478bd9Sstevel@tonic-gate {"0", "parenright", '0', ')', 0x0b}, 45237c478bd9Sstevel@tonic-gate {"minus", "underscore", '-', '_', 0x0c}, 45247c478bd9Sstevel@tonic-gate {"equal", "plus", '=', '+', 0x0d}, 45257c478bd9Sstevel@tonic-gate {"backspace", 0, '\b', 0, 0x0e}, 45267c478bd9Sstevel@tonic-gate {"tab", 0, '\t', 0, 0x0f}, 45277c478bd9Sstevel@tonic-gate {"q", "Q", 'q', 'Q', 0x10}, 45287c478bd9Sstevel@tonic-gate {"w", "W", 'w', 'W', 0x11}, 45297c478bd9Sstevel@tonic-gate {"e", "E", 'e', 'E', 0x12}, 45307c478bd9Sstevel@tonic-gate {"r", "R", 'r', 'R', 0x13}, 45317c478bd9Sstevel@tonic-gate {"t", "T", 't', 'T', 0x14}, 45327c478bd9Sstevel@tonic-gate {"y", "Y", 'y', 'Y', 0x15}, 45337c478bd9Sstevel@tonic-gate {"u", "U", 'u', 'U', 0x16}, 45347c478bd9Sstevel@tonic-gate {"i", "I", 'i', 'I', 0x17}, 45357c478bd9Sstevel@tonic-gate {"o", "O", 'o', 'O', 0x18}, 45367c478bd9Sstevel@tonic-gate {"p", "P", 'p', 'P', 0x19}, 45377c478bd9Sstevel@tonic-gate {"bracketleft", "braceleft", '[', '{', 0x1a}, 45387c478bd9Sstevel@tonic-gate {"bracketright", "braceright", ']', '}', 0x1b}, 45397c478bd9Sstevel@tonic-gate {"enter", 0, '\n', 0, 0x1c}, 45407c478bd9Sstevel@tonic-gate {"control", 0, 0, 0, 0x1d}, 45417c478bd9Sstevel@tonic-gate {"a", "A", 'a', 'A', 0x1e}, 45427c478bd9Sstevel@tonic-gate {"s", "S", 's', 'S', 0x1f}, 45437c478bd9Sstevel@tonic-gate {"d", "D", 'd', 'D', 0x20}, 45447c478bd9Sstevel@tonic-gate {"f", "F", 'f', 'F', 0x21}, 45457c478bd9Sstevel@tonic-gate {"g", "G", 'g', 'G', 0x22}, 45467c478bd9Sstevel@tonic-gate {"h", "H", 'h', 'H', 0x23}, 45477c478bd9Sstevel@tonic-gate {"j", "J", 'j', 'J', 0x24}, 45487c478bd9Sstevel@tonic-gate {"k", "K", 'k', 'K', 0x25}, 45497c478bd9Sstevel@tonic-gate {"l", "L", 'l', 'L', 0x26}, 45507c478bd9Sstevel@tonic-gate {"semicolon", "colon", ';', ':', 0x27}, 45517c478bd9Sstevel@tonic-gate {"quote", "doublequote", '\'', '"', 0x28}, 45527c478bd9Sstevel@tonic-gate {"backquote", "tilde", '`', '~', 0x29}, 45537c478bd9Sstevel@tonic-gate {"shift", 0, 0, 0, 0x2a}, 45547c478bd9Sstevel@tonic-gate {"backslash", "bar", '\\', '|', 0x2b}, 45557c478bd9Sstevel@tonic-gate {"z", "Z", 'z', 'Z', 0x2c}, 45567c478bd9Sstevel@tonic-gate {"x", "X", 'x', 'X', 0x2d}, 45577c478bd9Sstevel@tonic-gate {"c", "C", 'c', 'C', 0x2e}, 45587c478bd9Sstevel@tonic-gate {"v", "V", 'v', 'V', 0x2f}, 45597c478bd9Sstevel@tonic-gate {"b", "B", 'b', 'B', 0x30}, 45607c478bd9Sstevel@tonic-gate {"n", "N", 'n', 'N', 0x31}, 45617c478bd9Sstevel@tonic-gate {"m", "M", 'm', 'M', 0x32}, 45627c478bd9Sstevel@tonic-gate {"comma", "less", ',', '<', 0x33}, 45637c478bd9Sstevel@tonic-gate {"period", "greater", '.', '>', 0x34}, 45647c478bd9Sstevel@tonic-gate {"slash", "question", '/', '?', 0x35}, 45657c478bd9Sstevel@tonic-gate {"alt", 0, 0, 0, 0x38}, 45667c478bd9Sstevel@tonic-gate {"space", 0, ' ', 0, 0x39}, 45677c478bd9Sstevel@tonic-gate {"capslock", 0, 0, 0, 0x3a}, 45687c478bd9Sstevel@tonic-gate {"F1", 0, 0, 0, 0x3b}, 45697c478bd9Sstevel@tonic-gate {"F2", 0, 0, 0, 0x3c}, 45707c478bd9Sstevel@tonic-gate {"F3", 0, 0, 0, 0x3d}, 45717c478bd9Sstevel@tonic-gate {"F4", 0, 0, 0, 0x3e}, 45727c478bd9Sstevel@tonic-gate {"F5", 0, 0, 0, 0x3f}, 45737c478bd9Sstevel@tonic-gate {"F6", 0, 0, 0, 0x40}, 45747c478bd9Sstevel@tonic-gate {"F7", 0, 0, 0, 0x41}, 45757c478bd9Sstevel@tonic-gate {"F8", 0, 0, 0, 0x42}, 45767c478bd9Sstevel@tonic-gate {"F9", 0, 0, 0, 0x43}, 45777c478bd9Sstevel@tonic-gate {"F10", 0, 0, 0, 0x44}, 45787c478bd9Sstevel@tonic-gate /* Caution: do not add NumLock here! we cannot deal with it properly. */ 45797c478bd9Sstevel@tonic-gate {"delete", 0, 0x7f, 0, 0x53} 45807c478bd9Sstevel@tonic-gate }; 45817c478bd9Sstevel@tonic-gate 45827c478bd9Sstevel@tonic-gate static int 45837c478bd9Sstevel@tonic-gate setkey_func (char *arg, int flags) 45847c478bd9Sstevel@tonic-gate { 45857c478bd9Sstevel@tonic-gate char *to_key, *from_key; 45867c478bd9Sstevel@tonic-gate int to_code, from_code; 45877c478bd9Sstevel@tonic-gate int map_in_interrupt = 0; 45887c478bd9Sstevel@tonic-gate 4589*1b8adde7SWilliam Kucharski auto int find_key_code (char *key); 4590*1b8adde7SWilliam Kucharski auto int find_ascii_code (char *key); 4591*1b8adde7SWilliam Kucharski 4592*1b8adde7SWilliam Kucharski auto int find_key_code (char *key) 45937c478bd9Sstevel@tonic-gate { 45947c478bd9Sstevel@tonic-gate int i; 45957c478bd9Sstevel@tonic-gate 45967c478bd9Sstevel@tonic-gate for (i = 0; i < sizeof (keysym_table) / sizeof (keysym_table[0]); i++) 45977c478bd9Sstevel@tonic-gate { 45987c478bd9Sstevel@tonic-gate if (keysym_table[i].unshifted_name && 45997c478bd9Sstevel@tonic-gate grub_strcmp (key, keysym_table[i].unshifted_name) == 0) 46007c478bd9Sstevel@tonic-gate return keysym_table[i].keycode; 46017c478bd9Sstevel@tonic-gate else if (keysym_table[i].shifted_name && 46027c478bd9Sstevel@tonic-gate grub_strcmp (key, keysym_table[i].shifted_name) == 0) 46037c478bd9Sstevel@tonic-gate return keysym_table[i].keycode; 46047c478bd9Sstevel@tonic-gate } 46057c478bd9Sstevel@tonic-gate 46067c478bd9Sstevel@tonic-gate return 0; 46077c478bd9Sstevel@tonic-gate } 46087c478bd9Sstevel@tonic-gate 4609*1b8adde7SWilliam Kucharski auto int find_ascii_code (char *key) 46107c478bd9Sstevel@tonic-gate { 46117c478bd9Sstevel@tonic-gate int i; 46127c478bd9Sstevel@tonic-gate 46137c478bd9Sstevel@tonic-gate for (i = 0; i < sizeof (keysym_table) / sizeof (keysym_table[0]); i++) 46147c478bd9Sstevel@tonic-gate { 46157c478bd9Sstevel@tonic-gate if (keysym_table[i].unshifted_name && 46167c478bd9Sstevel@tonic-gate grub_strcmp (key, keysym_table[i].unshifted_name) == 0) 46177c478bd9Sstevel@tonic-gate return keysym_table[i].unshifted_ascii; 46187c478bd9Sstevel@tonic-gate else if (keysym_table[i].shifted_name && 46197c478bd9Sstevel@tonic-gate grub_strcmp (key, keysym_table[i].shifted_name) == 0) 46207c478bd9Sstevel@tonic-gate return keysym_table[i].shifted_ascii; 46217c478bd9Sstevel@tonic-gate } 46227c478bd9Sstevel@tonic-gate 46237c478bd9Sstevel@tonic-gate return 0; 46247c478bd9Sstevel@tonic-gate } 46257c478bd9Sstevel@tonic-gate 46267c478bd9Sstevel@tonic-gate to_key = arg; 46277c478bd9Sstevel@tonic-gate from_key = skip_to (0, to_key); 46287c478bd9Sstevel@tonic-gate 46297c478bd9Sstevel@tonic-gate if (! *to_key) 46307c478bd9Sstevel@tonic-gate { 46317c478bd9Sstevel@tonic-gate /* If the user specifies no argument, reset the key mappings. */ 46327c478bd9Sstevel@tonic-gate grub_memset (bios_key_map, 0, KEY_MAP_SIZE * sizeof (unsigned short)); 46337c478bd9Sstevel@tonic-gate grub_memset (ascii_key_map, 0, KEY_MAP_SIZE * sizeof (unsigned short)); 46347c478bd9Sstevel@tonic-gate 46357c478bd9Sstevel@tonic-gate return 0; 46367c478bd9Sstevel@tonic-gate } 46377c478bd9Sstevel@tonic-gate else if (! *from_key) 46387c478bd9Sstevel@tonic-gate { 46397c478bd9Sstevel@tonic-gate /* The user must specify two arguments or zero argument. */ 46407c478bd9Sstevel@tonic-gate errnum = ERR_BAD_ARGUMENT; 46417c478bd9Sstevel@tonic-gate return 1; 46427c478bd9Sstevel@tonic-gate } 46437c478bd9Sstevel@tonic-gate 46447c478bd9Sstevel@tonic-gate nul_terminate (to_key); 46457c478bd9Sstevel@tonic-gate nul_terminate (from_key); 46467c478bd9Sstevel@tonic-gate 46477c478bd9Sstevel@tonic-gate to_code = find_ascii_code (to_key); 46487c478bd9Sstevel@tonic-gate from_code = find_ascii_code (from_key); 46497c478bd9Sstevel@tonic-gate if (! to_code || ! from_code) 46507c478bd9Sstevel@tonic-gate { 46517c478bd9Sstevel@tonic-gate map_in_interrupt = 1; 46527c478bd9Sstevel@tonic-gate to_code = find_key_code (to_key); 46537c478bd9Sstevel@tonic-gate from_code = find_key_code (from_key); 46547c478bd9Sstevel@tonic-gate if (! to_code || ! from_code) 46557c478bd9Sstevel@tonic-gate { 46567c478bd9Sstevel@tonic-gate errnum = ERR_BAD_ARGUMENT; 46577c478bd9Sstevel@tonic-gate return 1; 46587c478bd9Sstevel@tonic-gate } 46597c478bd9Sstevel@tonic-gate } 46607c478bd9Sstevel@tonic-gate 46617c478bd9Sstevel@tonic-gate if (map_in_interrupt) 46627c478bd9Sstevel@tonic-gate { 46637c478bd9Sstevel@tonic-gate int i; 46647c478bd9Sstevel@tonic-gate 46657c478bd9Sstevel@tonic-gate /* Find an empty slot. */ 46667c478bd9Sstevel@tonic-gate for (i = 0; i < KEY_MAP_SIZE; i++) 46677c478bd9Sstevel@tonic-gate { 46687c478bd9Sstevel@tonic-gate if ((bios_key_map[i] & 0xff) == from_code) 46697c478bd9Sstevel@tonic-gate /* Perhaps the user wants to overwrite the map. */ 46707c478bd9Sstevel@tonic-gate break; 46717c478bd9Sstevel@tonic-gate 46727c478bd9Sstevel@tonic-gate if (! bios_key_map[i]) 46737c478bd9Sstevel@tonic-gate break; 46747c478bd9Sstevel@tonic-gate } 46757c478bd9Sstevel@tonic-gate 46767c478bd9Sstevel@tonic-gate if (i == KEY_MAP_SIZE) 46777c478bd9Sstevel@tonic-gate { 46787c478bd9Sstevel@tonic-gate errnum = ERR_WONT_FIT; 46797c478bd9Sstevel@tonic-gate return 1; 46807c478bd9Sstevel@tonic-gate } 46817c478bd9Sstevel@tonic-gate 46827c478bd9Sstevel@tonic-gate if (to_code == from_code) 46837c478bd9Sstevel@tonic-gate /* If TO is equal to FROM, delete the entry. */ 46847c478bd9Sstevel@tonic-gate grub_memmove ((char *) &bios_key_map[i], 46857c478bd9Sstevel@tonic-gate (char *) &bios_key_map[i + 1], 46867c478bd9Sstevel@tonic-gate sizeof (unsigned short) * (KEY_MAP_SIZE - i)); 46877c478bd9Sstevel@tonic-gate else 46887c478bd9Sstevel@tonic-gate bios_key_map[i] = (to_code << 8) | from_code; 46897c478bd9Sstevel@tonic-gate 46907c478bd9Sstevel@tonic-gate /* Ugly but should work. */ 46917c478bd9Sstevel@tonic-gate unset_int15_handler (); 46927c478bd9Sstevel@tonic-gate set_int15_handler (); 46937c478bd9Sstevel@tonic-gate } 46947c478bd9Sstevel@tonic-gate else 46957c478bd9Sstevel@tonic-gate { 46967c478bd9Sstevel@tonic-gate int i; 46977c478bd9Sstevel@tonic-gate 46987c478bd9Sstevel@tonic-gate /* Find an empty slot. */ 46997c478bd9Sstevel@tonic-gate for (i = 0; i < KEY_MAP_SIZE; i++) 47007c478bd9Sstevel@tonic-gate { 47017c478bd9Sstevel@tonic-gate if ((ascii_key_map[i] & 0xff) == from_code) 47027c478bd9Sstevel@tonic-gate /* Perhaps the user wants to overwrite the map. */ 47037c478bd9Sstevel@tonic-gate break; 47047c478bd9Sstevel@tonic-gate 47057c478bd9Sstevel@tonic-gate if (! ascii_key_map[i]) 47067c478bd9Sstevel@tonic-gate break; 47077c478bd9Sstevel@tonic-gate } 47087c478bd9Sstevel@tonic-gate 47097c478bd9Sstevel@tonic-gate if (i == KEY_MAP_SIZE) 47107c478bd9Sstevel@tonic-gate { 47117c478bd9Sstevel@tonic-gate errnum = ERR_WONT_FIT; 47127c478bd9Sstevel@tonic-gate return 1; 47137c478bd9Sstevel@tonic-gate } 47147c478bd9Sstevel@tonic-gate 47157c478bd9Sstevel@tonic-gate if (to_code == from_code) 47167c478bd9Sstevel@tonic-gate /* If TO is equal to FROM, delete the entry. */ 47177c478bd9Sstevel@tonic-gate grub_memmove ((char *) &ascii_key_map[i], 47187c478bd9Sstevel@tonic-gate (char *) &ascii_key_map[i + 1], 47197c478bd9Sstevel@tonic-gate sizeof (unsigned short) * (KEY_MAP_SIZE - i)); 47207c478bd9Sstevel@tonic-gate else 47217c478bd9Sstevel@tonic-gate ascii_key_map[i] = (to_code << 8) | from_code; 47227c478bd9Sstevel@tonic-gate } 47237c478bd9Sstevel@tonic-gate 47247c478bd9Sstevel@tonic-gate return 0; 47257c478bd9Sstevel@tonic-gate } 47267c478bd9Sstevel@tonic-gate 47277c478bd9Sstevel@tonic-gate static struct builtin builtin_setkey = 47287c478bd9Sstevel@tonic-gate { 47297c478bd9Sstevel@tonic-gate "setkey", 47307c478bd9Sstevel@tonic-gate setkey_func, 47317c478bd9Sstevel@tonic-gate BUILTIN_CMDLINE | BUILTIN_MENU | BUILTIN_HELP_LIST, 47327c478bd9Sstevel@tonic-gate "setkey [TO_KEY FROM_KEY]", 47337c478bd9Sstevel@tonic-gate "Change the keyboard map. The key FROM_KEY is mapped to the key TO_KEY." 47347c478bd9Sstevel@tonic-gate " A key must be an alphabet, a digit, or one of these: escape, exclam," 47357c478bd9Sstevel@tonic-gate " at, numbersign, dollar, percent, caret, ampersand, asterisk, parenleft," 47367c478bd9Sstevel@tonic-gate " parenright, minus, underscore, equal, plus, backspace, tab, bracketleft," 47377c478bd9Sstevel@tonic-gate " braceleft, bracketright, braceright, enter, control, semicolon, colon," 47387c478bd9Sstevel@tonic-gate " quote, doublequote, backquote, tilde, shift, backslash, bar, comma," 47397c478bd9Sstevel@tonic-gate " less, period, greater, slash, question, alt, space, capslock, FX (X" 47407c478bd9Sstevel@tonic-gate " is a digit), and delete. If no argument is specified, reset key" 47417c478bd9Sstevel@tonic-gate " mappings." 47427c478bd9Sstevel@tonic-gate }; 47437c478bd9Sstevel@tonic-gate 47447c478bd9Sstevel@tonic-gate 47457c478bd9Sstevel@tonic-gate /* setup */ 47467c478bd9Sstevel@tonic-gate static int 47477c478bd9Sstevel@tonic-gate setup_func (char *arg, int flags) 47487c478bd9Sstevel@tonic-gate { 47497c478bd9Sstevel@tonic-gate /* Point to the string of the installed drive/partition. */ 47507c478bd9Sstevel@tonic-gate char *install_ptr; 47517c478bd9Sstevel@tonic-gate /* Point to the string of the drive/parition where the GRUB images 47527c478bd9Sstevel@tonic-gate reside. */ 47537c478bd9Sstevel@tonic-gate char *image_ptr; 47547c478bd9Sstevel@tonic-gate unsigned long installed_drive, installed_partition; 47557c478bd9Sstevel@tonic-gate unsigned long image_drive, image_partition; 47567c478bd9Sstevel@tonic-gate unsigned long tmp_drive, tmp_partition; 47577c478bd9Sstevel@tonic-gate char stage1[64]; 47587c478bd9Sstevel@tonic-gate char stage2[64]; 47597c478bd9Sstevel@tonic-gate char config_filename[64]; 47607c478bd9Sstevel@tonic-gate char real_config_filename[64]; 47617c478bd9Sstevel@tonic-gate char cmd_arg[256]; 47627c478bd9Sstevel@tonic-gate char device[16]; 47637c478bd9Sstevel@tonic-gate char *buffer = (char *) RAW_ADDR (0x100000); 47647c478bd9Sstevel@tonic-gate int is_force_lba = 0; 47657c478bd9Sstevel@tonic-gate char *stage2_arg = 0; 47667c478bd9Sstevel@tonic-gate char *prefix = 0; 47677c478bd9Sstevel@tonic-gate 47687c478bd9Sstevel@tonic-gate auto int check_file (char *file); 47697c478bd9Sstevel@tonic-gate auto void sprint_device (int drive, int partition); 47707c478bd9Sstevel@tonic-gate auto int embed_stage1_5 (char * stage1_5, int drive, int partition); 47717c478bd9Sstevel@tonic-gate 47727c478bd9Sstevel@tonic-gate /* Check if the file FILE exists like Autoconf. */ 47737c478bd9Sstevel@tonic-gate int check_file (char *file) 47747c478bd9Sstevel@tonic-gate { 47757c478bd9Sstevel@tonic-gate int ret; 47767c478bd9Sstevel@tonic-gate 47777c478bd9Sstevel@tonic-gate grub_printf (" Checking if \"%s\" exists... ", file); 47787c478bd9Sstevel@tonic-gate ret = grub_open (file); 47797c478bd9Sstevel@tonic-gate if (ret) 47807c478bd9Sstevel@tonic-gate { 47817c478bd9Sstevel@tonic-gate grub_close (); 47827c478bd9Sstevel@tonic-gate grub_printf ("yes\n"); 47837c478bd9Sstevel@tonic-gate } 47847c478bd9Sstevel@tonic-gate else 47857c478bd9Sstevel@tonic-gate grub_printf ("no\n"); 47867c478bd9Sstevel@tonic-gate 47877c478bd9Sstevel@tonic-gate return ret; 47887c478bd9Sstevel@tonic-gate } 47897c478bd9Sstevel@tonic-gate 47907c478bd9Sstevel@tonic-gate /* Construct a device name in DEVICE. */ 47917c478bd9Sstevel@tonic-gate void sprint_device (int drive, int partition) 47927c478bd9Sstevel@tonic-gate { 47937c478bd9Sstevel@tonic-gate grub_sprintf (device, "(%cd%d", 47947c478bd9Sstevel@tonic-gate (drive & 0x80) ? 'h' : 'f', 47957c478bd9Sstevel@tonic-gate drive & ~0x80); 47967c478bd9Sstevel@tonic-gate if ((partition & 0xFF0000) != 0xFF0000) 47977c478bd9Sstevel@tonic-gate { 47987c478bd9Sstevel@tonic-gate char tmp[16]; 47997c478bd9Sstevel@tonic-gate grub_sprintf (tmp, ",%d", (partition >> 16) & 0xFF); 48007c478bd9Sstevel@tonic-gate grub_strncat (device, tmp, 256); 48017c478bd9Sstevel@tonic-gate } 48027c478bd9Sstevel@tonic-gate if ((partition & 0x00FF00) != 0x00FF00) 48037c478bd9Sstevel@tonic-gate { 48047c478bd9Sstevel@tonic-gate char tmp[16]; 48057c478bd9Sstevel@tonic-gate grub_sprintf (tmp, ",%c", 'a' + ((partition >> 8) & 0xFF)); 48067c478bd9Sstevel@tonic-gate grub_strncat (device, tmp, 256); 48077c478bd9Sstevel@tonic-gate } 48087c478bd9Sstevel@tonic-gate grub_strncat (device, ")", 256); 48097c478bd9Sstevel@tonic-gate } 48107c478bd9Sstevel@tonic-gate 48117c478bd9Sstevel@tonic-gate int embed_stage1_5 (char *stage1_5, int drive, int partition) 48127c478bd9Sstevel@tonic-gate { 48137c478bd9Sstevel@tonic-gate /* We install GRUB into the MBR, so try to embed the 48147c478bd9Sstevel@tonic-gate Stage 1.5 in the sectors right after the MBR. */ 48157c478bd9Sstevel@tonic-gate sprint_device (drive, partition); 48167c478bd9Sstevel@tonic-gate grub_sprintf (cmd_arg, "%s %s", stage1_5, device); 48177c478bd9Sstevel@tonic-gate 48187c478bd9Sstevel@tonic-gate /* Notify what will be run. */ 48197c478bd9Sstevel@tonic-gate grub_printf (" Running \"embed %s\"... ", cmd_arg); 48207c478bd9Sstevel@tonic-gate 48217c478bd9Sstevel@tonic-gate embed_func (cmd_arg, flags); 48227c478bd9Sstevel@tonic-gate if (! errnum) 48237c478bd9Sstevel@tonic-gate { 48247c478bd9Sstevel@tonic-gate /* Construct the blocklist representation. */ 48257c478bd9Sstevel@tonic-gate grub_sprintf (buffer, "%s%s", device, embed_info); 48267c478bd9Sstevel@tonic-gate grub_printf ("succeeded\n"); 48277c478bd9Sstevel@tonic-gate return 1; 48287c478bd9Sstevel@tonic-gate } 48297c478bd9Sstevel@tonic-gate else 48307c478bd9Sstevel@tonic-gate { 48317c478bd9Sstevel@tonic-gate grub_printf ("failed (this is not fatal)\n"); 48327c478bd9Sstevel@tonic-gate return 0; 48337c478bd9Sstevel@tonic-gate } 48347c478bd9Sstevel@tonic-gate } 48357c478bd9Sstevel@tonic-gate 48367c478bd9Sstevel@tonic-gate struct stage1_5_map { 48377c478bd9Sstevel@tonic-gate char *fsys; 48387c478bd9Sstevel@tonic-gate char *name; 48397c478bd9Sstevel@tonic-gate }; 48407c478bd9Sstevel@tonic-gate struct stage1_5_map stage1_5_map[] = 48417c478bd9Sstevel@tonic-gate { 48427c478bd9Sstevel@tonic-gate {"ext2fs", "/e2fs_stage1_5"}, 48437c478bd9Sstevel@tonic-gate {"fat", "/fat_stage1_5"}, 48447c478bd9Sstevel@tonic-gate {"ufs2", "/ufs2_stage1_5"}, 48457c478bd9Sstevel@tonic-gate {"ffs", "/ffs_stage1_5"}, 48467c478bd9Sstevel@tonic-gate {"iso9660", "/iso9660_stage1_5"}, 48477c478bd9Sstevel@tonic-gate {"jfs", "/jfs_stage1_5"}, 48487c478bd9Sstevel@tonic-gate {"minix", "/minix_stage1_5"}, 48497c478bd9Sstevel@tonic-gate {"reiserfs", "/reiserfs_stage1_5"}, 48507c478bd9Sstevel@tonic-gate {"vstafs", "/vstafs_stage1_5"}, 48517c478bd9Sstevel@tonic-gate {"xfs", "/xfs_stage1_5"}, 48527c478bd9Sstevel@tonic-gate {"ufs", "/ufs_stage1_5"} 48537c478bd9Sstevel@tonic-gate }; 48547c478bd9Sstevel@tonic-gate 48557c478bd9Sstevel@tonic-gate tmp_drive = saved_drive; 48567c478bd9Sstevel@tonic-gate tmp_partition = saved_partition; 48577c478bd9Sstevel@tonic-gate 48587c478bd9Sstevel@tonic-gate /* Check if the user specifies --force-lba. */ 48597c478bd9Sstevel@tonic-gate while (1) 48607c478bd9Sstevel@tonic-gate { 48617c478bd9Sstevel@tonic-gate if (grub_memcmp ("--force-lba", arg, sizeof ("--force-lba") - 1) == 0) 48627c478bd9Sstevel@tonic-gate { 48637c478bd9Sstevel@tonic-gate is_force_lba = 1; 48647c478bd9Sstevel@tonic-gate arg = skip_to (0, arg); 48657c478bd9Sstevel@tonic-gate } 48667c478bd9Sstevel@tonic-gate else if (grub_memcmp ("--prefix=", arg, sizeof ("--prefix=") - 1) == 0) 48677c478bd9Sstevel@tonic-gate { 48687c478bd9Sstevel@tonic-gate prefix = arg + sizeof ("--prefix=") - 1; 48697c478bd9Sstevel@tonic-gate arg = skip_to (0, arg); 48707c478bd9Sstevel@tonic-gate nul_terminate (prefix); 48717c478bd9Sstevel@tonic-gate } 48727c478bd9Sstevel@tonic-gate #ifdef GRUB_UTIL 48737c478bd9Sstevel@tonic-gate else if (grub_memcmp ("--stage2=", arg, sizeof ("--stage2=") - 1) == 0) 48747c478bd9Sstevel@tonic-gate { 48757c478bd9Sstevel@tonic-gate stage2_arg = arg; 48767c478bd9Sstevel@tonic-gate arg = skip_to (0, arg); 48777c478bd9Sstevel@tonic-gate nul_terminate (stage2_arg); 48787c478bd9Sstevel@tonic-gate } 48797c478bd9Sstevel@tonic-gate #endif /* GRUB_UTIL */ 48807c478bd9Sstevel@tonic-gate else 48817c478bd9Sstevel@tonic-gate break; 48827c478bd9Sstevel@tonic-gate } 48837c478bd9Sstevel@tonic-gate 48847c478bd9Sstevel@tonic-gate install_ptr = arg; 48857c478bd9Sstevel@tonic-gate image_ptr = skip_to (0, install_ptr); 48867c478bd9Sstevel@tonic-gate 48877c478bd9Sstevel@tonic-gate /* Make sure that INSTALL_PTR is valid. */ 48887c478bd9Sstevel@tonic-gate set_device (install_ptr); 48897c478bd9Sstevel@tonic-gate if (errnum) 48907c478bd9Sstevel@tonic-gate return 1; 48917c478bd9Sstevel@tonic-gate 48927c478bd9Sstevel@tonic-gate installed_drive = current_drive; 48937c478bd9Sstevel@tonic-gate installed_partition = current_partition; 48947c478bd9Sstevel@tonic-gate 48957c478bd9Sstevel@tonic-gate /* Mount the drive pointed by IMAGE_PTR. */ 48967c478bd9Sstevel@tonic-gate if (*image_ptr) 48977c478bd9Sstevel@tonic-gate { 48987c478bd9Sstevel@tonic-gate /* If the drive/partition where the images reside is specified, 48997c478bd9Sstevel@tonic-gate get the drive and the partition. */ 49007c478bd9Sstevel@tonic-gate set_device (image_ptr); 49017c478bd9Sstevel@tonic-gate if (errnum) 49027c478bd9Sstevel@tonic-gate return 1; 49037c478bd9Sstevel@tonic-gate } 49047c478bd9Sstevel@tonic-gate else 49057c478bd9Sstevel@tonic-gate { 49067c478bd9Sstevel@tonic-gate /* If omitted, use SAVED_PARTITION and SAVED_DRIVE. */ 49077c478bd9Sstevel@tonic-gate current_drive = saved_drive; 49087c478bd9Sstevel@tonic-gate current_partition = saved_partition; 49097c478bd9Sstevel@tonic-gate } 49107c478bd9Sstevel@tonic-gate 49117c478bd9Sstevel@tonic-gate image_drive = saved_drive = current_drive; 49127c478bd9Sstevel@tonic-gate image_partition = saved_partition = current_partition; 49137c478bd9Sstevel@tonic-gate 49147c478bd9Sstevel@tonic-gate /* Open it. */ 49157c478bd9Sstevel@tonic-gate if (! open_device ()) 49167c478bd9Sstevel@tonic-gate goto fail; 49177c478bd9Sstevel@tonic-gate 49187c478bd9Sstevel@tonic-gate /* Check if stage1 exists. If the user doesn't specify the option 49197c478bd9Sstevel@tonic-gate `--prefix', attempt /boot/grub and /grub. */ 49207c478bd9Sstevel@tonic-gate /* NOTE: It is dangerous to run this command without `--prefix' in the 49217c478bd9Sstevel@tonic-gate grub shell, since that affects `--stage2'. */ 49227c478bd9Sstevel@tonic-gate if (! prefix) 49237c478bd9Sstevel@tonic-gate { 49247c478bd9Sstevel@tonic-gate prefix = "/boot/grub"; 49257c478bd9Sstevel@tonic-gate grub_sprintf (stage1, "%s%s", prefix, "/stage1"); 49267c478bd9Sstevel@tonic-gate if (! check_file (stage1)) 49277c478bd9Sstevel@tonic-gate { 49287c478bd9Sstevel@tonic-gate errnum = ERR_NONE; 49297c478bd9Sstevel@tonic-gate prefix = "/grub"; 49307c478bd9Sstevel@tonic-gate grub_sprintf (stage1, "%s%s", prefix, "/stage1"); 49317c478bd9Sstevel@tonic-gate if (! check_file (stage1)) 49327c478bd9Sstevel@tonic-gate goto fail; 49337c478bd9Sstevel@tonic-gate } 49347c478bd9Sstevel@tonic-gate } 49357c478bd9Sstevel@tonic-gate else 49367c478bd9Sstevel@tonic-gate { 49377c478bd9Sstevel@tonic-gate grub_sprintf (stage1, "%s%s", prefix, "/stage1"); 49387c478bd9Sstevel@tonic-gate if (! check_file (stage1)) 49397c478bd9Sstevel@tonic-gate goto fail; 49407c478bd9Sstevel@tonic-gate } 49417c478bd9Sstevel@tonic-gate 49427c478bd9Sstevel@tonic-gate /* The prefix was determined. */ 49437c478bd9Sstevel@tonic-gate grub_sprintf (stage2, "%s%s", prefix, "/stage2"); 49447c478bd9Sstevel@tonic-gate grub_sprintf (config_filename, "%s%s", prefix, "/menu.lst"); 49457c478bd9Sstevel@tonic-gate *real_config_filename = 0; 49467c478bd9Sstevel@tonic-gate 49477c478bd9Sstevel@tonic-gate /* Check if stage2 exists. */ 49487c478bd9Sstevel@tonic-gate if (! check_file (stage2)) 49497c478bd9Sstevel@tonic-gate goto fail; 49507c478bd9Sstevel@tonic-gate 49517c478bd9Sstevel@tonic-gate { 49527c478bd9Sstevel@tonic-gate char *fsys = fsys_table[fsys_type].name; 49537c478bd9Sstevel@tonic-gate int i; 49547c478bd9Sstevel@tonic-gate int size = sizeof (stage1_5_map) / sizeof (stage1_5_map[0]); 49557c478bd9Sstevel@tonic-gate 49567c478bd9Sstevel@tonic-gate /* Iterate finding the same filesystem name as FSYS. */ 49577c478bd9Sstevel@tonic-gate for (i = 0; i < size; i++) 49587c478bd9Sstevel@tonic-gate if (grub_strcmp (fsys, stage1_5_map[i].fsys) == 0) 49597c478bd9Sstevel@tonic-gate { 49607c478bd9Sstevel@tonic-gate /* OK, check if the Stage 1.5 exists. */ 49617c478bd9Sstevel@tonic-gate char stage1_5[64]; 49627c478bd9Sstevel@tonic-gate 49637c478bd9Sstevel@tonic-gate grub_sprintf (stage1_5, "%s%s", prefix, stage1_5_map[i].name); 49647c478bd9Sstevel@tonic-gate if (check_file (stage1_5)) 49657c478bd9Sstevel@tonic-gate { 49667c478bd9Sstevel@tonic-gate if (embed_stage1_5 (stage1_5, 49677c478bd9Sstevel@tonic-gate installed_drive, installed_partition) 49687c478bd9Sstevel@tonic-gate || embed_stage1_5 (stage1_5, 49697c478bd9Sstevel@tonic-gate image_drive, image_partition)) 49707c478bd9Sstevel@tonic-gate { 49717c478bd9Sstevel@tonic-gate grub_strcpy (real_config_filename, config_filename); 49727c478bd9Sstevel@tonic-gate sprint_device (image_drive, image_partition); 49737c478bd9Sstevel@tonic-gate grub_sprintf (config_filename, "%s%s", device, stage2); 49747c478bd9Sstevel@tonic-gate grub_strcpy (stage2, buffer); 49757c478bd9Sstevel@tonic-gate } 49767c478bd9Sstevel@tonic-gate } 49777c478bd9Sstevel@tonic-gate errnum = 0; 49787c478bd9Sstevel@tonic-gate break; 49797c478bd9Sstevel@tonic-gate } 49807c478bd9Sstevel@tonic-gate } 49817c478bd9Sstevel@tonic-gate 49827c478bd9Sstevel@tonic-gate /* Construct a string that is used by the command "install" as its 49837c478bd9Sstevel@tonic-gate arguments. */ 49847c478bd9Sstevel@tonic-gate sprint_device (installed_drive, installed_partition); 49857c478bd9Sstevel@tonic-gate 49867c478bd9Sstevel@tonic-gate #if 1 49877c478bd9Sstevel@tonic-gate /* Don't embed a drive number unnecessarily. */ 49887c478bd9Sstevel@tonic-gate grub_sprintf (cmd_arg, "%s%s%s%s %s%s %s p %s %s", 49897c478bd9Sstevel@tonic-gate is_force_lba? "--force-lba " : "", 49907c478bd9Sstevel@tonic-gate stage2_arg? stage2_arg : "", 49917c478bd9Sstevel@tonic-gate stage2_arg? " " : "", 49927c478bd9Sstevel@tonic-gate stage1, 49937c478bd9Sstevel@tonic-gate (installed_drive != image_drive) ? "d " : "", 49947c478bd9Sstevel@tonic-gate device, 49957c478bd9Sstevel@tonic-gate stage2, 49967c478bd9Sstevel@tonic-gate config_filename, 49977c478bd9Sstevel@tonic-gate real_config_filename); 49987c478bd9Sstevel@tonic-gate #else /* NOT USED */ 49997c478bd9Sstevel@tonic-gate /* This code was used, because we belived some BIOSes had a problem 50007c478bd9Sstevel@tonic-gate that they didn't pass a booting drive correctly. It turned out, 50017c478bd9Sstevel@tonic-gate however, stage1 could trash a booting drive when checking LBA support, 50027c478bd9Sstevel@tonic-gate because some BIOSes modified the register %dx in INT 13H, AH=48H. 50037c478bd9Sstevel@tonic-gate So it becamed unclear whether GRUB should use a pre-defined booting 50047c478bd9Sstevel@tonic-gate drive or not. If the problem still exists, it would be necessary to 50057c478bd9Sstevel@tonic-gate switch back to this code. */ 50067c478bd9Sstevel@tonic-gate grub_sprintf (cmd_arg, "%s%s%s%s d %s %s p %s %s", 50077c478bd9Sstevel@tonic-gate is_force_lba? "--force-lba " : "", 50087c478bd9Sstevel@tonic-gate stage2_arg? stage2_arg : "", 50097c478bd9Sstevel@tonic-gate stage2_arg? " " : "", 50107c478bd9Sstevel@tonic-gate stage1, 50117c478bd9Sstevel@tonic-gate device, 50127c478bd9Sstevel@tonic-gate stage2, 50137c478bd9Sstevel@tonic-gate config_filename, 50147c478bd9Sstevel@tonic-gate real_config_filename); 50157c478bd9Sstevel@tonic-gate #endif /* NOT USED */ 50167c478bd9Sstevel@tonic-gate 50177c478bd9Sstevel@tonic-gate /* Notify what will be run. */ 50187c478bd9Sstevel@tonic-gate grub_printf (" Running \"install %s\"... ", cmd_arg); 50197c478bd9Sstevel@tonic-gate 50207c478bd9Sstevel@tonic-gate /* Make sure that SAVED_DRIVE and SAVED_PARTITION are identical 50217c478bd9Sstevel@tonic-gate with IMAGE_DRIVE and IMAGE_PARTITION, respectively. */ 50227c478bd9Sstevel@tonic-gate saved_drive = image_drive; 50237c478bd9Sstevel@tonic-gate saved_partition = image_partition; 50247c478bd9Sstevel@tonic-gate 50257c478bd9Sstevel@tonic-gate /* Run the command. */ 50267c478bd9Sstevel@tonic-gate if (! install_func (cmd_arg, flags)) 50277c478bd9Sstevel@tonic-gate grub_printf ("succeeded\nDone.\n"); 50287c478bd9Sstevel@tonic-gate else 50297c478bd9Sstevel@tonic-gate grub_printf ("failed\n"); 50307c478bd9Sstevel@tonic-gate 50317c478bd9Sstevel@tonic-gate fail: 50327c478bd9Sstevel@tonic-gate saved_drive = tmp_drive; 50337c478bd9Sstevel@tonic-gate saved_partition = tmp_partition; 50347c478bd9Sstevel@tonic-gate return errnum; 50357c478bd9Sstevel@tonic-gate } 50367c478bd9Sstevel@tonic-gate 50377c478bd9Sstevel@tonic-gate static struct builtin builtin_setup = 50387c478bd9Sstevel@tonic-gate { 50397c478bd9Sstevel@tonic-gate "setup", 50407c478bd9Sstevel@tonic-gate setup_func, 50417c478bd9Sstevel@tonic-gate BUILTIN_CMDLINE | BUILTIN_HELP_LIST, 50427c478bd9Sstevel@tonic-gate "setup [--prefix=DIR] [--stage2=STAGE2_FILE] [--force-lba] INSTALL_DEVICE [IMAGE_DEVICE]", 50437c478bd9Sstevel@tonic-gate "Set up the installation of GRUB automatically. This command uses" 50447c478bd9Sstevel@tonic-gate " the more flexible command \"install\" in the backend and installs" 50457c478bd9Sstevel@tonic-gate " GRUB into the device INSTALL_DEVICE. If IMAGE_DEVICE is specified," 50467c478bd9Sstevel@tonic-gate " then find the GRUB images in the device IMAGE_DEVICE, otherwise" 50477c478bd9Sstevel@tonic-gate " use the current \"root device\", which can be set by the command" 50487c478bd9Sstevel@tonic-gate " \"root\". If you know that your BIOS should support LBA but GRUB" 50497c478bd9Sstevel@tonic-gate " doesn't work in LBA mode, specify the option `--force-lba'." 50507c478bd9Sstevel@tonic-gate " If you install GRUB under the grub shell and you cannot unmount the" 50517c478bd9Sstevel@tonic-gate " partition where GRUB images reside, specify the option `--stage2'" 50527c478bd9Sstevel@tonic-gate " to tell GRUB the file name under your OS." 50537c478bd9Sstevel@tonic-gate }; 50547c478bd9Sstevel@tonic-gate 50557c478bd9Sstevel@tonic-gate 50567c478bd9Sstevel@tonic-gate #if defined(SUPPORT_SERIAL) || defined(SUPPORT_HERCULES) || defined(SUPPORT_GRAPHICS) 50577c478bd9Sstevel@tonic-gate /* terminal */ 50587c478bd9Sstevel@tonic-gate static int 50597c478bd9Sstevel@tonic-gate terminal_func (char *arg, int flags) 50607c478bd9Sstevel@tonic-gate { 50617c478bd9Sstevel@tonic-gate /* The index of the default terminal in TERM_TABLE. */ 50627c478bd9Sstevel@tonic-gate int default_term = -1; 50637c478bd9Sstevel@tonic-gate struct term_entry *prev_term = current_term; 50647c478bd9Sstevel@tonic-gate int to = -1; 50657c478bd9Sstevel@tonic-gate int lines = 0; 50667c478bd9Sstevel@tonic-gate int no_message = 0; 50677c478bd9Sstevel@tonic-gate unsigned long term_flags = 0; 50687c478bd9Sstevel@tonic-gate /* XXX: Assume less than 32 terminals. */ 50697c478bd9Sstevel@tonic-gate unsigned long term_bitmap = 0; 50707c478bd9Sstevel@tonic-gate 50717c478bd9Sstevel@tonic-gate /* Get GNU-style long options. */ 50727c478bd9Sstevel@tonic-gate while (1) 50737c478bd9Sstevel@tonic-gate { 50747c478bd9Sstevel@tonic-gate if (grub_memcmp (arg, "--dumb", sizeof ("--dumb") - 1) == 0) 50757c478bd9Sstevel@tonic-gate term_flags |= TERM_DUMB; 50767c478bd9Sstevel@tonic-gate else if (grub_memcmp (arg, "--no-echo", sizeof ("--no-echo") - 1) == 0) 50777c478bd9Sstevel@tonic-gate /* ``--no-echo'' implies ``--no-edit''. */ 50787c478bd9Sstevel@tonic-gate term_flags |= (TERM_NO_ECHO | TERM_NO_EDIT); 50797c478bd9Sstevel@tonic-gate else if (grub_memcmp (arg, "--no-edit", sizeof ("--no-edit") - 1) == 0) 50807c478bd9Sstevel@tonic-gate term_flags |= TERM_NO_EDIT; 50817c478bd9Sstevel@tonic-gate else if (grub_memcmp (arg, "--timeout=", sizeof ("--timeout=") - 1) == 0) 50827c478bd9Sstevel@tonic-gate { 50837c478bd9Sstevel@tonic-gate char *val = arg + sizeof ("--timeout=") - 1; 50847c478bd9Sstevel@tonic-gate 50857c478bd9Sstevel@tonic-gate if (! safe_parse_maxint (&val, &to)) 50867c478bd9Sstevel@tonic-gate return 1; 50877c478bd9Sstevel@tonic-gate } 50887c478bd9Sstevel@tonic-gate else if (grub_memcmp (arg, "--lines=", sizeof ("--lines=") - 1) == 0) 50897c478bd9Sstevel@tonic-gate { 50907c478bd9Sstevel@tonic-gate char *val = arg + sizeof ("--lines=") - 1; 50917c478bd9Sstevel@tonic-gate 50927c478bd9Sstevel@tonic-gate if (! safe_parse_maxint (&val, &lines)) 50937c478bd9Sstevel@tonic-gate return 1; 50947c478bd9Sstevel@tonic-gate 50957c478bd9Sstevel@tonic-gate /* Probably less than four is meaningless.... */ 50967c478bd9Sstevel@tonic-gate if (lines < 4) 50977c478bd9Sstevel@tonic-gate { 50987c478bd9Sstevel@tonic-gate errnum = ERR_BAD_ARGUMENT; 50997c478bd9Sstevel@tonic-gate return 1; 51007c478bd9Sstevel@tonic-gate } 51017c478bd9Sstevel@tonic-gate } 51027c478bd9Sstevel@tonic-gate else if (grub_memcmp (arg, "--silent", sizeof ("--silent") - 1) == 0) 51037c478bd9Sstevel@tonic-gate no_message = 1; 51047c478bd9Sstevel@tonic-gate else 51057c478bd9Sstevel@tonic-gate break; 51067c478bd9Sstevel@tonic-gate 51077c478bd9Sstevel@tonic-gate arg = skip_to (0, arg); 51087c478bd9Sstevel@tonic-gate } 51097c478bd9Sstevel@tonic-gate 51107c478bd9Sstevel@tonic-gate /* If no argument is specified, show current setting. */ 51117c478bd9Sstevel@tonic-gate if (! *arg) 51127c478bd9Sstevel@tonic-gate { 51137c478bd9Sstevel@tonic-gate grub_printf ("%s%s%s%s\n", 51147c478bd9Sstevel@tonic-gate current_term->name, 51157c478bd9Sstevel@tonic-gate current_term->flags & TERM_DUMB ? " (dumb)" : "", 51167c478bd9Sstevel@tonic-gate current_term->flags & TERM_NO_EDIT ? " (no edit)" : "", 51177c478bd9Sstevel@tonic-gate current_term->flags & TERM_NO_ECHO ? " (no echo)" : ""); 51187c478bd9Sstevel@tonic-gate return 0; 51197c478bd9Sstevel@tonic-gate } 51207c478bd9Sstevel@tonic-gate 51217c478bd9Sstevel@tonic-gate while (*arg) 51227c478bd9Sstevel@tonic-gate { 51237c478bd9Sstevel@tonic-gate int i; 51247c478bd9Sstevel@tonic-gate char *next = skip_to (0, arg); 51257c478bd9Sstevel@tonic-gate 51267c478bd9Sstevel@tonic-gate nul_terminate (arg); 51277c478bd9Sstevel@tonic-gate 51287c478bd9Sstevel@tonic-gate for (i = 0; term_table[i].name; i++) 51297c478bd9Sstevel@tonic-gate { 51307c478bd9Sstevel@tonic-gate if (grub_strcmp (arg, term_table[i].name) == 0) 51317c478bd9Sstevel@tonic-gate { 51327c478bd9Sstevel@tonic-gate if (term_table[i].flags & TERM_NEED_INIT) 51337c478bd9Sstevel@tonic-gate { 51347c478bd9Sstevel@tonic-gate errnum = ERR_DEV_NEED_INIT; 51357c478bd9Sstevel@tonic-gate return 1; 51367c478bd9Sstevel@tonic-gate } 51377c478bd9Sstevel@tonic-gate 51387c478bd9Sstevel@tonic-gate if (default_term < 0) 51397c478bd9Sstevel@tonic-gate default_term = i; 51407c478bd9Sstevel@tonic-gate 51417c478bd9Sstevel@tonic-gate term_bitmap |= (1 << i); 51427c478bd9Sstevel@tonic-gate break; 51437c478bd9Sstevel@tonic-gate } 51447c478bd9Sstevel@tonic-gate } 51457c478bd9Sstevel@tonic-gate 51467c478bd9Sstevel@tonic-gate if (! term_table[i].name) 51477c478bd9Sstevel@tonic-gate { 51487c478bd9Sstevel@tonic-gate errnum = ERR_BAD_ARGUMENT; 51497c478bd9Sstevel@tonic-gate return 1; 51507c478bd9Sstevel@tonic-gate } 51517c478bd9Sstevel@tonic-gate 51527c478bd9Sstevel@tonic-gate arg = next; 51537c478bd9Sstevel@tonic-gate } 51547c478bd9Sstevel@tonic-gate 51557c478bd9Sstevel@tonic-gate /* If multiple terminals are specified, wait until the user pushes any 51567c478bd9Sstevel@tonic-gate key on one of the terminals. */ 51577c478bd9Sstevel@tonic-gate if (term_bitmap & ~(1 << default_term)) 51587c478bd9Sstevel@tonic-gate { 51597c478bd9Sstevel@tonic-gate int time1, time2 = -1; 51607c478bd9Sstevel@tonic-gate 51617c478bd9Sstevel@tonic-gate /* XXX: Disable the pager. */ 51627c478bd9Sstevel@tonic-gate count_lines = -1; 51637c478bd9Sstevel@tonic-gate 51647c478bd9Sstevel@tonic-gate /* Get current time. */ 51657c478bd9Sstevel@tonic-gate while ((time1 = getrtsecs ()) == 0xFF) 51667c478bd9Sstevel@tonic-gate ; 51677c478bd9Sstevel@tonic-gate 51687c478bd9Sstevel@tonic-gate /* Wait for a key input. */ 51697c478bd9Sstevel@tonic-gate while (to) 51707c478bd9Sstevel@tonic-gate { 51717c478bd9Sstevel@tonic-gate int i; 51727c478bd9Sstevel@tonic-gate 51737c478bd9Sstevel@tonic-gate for (i = 0; term_table[i].name; i++) 51747c478bd9Sstevel@tonic-gate { 51757c478bd9Sstevel@tonic-gate if (term_bitmap & (1 << i)) 51767c478bd9Sstevel@tonic-gate { 51777c478bd9Sstevel@tonic-gate if (term_table[i].checkkey () >= 0) 51787c478bd9Sstevel@tonic-gate { 51797c478bd9Sstevel@tonic-gate (void) term_table[i].getkey (); 51807c478bd9Sstevel@tonic-gate default_term = i; 51817c478bd9Sstevel@tonic-gate 51827c478bd9Sstevel@tonic-gate goto end; 51837c478bd9Sstevel@tonic-gate } 51847c478bd9Sstevel@tonic-gate } 51857c478bd9Sstevel@tonic-gate } 51867c478bd9Sstevel@tonic-gate 51877c478bd9Sstevel@tonic-gate /* Prompt the user, once per sec. */ 51887c478bd9Sstevel@tonic-gate if ((time1 = getrtsecs ()) != time2 && time1 != 0xFF) 51897c478bd9Sstevel@tonic-gate { 51907c478bd9Sstevel@tonic-gate if (! no_message) 51917c478bd9Sstevel@tonic-gate { 51927c478bd9Sstevel@tonic-gate /* Need to set CURRENT_TERM to each of selected 51937c478bd9Sstevel@tonic-gate terminals. */ 51947c478bd9Sstevel@tonic-gate for (i = 0; term_table[i].name; i++) 51957c478bd9Sstevel@tonic-gate if (term_bitmap & (1 << i)) 51967c478bd9Sstevel@tonic-gate { 51977c478bd9Sstevel@tonic-gate current_term = term_table + i; 51987c478bd9Sstevel@tonic-gate grub_printf ("\rPress any key to continue.\n"); 51997c478bd9Sstevel@tonic-gate } 52007c478bd9Sstevel@tonic-gate 52017c478bd9Sstevel@tonic-gate /* Restore CURRENT_TERM. */ 52027c478bd9Sstevel@tonic-gate current_term = prev_term; 52037c478bd9Sstevel@tonic-gate } 52047c478bd9Sstevel@tonic-gate 52057c478bd9Sstevel@tonic-gate time2 = time1; 52067c478bd9Sstevel@tonic-gate if (to > 0) 52077c478bd9Sstevel@tonic-gate to--; 52087c478bd9Sstevel@tonic-gate } 52097c478bd9Sstevel@tonic-gate } 52107c478bd9Sstevel@tonic-gate } 52117c478bd9Sstevel@tonic-gate 52127c478bd9Sstevel@tonic-gate end: 52137c478bd9Sstevel@tonic-gate current_term = term_table + default_term; 52147c478bd9Sstevel@tonic-gate current_term->flags = term_flags; 52157c478bd9Sstevel@tonic-gate 52167c478bd9Sstevel@tonic-gate if (lines) 52177c478bd9Sstevel@tonic-gate max_lines = lines; 52187c478bd9Sstevel@tonic-gate else 52197c478bd9Sstevel@tonic-gate max_lines = current_term->max_lines; 52207c478bd9Sstevel@tonic-gate 52217c478bd9Sstevel@tonic-gate /* If the interface is currently the command-line, 52227c478bd9Sstevel@tonic-gate restart it to repaint the screen. */ 52237c478bd9Sstevel@tonic-gate if ((current_term != prev_term) && (flags & BUILTIN_CMDLINE)){ 52247c478bd9Sstevel@tonic-gate if (prev_term->shutdown) 52257c478bd9Sstevel@tonic-gate prev_term->shutdown(); 52267c478bd9Sstevel@tonic-gate if (current_term->startup) 52277c478bd9Sstevel@tonic-gate current_term->startup(); 52287c478bd9Sstevel@tonic-gate grub_longjmp (restart_cmdline_env, 0); 52297c478bd9Sstevel@tonic-gate } 52307c478bd9Sstevel@tonic-gate 52317c478bd9Sstevel@tonic-gate return 0; 52327c478bd9Sstevel@tonic-gate } 52337c478bd9Sstevel@tonic-gate 52347c478bd9Sstevel@tonic-gate static struct builtin builtin_terminal = 52357c478bd9Sstevel@tonic-gate { 52367c478bd9Sstevel@tonic-gate "terminal", 52377c478bd9Sstevel@tonic-gate terminal_func, 52387c478bd9Sstevel@tonic-gate BUILTIN_MENU | BUILTIN_CMDLINE | BUILTIN_HELP_LIST, 52397c478bd9Sstevel@tonic-gate "terminal [--dumb] [--no-echo] [--no-edit] [--timeout=SECS] [--lines=LINES] [--silent] [console] [serial] [hercules] [graphics]", 52407c478bd9Sstevel@tonic-gate "Select a terminal. When multiple terminals are specified, wait until" 52417c478bd9Sstevel@tonic-gate " you push any key to continue. If both console and serial are specified," 52427c478bd9Sstevel@tonic-gate " the terminal to which you input a key first will be selected. If no" 52437c478bd9Sstevel@tonic-gate " argument is specified, print current setting. The option --dumb" 52447c478bd9Sstevel@tonic-gate " specifies that your terminal is dumb, otherwise, vt100-compatibility" 52457c478bd9Sstevel@tonic-gate " is assumed. If you specify --no-echo, input characters won't be echoed." 52467c478bd9Sstevel@tonic-gate " If you specify --no-edit, the BASH-like editing feature will be disabled." 52477c478bd9Sstevel@tonic-gate " If --timeout is present, this command will wait at most for SECS" 52487c478bd9Sstevel@tonic-gate " seconds. The option --lines specifies the maximum number of lines." 52497c478bd9Sstevel@tonic-gate " The option --silent is used to suppress messages." 52507c478bd9Sstevel@tonic-gate }; 52517c478bd9Sstevel@tonic-gate #endif /* SUPPORT_SERIAL || SUPPORT_HERCULES || SUPPORT_GRAPHICS */ 52527c478bd9Sstevel@tonic-gate 52537c478bd9Sstevel@tonic-gate 52547c478bd9Sstevel@tonic-gate #ifdef SUPPORT_SERIAL 52557c478bd9Sstevel@tonic-gate static int 52567c478bd9Sstevel@tonic-gate terminfo_func (char *arg, int flags) 52577c478bd9Sstevel@tonic-gate { 52587c478bd9Sstevel@tonic-gate struct terminfo term; 52597c478bd9Sstevel@tonic-gate 52607c478bd9Sstevel@tonic-gate if (*arg) 52617c478bd9Sstevel@tonic-gate { 52627c478bd9Sstevel@tonic-gate struct 52637c478bd9Sstevel@tonic-gate { 52647c478bd9Sstevel@tonic-gate const char *name; 52657c478bd9Sstevel@tonic-gate char *var; 52667c478bd9Sstevel@tonic-gate } 52677c478bd9Sstevel@tonic-gate options[] = 52687c478bd9Sstevel@tonic-gate { 52697c478bd9Sstevel@tonic-gate {"--name=", term.name}, 52707c478bd9Sstevel@tonic-gate {"--cursor-address=", term.cursor_address}, 52717c478bd9Sstevel@tonic-gate {"--clear-screen=", term.clear_screen}, 52727c478bd9Sstevel@tonic-gate {"--enter-standout-mode=", term.enter_standout_mode}, 52737c478bd9Sstevel@tonic-gate {"--exit-standout-mode=", term.exit_standout_mode} 52747c478bd9Sstevel@tonic-gate }; 52757c478bd9Sstevel@tonic-gate 52767c478bd9Sstevel@tonic-gate grub_memset (&term, 0, sizeof (term)); 52777c478bd9Sstevel@tonic-gate 52787c478bd9Sstevel@tonic-gate while (*arg) 52797c478bd9Sstevel@tonic-gate { 52807c478bd9Sstevel@tonic-gate int i; 52817c478bd9Sstevel@tonic-gate char *next = skip_to (0, arg); 52827c478bd9Sstevel@tonic-gate 52837c478bd9Sstevel@tonic-gate nul_terminate (arg); 52847c478bd9Sstevel@tonic-gate 52857c478bd9Sstevel@tonic-gate for (i = 0; i < sizeof (options) / sizeof (options[0]); i++) 52867c478bd9Sstevel@tonic-gate { 52877c478bd9Sstevel@tonic-gate const char *name = options[i].name; 52887c478bd9Sstevel@tonic-gate int len = grub_strlen (name); 52897c478bd9Sstevel@tonic-gate 52907c478bd9Sstevel@tonic-gate if (! grub_memcmp (arg, name, len)) 52917c478bd9Sstevel@tonic-gate { 52927c478bd9Sstevel@tonic-gate grub_strcpy (options[i].var, ti_unescape_string (arg + len)); 52937c478bd9Sstevel@tonic-gate break; 52947c478bd9Sstevel@tonic-gate } 52957c478bd9Sstevel@tonic-gate } 52967c478bd9Sstevel@tonic-gate 52977c478bd9Sstevel@tonic-gate if (i == sizeof (options) / sizeof (options[0])) 52987c478bd9Sstevel@tonic-gate { 52997c478bd9Sstevel@tonic-gate errnum = ERR_BAD_ARGUMENT; 53007c478bd9Sstevel@tonic-gate return errnum; 53017c478bd9Sstevel@tonic-gate } 53027c478bd9Sstevel@tonic-gate 53037c478bd9Sstevel@tonic-gate arg = next; 53047c478bd9Sstevel@tonic-gate } 53057c478bd9Sstevel@tonic-gate 53067c478bd9Sstevel@tonic-gate if (term.name[0] == 0 || term.cursor_address[0] == 0) 53077c478bd9Sstevel@tonic-gate { 53087c478bd9Sstevel@tonic-gate errnum = ERR_BAD_ARGUMENT; 53097c478bd9Sstevel@tonic-gate return errnum; 53107c478bd9Sstevel@tonic-gate } 53117c478bd9Sstevel@tonic-gate 53127c478bd9Sstevel@tonic-gate ti_set_term (&term); 53137c478bd9Sstevel@tonic-gate } 53147c478bd9Sstevel@tonic-gate else 53157c478bd9Sstevel@tonic-gate { 53167c478bd9Sstevel@tonic-gate /* No option specifies printing out current settings. */ 53177c478bd9Sstevel@tonic-gate ti_get_term (&term); 53187c478bd9Sstevel@tonic-gate 53197c478bd9Sstevel@tonic-gate grub_printf ("name=%s\n", 53207c478bd9Sstevel@tonic-gate ti_escape_string (term.name)); 53217c478bd9Sstevel@tonic-gate grub_printf ("cursor_address=%s\n", 53227c478bd9Sstevel@tonic-gate ti_escape_string (term.cursor_address)); 53237c478bd9Sstevel@tonic-gate grub_printf ("clear_screen=%s\n", 53247c478bd9Sstevel@tonic-gate ti_escape_string (term.clear_screen)); 53257c478bd9Sstevel@tonic-gate grub_printf ("enter_standout_mode=%s\n", 53267c478bd9Sstevel@tonic-gate ti_escape_string (term.enter_standout_mode)); 53277c478bd9Sstevel@tonic-gate grub_printf ("exit_standout_mode=%s\n", 53287c478bd9Sstevel@tonic-gate ti_escape_string (term.exit_standout_mode)); 53297c478bd9Sstevel@tonic-gate } 53307c478bd9Sstevel@tonic-gate 53317c478bd9Sstevel@tonic-gate return 0; 53327c478bd9Sstevel@tonic-gate } 53337c478bd9Sstevel@tonic-gate 53347c478bd9Sstevel@tonic-gate static struct builtin builtin_terminfo = 53357c478bd9Sstevel@tonic-gate { 53367c478bd9Sstevel@tonic-gate "terminfo", 53377c478bd9Sstevel@tonic-gate terminfo_func, 53387c478bd9Sstevel@tonic-gate BUILTIN_MENU | BUILTIN_CMDLINE | BUILTIN_HELP_LIST, 53397c478bd9Sstevel@tonic-gate "terminfo [--name=NAME --cursor-address=SEQ [--clear-screen=SEQ]" 53407c478bd9Sstevel@tonic-gate " [--enter-standout-mode=SEQ] [--exit-standout-mode=SEQ]]", 53417c478bd9Sstevel@tonic-gate 53427c478bd9Sstevel@tonic-gate "Define the capabilities of your terminal. Use this command to" 53437c478bd9Sstevel@tonic-gate " define escape sequences, if it is not vt100-compatible." 53447c478bd9Sstevel@tonic-gate " You may use \\e for ESC and ^X for a control character." 53457c478bd9Sstevel@tonic-gate " If no option is specified, the current settings are printed." 53467c478bd9Sstevel@tonic-gate }; 53477c478bd9Sstevel@tonic-gate #endif /* SUPPORT_SERIAL */ 53487c478bd9Sstevel@tonic-gate 53497c478bd9Sstevel@tonic-gate 53507c478bd9Sstevel@tonic-gate /* testload */ 53517c478bd9Sstevel@tonic-gate static int 53527c478bd9Sstevel@tonic-gate testload_func (char *arg, int flags) 53537c478bd9Sstevel@tonic-gate { 53547c478bd9Sstevel@tonic-gate int i; 53557c478bd9Sstevel@tonic-gate 53567c478bd9Sstevel@tonic-gate kernel_type = KERNEL_TYPE_NONE; 53577c478bd9Sstevel@tonic-gate 53587c478bd9Sstevel@tonic-gate if (! grub_open (arg)) 53597c478bd9Sstevel@tonic-gate return 1; 53607c478bd9Sstevel@tonic-gate 53617c478bd9Sstevel@tonic-gate disk_read_hook = disk_read_print_func; 53627c478bd9Sstevel@tonic-gate 53637c478bd9Sstevel@tonic-gate /* Perform filesystem test on the specified file. */ 53647c478bd9Sstevel@tonic-gate /* Read whole file first. */ 53657c478bd9Sstevel@tonic-gate grub_printf ("Whole file: "); 53667c478bd9Sstevel@tonic-gate 53677c478bd9Sstevel@tonic-gate grub_read ((char *) RAW_ADDR (0x100000), -1); 53687c478bd9Sstevel@tonic-gate 53697c478bd9Sstevel@tonic-gate /* Now compare two sections of the file read differently. */ 53707c478bd9Sstevel@tonic-gate 53717c478bd9Sstevel@tonic-gate for (i = 0; i < 0x10ac0; i++) 53727c478bd9Sstevel@tonic-gate { 53737c478bd9Sstevel@tonic-gate *((unsigned char *) RAW_ADDR (0x200000 + i)) = 0; 53747c478bd9Sstevel@tonic-gate *((unsigned char *) RAW_ADDR (0x300000 + i)) = 1; 53757c478bd9Sstevel@tonic-gate } 53767c478bd9Sstevel@tonic-gate 53777c478bd9Sstevel@tonic-gate /* First partial read. */ 53787c478bd9Sstevel@tonic-gate grub_printf ("\nPartial read 1: "); 53797c478bd9Sstevel@tonic-gate 53807c478bd9Sstevel@tonic-gate grub_seek (0); 53817c478bd9Sstevel@tonic-gate grub_read ((char *) RAW_ADDR (0x200000), 0x7); 53827c478bd9Sstevel@tonic-gate grub_read ((char *) RAW_ADDR (0x200007), 0x100); 53837c478bd9Sstevel@tonic-gate grub_read ((char *) RAW_ADDR (0x200107), 0x10); 53847c478bd9Sstevel@tonic-gate grub_read ((char *) RAW_ADDR (0x200117), 0x999); 53857c478bd9Sstevel@tonic-gate grub_read ((char *) RAW_ADDR (0x200ab0), 0x10); 53867c478bd9Sstevel@tonic-gate grub_read ((char *) RAW_ADDR (0x200ac0), 0x10000); 53877c478bd9Sstevel@tonic-gate 53887c478bd9Sstevel@tonic-gate /* Second partial read. */ 53897c478bd9Sstevel@tonic-gate grub_printf ("\nPartial read 2: "); 53907c478bd9Sstevel@tonic-gate 53917c478bd9Sstevel@tonic-gate grub_seek (0); 53927c478bd9Sstevel@tonic-gate grub_read ((char *) RAW_ADDR (0x300000), 0x10000); 53937c478bd9Sstevel@tonic-gate grub_read ((char *) RAW_ADDR (0x310000), 0x10); 53947c478bd9Sstevel@tonic-gate grub_read ((char *) RAW_ADDR (0x310010), 0x7); 53957c478bd9Sstevel@tonic-gate grub_read ((char *) RAW_ADDR (0x310017), 0x10); 53967c478bd9Sstevel@tonic-gate grub_read ((char *) RAW_ADDR (0x310027), 0x999); 53977c478bd9Sstevel@tonic-gate grub_read ((char *) RAW_ADDR (0x3109c0), 0x100); 53987c478bd9Sstevel@tonic-gate 53997c478bd9Sstevel@tonic-gate grub_printf ("\nHeader1 = 0x%x, next = 0x%x, next = 0x%x, next = 0x%x\n", 54007c478bd9Sstevel@tonic-gate *((int *) RAW_ADDR (0x200000)), 54017c478bd9Sstevel@tonic-gate *((int *) RAW_ADDR (0x200004)), 54027c478bd9Sstevel@tonic-gate *((int *) RAW_ADDR (0x200008)), 54037c478bd9Sstevel@tonic-gate *((int *) RAW_ADDR (0x20000c))); 54047c478bd9Sstevel@tonic-gate 54057c478bd9Sstevel@tonic-gate grub_printf ("Header2 = 0x%x, next = 0x%x, next = 0x%x, next = 0x%x\n", 54067c478bd9Sstevel@tonic-gate *((int *) RAW_ADDR (0x300000)), 54077c478bd9Sstevel@tonic-gate *((int *) RAW_ADDR (0x300004)), 54087c478bd9Sstevel@tonic-gate *((int *) RAW_ADDR (0x300008)), 54097c478bd9Sstevel@tonic-gate *((int *) RAW_ADDR (0x30000c))); 54107c478bd9Sstevel@tonic-gate 54117c478bd9Sstevel@tonic-gate for (i = 0; i < 0x10ac0; i++) 54127c478bd9Sstevel@tonic-gate if (*((unsigned char *) RAW_ADDR (0x200000 + i)) 54137c478bd9Sstevel@tonic-gate != *((unsigned char *) RAW_ADDR (0x300000 + i))) 54147c478bd9Sstevel@tonic-gate break; 54157c478bd9Sstevel@tonic-gate 54167c478bd9Sstevel@tonic-gate grub_printf ("Max is 0x10ac0: i=0x%x, filepos=0x%x\n", i, filepos); 54177c478bd9Sstevel@tonic-gate disk_read_hook = 0; 54187c478bd9Sstevel@tonic-gate grub_close (); 54197c478bd9Sstevel@tonic-gate return 0; 54207c478bd9Sstevel@tonic-gate } 54217c478bd9Sstevel@tonic-gate 54227c478bd9Sstevel@tonic-gate static struct builtin builtin_testload = 54237c478bd9Sstevel@tonic-gate { 54247c478bd9Sstevel@tonic-gate "testload", 54257c478bd9Sstevel@tonic-gate testload_func, 54267c478bd9Sstevel@tonic-gate BUILTIN_CMDLINE, 54277c478bd9Sstevel@tonic-gate "testload FILE", 54287c478bd9Sstevel@tonic-gate "Read the entire contents of FILE in several different ways and" 54297c478bd9Sstevel@tonic-gate " compares them, to test the filesystem code. The output is somewhat" 54307c478bd9Sstevel@tonic-gate " cryptic, but if no errors are reported and the final `i=X," 54317c478bd9Sstevel@tonic-gate " filepos=Y' reading has X and Y equal, then it is definitely" 54327c478bd9Sstevel@tonic-gate " consistent, and very likely works correctly subject to a" 54337c478bd9Sstevel@tonic-gate " consistent offset error. If this test succeeds, then a good next" 54347c478bd9Sstevel@tonic-gate " step is to try loading a kernel." 54357c478bd9Sstevel@tonic-gate }; 54367c478bd9Sstevel@tonic-gate 54377c478bd9Sstevel@tonic-gate 54387c478bd9Sstevel@tonic-gate /* testvbe MODE */ 54397c478bd9Sstevel@tonic-gate static int 54407c478bd9Sstevel@tonic-gate testvbe_func (char *arg, int flags) 54417c478bd9Sstevel@tonic-gate { 54427c478bd9Sstevel@tonic-gate int mode_number; 54437c478bd9Sstevel@tonic-gate struct vbe_controller controller; 54447c478bd9Sstevel@tonic-gate struct vbe_mode mode; 54457c478bd9Sstevel@tonic-gate 54467c478bd9Sstevel@tonic-gate if (! *arg) 54477c478bd9Sstevel@tonic-gate { 54487c478bd9Sstevel@tonic-gate errnum = ERR_BAD_ARGUMENT; 54497c478bd9Sstevel@tonic-gate return 1; 54507c478bd9Sstevel@tonic-gate } 54517c478bd9Sstevel@tonic-gate 54527c478bd9Sstevel@tonic-gate if (! safe_parse_maxint (&arg, &mode_number)) 54537c478bd9Sstevel@tonic-gate return 1; 54547c478bd9Sstevel@tonic-gate 54557c478bd9Sstevel@tonic-gate /* Preset `VBE2'. */ 54567c478bd9Sstevel@tonic-gate grub_memmove (controller.signature, "VBE2", 4); 54577c478bd9Sstevel@tonic-gate 54587c478bd9Sstevel@tonic-gate /* Detect VBE BIOS. */ 54597c478bd9Sstevel@tonic-gate if (get_vbe_controller_info (&controller) != 0x004F) 54607c478bd9Sstevel@tonic-gate { 54617c478bd9Sstevel@tonic-gate grub_printf (" VBE BIOS is not present.\n"); 54627c478bd9Sstevel@tonic-gate return 0; 54637c478bd9Sstevel@tonic-gate } 54647c478bd9Sstevel@tonic-gate 54657c478bd9Sstevel@tonic-gate if (controller.version < 0x0200) 54667c478bd9Sstevel@tonic-gate { 54677c478bd9Sstevel@tonic-gate grub_printf (" VBE version %d.%d is not supported.\n", 54687c478bd9Sstevel@tonic-gate (int) (controller.version >> 8), 54697c478bd9Sstevel@tonic-gate (int) (controller.version & 0xFF)); 54707c478bd9Sstevel@tonic-gate return 0; 54717c478bd9Sstevel@tonic-gate } 54727c478bd9Sstevel@tonic-gate 54737c478bd9Sstevel@tonic-gate if (get_vbe_mode_info (mode_number, &mode) != 0x004F 54747c478bd9Sstevel@tonic-gate || (mode.mode_attributes & 0x0091) != 0x0091) 54757c478bd9Sstevel@tonic-gate { 54767c478bd9Sstevel@tonic-gate grub_printf (" Mode 0x%x is not supported.\n", mode_number); 54777c478bd9Sstevel@tonic-gate return 0; 54787c478bd9Sstevel@tonic-gate } 54797c478bd9Sstevel@tonic-gate 54807c478bd9Sstevel@tonic-gate /* Now trip to the graphics mode. */ 54817c478bd9Sstevel@tonic-gate if (set_vbe_mode (mode_number | (1 << 14)) != 0x004F) 54827c478bd9Sstevel@tonic-gate { 54837c478bd9Sstevel@tonic-gate grub_printf (" Switching to Mode 0x%x failed.\n", mode_number); 54847c478bd9Sstevel@tonic-gate return 0; 54857c478bd9Sstevel@tonic-gate } 54867c478bd9Sstevel@tonic-gate 54877c478bd9Sstevel@tonic-gate /* Draw something on the screen... */ 54887c478bd9Sstevel@tonic-gate { 54897c478bd9Sstevel@tonic-gate unsigned char *base_buf = (unsigned char *) mode.phys_base; 54907c478bd9Sstevel@tonic-gate int scanline = controller.version >= 0x0300 54917c478bd9Sstevel@tonic-gate ? mode.linear_bytes_per_scanline : mode.bytes_per_scanline; 54927c478bd9Sstevel@tonic-gate /* FIXME: this assumes that any depth is a modulo of 8. */ 54937c478bd9Sstevel@tonic-gate int bpp = mode.bits_per_pixel / 8; 54947c478bd9Sstevel@tonic-gate int width = mode.x_resolution; 54957c478bd9Sstevel@tonic-gate int height = mode.y_resolution; 54967c478bd9Sstevel@tonic-gate int x, y; 54977c478bd9Sstevel@tonic-gate unsigned color = 0; 54987c478bd9Sstevel@tonic-gate 54997c478bd9Sstevel@tonic-gate /* Iterate drawing on the screen, until the user hits any key. */ 55007c478bd9Sstevel@tonic-gate while (checkkey () == -1) 55017c478bd9Sstevel@tonic-gate { 55027c478bd9Sstevel@tonic-gate for (y = 0; y < height; y++) 55037c478bd9Sstevel@tonic-gate { 55047c478bd9Sstevel@tonic-gate unsigned char *line_buf = base_buf + scanline * y; 55057c478bd9Sstevel@tonic-gate 55067c478bd9Sstevel@tonic-gate for (x = 0; x < width; x++) 55077c478bd9Sstevel@tonic-gate { 55087c478bd9Sstevel@tonic-gate unsigned char *buf = line_buf + bpp * x; 55097c478bd9Sstevel@tonic-gate int i; 55107c478bd9Sstevel@tonic-gate 55117c478bd9Sstevel@tonic-gate for (i = 0; i < bpp; i++, buf++) 55127c478bd9Sstevel@tonic-gate *buf = (color >> (i * 8)) & 0xff; 55137c478bd9Sstevel@tonic-gate } 55147c478bd9Sstevel@tonic-gate 55157c478bd9Sstevel@tonic-gate color++; 55167c478bd9Sstevel@tonic-gate } 55177c478bd9Sstevel@tonic-gate } 55187c478bd9Sstevel@tonic-gate 55197c478bd9Sstevel@tonic-gate /* Discard the input. */ 55207c478bd9Sstevel@tonic-gate getkey (); 55217c478bd9Sstevel@tonic-gate } 55227c478bd9Sstevel@tonic-gate 55237c478bd9Sstevel@tonic-gate /* Back to the default text mode. */ 55247c478bd9Sstevel@tonic-gate if (set_vbe_mode (0x03) != 0x004F) 55257c478bd9Sstevel@tonic-gate { 55267c478bd9Sstevel@tonic-gate /* Why?! */ 55277c478bd9Sstevel@tonic-gate grub_reboot (); 55287c478bd9Sstevel@tonic-gate } 55297c478bd9Sstevel@tonic-gate 55307c478bd9Sstevel@tonic-gate return 0; 55317c478bd9Sstevel@tonic-gate } 55327c478bd9Sstevel@tonic-gate 55337c478bd9Sstevel@tonic-gate static struct builtin builtin_testvbe = 55347c478bd9Sstevel@tonic-gate { 55357c478bd9Sstevel@tonic-gate "testvbe", 55367c478bd9Sstevel@tonic-gate testvbe_func, 55377c478bd9Sstevel@tonic-gate BUILTIN_CMDLINE | BUILTIN_HELP_LIST, 55387c478bd9Sstevel@tonic-gate "testvbe MODE", 55397c478bd9Sstevel@tonic-gate "Test the VBE mode MODE. Hit any key to return." 55407c478bd9Sstevel@tonic-gate }; 55417c478bd9Sstevel@tonic-gate 55427c478bd9Sstevel@tonic-gate 55437c478bd9Sstevel@tonic-gate #ifdef SUPPORT_NETBOOT 55447c478bd9Sstevel@tonic-gate /* tftpserver */ 55457c478bd9Sstevel@tonic-gate static int 55467c478bd9Sstevel@tonic-gate tftpserver_func (char *arg, int flags) 55477c478bd9Sstevel@tonic-gate { 55487c478bd9Sstevel@tonic-gate if (! *arg || ! ifconfig (0, 0, 0, arg)) 55497c478bd9Sstevel@tonic-gate { 55507c478bd9Sstevel@tonic-gate errnum = ERR_BAD_ARGUMENT; 55517c478bd9Sstevel@tonic-gate return 1; 55527c478bd9Sstevel@tonic-gate } 55537c478bd9Sstevel@tonic-gate 55547c478bd9Sstevel@tonic-gate print_network_configuration (); 55557c478bd9Sstevel@tonic-gate return 0; 55567c478bd9Sstevel@tonic-gate } 55577c478bd9Sstevel@tonic-gate 55587c478bd9Sstevel@tonic-gate static struct builtin builtin_tftpserver = 55597c478bd9Sstevel@tonic-gate { 55607c478bd9Sstevel@tonic-gate "tftpserver", 55617c478bd9Sstevel@tonic-gate tftpserver_func, 55627c478bd9Sstevel@tonic-gate BUILTIN_CMDLINE | BUILTIN_MENU | BUILTIN_HELP_LIST, 55637c478bd9Sstevel@tonic-gate "tftpserver IPADDR", 55647c478bd9Sstevel@tonic-gate "Override the TFTP server address." 55657c478bd9Sstevel@tonic-gate }; 55667c478bd9Sstevel@tonic-gate #endif /* SUPPORT_NETBOOT */ 55677c478bd9Sstevel@tonic-gate 55687c478bd9Sstevel@tonic-gate 55697c478bd9Sstevel@tonic-gate /* timeout */ 55707c478bd9Sstevel@tonic-gate static int 55717c478bd9Sstevel@tonic-gate timeout_func (char *arg, int flags) 55727c478bd9Sstevel@tonic-gate { 55737c478bd9Sstevel@tonic-gate if (! safe_parse_maxint (&arg, &grub_timeout)) 55747c478bd9Sstevel@tonic-gate return 1; 55757c478bd9Sstevel@tonic-gate 55767c478bd9Sstevel@tonic-gate return 0; 55777c478bd9Sstevel@tonic-gate } 55787c478bd9Sstevel@tonic-gate 55797c478bd9Sstevel@tonic-gate static struct builtin builtin_timeout = 55807c478bd9Sstevel@tonic-gate { 55817c478bd9Sstevel@tonic-gate "timeout", 55827c478bd9Sstevel@tonic-gate timeout_func, 55837c478bd9Sstevel@tonic-gate BUILTIN_MENU, 55847c478bd9Sstevel@tonic-gate #if 0 55857c478bd9Sstevel@tonic-gate "timeout SEC", 55867c478bd9Sstevel@tonic-gate "Set a timeout, in SEC seconds, before automatically booting the" 55877c478bd9Sstevel@tonic-gate " default entry (normally the first entry defined)." 55887c478bd9Sstevel@tonic-gate #endif 55897c478bd9Sstevel@tonic-gate }; 55907c478bd9Sstevel@tonic-gate 55917c478bd9Sstevel@tonic-gate 55927c478bd9Sstevel@tonic-gate /* title */ 55937c478bd9Sstevel@tonic-gate static int 55947c478bd9Sstevel@tonic-gate title_func (char *arg, int flags) 55957c478bd9Sstevel@tonic-gate { 55967c478bd9Sstevel@tonic-gate /* This function is not actually used at least currently. */ 55977c478bd9Sstevel@tonic-gate return 0; 55987c478bd9Sstevel@tonic-gate } 55997c478bd9Sstevel@tonic-gate 56007c478bd9Sstevel@tonic-gate static struct builtin builtin_title = 56017c478bd9Sstevel@tonic-gate { 56027c478bd9Sstevel@tonic-gate "title", 56037c478bd9Sstevel@tonic-gate title_func, 56047c478bd9Sstevel@tonic-gate BUILTIN_TITLE, 56057c478bd9Sstevel@tonic-gate #if 0 56067c478bd9Sstevel@tonic-gate "title [NAME ...]", 56077c478bd9Sstevel@tonic-gate "Start a new boot entry, and set its name to the contents of the" 56087c478bd9Sstevel@tonic-gate " rest of the line, starting with the first non-space character." 56097c478bd9Sstevel@tonic-gate #endif 56107c478bd9Sstevel@tonic-gate }; 56117c478bd9Sstevel@tonic-gate 56127c478bd9Sstevel@tonic-gate 56137c478bd9Sstevel@tonic-gate /* unhide */ 56147c478bd9Sstevel@tonic-gate static int 56157c478bd9Sstevel@tonic-gate unhide_func (char *arg, int flags) 56167c478bd9Sstevel@tonic-gate { 56177c478bd9Sstevel@tonic-gate if (! set_device (arg)) 56187c478bd9Sstevel@tonic-gate return 1; 56197c478bd9Sstevel@tonic-gate 56207c478bd9Sstevel@tonic-gate if (! set_partition_hidden_flag (0)) 56217c478bd9Sstevel@tonic-gate return 1; 56227c478bd9Sstevel@tonic-gate 56237c478bd9Sstevel@tonic-gate return 0; 56247c478bd9Sstevel@tonic-gate } 56257c478bd9Sstevel@tonic-gate 56267c478bd9Sstevel@tonic-gate static struct builtin builtin_unhide = 56277c478bd9Sstevel@tonic-gate { 56287c478bd9Sstevel@tonic-gate "unhide", 56297c478bd9Sstevel@tonic-gate unhide_func, 56307c478bd9Sstevel@tonic-gate BUILTIN_CMDLINE | BUILTIN_MENU | BUILTIN_HELP_LIST, 56317c478bd9Sstevel@tonic-gate "unhide PARTITION", 56327c478bd9Sstevel@tonic-gate "Unhide PARTITION by clearing the \"hidden\" bit in its" 56337c478bd9Sstevel@tonic-gate " partition type code." 56347c478bd9Sstevel@tonic-gate }; 56357c478bd9Sstevel@tonic-gate 56367c478bd9Sstevel@tonic-gate 56377c478bd9Sstevel@tonic-gate /* uppermem */ 56387c478bd9Sstevel@tonic-gate static int 56397c478bd9Sstevel@tonic-gate uppermem_func (char *arg, int flags) 56407c478bd9Sstevel@tonic-gate { 56417c478bd9Sstevel@tonic-gate if (! safe_parse_maxint (&arg, (int *) &mbi.mem_upper)) 56427c478bd9Sstevel@tonic-gate return 1; 56437c478bd9Sstevel@tonic-gate 56447c478bd9Sstevel@tonic-gate mbi.flags &= ~MB_INFO_MEM_MAP; 56457c478bd9Sstevel@tonic-gate return 0; 56467c478bd9Sstevel@tonic-gate } 56477c478bd9Sstevel@tonic-gate 56487c478bd9Sstevel@tonic-gate static struct builtin builtin_uppermem = 56497c478bd9Sstevel@tonic-gate { 56507c478bd9Sstevel@tonic-gate "uppermem", 56517c478bd9Sstevel@tonic-gate uppermem_func, 56527c478bd9Sstevel@tonic-gate BUILTIN_CMDLINE | BUILTIN_HELP_LIST, 56537c478bd9Sstevel@tonic-gate "uppermem KBYTES", 56547c478bd9Sstevel@tonic-gate "Force GRUB to assume that only KBYTES kilobytes of upper memory are" 56557c478bd9Sstevel@tonic-gate " installed. Any system address range maps are discarded." 56567c478bd9Sstevel@tonic-gate }; 56577c478bd9Sstevel@tonic-gate 56587c478bd9Sstevel@tonic-gate 56597c478bd9Sstevel@tonic-gate /* vbeprobe */ 56607c478bd9Sstevel@tonic-gate static int 56617c478bd9Sstevel@tonic-gate vbeprobe_func (char *arg, int flags) 56627c478bd9Sstevel@tonic-gate { 56637c478bd9Sstevel@tonic-gate struct vbe_controller controller; 56647c478bd9Sstevel@tonic-gate unsigned short *mode_list; 56657c478bd9Sstevel@tonic-gate int mode_number = -1; 56667c478bd9Sstevel@tonic-gate 56677c478bd9Sstevel@tonic-gate auto unsigned long vbe_far_ptr_to_linear (unsigned long); 56687c478bd9Sstevel@tonic-gate 56697c478bd9Sstevel@tonic-gate unsigned long vbe_far_ptr_to_linear (unsigned long ptr) 56707c478bd9Sstevel@tonic-gate { 56717c478bd9Sstevel@tonic-gate unsigned short seg = (ptr >> 16); 56727c478bd9Sstevel@tonic-gate unsigned short off = (ptr & 0xFFFF); 56737c478bd9Sstevel@tonic-gate 56747c478bd9Sstevel@tonic-gate return (seg << 4) + off; 56757c478bd9Sstevel@tonic-gate } 56767c478bd9Sstevel@tonic-gate 56777c478bd9Sstevel@tonic-gate if (*arg) 56787c478bd9Sstevel@tonic-gate { 56797c478bd9Sstevel@tonic-gate if (! safe_parse_maxint (&arg, &mode_number)) 56807c478bd9Sstevel@tonic-gate return 1; 56817c478bd9Sstevel@tonic-gate } 56827c478bd9Sstevel@tonic-gate 56837c478bd9Sstevel@tonic-gate /* Set the signature to `VBE2', to obtain VBE 3.0 information. */ 56847c478bd9Sstevel@tonic-gate grub_memmove (controller.signature, "VBE2", 4); 56857c478bd9Sstevel@tonic-gate 56867c478bd9Sstevel@tonic-gate if (get_vbe_controller_info (&controller) != 0x004F) 56877c478bd9Sstevel@tonic-gate { 56887c478bd9Sstevel@tonic-gate grub_printf (" VBE BIOS is not present.\n"); 56897c478bd9Sstevel@tonic-gate return 0; 56907c478bd9Sstevel@tonic-gate } 56917c478bd9Sstevel@tonic-gate 56927c478bd9Sstevel@tonic-gate /* Check the version. */ 56937c478bd9Sstevel@tonic-gate if (controller.version < 0x0200) 56947c478bd9Sstevel@tonic-gate { 56957c478bd9Sstevel@tonic-gate grub_printf (" VBE version %d.%d is not supported.\n", 56967c478bd9Sstevel@tonic-gate (int) (controller.version >> 8), 56977c478bd9Sstevel@tonic-gate (int) (controller.version & 0xFF)); 56987c478bd9Sstevel@tonic-gate return 0; 56997c478bd9Sstevel@tonic-gate } 57007c478bd9Sstevel@tonic-gate 57017c478bd9Sstevel@tonic-gate /* Print some information. */ 57027c478bd9Sstevel@tonic-gate grub_printf (" VBE version %d.%d\n", 57037c478bd9Sstevel@tonic-gate (int) (controller.version >> 8), 57047c478bd9Sstevel@tonic-gate (int) (controller.version & 0xFF)); 57057c478bd9Sstevel@tonic-gate 57067c478bd9Sstevel@tonic-gate /* Iterate probing modes. */ 57077c478bd9Sstevel@tonic-gate for (mode_list 57087c478bd9Sstevel@tonic-gate = (unsigned short *) vbe_far_ptr_to_linear (controller.video_mode); 57097c478bd9Sstevel@tonic-gate *mode_list != 0xFFFF; 57107c478bd9Sstevel@tonic-gate mode_list++) 57117c478bd9Sstevel@tonic-gate { 57127c478bd9Sstevel@tonic-gate struct vbe_mode mode; 57137c478bd9Sstevel@tonic-gate 57147c478bd9Sstevel@tonic-gate if (get_vbe_mode_info (*mode_list, &mode) != 0x004F) 57157c478bd9Sstevel@tonic-gate continue; 57167c478bd9Sstevel@tonic-gate 57177c478bd9Sstevel@tonic-gate /* Skip this, if this is not supported or linear frame buffer 57187c478bd9Sstevel@tonic-gate mode is not support. */ 57197c478bd9Sstevel@tonic-gate if ((mode.mode_attributes & 0x0081) != 0x0081) 57207c478bd9Sstevel@tonic-gate continue; 57217c478bd9Sstevel@tonic-gate 57227c478bd9Sstevel@tonic-gate if (mode_number == -1 || mode_number == *mode_list) 57237c478bd9Sstevel@tonic-gate { 57247c478bd9Sstevel@tonic-gate char *model; 57257c478bd9Sstevel@tonic-gate switch (mode.memory_model) 57267c478bd9Sstevel@tonic-gate { 57277c478bd9Sstevel@tonic-gate case 0x00: model = "Text"; break; 57287c478bd9Sstevel@tonic-gate case 0x01: model = "CGA graphics"; break; 57297c478bd9Sstevel@tonic-gate case 0x02: model = "Hercules graphics"; break; 57307c478bd9Sstevel@tonic-gate case 0x03: model = "Planar"; break; 57317c478bd9Sstevel@tonic-gate case 0x04: model = "Packed pixel"; break; 57327c478bd9Sstevel@tonic-gate case 0x05: model = "Non-chain 4, 256 color"; break; 57337c478bd9Sstevel@tonic-gate case 0x06: model = "Direct Color"; break; 57347c478bd9Sstevel@tonic-gate case 0x07: model = "YUV"; break; 57357c478bd9Sstevel@tonic-gate default: model = "Unknown"; break; 57367c478bd9Sstevel@tonic-gate } 57377c478bd9Sstevel@tonic-gate 57387c478bd9Sstevel@tonic-gate grub_printf (" 0x%x: %s, %ux%ux%u\n", 57397c478bd9Sstevel@tonic-gate (unsigned) *mode_list, 57407c478bd9Sstevel@tonic-gate model, 57417c478bd9Sstevel@tonic-gate (unsigned) mode.x_resolution, 57427c478bd9Sstevel@tonic-gate (unsigned) mode.y_resolution, 57437c478bd9Sstevel@tonic-gate (unsigned) mode.bits_per_pixel); 57447c478bd9Sstevel@tonic-gate 57457c478bd9Sstevel@tonic-gate if (mode_number != -1) 57467c478bd9Sstevel@tonic-gate break; 57477c478bd9Sstevel@tonic-gate } 57487c478bd9Sstevel@tonic-gate } 57497c478bd9Sstevel@tonic-gate 57507c478bd9Sstevel@tonic-gate if (mode_number != -1 && mode_number != *mode_list) 57517c478bd9Sstevel@tonic-gate grub_printf (" Mode 0x%x is not found or supported.\n", mode_number); 57527c478bd9Sstevel@tonic-gate 57537c478bd9Sstevel@tonic-gate return 0; 57547c478bd9Sstevel@tonic-gate } 57557c478bd9Sstevel@tonic-gate 57567c478bd9Sstevel@tonic-gate static struct builtin builtin_vbeprobe = 57577c478bd9Sstevel@tonic-gate { 57587c478bd9Sstevel@tonic-gate "vbeprobe", 57597c478bd9Sstevel@tonic-gate vbeprobe_func, 57607c478bd9Sstevel@tonic-gate BUILTIN_CMDLINE | BUILTIN_HELP_LIST, 57617c478bd9Sstevel@tonic-gate "vbeprobe [MODE]", 57627c478bd9Sstevel@tonic-gate "Probe VBE information. If the mode number MODE is specified, show only" 57637c478bd9Sstevel@tonic-gate " the information about only the mode." 57647c478bd9Sstevel@tonic-gate }; 57657c478bd9Sstevel@tonic-gate 57667c478bd9Sstevel@tonic-gate 57677c478bd9Sstevel@tonic-gate /* The table of builtin commands. Sorted in dictionary order. */ 57687c478bd9Sstevel@tonic-gate struct builtin *builtin_table[] = 57697c478bd9Sstevel@tonic-gate { 57707c478bd9Sstevel@tonic-gate #ifdef SUPPORT_GRAPHICS 57717c478bd9Sstevel@tonic-gate &builtin_background, 57727c478bd9Sstevel@tonic-gate #endif 57737c478bd9Sstevel@tonic-gate &builtin_blocklist, 57747c478bd9Sstevel@tonic-gate &builtin_boot, 5775b1b8ab34Slling &builtin_bootfs, 57767c478bd9Sstevel@tonic-gate #ifdef SUPPORT_NETBOOT 57777c478bd9Sstevel@tonic-gate &builtin_bootp, 57787c478bd9Sstevel@tonic-gate #endif /* SUPPORT_NETBOOT */ 57797c478bd9Sstevel@tonic-gate &builtin_cat, 57807c478bd9Sstevel@tonic-gate &builtin_chainloader, 57817c478bd9Sstevel@tonic-gate &builtin_clear, 57827c478bd9Sstevel@tonic-gate &builtin_cmp, 57837c478bd9Sstevel@tonic-gate &builtin_color, 57847c478bd9Sstevel@tonic-gate &builtin_configfile, 57857c478bd9Sstevel@tonic-gate &builtin_debug, 57867c478bd9Sstevel@tonic-gate &builtin_default, 57877c478bd9Sstevel@tonic-gate #ifdef GRUB_UTIL 57887c478bd9Sstevel@tonic-gate &builtin_device, 57897c478bd9Sstevel@tonic-gate #endif /* GRUB_UTIL */ 57907c478bd9Sstevel@tonic-gate #ifdef SUPPORT_NETBOOT 57917c478bd9Sstevel@tonic-gate &builtin_dhcp, 57927c478bd9Sstevel@tonic-gate #endif /* SUPPORT_NETBOOT */ 57937c478bd9Sstevel@tonic-gate &builtin_displayapm, 57947c478bd9Sstevel@tonic-gate &builtin_displaymem, 57957c478bd9Sstevel@tonic-gate #ifdef GRUB_UTIL 57967c478bd9Sstevel@tonic-gate &builtin_dump, 57977c478bd9Sstevel@tonic-gate #endif /* GRUB_UTIL */ 57987c478bd9Sstevel@tonic-gate &builtin_embed, 57997c478bd9Sstevel@tonic-gate &builtin_fallback, 58007c478bd9Sstevel@tonic-gate &builtin_find, 5801eb2bd662Svikram &builtin_findroot, 58027c478bd9Sstevel@tonic-gate #ifdef SUPPORT_GRAPHICS 58037c478bd9Sstevel@tonic-gate &builtin_foreground, 58047c478bd9Sstevel@tonic-gate #endif 58057c478bd9Sstevel@tonic-gate &builtin_fstest, 58067c478bd9Sstevel@tonic-gate &builtin_geometry, 58077c478bd9Sstevel@tonic-gate &builtin_halt, 58087c478bd9Sstevel@tonic-gate &builtin_help, 58097c478bd9Sstevel@tonic-gate &builtin_hiddenmenu, 58107c478bd9Sstevel@tonic-gate &builtin_hide, 58117c478bd9Sstevel@tonic-gate #ifdef SUPPORT_NETBOOT 58127c478bd9Sstevel@tonic-gate &builtin_ifconfig, 58137c478bd9Sstevel@tonic-gate #endif /* SUPPORT_NETBOOT */ 58147c478bd9Sstevel@tonic-gate &builtin_impsprobe, 58157c478bd9Sstevel@tonic-gate &builtin_initrd, 58167c478bd9Sstevel@tonic-gate &builtin_install, 58177c478bd9Sstevel@tonic-gate &builtin_ioprobe, 58187c478bd9Sstevel@tonic-gate &builtin_kernel, 5819ae115bc7Smrj &builtin_kernel_dollar, 58207c478bd9Sstevel@tonic-gate &builtin_lock, 58217c478bd9Sstevel@tonic-gate &builtin_makeactive, 58227c478bd9Sstevel@tonic-gate &builtin_map, 58237c478bd9Sstevel@tonic-gate #ifdef USE_MD5_PASSWORDS 58247c478bd9Sstevel@tonic-gate &builtin_md5crypt, 58257c478bd9Sstevel@tonic-gate #endif /* USE_MD5_PASSWORDS */ 5826342440ecSPrasad Singamsetty &builtin_min_mem64, 58277c478bd9Sstevel@tonic-gate &builtin_module, 5828ae115bc7Smrj &builtin_module_dollar, 58297c478bd9Sstevel@tonic-gate &builtin_modulenounzip, 58307c478bd9Sstevel@tonic-gate &builtin_pager, 58317c478bd9Sstevel@tonic-gate &builtin_partnew, 58327c478bd9Sstevel@tonic-gate &builtin_parttype, 58337c478bd9Sstevel@tonic-gate &builtin_password, 58347c478bd9Sstevel@tonic-gate &builtin_pause, 58357c478bd9Sstevel@tonic-gate #if defined(RPC_DEBUG) && defined(SUPPORT_NETBOOT) 58367c478bd9Sstevel@tonic-gate &builtin_portmap, 58377c478bd9Sstevel@tonic-gate #endif /* RPC_DEBUG && SUPPORT_NETBOOT */ 58387c478bd9Sstevel@tonic-gate #ifdef GRUB_UTIL 58397c478bd9Sstevel@tonic-gate &builtin_quit, 58407c478bd9Sstevel@tonic-gate #endif /* GRUB_UTIL */ 58417c478bd9Sstevel@tonic-gate #ifdef SUPPORT_NETBOOT 58427c478bd9Sstevel@tonic-gate &builtin_rarp, 58437c478bd9Sstevel@tonic-gate #endif /* SUPPORT_NETBOOT */ 58447c478bd9Sstevel@tonic-gate &builtin_read, 58457c478bd9Sstevel@tonic-gate &builtin_reboot, 58467c478bd9Sstevel@tonic-gate &builtin_root, 58477c478bd9Sstevel@tonic-gate &builtin_rootnoverify, 58487c478bd9Sstevel@tonic-gate &builtin_savedefault, 58497c478bd9Sstevel@tonic-gate #ifdef SUPPORT_SERIAL 58507c478bd9Sstevel@tonic-gate &builtin_serial, 58517c478bd9Sstevel@tonic-gate #endif /* SUPPORT_SERIAL */ 58527c478bd9Sstevel@tonic-gate &builtin_setkey, 58537c478bd9Sstevel@tonic-gate &builtin_setup, 58547c478bd9Sstevel@tonic-gate #ifdef SUPPORT_GRAPHICS 58557c478bd9Sstevel@tonic-gate &builtin_splashimage, 58567c478bd9Sstevel@tonic-gate #endif /* SUPPORT_GRAPHICS */ 58577c478bd9Sstevel@tonic-gate #if defined(SUPPORT_SERIAL) || defined(SUPPORT_HERCULES) || defined(SUPPORT_GRAPHICS) 58587c478bd9Sstevel@tonic-gate &builtin_terminal, 58597c478bd9Sstevel@tonic-gate #endif /* SUPPORT_SERIAL || SUPPORT_HERCULES || SUPPORT_GRAPHICS */ 58607c478bd9Sstevel@tonic-gate #ifdef SUPPORT_SERIAL 58617c478bd9Sstevel@tonic-gate &builtin_terminfo, 58627c478bd9Sstevel@tonic-gate #endif /* SUPPORT_SERIAL */ 58637c478bd9Sstevel@tonic-gate &builtin_testload, 58647c478bd9Sstevel@tonic-gate &builtin_testvbe, 58657c478bd9Sstevel@tonic-gate #ifdef SUPPORT_NETBOOT 58667c478bd9Sstevel@tonic-gate &builtin_tftpserver, 58677c478bd9Sstevel@tonic-gate #endif /* SUPPORT_NETBOOT */ 58687c478bd9Sstevel@tonic-gate &builtin_timeout, 58697c478bd9Sstevel@tonic-gate &builtin_title, 58707c478bd9Sstevel@tonic-gate &builtin_unhide, 58717c478bd9Sstevel@tonic-gate &builtin_uppermem, 58727c478bd9Sstevel@tonic-gate &builtin_vbeprobe, 58731fac5a60Ssetje &builtin_verbose, 58747c478bd9Sstevel@tonic-gate 0 58757c478bd9Sstevel@tonic-gate }; 5876