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 *
| 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: devices.c,v 1.5 1995/05/05 23:47:38 jkh Exp $
| 7 * $Id: devices.c,v 1.6 1995/05/06 09:34:09 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 47/* Where we start displaying chunk information on the screen */ 48#define CHUNK_START_ROW 5 49 50/* Get all device information for a given device class */ 51Device * 52device_get_all(DeviceType which, int *ndevs) 53{ 54 char **names; 55 Device *devs = NULL; 56 57 *ndevs = 0; 58 if (which == DEVICE_TYPE_DISK || which == DEVICE_TYPE_ANY) { 59 if ((names = Disk_Names()) != NULL) { 60 int i; 61 62 for (i = 0; names[i]; i++) 63 ++*ndevs; 64 devs = safe_malloc(sizeof(Device) * (*ndevs + 1)); 65 for (i = 0; names[i]; i++) { 66 strcpy(devs[i].name, names[i]); 67 devs[i].type = DEVICE_TYPE_DISK; 68 } 69 devs[i].name[0] = '\0'; 70 free(names); 71 } 72 } 73 /* put detection for other classes here just as soon as I figure out how */ 74 return devs; 75} 76 77static struct chunk *chunk_info[10]; 78static int current_chunk; 79 80static void 81record_chunks(struct disk *d) 82{ 83 struct chunk *c1; 84 int i = 0; 85 int last_free = 0; 86 if (!d->chunks) 87 msgFatal("No chunk list found for %s!", d->name); 88 c1 = d->chunks->part; 89 while (c1) { 90 if (c1->type == unused && c1->size > last_free) { 91 last_free = c1->size; 92 current_chunk = i; 93 } 94 chunk_info[i++] = c1; 95 c1 = c1->next; 96 } 97 chunk_info[i] = NULL; 98} 99 100static void 101print_chunks(struct disk *d) 102{ 103 int row; 104 int i;
| 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 47/* Where we start displaying chunk information on the screen */ 48#define CHUNK_START_ROW 5 49 50/* Get all device information for a given device class */ 51Device * 52device_get_all(DeviceType which, int *ndevs) 53{ 54 char **names; 55 Device *devs = NULL; 56 57 *ndevs = 0; 58 if (which == DEVICE_TYPE_DISK || which == DEVICE_TYPE_ANY) { 59 if ((names = Disk_Names()) != NULL) { 60 int i; 61 62 for (i = 0; names[i]; i++) 63 ++*ndevs; 64 devs = safe_malloc(sizeof(Device) * (*ndevs + 1)); 65 for (i = 0; names[i]; i++) { 66 strcpy(devs[i].name, names[i]); 67 devs[i].type = DEVICE_TYPE_DISK; 68 } 69 devs[i].name[0] = '\0'; 70 free(names); 71 } 72 } 73 /* put detection for other classes here just as soon as I figure out how */ 74 return devs; 75} 76 77static struct chunk *chunk_info[10]; 78static int current_chunk; 79 80static void 81record_chunks(struct disk *d) 82{ 83 struct chunk *c1; 84 int i = 0; 85 int last_free = 0; 86 if (!d->chunks) 87 msgFatal("No chunk list found for %s!", d->name); 88 c1 = d->chunks->part; 89 while (c1) { 90 if (c1->type == unused && c1->size > last_free) { 91 last_free = c1->size; 92 current_chunk = i; 93 } 94 chunk_info[i++] = c1; 95 c1 = c1->next; 96 } 97 chunk_info[i] = NULL; 98} 99 100static void 101print_chunks(struct disk *d) 102{ 103 int row; 104 int i;
|
105 int b_attr = ColorDisplay ? A_BOLD : A_UNDERLINE;
| |
106 107 attrset(A_NORMAL); 108 mvaddstr(0, 0, "Disk name:\t");
| 105 106 attrset(A_NORMAL); 107 mvaddstr(0, 0, "Disk name:\t");
|
109 attrset(b_attr); addstr(d->name); attrset(A_NORMAL);
| 108 attrset(A_REVERSE); addstr(d->name); attrset(A_NORMAL);
|
110 attrset(A_REVERSE); mvaddstr(0, 55, "Master Partition Editor"); attrset(A_NORMAL); 111 mvprintw(1, 0, 112 "BIOS Geometry:\t%lu cyls/%lu heads/%lu sectors", 113 d->bios_cyl, d->bios_hd, d->bios_sect); 114 mvprintw(3, 1, "%10s %10s %10s %8s %8s %8s %8s %8s", 115 "Offset", "Size", "End", "Name", "PType", "Desc", 116 "Subtype", "Flags"); 117 for (i = 0, row = CHUNK_START_ROW; chunk_info[i]; i++, row++) { 118 if (i == current_chunk)
| 109 attrset(A_REVERSE); mvaddstr(0, 55, "Master Partition Editor"); attrset(A_NORMAL); 110 mvprintw(1, 0, 111 "BIOS Geometry:\t%lu cyls/%lu heads/%lu sectors", 112 d->bios_cyl, d->bios_hd, d->bios_sect); 113 mvprintw(3, 1, "%10s %10s %10s %8s %8s %8s %8s %8s", 114 "Offset", "Size", "End", "Name", "PType", "Desc", 115 "Subtype", "Flags"); 116 for (i = 0, row = CHUNK_START_ROW; chunk_info[i]; i++, row++) { 117 if (i == current_chunk)
|
119 attrset(b_attr);
| 118 attrset(A_REVERSE);
|
120 mvprintw(row, 2, "%10lu %10lu %10lu %8s %8d %8s %8d %6lx", 121 chunk_info[i]->offset, chunk_info[i]->size, 122 chunk_info[i]->end, chunk_info[i]->name, 123 chunk_info[i]->type, chunk_n[chunk_info[i]->type], 124 chunk_info[i]->subtype, chunk_info[i]->flags); 125 if (i == current_chunk) 126 attrset(A_NORMAL); 127 } 128} 129 130static void 131print_command_summary() 132{
| 119 mvprintw(row, 2, "%10lu %10lu %10lu %8s %8d %8s %8d %6lx", 120 chunk_info[i]->offset, chunk_info[i]->size, 121 chunk_info[i]->end, chunk_info[i]->name, 122 chunk_info[i]->type, chunk_n[chunk_info[i]->type], 123 chunk_info[i]->subtype, chunk_info[i]->flags); 124 if (i == current_chunk) 125 attrset(A_NORMAL); 126 } 127} 128 129static void 130print_command_summary() 131{
|
133 int b_attr = ColorDisplay ? A_BOLD : A_UNDERLINE; 134
| |
135 mvprintw(14, 0, "The following commands are supported (in upper or lower case):"); 136 mvprintw(16, 0, "A = Use Entire Disk B = Bad Block Scan C = Create Partition"); 137 mvprintw(17, 0, "D = Delete Partition G = Set BIOS Geometry S = Set Bootable"); 138 mvprintw(18, 0, "U = Undo All Changes W = `Wizard' Mode ESC = Proceed to next screen"); 139 mvprintw(20, 0, "The currently selected partition is displayed in ");
| 132 mvprintw(14, 0, "The following commands are supported (in upper or lower case):"); 133 mvprintw(16, 0, "A = Use Entire Disk B = Bad Block Scan C = Create Partition"); 134 mvprintw(17, 0, "D = Delete Partition G = Set BIOS Geometry S = Set Bootable"); 135 mvprintw(18, 0, "U = Undo All Changes W = `Wizard' Mode ESC = Proceed to next screen"); 136 mvprintw(20, 0, "The currently selected partition is displayed in ");
|
140 attrset(b_attr); addstr(ColorDisplay ? "bold" : "underline"); attrset(A_NORMAL);
| 137 attrset(A_REVERSE); addstr("reverse video"); attrset(A_NORMAL);
|
141 move(0, 0); 142} 143 144struct disk * 145device_slice_disk(struct disk *d) 146{ 147 char *p; 148 int key = 0; 149 Boolean chunking; 150 char *msg = NULL; 151 char name[40]; 152 153 dialog_clear(); 154 chunking = TRUE; 155 strncpy(name, d->name, 40); 156 keypad(stdscr, TRUE); 157 158 record_chunks(d); 159 while (chunking) { 160 clear(); 161 print_chunks(d); 162 print_command_summary(); 163 if (msg) { 164 standout(); mvprintw(23, 0, msg); standend(); 165 beep(); 166 msg = NULL; 167 } 168 refresh(); 169 170 key = toupper(getch()); 171 switch (key) { 172 case KEY_UP: 173 case '-': 174 if (current_chunk != 0) 175 --current_chunk; 176 break; 177 178 case KEY_DOWN: 179 case '+': 180 case '\r': 181 case '\n': 182 if (chunk_info[current_chunk + 1]) 183 ++current_chunk; 184 break; 185 186 case KEY_HOME: 187 current_chunk = 0; 188 break; 189 190 case KEY_END: 191 while (chunk_info[current_chunk + 1]) 192 ++current_chunk; 193 break; 194 195 case KEY_F(1): 196 case '?': 197 systemDisplayFile("slice.hlp"); 198 break; 199 200 case 'A': 201 All_FreeBSD(d); 202 record_chunks(d); 203 break; 204 205 case 'B': 206 if (chunk_info[current_chunk]->type != freebsd) 207 msg = "Can only scan for bad blocks in FreeBSD partition."; 208 else if (strncmp(name, "sd", 2) || 209 !msgYesNo("This typically makes sense only for ESDI, IDE or MFM drives.\nAre you sure you want to do this on a SCSI disk?")) 210 chunk_info[current_chunk]->flags |= CHUNK_BAD144; 211 break; 212 213 case 'C': 214 if (chunk_info[current_chunk]->type != unused) 215 msg = "Partition in use, delete it first or move to an unused one."; 216 else { 217 char *val, tmp[20]; 218 int size; 219 220 snprintf(tmp, 20, "%d", chunk_info[current_chunk]->size); 221 val = msgGetInput(tmp, "Please specify size for new FreeBSD partition"); 222 if (val && (size = strtol(val, 0, 0)) > 0) { 223 Create_Chunk(d, chunk_info[current_chunk]->offset, 224 size, 225 freebsd, 226 3, 227 (chunk_info[current_chunk]->flags & 228 CHUNK_ALIGN)); 229 record_chunks(d); 230 } 231 } 232 break; 233 234 case 'D': 235 if (chunk_info[current_chunk]->type == unused) 236 msg = "Partition is already unused!"; 237 else { 238 Delete_Chunk(d, chunk_info[current_chunk]); 239 record_chunks(d); 240 } 241 break; 242 243 case 'G': 244 /* Set geometry */ 245 break; 246 247 case 'S': 248 /* Set Bootable */ 249 break; 250 251 case 'U': 252 Free_Disk(d); 253 d = Open_Disk(name); 254 if (!d) 255 msgFatal("Can't reopen disk %s!", name); 256 record_chunks(d); 257 break; 258 259 case 'W': 260 if (!msgYesNo("Are you sure you want to go into Wizard mode?\nNo seat belts whatsoever are provided!")) { 261 clear(); 262 dialog_clear(); 263 end_dialog(); 264 DialogActive = FALSE; 265 slice_wizard(d); 266 clear(); 267 dialog_clear(); 268 DialogActive = TRUE; 269 record_chunks(d); 270 } 271 else 272 msg = "Wise choice!"; 273 break; 274 275 case 27: /* ESC */ 276 chunking = FALSE; 277 break; 278 279 default: 280 beep(); 281 msg = "Type F1 or ? for help"; 282 break; 283 } 284 } 285 p = CheckRules(d); 286 if (p) { 287 msgConfirm(p); 288 free(p); 289 } 290 clear(); 291 refresh(); 292 return d; 293} 294 295/* 296 * Create a menu listing all the devices in the system. The pass-in menu 297 * is expected to be a "prototype" from which the new menu is cloned. 298 */ 299DMenu * 300device_create_disk_menu(DMenu *menu, Device **rdevs, int (*hook)()) 301{ 302 Device *devices; 303 int numdevs; 304 305 devices = device_get_all(DEVICE_TYPE_DISK, &numdevs); 306 *rdevs = devices; 307 if (!devices) { 308 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."); 309 return NULL; 310 } 311 else { 312 Device *start; 313 DMenu *tmp; 314 int i; 315 316 tmp = (DMenu *)safe_malloc(sizeof(DMenu) + 317 (sizeof(DMenuItem) * (numdevs + 1))); 318 bcopy(menu, tmp, sizeof(DMenu)); 319 for (start = devices, i = 0; start->name[0]; start++, i++) { 320 tmp->items[i].title = start->name; 321 if (!strncmp(start->name, "sd", 2)) 322 tmp->items[i].prompt = "SCSI disk"; 323 else if (!strncmp(start->name, "wd", 2)) 324 tmp->items[i].prompt = "IDE/ESDI/MFM/ST506 disk"; 325 else 326 msgFatal("Unknown disk type: %s!", start->name); 327 tmp->items[i].type = DMENU_CALL; 328 tmp->items[i].ptr = hook; 329 tmp->items[i].disabled = FALSE; 330 } 331 tmp->items[i].type = DMENU_NOP; 332 tmp->items[i].title = NULL; 333 return tmp; 334 } 335}
| 138 move(0, 0); 139} 140 141struct disk * 142device_slice_disk(struct disk *d) 143{ 144 char *p; 145 int key = 0; 146 Boolean chunking; 147 char *msg = NULL; 148 char name[40]; 149 150 dialog_clear(); 151 chunking = TRUE; 152 strncpy(name, d->name, 40); 153 keypad(stdscr, TRUE); 154 155 record_chunks(d); 156 while (chunking) { 157 clear(); 158 print_chunks(d); 159 print_command_summary(); 160 if (msg) { 161 standout(); mvprintw(23, 0, msg); standend(); 162 beep(); 163 msg = NULL; 164 } 165 refresh(); 166 167 key = toupper(getch()); 168 switch (key) { 169 case KEY_UP: 170 case '-': 171 if (current_chunk != 0) 172 --current_chunk; 173 break; 174 175 case KEY_DOWN: 176 case '+': 177 case '\r': 178 case '\n': 179 if (chunk_info[current_chunk + 1]) 180 ++current_chunk; 181 break; 182 183 case KEY_HOME: 184 current_chunk = 0; 185 break; 186 187 case KEY_END: 188 while (chunk_info[current_chunk + 1]) 189 ++current_chunk; 190 break; 191 192 case KEY_F(1): 193 case '?': 194 systemDisplayFile("slice.hlp"); 195 break; 196 197 case 'A': 198 All_FreeBSD(d); 199 record_chunks(d); 200 break; 201 202 case 'B': 203 if (chunk_info[current_chunk]->type != freebsd) 204 msg = "Can only scan for bad blocks in FreeBSD partition."; 205 else if (strncmp(name, "sd", 2) || 206 !msgYesNo("This typically makes sense only for ESDI, IDE or MFM drives.\nAre you sure you want to do this on a SCSI disk?")) 207 chunk_info[current_chunk]->flags |= CHUNK_BAD144; 208 break; 209 210 case 'C': 211 if (chunk_info[current_chunk]->type != unused) 212 msg = "Partition in use, delete it first or move to an unused one."; 213 else { 214 char *val, tmp[20]; 215 int size; 216 217 snprintf(tmp, 20, "%d", chunk_info[current_chunk]->size); 218 val = msgGetInput(tmp, "Please specify size for new FreeBSD partition"); 219 if (val && (size = strtol(val, 0, 0)) > 0) { 220 Create_Chunk(d, chunk_info[current_chunk]->offset, 221 size, 222 freebsd, 223 3, 224 (chunk_info[current_chunk]->flags & 225 CHUNK_ALIGN)); 226 record_chunks(d); 227 } 228 } 229 break; 230 231 case 'D': 232 if (chunk_info[current_chunk]->type == unused) 233 msg = "Partition is already unused!"; 234 else { 235 Delete_Chunk(d, chunk_info[current_chunk]); 236 record_chunks(d); 237 } 238 break; 239 240 case 'G': 241 /* Set geometry */ 242 break; 243 244 case 'S': 245 /* Set Bootable */ 246 break; 247 248 case 'U': 249 Free_Disk(d); 250 d = Open_Disk(name); 251 if (!d) 252 msgFatal("Can't reopen disk %s!", name); 253 record_chunks(d); 254 break; 255 256 case 'W': 257 if (!msgYesNo("Are you sure you want to go into Wizard mode?\nNo seat belts whatsoever are provided!")) { 258 clear(); 259 dialog_clear(); 260 end_dialog(); 261 DialogActive = FALSE; 262 slice_wizard(d); 263 clear(); 264 dialog_clear(); 265 DialogActive = TRUE; 266 record_chunks(d); 267 } 268 else 269 msg = "Wise choice!"; 270 break; 271 272 case 27: /* ESC */ 273 chunking = FALSE; 274 break; 275 276 default: 277 beep(); 278 msg = "Type F1 or ? for help"; 279 break; 280 } 281 } 282 p = CheckRules(d); 283 if (p) { 284 msgConfirm(p); 285 free(p); 286 } 287 clear(); 288 refresh(); 289 return d; 290} 291 292/* 293 * Create a menu listing all the devices in the system. The pass-in menu 294 * is expected to be a "prototype" from which the new menu is cloned. 295 */ 296DMenu * 297device_create_disk_menu(DMenu *menu, Device **rdevs, int (*hook)()) 298{ 299 Device *devices; 300 int numdevs; 301 302 devices = device_get_all(DEVICE_TYPE_DISK, &numdevs); 303 *rdevs = devices; 304 if (!devices) { 305 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."); 306 return NULL; 307 } 308 else { 309 Device *start; 310 DMenu *tmp; 311 int i; 312 313 tmp = (DMenu *)safe_malloc(sizeof(DMenu) + 314 (sizeof(DMenuItem) * (numdevs + 1))); 315 bcopy(menu, tmp, sizeof(DMenu)); 316 for (start = devices, i = 0; start->name[0]; start++, i++) { 317 tmp->items[i].title = start->name; 318 if (!strncmp(start->name, "sd", 2)) 319 tmp->items[i].prompt = "SCSI disk"; 320 else if (!strncmp(start->name, "wd", 2)) 321 tmp->items[i].prompt = "IDE/ESDI/MFM/ST506 disk"; 322 else 323 msgFatal("Unknown disk type: %s!", start->name); 324 tmp->items[i].type = DMENU_CALL; 325 tmp->items[i].ptr = hook; 326 tmp->items[i].disabled = FALSE; 327 } 328 tmp->items[i].type = DMENU_NOP; 329 tmp->items[i].title = NULL; 330 return tmp; 331 } 332}
|