if_iwm - Use chan list from ieee80211_scan_state for scan, not ic_channels.
[dragonfly.git] / usr.sbin / installer / dfuibe_installer / fn_disk.c
blob1508b9c4ad744bfc3f399a1d0bad591f045c01de
1 /*
2 * Copyright (c)2004 The DragonFly Project. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
8 * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
11 * Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in
13 * the documentation and/or other materials provided with the
14 * distribution.
16 * Neither the name of the DragonFly Project nor the names of its
17 * contributors may be used to endorse or promote products derived
18 * from this software without specific prior written permission.
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
24 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
25 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
26 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
27 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
29 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
31 * OF THE POSSIBILITY OF SUCH DAMAGE.
35 * fn_disk.c
36 * Disk functions for installer.
37 * $Id: fn_disk.c,v 1.40 2005/03/13 01:53:58 cpressey Exp $
40 #include <stdlib.h>
41 #include <string.h>
43 #ifdef ENABLE_NLS
44 #include <libintl.h>
45 #define _(String) gettext (String)
46 #else
47 #define _(String) (String)
48 #endif
50 #include "libaura/mem.h"
51 #include "libaura/fspred.h"
53 #include "libdfui/dfui.h"
54 #include "libdfui/system.h"
56 #include "libinstaller/commands.h"
57 #include "libinstaller/diskutil.h"
58 #include "libinstaller/functions.h"
59 #include "libinstaller/uiutil.h"
61 #include "fn.h"
62 #include "pathnames.h"
64 /*** DISK-RELATED FUNCTIONS ***/
67 * Ask the user which physical disk they want.
68 * Changes ss->selected_disk if successful.
70 void
71 fn_select_disk(struct i_fn_args *a)
73 struct dfui_form *f;
74 struct dfui_action *k;
75 struct dfui_response *r;
76 struct disk *d;
78 f = dfui_form_create(
79 "select_disk",
80 _("Select Disk"),
81 a->short_desc,
82 "",
84 "p", "role", "menu",
85 "p", "special", "dfinstaller_select_disk",
87 NULL
90 for (d = storage_disk_first(a->s); d != NULL; d = disk_next(d)) {
91 dfui_form_action_add(f, disk_get_device_name(d),
92 dfui_info_new(disk_get_desc(d), "", ""));
95 k = dfui_form_action_add(f, "cancel",
96 dfui_info_new(a->cancel_desc, "", ""));
97 dfui_action_property_set(k, "accelerator", "ESC");
99 if (!dfui_be_present(a->c, f, &r))
100 abort_backend();
102 if (strcmp(dfui_response_get_action_id(r), "cancel") == 0) {
103 a->result = 0;
104 } else {
105 d = disk_find(a->s, dfui_response_get_action_id(r));
106 if (d == NULL) {
107 inform(a->c, _("Internal error - response from frontend "
108 "should be a valid device name."));
109 a->result = 0;
110 } else {
111 storage_set_selected_disk(a->s, d);
112 a->result = 1;
116 dfui_form_free(f);
117 dfui_response_free(r);
121 * Ask the user which slice on a the selected disk they want.
122 * Changes ss->selected_slice.
124 void
125 fn_select_slice(struct i_fn_args *a)
127 struct dfui_form *f;
128 struct dfui_action *k;
129 struct dfui_response *r;
130 struct slice *s;
131 char string[16];
133 f = dfui_form_create(
134 "select_slice",
135 _("Select Primary Partition"),
136 a->short_desc,
139 "p", "role", "menu",
140 "p", "special", "dfinstaller_select_slice",
142 NULL
145 for (s = disk_slice_first(storage_get_selected_disk(a->s));
146 s != NULL; s = slice_next(s)) {
147 snprintf(string, 16, "%d", slice_get_number(s));
148 dfui_form_action_add(f, string,
149 dfui_info_new(slice_get_desc(s), "", ""));
152 k = dfui_form_action_add(f, "cancel",
153 dfui_info_new(a->cancel_desc, "", ""));
154 dfui_action_property_set(k, "accelerator", "ESC");
156 if (!dfui_be_present(a->c, f, &r))
157 abort_backend();
159 if (strcmp(dfui_response_get_action_id(r), "cancel") == 0) {
160 a->result = 0;
161 } else {
162 s = slice_find(storage_get_selected_disk(a->s),
163 atoi(dfui_response_get_action_id(r)));
164 if (s == NULL) {
165 inform(a->c, _("Internal error - response from frontend "
166 "should be a valid slice number."));
167 a->result = 0;
168 } else {
169 storage_set_selected_slice(a->s, s);
170 a->result = 1;
174 dfui_form_free(f);
175 dfui_response_free(r);
179 * If ss->selected_disk == NULL, user will be asked for which disk.
180 * Returns 1 if disk was formatted, 0 if it wasn't.
181 * If it was, ss->selected_disk and ss->selected_slice are set to it.
183 void
184 fn_format_disk(struct i_fn_args *a)
186 struct commands *cmds;
187 char *selected_disk_string;
189 if (storage_get_selected_disk(a->s) == NULL) {
190 a->short_desc = _("Select a disk to format.");
191 a->cancel_desc = _("Return to Utilities Menu");
192 fn_select_disk(a);
193 if (!a->result || storage_get_selected_disk(a->s) == NULL) {
194 a->result = 0;
195 return;
199 if (confirm_dangerous_action(a->c,
200 _("WARNING! ALL data in ALL partitions on the disk\n\n"
201 "%s\n\nwill be IRREVOCABLY ERASED!\n\nAre you ABSOLUTELY "
202 "SURE you wish to take this action? This is your "
203 "LAST CHANCE to cancel!"), disk_get_desc(storage_get_selected_disk(a->s)))) {
204 cmds = commands_new();
206 command_add(cmds, "%s%s -BI %s",
207 a->os_root, cmd_name(a, "FDISK"),
208 disk_get_device_name(storage_get_selected_disk(a->s)));
210 if (!commands_execute(a, cmds)) {
211 inform(a->c, _("The disk\n\n%s\n\nwas "
212 "not correctly formatted, and may "
213 "now be in an inconsistent state. "
214 "We recommend re-formatting it "
215 "before attempting to install "
216 "%s on it."),
217 disk_get_desc(storage_get_selected_disk(a->s)),
218 OPERATING_SYSTEM_NAME);
219 commands_free(cmds);
220 a->result = 0;
221 return;
223 commands_free(cmds);
226 * Since one of the disks has now changed, we must
227 * refresh our view of them and re-select the disk
228 * since the selected_disk pointer will be invalidated.
230 selected_disk_string = aura_strdup(
231 disk_get_device_name(storage_get_selected_disk(a->s)));
232 if (!survey_storage(a)) {
233 inform(a->c, _("Errors occurred while probing "
234 "the system for its storage capabilities."));
236 storage_set_selected_disk(a->s, disk_find(a->s, selected_disk_string));
237 free(selected_disk_string);
240 * Note that we formatted this disk and that we want
241 * to use the first (and only) slice of it.
243 disk_set_formatted(storage_get_selected_disk(a->s), 1);
244 storage_set_selected_slice(a->s, disk_slice_first(storage_get_selected_disk(a->s)));
246 if (!format_slice(a)) {
247 inform(a->c, _("The sole primary partition of "
248 "the disk\n\n%s\n\nwas "
249 "not correctly formatted, and may "
250 "now be in an inconsistent state. "
251 "We recommend re-formatting the "
252 "disk before attempting to install "
253 "%s on it."),
254 disk_get_desc(storage_get_selected_disk(a->s)),
255 OPERATING_SYSTEM_NAME);
256 a->result = 0;
257 return;
260 inform(a->c, _("The disk\n\n%s\n\nwas formatted."),
261 disk_get_desc(storage_get_selected_disk(a->s)));
262 a->result = 1;
263 } else {
264 inform(a->c, _("Action cancelled - no disks were formatted."));
265 a->result = 0;
270 * Wipes the start of the selected disk.
272 void
273 fn_wipe_start_of_disk(struct i_fn_args *a)
275 struct commands *cmds;
277 a->short_desc = _("If you are having problems formatting a disk, "
278 "it may be because of junk that has accumulated "
279 "in the boot block and the partition table. "
280 "A cure for this is to wipe out everything on "
281 "the first few sectors of the disk. However, this "
282 "is a rather drastic action to take, so it is not "
283 "recommended unless you are otherwise "
284 "encountering problems.");
285 a->cancel_desc = _("Return to Utilities Menu");
286 fn_select_disk(a);
287 if (!a->result)
288 return;
290 /* XXX check to make sure no slices on this disk are mounted first? */
291 if (storage_get_selected_disk(a->s) != NULL && confirm_dangerous_action(a->c,
292 _("WARNING! ALL data in ALL partitions on the disk\n\n"
293 "%s\n\nwill be IRREVOCABLY ERASED!\n\nAre you ABSOLUTELY "
294 "SURE you wish to take this action? This is your "
295 "LAST CHANCE to cancel!"), disk_get_desc(storage_get_selected_disk(a->s)))) {
296 cmds = commands_new();
297 command_add(cmds,
298 "%s%s if=/dev/zero of=/dev/%s bs=32k count=16",
299 a->os_root, cmd_name(a, "DD"),
300 disk_get_device_name(storage_get_selected_disk(a->s)));
301 if (commands_execute(a, cmds)) {
302 inform(a->c, _("Start of disk was successfully wiped."));
303 } else {
304 inform(a->c, _("Some errors occurred. "
305 "Start of disk was not successfully wiped."));
307 commands_free(cmds);
312 * Wipes the start of the selected slice.
314 void
315 fn_wipe_start_of_slice(struct i_fn_args *a)
317 struct commands *cmds;
319 a->short_desc =
320 _("If you are having problems formatting a primary partition, "
321 "it may be because of junk that has accumulated in the "
322 "partition's `disklabel'. A cure for this is to wipe out "
323 "everything on the first few sectors of the primary partition. "
324 "However, this is a rather drastic action to take, so it is not "
325 "recommended unless you are otherwise encountering problems.");
326 a->cancel_desc = _("Return to Utilities Menu");
327 fn_select_slice(a);
328 if (!a->result)
329 return;
331 if (confirm_dangerous_action(a->c,
332 _("WARNING! ALL data in primary partition #%d,\n\n%s\n\non the "
333 "disk\n\n%s\n\n will be IRREVOCABLY ERASED!\n\nAre you "
334 "ABSOLUTELY SURE you wish to take this action? This is "
335 "your LAST CHANCE to cancel!"),
336 slice_get_number(storage_get_selected_slice(a->s)),
337 slice_get_desc(storage_get_selected_slice(a->s)),
338 disk_get_desc(storage_get_selected_disk(a->s)))) {
339 /* XXX check to make sure this slice is not mounted first */
340 cmds = commands_new();
341 command_add(cmds, "%s%s if=/dev/zero of=/dev/%s bs=32k count=16",
342 a->os_root, cmd_name(a, "DD"),
343 slice_get_device_name(storage_get_selected_slice(a->s)));
344 if (commands_execute(a, cmds)) {
345 inform(a->c, _("Start of primary partition was successfully wiped."));
346 } else {
347 inform(a->c, _("Some errors occurred. "
348 "Start of primary partition was not successfully wiped."));
350 commands_free(cmds);
354 static void
355 ask_to_wipe_boot_sector(struct i_fn_args *a, struct commands *fcmds)
357 struct commands *cmds;
358 struct command *cmd;
359 char *disk;
361 for (cmd = command_get_first(fcmds); cmd != NULL;
362 cmd = command_get_next(cmd)) {
363 disk = command_get_tag(cmd);
364 if (disk != NULL &&
365 command_get_result(cmd) > 0 &&
366 command_get_result(cmd) < 256) {
367 switch (dfui_be_present_dialog(a->c,
368 _("Bootblock Install Failed"),
369 _("Re-Initialize Bootblock|Cancel"),
370 _("Warning: bootblocks were not successfully "
371 "installed on the disk `%s'. This may be "
372 "because the disk is new and not yet "
373 "formatted. If this is the case, it might "
374 "help to re-initialize the boot sector, "
375 "then try installing the bootblock again. "
376 "Note that this should not affect the "
377 "partition table of the disk."),
378 disk)) {
379 case 1:
380 cmds = commands_new();
381 command_add(cmds,
382 "%s%s | %s%s -B /dev/%s",
383 a->os_root, cmd_name(a, "YES"),
384 a->os_root, cmd_name(a, "FDISK"),
385 disk);
386 if (commands_execute(a, cmds)) {
387 inform(a->c, _("Boot sector successfully initialized."));
388 } else {
389 inform(a->c, _("Some errors occurred. "
390 "Boot sector was not successfully initialized."));
392 commands_free(cmds);
393 break;
394 default:
395 break;
401 void
402 fn_install_bootblocks(struct i_fn_args *a, const char *device)
404 struct dfui_form *f;
405 struct dfui_response *r;
406 struct dfui_dataset *ds;
407 struct disk *d;
408 struct commands *cmds;
409 struct command *cmd;
410 char disk[64], boot0cfg[32], packet[32];
411 char msg_buf[1][1024];
413 snprintf(msg_buf[0], sizeof(msg_buf[0]),
414 "'Packet Mode' refers to using newer BIOS calls to boot "
415 "from a partition of the disk. It is generally not "
416 "required unless:\n\n"
417 "- your BIOS does not support legacy mode; or\n"
418 "- your %s primary partition resides on a "
419 "cylinder of the disk beyond cylinder 1024; or\n"
420 "- you just can't get it to boot without it.",
421 OPERATING_SYSTEM_NAME);
423 f = dfui_form_create(
424 "install_bootstrap",
425 _("Install Bootblock(s)"),
426 a->short_desc,
428 msg_buf[0],
430 "p", "special", "dfinstaller_install_bootstrap",
432 "f", "disk", _("Disk Drive"),
433 _("The disk on which you wish to install a bootblock"), "",
434 "p", "editable", "false",
435 "f", "boot0cfg", _("Install Bootblock?"),
436 _("Install a bootblock on this disk"), "",
437 "p", "control", "checkbox",
438 "f", "packet", _("Packet Mode?"),
439 _("Select this to use 'packet mode' to boot the disk"), "",
440 "p", "control", "checkbox",
442 "a", "ok", _("Accept and Install Bootblocks"), "", "",
443 "a", "cancel", a->cancel_desc, "", "",
444 "p", "accelerator", "ESC",
446 NULL
449 dfui_form_set_multiple(f, 1);
451 if (device != NULL) {
452 ds = dfui_dataset_new();
453 dfui_dataset_celldata_add(ds, "disk", device);
454 dfui_dataset_celldata_add(ds, "boot0cfg", "Y");
455 dfui_dataset_celldata_add(ds, "packet", "Y");
456 dfui_form_dataset_add(f, ds);
457 } else {
458 for (d = storage_disk_first(a->s); d != NULL; d = disk_next(d)) {
459 ds = dfui_dataset_new();
460 dfui_dataset_celldata_add(ds, "disk",
461 disk_get_device_name(d));
462 dfui_dataset_celldata_add(ds, "boot0cfg", "Y");
463 dfui_dataset_celldata_add(ds, "packet", "Y");
464 dfui_form_dataset_add(f, ds);
468 if (!dfui_be_present(a->c, f, &r))
469 abort_backend();
471 a->result = 0;
472 if (strcmp(dfui_response_get_action_id(r), "ok") == 0) {
473 cmds = commands_new();
475 for (ds = dfui_response_dataset_get_first(r); ds != NULL;
476 ds = dfui_dataset_get_next(ds)) {
477 strlcpy(disk, dfui_dataset_get_value(ds, "disk"), 64);
478 strlcpy(boot0cfg, dfui_dataset_get_value(ds, "boot0cfg"), 32);
479 strlcpy(packet, dfui_dataset_get_value(ds, "packet"), 32);
481 if (strcasecmp(boot0cfg, "Y") == 0) {
482 cmd = command_add(cmds, "%s%s -B -o %spacket %s",
483 a->os_root, cmd_name(a, "BOOT0CFG"),
484 strcasecmp(packet, "Y") == 0 ? "" : "no",
485 disk);
486 command_set_failure_mode(cmd, COMMAND_FAILURE_WARN);
487 command_set_tag(cmd, "%s", disk);
488 cmd = command_add(cmds, "%s%s -v %s",
489 a->os_root, cmd_name(a, "BOOT0CFG"),
490 disk);
491 command_set_failure_mode(cmd, COMMAND_FAILURE_WARN);
492 command_set_tag(cmd, "%s", disk);
496 if (!commands_execute(a, cmds)) {
497 ask_to_wipe_boot_sector(a, cmds);
498 } else {
499 inform(a->c, _("Bootblocks were successfully installed!"));
500 a->result = 1;
502 commands_free(cmds);
505 dfui_form_free(f);
506 dfui_response_free(r);
509 void
510 fn_format_msdos_floppy(struct i_fn_args *a)
512 struct commands *cmds;
514 switch (dfui_be_present_dialog(a->c, _("Format MSDOS Floppy"),
515 _("Format Floppy|Return to Utilities Menu"),
516 _("Please insert the floppy to be formatted "
517 "in unit 0 (``drive A:'')."))) {
518 case 1:
519 cmds = commands_new();
520 command_add(cmds, "%s%s -y -f 1440 /dev/fd0",
521 a->os_root, cmd_name(a, "FDFORMAT"));
522 command_add(cmds, "%s%s -f 1440 fd0",
523 a->os_root, cmd_name(a, "NEWFS_MSDOS"));
524 if (commands_execute(a, cmds))
525 inform(a->c, _("Floppy successfully formatted!"));
526 else
527 inform(a->c, _("Floppy was not successfully formatted."));
528 break;
529 case 2:
530 return;
531 default:
532 abort_backend();
536 void
537 fn_create_cdboot_floppy(struct i_fn_args *a)
539 struct commands *cmds;
540 char msg_buf[1][1024];
542 snprintf(msg_buf[0], sizeof(msg_buf[0]),
543 "%s cannot be installed from a floppy; "
544 "it must be installed from a booted CD-ROM. "
545 "However, many older systems do not support booting "
546 "from a CD-ROM. For these systems, a boot disk can be "
547 "created. This boot disk contains the Smart Boot "
548 "Manager program, which can boot a CD-ROM even "
549 "on systems with BIOSes which do not support booting "
550 "from the CD-ROM.\n\n"
551 "Smart Boot Manager is not a part of %s; "
552 "the Smart Boot Manager project can be found here:\n\n"
553 "http://btmgr.sourceforge.net/\n\n"
554 "To create a CDBoot floppy, insert a blank floppy "
555 "in unit 0 (``drive A:'') before proceeding."
557 OPERATING_SYSTEM_NAME, OPERATING_SYSTEM_NAME);
559 switch (dfui_be_present_dialog(a->c, _("Create CDBoot Floppy"),
560 _("Create CDBoot Floppy|Return to Utilities Menu"),
561 "%s", msg_buf[0])) {
562 case 1:
563 cmds = commands_new();
564 command_add(cmds, "%s%s -c %sboot/cdboot.flp.bz2 | "
565 "%s%s of=/dev/fd0 bs=32k",
566 a->os_root, cmd_name(a, "BUNZIP2"),
567 a->os_root,
568 a->os_root, cmd_name(a, "DD"));
569 if (commands_execute(a, cmds))
570 inform(a->c, _("CDBoot floppy successfully created!"));
571 else
572 inform(a->c, _("CDBoot floppy was not successfully created."));
573 break;
574 case 2:
575 return;
576 default:
577 abort_backend();
581 /**** NON-fn_ FUNCTIONS ***/
584 format_slice(struct i_fn_args *a)
586 struct commands *cmds;
587 struct command *cmd;
588 int result;
589 int cyl, hd, sec;
591 cmds = commands_new();
594 * The information in a->s NEEDS to be accurate here!
595 * Presumably we just did a survey_storage() recently.
596 * XXX should we do another one here anyway just to be paranoid?
600 * Make sure the survey did get disk info correctly or fail
602 if ((storage_get_selected_disk(a->s) == NULL) ||
603 (storage_get_selected_slice(a->s) == NULL))
604 return 0;
607 * Set the slice's sysid to 165.
609 disk_get_geometry(storage_get_selected_disk(a->s), &cyl, &hd, &sec);
610 command_add(cmds, "%s%s 'g c%d h%d s%d' >%snew.fdisk",
611 a->os_root, cmd_name(a, "ECHO"),
612 cyl, hd, sec,
613 a->tmp);
614 command_add(cmds, "%s%s 'p %d %d %lu %lu' >>%snew.fdisk",
615 a->os_root, cmd_name(a, "ECHO"),
616 slice_get_number(storage_get_selected_slice(a->s)),
617 165,
618 slice_get_start(storage_get_selected_slice(a->s)),
619 slice_get_size(storage_get_selected_slice(a->s)),
620 a->tmp);
621 if (slice_get_flags(storage_get_selected_slice(a->s)) & 0x80) {
622 command_add(cmds, "%s%s 'a %d' >>%snew.fdisk",
623 a->os_root, cmd_name(a, "ECHO"),
624 slice_get_number(storage_get_selected_slice(a->s)),
625 a->tmp);
628 command_add(cmds, "%s%s %snew.fdisk",
629 a->os_root, cmd_name(a, "CAT"), a->tmp);
630 temp_file_add(a, "new.fdisk");
633 * Execute the fdisk script.
635 cmd = command_add(cmds, "%s%s -v -f %snew.fdisk %s",
636 a->os_root, cmd_name(a, "FDISK"), a->tmp,
637 disk_get_device_name(storage_get_selected_disk(a->s)));
638 if (slice_get_size(storage_get_selected_slice(a->s)) == 0xFFFFFFFFU)
639 command_set_failure_mode(cmd, COMMAND_FAILURE_IGNORE);
642 * If there is an old 'virgin' disklabel hanging around
643 * in the temp dir, get rid of it. This won't happen
644 * from a real CD, but might happen with '-o' installs.
646 command_add(cmds, "%s%s -f %sinstall.disklabel.%s",
647 a->os_root, cmd_name(a, "RM"),
648 a->tmp,
649 slice_get_device_name(storage_get_selected_slice(a->s)));
651 result = commands_execute(a, cmds);
653 commands_free(cmds);
655 return(result);