Deleted Added
full compact
devices.c (8307) devices.c (8314)
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}