disks.c revision 9202
1/* 2 * The new sysinstall program. 3 * 4 * This is probably the last program in the `sysinstall' line - the next 5 * generation being essentially a complete rewrite. 6 * 7 * $Id: disks.c,v 1.30.2.7 1995/06/08 09:48:31 jkh Exp $ 8 * 9 * Copyright (c) 1995 10 * Jordan Hubbard. All rights reserved. 11 * 12 * Redistribution and use in source and binary forms, with or without 13 * modification, are permitted provided that the following conditions 14 * are met: 15 * 1. Redistributions of source code must retain the above copyright 16 * notice, this list of conditions and the following disclaimer, 17 * verbatim and that no modifications are made prior to this 18 * point in the file. 19 * 2. Redistributions in binary form must reproduce the above copyright 20 * notice, this list of conditions and the following disclaimer in the 21 * documentation and/or other materials provided with the distribution. 22 * 3. All advertising materials mentioning features or use of this software 23 * must display the following acknowledgement: 24 * This product includes software developed by Jordan Hubbard 25 * for the FreeBSD Project. 26 * 4. The name of Jordan Hubbard or the FreeBSD project may not be used to 27 * endorse or promote products derived from this software without specific 28 * prior written permission. 29 * 30 * THIS SOFTWARE IS PROVIDED BY JORDAN HUBBARD ``AS IS'' AND 31 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 32 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 33 * ARE DISCLAIMED. IN NO EVENT SHALL JORDAN HUBBARD OR HIS PETS BE LIABLE 34 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 35 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 36 * OR SERVICES; LOSS OF USE, DATA, LIFE OR PROFITS; OR BUSINESS INTERRUPTION) 37 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 38 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 39 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 40 * SUCH DAMAGE. 41 * 42 */ 43 44#include "sysinstall.h" 45#include <ctype.h> 46#include <sys/disklabel.h> 47 48/* Where we start displaying chunk information on the screen */ 49#define CHUNK_START_ROW 5 50 51/* Where we keep track of MBR chunks */ 52static struct chunk *chunk_info[10]; 53static int current_chunk; 54 55static void 56record_chunks(Disk *d) 57{ 58 struct chunk *c1; 59 int i = 0; 60 int last_free = 0; 61 if (!d->chunks) 62 msgFatal("No chunk list found for %s!", d->name); 63 c1 = d->chunks->part; 64 current_chunk = 0; 65 while (c1) { 66 if (c1->type == unused && c1->size > last_free) { 67 last_free = c1->size; 68 current_chunk = i; 69 } 70 chunk_info[i++] = c1; 71 c1 = c1->next; 72 } 73 chunk_info[i] = NULL; 74} 75 76static void 77print_chunks(Disk *d) 78{ 79 int row; 80 int i; 81 82 if ((!d->bios_cyl || d->bios_cyl > 65536) || (!d->bios_hd || d->bios_hd > 256) || (!d->bios_sect || d->bios_sect >= 64)) 83 msgConfirm("WARNING: The detected geometry is incorrect! Please adjust it to\nthe correct values manually with the (G)eometry command. If you are\nunsure about the correct geometry (which may be \"translated\"), please\nconsult the Hardware Guide in the Documentation submenu."); 84 85 attrset(A_NORMAL); 86 mvaddstr(0, 0, "Disk name:\t"); 87 clrtobot(); 88 attrset(A_REVERSE); addstr(d->name); attrset(A_NORMAL); 89 attrset(A_REVERSE); mvaddstr(0, 55, "FDISK Partition Editor"); attrset(A_NORMAL); 90 mvprintw(1, 0, 91 "BIOS Geometry:\t%lu cyls/%lu heads/%lu sectors", 92 d->bios_cyl, d->bios_hd, d->bios_sect); 93 mvprintw(3, 1, "%10s %10s %10s %8s %8s %8s %8s %8s", 94 "Offset", "Size", "End", "Name", "PType", "Desc", 95 "Subtype", "Flags"); 96 for (i = 0, row = CHUNK_START_ROW; chunk_info[i]; i++, row++) { 97 if (i == current_chunk) 98 attrset(A_REVERSE); 99 mvprintw(row, 2, "%10ld %10lu %10lu %8s %8d %8s %8d\t%-6s", 100 chunk_info[i]->offset, chunk_info[i]->size, 101 chunk_info[i]->end, chunk_info[i]->name, 102 chunk_info[i]->type, chunk_n[chunk_info[i]->type], 103 chunk_info[i]->subtype, ShowChunkFlags(chunk_info[i])); 104 if (i == current_chunk) 105 attrset(A_NORMAL); 106 } 107} 108 109static void 110print_command_summary() 111{ 112 mvprintw(14, 0, "The following commands are supported (in upper or lower case):"); 113 mvprintw(16, 0, "A = Use Entire Disk B = Bad Block Scan C = Create Partition"); 114 mvprintw(17, 0, "D = Delete Partition G = Set BIOS Geometry S = Set Bootable"); 115 mvprintw(18, 0, "U = Undo All Changes Q = Finish"); 116 mvprintw(20, 0, "The currently selected partition is displayed in "); 117 attrset(A_REVERSE); addstr("reverse"); attrset(A_NORMAL); addstr(" video."); 118 mvprintw(21, 0, "Use F1 or ? to get more help, arrow keys to move."); 119 move(0, 0); 120} 121 122static Disk * 123diskPartition(Disk *d) 124{ 125 char *p; 126 int key = 0; 127 Boolean chunking; 128 char *msg = NULL; 129 char name[40]; 130 131 chunking = TRUE; 132 strncpy(name, d->name, 40); 133 keypad(stdscr, TRUE); 134 135 clear(); 136 record_chunks(d); 137 while (chunking) { 138 print_chunks(d); 139 print_command_summary(); 140 if (msg) { 141 standout(); mvprintw(23, 0, msg); standend(); 142 beep(); 143 msg = NULL; 144 } 145 146 key = toupper(getch()); 147 switch (key) { 148 149 case '\014': /* ^L */ 150 clear(); 151 continue; 152 153 case KEY_UP: 154 case '-': 155 if (current_chunk != 0) 156 --current_chunk; 157 break; 158 159 case KEY_DOWN: 160 case '+': 161 case '\r': 162 case '\n': 163 if (chunk_info[current_chunk + 1]) 164 ++current_chunk; 165 break; 166 167 case KEY_HOME: 168 current_chunk = 0; 169 break; 170 171 case KEY_END: 172 while (chunk_info[current_chunk + 1]) 173 ++current_chunk; 174 break; 175 176 case KEY_F(1): 177 case '?': 178 systemDisplayFile("slice.hlp"); 179 break; 180 181 case 'A': 182 All_FreeBSD(d); 183 record_chunks(d); 184 break; 185 186 case 'B': 187 if (chunk_info[current_chunk]->type != freebsd) 188 msg = "Can only scan for bad blocks in FreeBSD partition."; 189 else if (strncmp(name, "sd", 2) || 190 !msgYesNo("This typically makes sense only for ESDI, IDE or MFM drives.\nAre you sure you want to do this on a SCSI disk?")) 191 if (chunk_info[current_chunk]->flags & CHUNK_BAD144) 192 chunk_info[current_chunk]->flags &= ~CHUNK_BAD144; 193 else 194 chunk_info[current_chunk]->flags |= CHUNK_BAD144; 195 break; 196 197 case 'C': 198 if (chunk_info[current_chunk]->type != unused) 199 msg = "Partition in use, delete it first or move to an unused one."; 200 else { 201 char *val, tmp[20], *cp; 202 int size; 203 204 snprintf(tmp, 20, "%d", chunk_info[current_chunk]->size); 205 val = msgGetInput(tmp, "Please specify the size for new FreeBSD partition in blocks, or append\na trailing `M' for megabytes (e.g. 20M)."); 206 if (val && (size = strtol(val, &cp, 0)) > 0) { 207 if (*cp && toupper(*cp) == 'M') 208 size *= 2048; 209 Create_Chunk(d, chunk_info[current_chunk]->offset, 210 size, 211 freebsd, 212 3, 213 (chunk_info[current_chunk]->flags & 214 CHUNK_ALIGN)); 215 record_chunks(d); 216 } 217 } 218 break; 219 220 case 'D': 221 if (chunk_info[current_chunk]->type == unused) 222 msg = "Partition is already unused!"; 223 else { 224 Delete_Chunk(d, chunk_info[current_chunk]); 225 record_chunks(d); 226 } 227 break; 228 229 case 'G': { 230 char *val, geometry[80]; 231 232 snprintf(geometry, 80, "%lu/%lu/%lu", 233 d->bios_cyl, d->bios_hd, d->bios_sect); 234 val = msgGetInput(geometry, 235"Please specify the new geometry in cyl/hd/sect format.\nDon't forget to use the two slash (/) separator characters!\nIt's not possible to parse the field without them."); 236 if (val) { 237 d->bios_cyl = strtol(val, &val, 0); 238 d->bios_hd = strtol(val + 1, &val, 0); 239 d->bios_sect = strtol(val + 1, 0, 0); 240 } 241 } 242 break; 243 244 case 'S': 245 /* Set Bootable */ 246 chunk_info[current_chunk]->flags |= CHUNK_ACTIVE; 247 break; 248 249 case 'U': 250 Free_Disk(d); 251 d = Open_Disk(name); 252 if (!d) 253 msgFatal("Can't reopen disk %s!", name); 254 record_chunks(d); 255 break; 256 257 case 'W': 258 if (!msgYesNo("Are you sure you want to go into Wizard mode?\nNo seat belts whatsoever are provided!")) { 259 dialog_clear(); 260 end_dialog(); 261 DialogActive = FALSE; 262 slice_wizard(d); 263 dialog_clear(); 264 DialogActive = TRUE; 265 record_chunks(d); 266 } 267 else 268 msg = "Wise choice!"; 269 break; 270 271 case 'Q': 272 chunking = FALSE; 273 break; 274 275 default: 276 beep(); 277 msg = "Type F1 or ? for help"; 278 break; 279 } 280 } 281 p = CheckRules(d); 282 if (p) { 283 msgConfirm(p); 284 free(p); 285 } 286 dialog_clear(); 287 variable_set2(DISK_PARTITIONED, "yes"); 288 return d; 289} 290 291static int 292partitionHook(char *str) 293{ 294 Device **devs = NULL; 295 296 /* Clip garbage off the ends */ 297 string_prune(str); 298 str = string_skipwhite(str); 299 /* Try and open all the disks */ 300 while (str) { 301 char *cp; 302 303 cp = index(str, '\n'); 304 if (cp) 305 *cp++ = 0; 306 if (!*str) { 307 beep(); 308 return 0; 309 } 310 devs = deviceFind(str, DEVICE_TYPE_DISK); 311 if (!devs) { 312 msgConfirm("Unable to find disk %s!", str); 313 return 0; 314 } 315 else if (devs[1]) 316 msgConfirm("Bizarre multiple match for %s!", str); 317 devs[0]->private = diskPartition((Disk *)devs[0]->private); 318 devs[0]->enabled = TRUE; 319 str = cp; 320 } 321 return devs ? 1 : 0; 322} 323 324int 325diskPartitionEditor(char *str) 326{ 327 DMenu *menu; 328 Device **devs; 329 int cnt; 330 331 devs = deviceFind(NULL, DEVICE_TYPE_DISK); 332 cnt = deviceCount(devs); 333 if (!cnt) { 334 msgConfirm("No disks found! Please verify that your disk controller is being\nproperly probed at boot time. See the Hardware Guide on the Documentation menu\nfor clues on diagnosing this type of problem."); 335 return 0; 336 } 337 else if (cnt == 1) { 338 devs[0]->private = diskPartition((Disk *)devs[0]->private); 339 devs[0]->enabled = TRUE; 340 } 341 else { 342 menu = deviceCreateMenu(&MenuDiskDevices, DEVICE_TYPE_DISK, partitionHook); 343 if (!menu) 344 msgConfirm("No devices suitable for installation found!\n\nPlease verify that your disk controller (and attached drives) were detected properly. This can be done by selecting the ``Bootmsg'' option on the main menu and reviewing the boot messages carefully."); 345 else { 346 dmenuOpenSimple(menu); 347 free(menu); 348 } 349 } 350 return 0; 351} 352