1 /* $OpenBSD: user.c,v 1.55 2021/05/15 15:20:17 krw Exp $ */ 2 3 /* 4 * Copyright (c) 1997 Tobias Weingartner 5 * 6 * Permission to use, copy, modify, and distribute this software for any 7 * purpose with or without fee is hereby granted, provided that the above 8 * copyright notice and this permission notice appear in all copies. 9 * 10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 */ 18 19 #include <sys/types.h> 20 #include <sys/disklabel.h> 21 22 #include <err.h> 23 #include <fcntl.h> 24 #include <stdio.h> 25 #include <string.h> 26 #include <unistd.h> 27 28 #include "part.h" 29 #include "mbr.h" 30 #include "misc.h" 31 #include "cmd.h" 32 #include "user.h" 33 #include "gpt.h" 34 #include "disk.h" 35 36 /* Our command table */ 37 struct cmd cmd_table[] = { 38 {"help", 1, Xhelp, "Command help list"}, 39 {"manual", 1, Xmanual, "Show entire OpenBSD man page for fdisk"}, 40 {"reinit", 1, Xreinit, "Re-initialize loaded MBR (to defaults)"}, 41 {"setpid", 1, Xsetpid, "Set the identifier of a given table entry"}, 42 {"disk", 0, Xdisk, "Edit current drive stats"}, 43 {"edit", 1, Xedit, "Edit given table entry"}, 44 {"flag", 1, Xflag, "Flag given table entry as bootable"}, 45 {"update", 0, Xupdate, "Update machine code in loaded MBR"}, 46 {"select", 0, Xselect, "Select extended partition table entry MBR"}, 47 {"swap", 1, Xswap, "Swap two partition entries"}, 48 {"print", 1, Xprint, "Print loaded MBR partition table"}, 49 {"write", 1, Xwrite, "Write loaded MBR to disk"}, 50 {"exit", 1, Xexit, "Exit edit of current MBR, without saving changes"}, 51 {"quit", 1, Xquit, "Quit edit of current MBR, saving current changes"}, 52 {"abort", 1, Xabort, "Abort program without saving current changes"}, 53 {NULL, 0, NULL, NULL} 54 }; 55 56 57 int modified; 58 59 void 60 USER_edit(off_t offset, off_t reloff) 61 { 62 static int editlevel; 63 struct dos_mbr dos_mbr; 64 struct mbr mbr; 65 char *cmd, *args; 66 int i, st, efi, error; 67 68 /* One level deeper */ 69 editlevel += 1; 70 71 /* Read MBR & partition */ 72 error = MBR_read(offset, &dos_mbr); 73 if (error == -1) 74 goto done; 75 76 /* Parse the sucker */ 77 MBR_parse(&dos_mbr, offset, reloff, &mbr); 78 79 if (editlevel == 1) { 80 memset(&gh, 0, sizeof(gh)); 81 memset(&gp, 0, sizeof(gp)); 82 efi = MBR_protective_mbr(&mbr); 83 if (efi != -1) 84 GPT_read(ANYGPT); 85 } 86 87 printf("Enter 'help' for information\n"); 88 89 /* Edit cycle */ 90 again: 91 do { 92 printf("%s%s: %d> ", disk.name, modified ? "*" : "", editlevel); 93 fflush(stdout); 94 ask_cmd(&cmd, &args); 95 96 if (cmd[0] == '\0') 97 continue; 98 for (i = 0; cmd_table[i].cmd != NULL; i++) 99 if (strstr(cmd_table[i].cmd, cmd) == cmd_table[i].cmd) 100 break; 101 102 /* Quick hack to put in '?' == 'help' */ 103 if (!strcmp(cmd, "?")) 104 i = 0; 105 106 /* Check for valid command */ 107 if ((cmd_table[i].cmd == NULL) || (letoh64(gh.gh_sig) == 108 GPTSIGNATURE && cmd_table[i].gpt == 0)) { 109 printf("Invalid command '%s'. Try 'help'.\n", cmd); 110 continue; 111 } 112 113 /* Call function */ 114 st = cmd_table[i].fcn(args, &mbr); 115 116 /* Update status */ 117 if (st == CMD_EXIT) 118 break; 119 if (st == CMD_SAVE) 120 break; 121 if (st == CMD_CLEAN) 122 modified = 0; 123 if (st == CMD_DIRTY) 124 modified = 1; 125 } while (1); 126 127 /* Write out MBR */ 128 if (modified) { 129 if (st == CMD_SAVE) { 130 if (Xwrite(NULL, &mbr) == CMD_CONT) 131 goto again; 132 } else 133 printf("Aborting changes to current MBR.\n"); 134 } 135 136 done: 137 /* One level less */ 138 editlevel -= 1; 139 } 140 141 void 142 USER_print_disk(int verbosity) 143 { 144 off_t offset, firstoff; 145 int i, efi, error; 146 struct dos_mbr dos_mbr; 147 struct mbr mbr; 148 149 offset = firstoff = 0; 150 151 do { 152 error = MBR_read(offset, &dos_mbr); 153 if (error == -1) 154 break; 155 MBR_parse(&dos_mbr, offset, firstoff, &mbr); 156 if (offset == 0) { 157 efi = MBR_protective_mbr(&mbr); 158 if (efi == -1) { 159 /* No valid 0xEE partition means no GPT. */ 160 if (verbosity == VERBOSE) { 161 printf("Primary GPT:\nNot Found\n"); 162 printf("\nSecondary GPT:\nNot Found\n"); 163 } 164 } else if (verbosity == TERSE) { 165 /* Should already have read one of Primary/Secondary GPT. */ 166 if (letoh64(gh.gh_sig) == GPTSIGNATURE) { 167 GPT_print("s", verbosity); 168 return; 169 } 170 } else { 171 /*. Read & print both primary and secondary GPT. */ 172 printf("Primary GPT:\n"); 173 GPT_read(PRIMARYGPT); 174 if (letoh64(gh.gh_sig) == GPTSIGNATURE) 175 GPT_print("s", verbosity); 176 else 177 printf("\tNot Found\n"); 178 printf("\nSecondary GPT:\n"); 179 GPT_read(SECONDARYGPT); 180 if (letoh64(gh.gh_sig) == GPTSIGNATURE) 181 GPT_print("s", verbosity); 182 else 183 printf("\tNot Found\n"); 184 } 185 if (verbosity == VERBOSE) 186 printf("\nMBR:\n"); 187 } 188 189 MBR_print(&mbr, NULL); 190 191 /* Print out extended partitions too */ 192 for (offset = i = 0; i < 4; i++) 193 if (mbr.part[i].id == DOSPTYP_EXTEND || 194 mbr.part[i].id == DOSPTYP_EXTENDL) { 195 offset = (off_t)mbr.part[i].bs; 196 if (firstoff == 0) 197 firstoff = offset; 198 } 199 } while (offset); 200 } 201