1 /* $OpenBSD: cmd.c,v 1.28 2001/01/28 00:56:07 weingart Exp $ */ 2 3 /* 4 * Copyright (c) 1997 Tobias Weingartner 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. All advertising materials mentioning features or use of this software 16 * must display the following acknowledgement: 17 * This product includes software developed by Tobias Weingartner. 18 * 4. The name of the author may not be used to endorse or promote products 19 * derived from this software without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 22 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 23 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 24 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 25 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 26 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 30 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 */ 32 33 #include <stdio.h> 34 #include <ctype.h> 35 #include <memory.h> 36 #include <stdlib.h> 37 #include <unistd.h> 38 #include <signal.h> 39 #include <sys/fcntl.h> 40 #include <sys/disklabel.h> 41 #include "disk.h" 42 #include "misc.h" 43 #include "user.h" 44 #include "part.h" 45 #include "cmd.h" 46 #define MAX(a, b) ((a) >= (b) ? (a) : (b)) 47 48 int 49 Xreinit(cmd, disk, mbr, tt, offset) 50 cmd_t *cmd; 51 disk_t *disk; 52 mbr_t *mbr; 53 mbr_t *tt; 54 int offset; 55 { 56 char buf[DEV_BSIZE]; 57 58 /* Copy template MBR */ 59 MBR_make(tt, buf); 60 MBR_parse(disk, buf, 0, 0, mbr); 61 62 MBR_init(disk, mbr); 63 64 /* Tell em we did something */ 65 printf("In memory copy is initialized to:\n"); 66 printf("Offset: %d\t", offset); 67 MBR_print(mbr); 68 printf("Use 'write' to update disk.\n"); 69 70 return (CMD_DIRTY); 71 } 72 73 int 74 Xdisk(cmd, disk, mbr, tt, offset) 75 cmd_t *cmd; 76 disk_t *disk; 77 mbr_t *mbr; 78 mbr_t *tt; 79 int offset; 80 { 81 int maxcyl = 1024; 82 int maxhead = 256; 83 int maxsec = 63; 84 85 /* Print out disk info */ 86 DISK_printmetrics(disk); 87 88 #if defined (__powerpc__) || defined (__mips__) 89 maxcyl = 9999999; 90 maxhead = 9999999; 91 maxsec = 9999999; 92 #endif 93 94 /* Ask for new info */ 95 if (ask_yn("Change disk geometry?")) { 96 disk->real->cylinders = ask_num("BIOS Cylinders", ASK_DEC, 97 disk->real->cylinders, 1, maxcyl, NULL); 98 disk->real->heads = ask_num("BIOS Heads", ASK_DEC, 99 disk->real->heads, 1, maxhead, NULL); 100 disk->real->sectors = ask_num("BIOS Sectors", ASK_DEC, 101 disk->real->sectors, 1, maxsec, NULL); 102 103 disk->real->size = disk->real->cylinders * disk->real->heads 104 * disk->real->sectors; 105 } 106 107 return (CMD_CONT); 108 } 109 110 int 111 Xedit(cmd, disk, mbr, tt, offset) 112 cmd_t *cmd; 113 disk_t *disk; 114 mbr_t *mbr; 115 mbr_t *tt; 116 int offset; 117 { 118 int pn, num, ret; 119 prt_t *pp; 120 121 ret = CMD_CONT; 122 123 if (!isdigit(cmd->args[0])) { 124 printf("Invalid argument: %s <partition number>\n", cmd->cmd); 125 return (ret); 126 } 127 pn = atoi(cmd->args); 128 129 if (pn < 0 || pn > 3) { 130 printf("Invalid partition number.\n"); 131 return (ret); 132 } 133 134 /* Print out current table entry */ 135 pp = &mbr->part[pn]; 136 PRT_print(0, NULL); 137 PRT_print(pn, pp); 138 139 #define EDIT(p, f, v, n, m, h) \ 140 if ((num = ask_num(p, f, v, n, m, h)) != v) \ 141 ret = CMD_DIRTY; \ 142 v = num; 143 144 /* Ask for partition type */ 145 EDIT("Partition id ('0' to disable) ", ASK_HEX, pp->id, 0, 0xFF, PRT_printall); 146 147 /* Unused, so just zero out */ 148 if (pp->id == DOSPTYP_UNUSED) { 149 memset(pp, 0, sizeof(*pp)); 150 printf("Partition %d is disabled.\n", pn); 151 return (ret); 152 } 153 154 /* Change table entry */ 155 if (ask_yn("Do you wish to edit in CHS mode?")) { 156 int maxcyl, maxhead, maxsect; 157 158 /* Shorter */ 159 maxcyl = disk->real->cylinders - 1; 160 maxhead = disk->real->heads - 1; 161 maxsect = disk->real->sectors; 162 163 /* Get data */ 164 EDIT("BIOS Starting cylinder", ASK_DEC, pp->scyl, 0, maxcyl, NULL); 165 EDIT("BIOS Starting head", ASK_DEC, pp->shead, 0, maxhead, NULL); 166 EDIT("BIOS Starting sector", ASK_DEC, pp->ssect, 1, maxsect, NULL); 167 EDIT("BIOS Ending cylinder", ASK_DEC, pp->ecyl, 0, maxcyl, NULL); 168 EDIT("BIOS Ending head", ASK_DEC, pp->ehead, 0, maxhead, NULL); 169 EDIT("BIOS Ending sector", ASK_DEC, pp->esect, 1, maxsect, NULL); 170 /* Fix up off/size values */ 171 PRT_fix_BN(disk, pp, pn); 172 /* Fix up CHS values for LBA */ 173 PRT_fix_CHS(disk, pp, pn); 174 } else { 175 u_int m; 176 177 /* Get data */ 178 EDIT("Partition offset", ASK_DEC, pp->bs, 0, 179 disk->real->size, NULL); 180 m = MAX(pp->ns, disk->real->size - pp->bs); 181 if ( m > disk->real->size - pp->bs) { 182 /* dont have default value extend beyond end of disk */ 183 m = disk->real->size - pp->bs; 184 } 185 EDIT("Partition size", ASK_DEC, pp->ns, 1, 186 m, NULL); 187 188 /* Fix up CHS values */ 189 PRT_fix_CHS(disk, pp, pn); 190 } 191 #undef EDIT 192 return (ret); 193 } 194 195 int 196 Xsetpid(cmd, disk, mbr, tt, offset) 197 cmd_t *cmd; 198 disk_t *disk; 199 mbr_t *mbr; 200 mbr_t *tt; 201 int offset; 202 { 203 int pn, num, ret; 204 prt_t *pp; 205 206 ret = CMD_CONT; 207 208 if (!isdigit(cmd->args[0])) { 209 printf("Invalid argument: %s <partition number>\n", cmd->cmd); 210 return (ret); 211 } 212 pn = atoi(cmd->args); 213 214 if (pn < 0 || pn > 3) { 215 printf("Invalid partition number.\n"); 216 return (ret); 217 } 218 219 /* Print out current table entry */ 220 pp = &mbr->part[pn]; 221 PRT_print(0, NULL); 222 PRT_print(pn, pp); 223 224 #define EDIT(p, f, v, n, m, h) \ 225 if ((num = ask_num(p, f, v, n, m, h)) != v) \ 226 ret = CMD_DIRTY; \ 227 v = num; 228 229 /* Ask for partition type */ 230 EDIT("Partition id ('0' to disable) ", ASK_HEX, pp->id, 0, 0xFF, PRT_printall); 231 232 #undef EDIT 233 return (ret); 234 } 235 int 236 Xselect(cmd, disk, mbr, tt, offset) 237 cmd_t *cmd; 238 disk_t *disk; 239 mbr_t *mbr; 240 mbr_t *tt; 241 int offset; 242 { 243 static int firstoff = 0; 244 int off; 245 int pn; 246 247 if (!isdigit(cmd->args[0])) { 248 printf("Invalid argument: %s <partition number>\n", cmd->cmd); 249 return (CMD_CONT); 250 } 251 252 pn = atoi(cmd->args); 253 off = mbr->part[pn].bs; 254 255 /* Sanity checks */ 256 if ((mbr->part[pn].id != DOSPTYP_EXTEND) && 257 (mbr->part[pn].id != DOSPTYP_EXTENDL)) { 258 printf("Partition %d is not an extended partition.\n", pn); 259 return (CMD_CONT); 260 } 261 262 if (firstoff == 0) 263 firstoff = off; 264 265 if (!off) { 266 printf("Loop to offset 0! Not selected.\n"); 267 return (CMD_CONT); 268 } else { 269 printf("Selected extended partition %d\n", pn); 270 printf("New MBR at offset %d.\n", off); 271 } 272 273 /* Recursion is beautifull! */ 274 USER_modify(disk, tt, off, firstoff); 275 return (CMD_CONT); 276 } 277 278 int 279 Xprint(cmd, disk, mbr, tt, offset) 280 cmd_t *cmd; 281 disk_t *disk; 282 mbr_t *mbr; 283 mbr_t *tt; 284 int offset; 285 { 286 287 DISK_printmetrics(disk); 288 printf("Offset: %d\t", offset); 289 MBR_print(mbr); 290 291 return (CMD_CONT); 292 } 293 294 int 295 Xwrite(cmd, disk, mbr, tt, offset) 296 cmd_t *cmd; 297 disk_t *disk; 298 mbr_t *mbr; 299 mbr_t *tt; 300 int offset; 301 { 302 char mbr_buf[DEV_BSIZE]; 303 int fd; 304 305 printf("Writing MBR at offset %d.\n", offset); 306 307 fd = DISK_open(disk->name, O_RDWR); 308 MBR_make(mbr, mbr_buf); 309 MBR_write(fd, offset, mbr_buf); 310 close(fd); 311 return (CMD_CLEAN); 312 } 313 314 int 315 Xquit(cmd, disk, r, tt, offset) 316 cmd_t *cmd; 317 disk_t *disk; 318 mbr_t *r; 319 mbr_t *tt; 320 int offset; 321 { 322 323 /* Nothing to do here */ 324 return (CMD_SAVE); 325 } 326 327 int 328 Xabort(cmd, disk, mbr, tt, offset) 329 cmd_t *cmd; 330 disk_t *disk; 331 mbr_t *mbr; 332 mbr_t *tt; 333 int offset; 334 { 335 exit(0); 336 337 /* NOTREACHED */ 338 return (CMD_CONT); 339 } 340 341 342 int 343 Xexit(cmd, disk, mbr, tt, offset) 344 cmd_t *cmd; 345 disk_t *disk; 346 mbr_t *mbr; 347 mbr_t *tt; 348 int offset; 349 { 350 351 /* Nothing to do here */ 352 return (CMD_EXIT); 353 } 354 355 int 356 Xhelp(cmd, disk, mbr, tt, offset) 357 cmd_t *cmd; 358 disk_t *disk; 359 mbr_t *mbr; 360 mbr_t *tt; 361 int offset; 362 { 363 cmd_table_t *cmd_table = cmd->table; 364 int i; 365 366 /* Hmm, print out cmd_table here... */ 367 for (i = 0; cmd_table[i].cmd != NULL; i++) 368 printf("\t%s\t\t%s\n", cmd_table[i].cmd, cmd_table[i].help); 369 return (CMD_CONT); 370 } 371 372 int 373 Xupdate(cmd, disk, mbr, tt, offset) 374 cmd_t *cmd; 375 disk_t *disk; 376 mbr_t *mbr; 377 mbr_t *tt; 378 int offset; 379 { 380 381 /* Update code */ 382 memcpy(mbr->code, tt->code, MBR_CODE_SIZE); 383 printf("Machine code updated.\n"); 384 return (CMD_DIRTY); 385 } 386 387 int 388 Xflag(cmd, disk, mbr, tt, offset) 389 cmd_t *cmd; 390 disk_t *disk; 391 mbr_t *mbr; 392 mbr_t *tt; 393 int offset; 394 { 395 int i, pn = -1; 396 397 /* Parse partition table entry number */ 398 if (!isdigit(cmd->args[0])) { 399 printf("Invalid argument: %s <partition number>\n", cmd->cmd); 400 return (CMD_CONT); 401 } 402 pn = atoi(cmd->args); 403 404 if (pn < 0 || pn > 3) { 405 printf("Invalid partition number.\n"); 406 return (CMD_CONT); 407 } 408 409 /* Set active flag */ 410 for (i = 0; i < 4; i++) { 411 if (i == pn) 412 mbr->part[i].flag = DOSACTIVE; 413 else 414 mbr->part[i].flag = 0x00; 415 } 416 417 printf("Partition %d marked active.\n", pn); 418 return (CMD_DIRTY); 419 } 420 421 int 422 Xmanual(cmd, disk, mbr, tt, offset) 423 cmd_t *cmd; 424 disk_t *disk; 425 mbr_t *mbr; 426 mbr_t *tt; 427 int offset; 428 { 429 char *pager = "/usr/bin/less"; 430 char *p; 431 sig_t opipe; 432 extern char manpage[]; 433 FILE *f; 434 435 opipe = signal(SIGPIPE, SIG_IGN); 436 if ((p = getenv("PAGER")) != NULL && (*p != '\0')) 437 pager = p; 438 f = popen(pager, "w"); 439 if (f) { 440 (void) fwrite(manpage, strlen(manpage), 1, f); 441 pclose(f); 442 } 443 444 (void)signal(SIGPIPE, opipe); 445 return (CMD_CONT); 446 } 447 448