Deleted Added
full compact
disks.c (8581) disks.c (8589)
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: disks.c,v 1.20 1995/05/17 14:39:38 jkh Exp $
7 * $Id: disks.c,v 1.21 1995/05/17 16:16:07 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
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 dialog_clear();
82 clear();
83 attrset(A_NORMAL);
84 mvaddstr(0, 0, "Disk name:\t");
85 attrset(A_REVERSE); addstr(d->name); attrset(A_NORMAL);
86 attrset(A_REVERSE); mvaddstr(0, 55, "Master Partition Editor"); attrset(A_NORMAL);
87 mvprintw(1, 0,
88 "BIOS Geometry:\t%lu cyls/%lu heads/%lu sectors",
89 d->bios_cyl, d->bios_hd, d->bios_sect);
90 mvprintw(3, 1, "%10s %10s %10s %8s %8s %8s %8s %8s",
91 "Offset", "Size", "End", "Name", "PType", "Desc",
92 "Subtype", "Flags");
93 for (i = 0, row = CHUNK_START_ROW; chunk_info[i]; i++, row++) {
94 if (i == current_chunk)
95 attrset(A_REVERSE);
96 mvprintw(row, 2, "%10lu %10lu %10lu %8s %8d %8s %8d %6lx",
97 chunk_info[i]->offset, chunk_info[i]->size,
98 chunk_info[i]->end, chunk_info[i]->name,
99 chunk_info[i]->type, chunk_n[chunk_info[i]->type],
100 chunk_info[i]->subtype, chunk_info[i]->flags);
101 if (i == current_chunk)
102 attrset(A_NORMAL);
103 }
104}
105
106static void
107print_command_summary()
108{
109 mvprintw(14, 0, "The following commands are supported (in upper or lower case):");
110 mvprintw(16, 0, "A = Use Entire Disk B = Bad Block Scan C = Create Partition");
111 mvprintw(17, 0, "D = Delete Partition G = Set BIOS Geometry S = Set Bootable");
112 mvprintw(18, 0, "U = Undo All Changes W = `Wizard' Mode ESC = Exit this screen");
113 mvprintw(20, 0, "The currently selected partition is displayed in ");
114 attrset(A_REVERSE); addstr("reverse video."); attrset(A_NORMAL);
115 mvprintw(21, 0, "Use F1 or ? to get more help, arrow keys to move.");
116 move(0, 0);
117}
118
119static Disk *
120diskPartition(Disk *d)
121{
122 char *p;
123 int key = 0;
124 Boolean chunking;
125 char *msg = NULL;
126 char name[40];
127
128 chunking = TRUE;
129 strncpy(name, d->name, 40);
130 keypad(stdscr, TRUE);
131
132 record_chunks(d);
133 while (chunking) {
134 print_chunks(d);
135 print_command_summary();
136 if (msg) {
137 standout(); mvprintw(23, 0, msg); standend();
138 beep();
139 msg = NULL;
140 }
141
142 key = toupper(getch());
143 switch (key) {
144 case KEY_UP:
145 case '-':
146 if (current_chunk != 0)
147 --current_chunk;
148 break;
149
150 case KEY_DOWN:
151 case '+':
152 case '\r':
153 case '\n':
154 if (chunk_info[current_chunk + 1])
155 ++current_chunk;
156 break;
157
158 case KEY_HOME:
159 current_chunk = 0;
160 break;
161
162 case KEY_END:
163 while (chunk_info[current_chunk + 1])
164 ++current_chunk;
165 break;
166
167 case KEY_F(1):
168 case '?':
169 systemDisplayFile("slice.hlp");
170 break;
171
172 case 'A':
173 All_FreeBSD(d);
174 record_chunks(d);
175 break;
176
177 case 'B':
178 if (chunk_info[current_chunk]->type != freebsd)
179 msg = "Can only scan for bad blocks in FreeBSD partition.";
180 else if (strncmp(name, "sd", 2) ||
181 !msgYesNo("This typically makes sense only for ESDI, IDE or MFM drives.\nAre you sure you want to do this on a SCSI disk?"))
83 attrset(A_NORMAL);
84 mvaddstr(0, 0, "Disk name:\t");
85 attrset(A_REVERSE); addstr(d->name); attrset(A_NORMAL);
86 attrset(A_REVERSE); mvaddstr(0, 55, "Master Partition Editor"); attrset(A_NORMAL);
87 mvprintw(1, 0,
88 "BIOS Geometry:\t%lu cyls/%lu heads/%lu sectors",
89 d->bios_cyl, d->bios_hd, d->bios_sect);
90 mvprintw(3, 1, "%10s %10s %10s %8s %8s %8s %8s %8s",
91 "Offset", "Size", "End", "Name", "PType", "Desc",
92 "Subtype", "Flags");
93 for (i = 0, row = CHUNK_START_ROW; chunk_info[i]; i++, row++) {
94 if (i == current_chunk)
95 attrset(A_REVERSE);
96 mvprintw(row, 2, "%10lu %10lu %10lu %8s %8d %8s %8d %6lx",
97 chunk_info[i]->offset, chunk_info[i]->size,
98 chunk_info[i]->end, chunk_info[i]->name,
99 chunk_info[i]->type, chunk_n[chunk_info[i]->type],
100 chunk_info[i]->subtype, chunk_info[i]->flags);
101 if (i == current_chunk)
102 attrset(A_NORMAL);
103 }
104}
105
106static void
107print_command_summary()
108{
109 mvprintw(14, 0, "The following commands are supported (in upper or lower case):");
110 mvprintw(16, 0, "A = Use Entire Disk B = Bad Block Scan C = Create Partition");
111 mvprintw(17, 0, "D = Delete Partition G = Set BIOS Geometry S = Set Bootable");
112 mvprintw(18, 0, "U = Undo All Changes W = `Wizard' Mode ESC = Exit this screen");
113 mvprintw(20, 0, "The currently selected partition is displayed in ");
114 attrset(A_REVERSE); addstr("reverse video."); attrset(A_NORMAL);
115 mvprintw(21, 0, "Use F1 or ? to get more help, arrow keys to move.");
116 move(0, 0);
117}
118
119static Disk *
120diskPartition(Disk *d)
121{
122 char *p;
123 int key = 0;
124 Boolean chunking;
125 char *msg = NULL;
126 char name[40];
127
128 chunking = TRUE;
129 strncpy(name, d->name, 40);
130 keypad(stdscr, TRUE);
131
132 record_chunks(d);
133 while (chunking) {
134 print_chunks(d);
135 print_command_summary();
136 if (msg) {
137 standout(); mvprintw(23, 0, msg); standend();
138 beep();
139 msg = NULL;
140 }
141
142 key = toupper(getch());
143 switch (key) {
144 case KEY_UP:
145 case '-':
146 if (current_chunk != 0)
147 --current_chunk;
148 break;
149
150 case KEY_DOWN:
151 case '+':
152 case '\r':
153 case '\n':
154 if (chunk_info[current_chunk + 1])
155 ++current_chunk;
156 break;
157
158 case KEY_HOME:
159 current_chunk = 0;
160 break;
161
162 case KEY_END:
163 while (chunk_info[current_chunk + 1])
164 ++current_chunk;
165 break;
166
167 case KEY_F(1):
168 case '?':
169 systemDisplayFile("slice.hlp");
170 break;
171
172 case 'A':
173 All_FreeBSD(d);
174 record_chunks(d);
175 break;
176
177 case 'B':
178 if (chunk_info[current_chunk]->type != freebsd)
179 msg = "Can only scan for bad blocks in FreeBSD partition.";
180 else if (strncmp(name, "sd", 2) ||
181 !msgYesNo("This typically makes sense only for ESDI, IDE or MFM drives.\nAre you sure you want to do this on a SCSI disk?"))
182 chunk_info[current_chunk]->flags |= CHUNK_BAD144;
182 if (chunk_info[current_chunk]->flags & CHUNK_BAD144)
183 chunk_info[current_chunk]->flags &= ~CHUNK_BAD144;
184 else
185 chunk_info[current_chunk]->flags |= CHUNK_BAD144;
183 break;
184
185 case 'C':
186 if (chunk_info[current_chunk]->type != unused)
187 msg = "Partition in use, delete it first or move to an unused one.";
188 else {
189 char *val, tmp[20], *cp;
190 int size;
191
192 snprintf(tmp, 20, "%d", chunk_info[current_chunk]->size);
193 val = msgGetInput(tmp, "Please specify the size for new FreeBSD partition in blocks, or append\na trailing `M' for megabytes (e.g. 20M).");
194 if (val && (size = strtol(val, &cp, 0)) > 0) {
195 if (*cp && toupper(*cp) == 'M')
196 size *= 2048;
197 Create_Chunk(d, chunk_info[current_chunk]->offset,
198 size,
199 freebsd,
200 3,
201 (chunk_info[current_chunk]->flags &
202 CHUNK_ALIGN));
203 record_chunks(d);
204 }
205 }
206 break;
207
208 case 'D':
209 if (chunk_info[current_chunk]->type == unused)
210 msg = "Partition is already unused!";
211 else {
212 Delete_Chunk(d, chunk_info[current_chunk]);
213 record_chunks(d);
214 }
215 break;
216
217 case 'G': {
218 char *val, geometry[80];
219
220 snprintf(geometry, 80, "%lu/%lu/%lu",
221 d->bios_cyl, d->bios_hd, d->bios_sect);
222 val = msgGetInput(geometry,
223"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.");
224 if (val) {
225 d->bios_cyl = strtol(val, &val, 0);
226 d->bios_hd = strtol(val + 1, &val, 0);
227 d->bios_sect = strtol(val + 1, 0, 0);
228 }
229 }
230 break;
231
232 case 'S':
233 /* Set Bootable */
234 chunk_info[current_chunk]->flags |= CHUNK_ACTIVE;
235 break;
236
237 case 'U':
238 Free_Disk(d);
239 d = Open_Disk(name);
240 if (!d)
241 msgFatal("Can't reopen disk %s!", name);
242 record_chunks(d);
243 break;
244
245 case 'W':
246 if (!msgYesNo("Are you sure you want to go into Wizard mode?\nNo seat belts whatsoever are provided!")) {
247 dialog_clear();
248 end_dialog();
249 DialogActive = FALSE;
250 slice_wizard(d);
251 dialog_clear();
252 DialogActive = TRUE;
253 record_chunks(d);
254 }
255 else
256 msg = "Wise choice!";
257 break;
258
259 case 27: /* ESC */
260 chunking = FALSE;
261 break;
262
263 default:
264 beep();
265 msg = "Type F1 or ? for help";
266 break;
267 }
268 }
269 p = CheckRules(d);
270 if (p) {
271 msgConfirm(p);
272 free(p);
273 }
274 dialog_clear();
275 refresh();
276 variable_set2(DISK_PARTITIONED, "yes");
277 return d;
278}
279
280static int
281partitionHook(char *str)
282{
283 Device **devs = NULL;
284
285 /* Clip garbage off the ends */
286 string_prune(str);
287 str = string_skipwhite(str);
288 /* Try and open all the disks */
289 while (str) {
290 char *cp;
291
292 cp = index(str, '\n');
293 if (cp)
294 *cp++ = 0;
295 if (!*str) {
296 beep();
297 return 0;
298 }
299 devs = deviceFind(str, DEVICE_TYPE_DISK);
300 if (!devs) {
301 msgConfirm("Unable to find disk %s!", str);
302 return 0;
303 }
304 else if (devs[1])
305 msgConfirm("Bizarre multiple match for %s!", str);
306 devs[0]->private = diskPartition((Disk *)devs[0]->private);
307 devs[0]->enabled = TRUE;
308 str = cp;
309 }
310 return devs ? 1 : 0;
311}
312
313int
314diskPartitionEditor(char *str)
315{
316 int scroll, choice, curr, max;
317 DMenu *menu;
318
319 menu = deviceCreateMenu(&MenuDiskDevices, DEVICE_TYPE_DISK, partitionHook);
320 if (!menu) {
321 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.");
322 }
323 else {
324 choice = scroll = curr = max = 0;
325 dmenuOpen(menu, &choice, &scroll, &curr, &max);
326 free(menu);
327 }
328 return 0;
329}
186 break;
187
188 case 'C':
189 if (chunk_info[current_chunk]->type != unused)
190 msg = "Partition in use, delete it first or move to an unused one.";
191 else {
192 char *val, tmp[20], *cp;
193 int size;
194
195 snprintf(tmp, 20, "%d", chunk_info[current_chunk]->size);
196 val = msgGetInput(tmp, "Please specify the size for new FreeBSD partition in blocks, or append\na trailing `M' for megabytes (e.g. 20M).");
197 if (val && (size = strtol(val, &cp, 0)) > 0) {
198 if (*cp && toupper(*cp) == 'M')
199 size *= 2048;
200 Create_Chunk(d, chunk_info[current_chunk]->offset,
201 size,
202 freebsd,
203 3,
204 (chunk_info[current_chunk]->flags &
205 CHUNK_ALIGN));
206 record_chunks(d);
207 }
208 }
209 break;
210
211 case 'D':
212 if (chunk_info[current_chunk]->type == unused)
213 msg = "Partition is already unused!";
214 else {
215 Delete_Chunk(d, chunk_info[current_chunk]);
216 record_chunks(d);
217 }
218 break;
219
220 case 'G': {
221 char *val, geometry[80];
222
223 snprintf(geometry, 80, "%lu/%lu/%lu",
224 d->bios_cyl, d->bios_hd, d->bios_sect);
225 val = msgGetInput(geometry,
226"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.");
227 if (val) {
228 d->bios_cyl = strtol(val, &val, 0);
229 d->bios_hd = strtol(val + 1, &val, 0);
230 d->bios_sect = strtol(val + 1, 0, 0);
231 }
232 }
233 break;
234
235 case 'S':
236 /* Set Bootable */
237 chunk_info[current_chunk]->flags |= CHUNK_ACTIVE;
238 break;
239
240 case 'U':
241 Free_Disk(d);
242 d = Open_Disk(name);
243 if (!d)
244 msgFatal("Can't reopen disk %s!", name);
245 record_chunks(d);
246 break;
247
248 case 'W':
249 if (!msgYesNo("Are you sure you want to go into Wizard mode?\nNo seat belts whatsoever are provided!")) {
250 dialog_clear();
251 end_dialog();
252 DialogActive = FALSE;
253 slice_wizard(d);
254 dialog_clear();
255 DialogActive = TRUE;
256 record_chunks(d);
257 }
258 else
259 msg = "Wise choice!";
260 break;
261
262 case 27: /* ESC */
263 chunking = FALSE;
264 break;
265
266 default:
267 beep();
268 msg = "Type F1 or ? for help";
269 break;
270 }
271 }
272 p = CheckRules(d);
273 if (p) {
274 msgConfirm(p);
275 free(p);
276 }
277 dialog_clear();
278 refresh();
279 variable_set2(DISK_PARTITIONED, "yes");
280 return d;
281}
282
283static int
284partitionHook(char *str)
285{
286 Device **devs = NULL;
287
288 /* Clip garbage off the ends */
289 string_prune(str);
290 str = string_skipwhite(str);
291 /* Try and open all the disks */
292 while (str) {
293 char *cp;
294
295 cp = index(str, '\n');
296 if (cp)
297 *cp++ = 0;
298 if (!*str) {
299 beep();
300 return 0;
301 }
302 devs = deviceFind(str, DEVICE_TYPE_DISK);
303 if (!devs) {
304 msgConfirm("Unable to find disk %s!", str);
305 return 0;
306 }
307 else if (devs[1])
308 msgConfirm("Bizarre multiple match for %s!", str);
309 devs[0]->private = diskPartition((Disk *)devs[0]->private);
310 devs[0]->enabled = TRUE;
311 str = cp;
312 }
313 return devs ? 1 : 0;
314}
315
316int
317diskPartitionEditor(char *str)
318{
319 int scroll, choice, curr, max;
320 DMenu *menu;
321
322 menu = deviceCreateMenu(&MenuDiskDevices, DEVICE_TYPE_DISK, partitionHook);
323 if (!menu) {
324 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.");
325 }
326 else {
327 choice = scroll = curr = max = 0;
328 dmenuOpen(menu, &choice, &scroll, &curr, &max);
329 free(menu);
330 }
331 return 0;
332}