1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 22 /* 23 * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #pragma ident "%Z%%M% %I% %E% SMI" 28 29 #include <sys/promif_impl.h> 30 #include <sys/uadmin.h> 31 #include <sys/machsystm.h> 32 #include <sys/hypervisor_api.h> 33 34 #ifdef _KMDB 35 36 extern int kmdb_dpi_get_master_cpuid(void); 37 extern void kmdb_dpi_kernpanic(int cpuid); 38 extern void prom_reboot(char *bootstr); 39 40 #define PIL_DECL(p) 41 #define PIL_SET7(p) 42 #define PIL_REST(p) 43 44 #else 45 46 extern int vx_handler(cell_t *argument_array); 47 48 #define PIL_DECL(p) int p 49 #define PIL_SET7(p) (p = spl7()) 50 #define PIL_REST(p) (splx(p)) 51 52 #endif 53 54 #define PROMIF_ENTER 0 55 #define PROMIF_EXIT 1 56 57 #define PROMIF_ISPRINT(c) (((c) >= ' ') && ((c) <= '~')) 58 59 static void promif_mon(int mode); 60 61 /*ARGSUSED*/ 62 int 63 promif_enter_mon(void *p) 64 { 65 PIL_DECL(pil); 66 67 PIL_SET7(pil); 68 69 prom_printf("\n"); 70 71 #ifdef _KMDB 72 promif_mon(PROMIF_ENTER); 73 #else 74 idle_other_cpus(); 75 promif_mon(PROMIF_ENTER); 76 resume_other_cpus(); 77 #endif 78 79 PIL_REST(pil); 80 81 return (0); 82 } 83 84 /*ARGSUSED*/ 85 int 86 promif_exit_to_mon(void *p) 87 { 88 PIL_DECL(pil); 89 90 PIL_SET7(pil); 91 92 prom_printf("Program terminated\n"); 93 94 promif_mon(PROMIF_EXIT); 95 96 PIL_REST(pil); 97 98 return (0); 99 } 100 101 static void 102 promif_mon(int mode) 103 { 104 char cmd; 105 char *prompt; 106 boolean_t invalid_option; 107 #ifdef _KMDB 108 static char *exit_prompt = "r)eboot, h)alt? "; 109 #else 110 char value[ 8 ]; /* holds "true" or "false" */ 111 char *boot_msg; 112 static char *null_msg = ".\" \""; 113 static char *ignore_msg = 114 "cr .\" Ignoring auto-boot? setting for this boot.\" cr"; 115 static char *exit_prompt = "r)eboot, o)k prompt, h)alt? "; 116 #endif 117 static char *enter_prompt = "c)ontinue, s)ync, r)eboot, h)alt? "; 118 119 prompt = (mode == PROMIF_EXIT) ? exit_prompt : enter_prompt; 120 121 for (;;) { 122 prom_printf("%s", prompt); 123 124 while (hv_cngetchar((uint8_t *)&cmd) != H_EOK) 125 ; 126 127 prom_printf("%c\n", cmd); 128 129 invalid_option = B_FALSE; 130 131 switch (cmd) { 132 133 case 'r': 134 /* 135 * Ideally, we would store the boot command string 136 * as we do in promif_reboot(). However, at this 137 * point the kernel is single-threaded and running 138 * at a high PIL. This environment precludes 139 * setting ldom variables. 140 */ 141 prom_printf("Resetting...\n"); 142 143 (void) hv_mach_sir(); 144 145 /* should not return */ 146 ASSERT(0); 147 break; 148 149 case 'h': 150 (void) hv_mach_exit(0); 151 ASSERT(0); 152 153 break; 154 155 #ifndef _KMDB 156 case 'o': 157 /* 158 * This option gives the user an "ok" prompt after 159 * the system reset regardless of the value of 160 * auto-boot? We offer this option because halt(1m) 161 * doesn't leave the user at the ok prompt (as it 162 * does on non-ldoms systems). If auto-boot? is 163 * true tell user we are overriding the setting 164 * for this boot only. 165 */ 166 if (mode == PROMIF_EXIT) { 167 bzero(value, sizeof (value)); 168 (void) promif_stree_getprop(prom_optionsnode(), 169 "auto-boot?", value); 170 boot_msg = strcmp(value, "true") ? null_msg : 171 ignore_msg; 172 (void) promif_ldom_setprop("reboot-command", 173 boot_msg, strlen(boot_msg) + 1); 174 (void) hv_mach_sir(); 175 } else { 176 invalid_option = B_TRUE; 177 } 178 break; 179 #endif 180 181 case '\r': 182 break; 183 184 case 's': 185 if (mode == PROMIF_ENTER) { 186 #ifdef _KMDB 187 kmdb_dpi_kernpanic(kmdb_dpi_get_master_cpuid()); 188 #else 189 cell_t arg = p1275_ptr2cell("sync"); 190 (void) vx_handler(&arg); 191 #endif 192 } else { 193 invalid_option = B_TRUE; 194 } 195 break; 196 197 case 'c': 198 if (mode == PROMIF_ENTER) { 199 return; 200 } else { 201 invalid_option = B_TRUE; 202 } 203 break; 204 205 default: 206 invalid_option = B_TRUE; 207 break; 208 } 209 210 if (invalid_option && PROMIF_ISPRINT(cmd)) 211 prom_printf("invalid option (%c)\n", cmd); 212 } 213 214 _NOTE(NOTREACHED) 215 } 216