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