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