#include <sys/diskmbr.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#ifdef ENABLE_NLS
#include <libintl.h>
#define _(String) gettext (String)
#else
#define _(String) (String)
#endif
#include "libaura/mem.h"
#include "libaura/fspred.h"
#include "libdfui/dfui.h"
#include "libdfui/system.h"
#include "libinstaller/commands.h"
#include "libinstaller/diskutil.h"
#include "libinstaller/functions.h"
#include "libinstaller/uiutil.h"
#include "fn.h"
#include "pathnames.h"
void
fn_select_disk(struct i_fn_args *a)
{
struct dfui_form *f;
struct dfui_action *k;
struct dfui_response *r;
struct disk *d;
f = dfui_form_create(
"select_disk",
_("Select Disk"),
a->short_desc,
"",
"p", "role", "menu",
"p", "special", "dfinstaller_select_disk",
NULL
);
for (d = storage_disk_first(a->s); d != NULL; d = disk_next(d)) {
dfui_form_action_add(f, disk_get_device_name(d),
dfui_info_new(disk_get_desc(d), "", ""));
}
k = dfui_form_action_add(f, "cancel",
dfui_info_new(a->cancel_desc, "", ""));
dfui_action_property_set(k, "accelerator", "ESC");
if (!dfui_be_present(a->c, f, &r))
abort_backend();
if (strcmp(dfui_response_get_action_id(r), "cancel") == 0) {
a->result = 0;
} else {
d = disk_find(a->s, dfui_response_get_action_id(r));
if (d == NULL) {
inform(a->c, _("Internal error - response from frontend "
"should be a valid device name."));
a->result = 0;
} else {
storage_set_selected_disk(a->s, d);
a->result = 1;
}
}
dfui_form_free(f);
dfui_response_free(r);
}
void
fn_select_slice(struct i_fn_args *a)
{
struct dfui_form *f;
struct dfui_action *k;
struct dfui_response *r;
struct slice *s;
char string[16];
f = dfui_form_create(
"select_slice",
_("Select Primary Partition"),
a->short_desc,
"",
"p", "role", "menu",
"p", "special", "dfinstaller_select_slice",
NULL
);
for (s = disk_slice_first(storage_get_selected_disk(a->s));
s != NULL; s = slice_next(s)) {
snprintf(string, 16, "%d", slice_get_number(s));
dfui_form_action_add(f, string,
dfui_info_new(slice_get_desc(s), "", ""));
}
k = dfui_form_action_add(f, "cancel",
dfui_info_new(a->cancel_desc, "", ""));
dfui_action_property_set(k, "accelerator", "ESC");
if (!dfui_be_present(a->c, f, &r))
abort_backend();
if (strcmp(dfui_response_get_action_id(r), "cancel") == 0) {
a->result = 0;
} else {
s = slice_find(storage_get_selected_disk(a->s),
atoi(dfui_response_get_action_id(r)));
if (s == NULL) {
inform(a->c, _("Internal error - response from frontend "
"should be a valid slice number."));
a->result = 0;
} else {
storage_set_selected_slice(a->s, s);
a->result = 1;
}
}
dfui_form_free(f);
dfui_response_free(r);
}
void
fn_format_disk_mbr(struct i_fn_args *a)
{
struct commands *cmds;
char *selected_disk_string;
if (storage_get_selected_disk(a->s) == NULL) {
a->short_desc = _("Select a disk to format.");
a->cancel_desc = _("Return to Utilities Menu");
fn_select_disk(a);
if (!a->result || storage_get_selected_disk(a->s) == NULL) {
a->result = 0;
return;
}
}
if (confirm_dangerous_action(a->c,
_("WARNING! ALL data in ALL partitions on the disk\n\n"
"%s\n\nwill be IRREVOCABLY ERASED!\n\nAre you ABSOLUTELY "
"SURE you wish to take this action? This is your "
"LAST CHANCE to cancel!"), disk_get_desc(storage_get_selected_disk(a->s)))) {
cmds = commands_new();
command_add(cmds,
"%s%s if=/dev/zero of=/dev/%s bs=32k count=16",
a->os_root, cmd_name(a, "DD"),
disk_get_device_name(storage_get_selected_disk(a->s)));
command_add(cmds, "%s%s -BI %s",
a->os_root, cmd_name(a, "FDISK"),
disk_get_device_name(storage_get_selected_disk(a->s)));
if (!commands_execute(a, cmds)) {
inform(a->c, _("The disk\n\n%s\n\nwas "
"not correctly formatted, and may "
"now be in an inconsistent state. "
"We recommend re-formatting it "
"before attempting to install "
"%s on it."),
disk_get_desc(storage_get_selected_disk(a->s)),
OPERATING_SYSTEM_NAME);
commands_free(cmds);
a->result = 0;
return;
}
commands_free(cmds);
selected_disk_string = aura_strdup(
disk_get_device_name(storage_get_selected_disk(a->s)));
if (!survey_storage(a)) {
inform(a->c, _("Errors occurred while probing "
"the system for its storage capabilities."));
}
storage_set_selected_disk(a->s, disk_find(a->s, selected_disk_string));
free(selected_disk_string);
disk_set_formatted(storage_get_selected_disk(a->s), 1);
storage_set_selected_slice(a->s, disk_slice_first(storage_get_selected_disk(a->s)));
if (!format_slice(a)) {
inform(a->c, _("The sole primary partition of "
"the disk\n\n%s\n\nwas "
"not correctly formatted, and may "
"now be in an inconsistent state. "
"We recommend re-formatting the "
"disk before attempting to install "
"%s on it."),
disk_get_desc(storage_get_selected_disk(a->s)),
OPERATING_SYSTEM_NAME);
a->result = 0;
return;
}
inform(a->c, _("The disk\n\n%s\n\nwas formatted."),
disk_get_desc(storage_get_selected_disk(a->s)));
a->result = 1;
} else {
inform(a->c, _("Action cancelled - no disks were formatted."));
a->result = 0;
}
}
void
fn_format_disk_uefi(struct i_fn_args *a)
{
struct commands *cmds;
char *selected_disk_string;
if (storage_get_selected_disk(a->s) == NULL) {
a->short_desc = _("Select a disk to format.");
a->cancel_desc = _("Return to Utilities Menu");
fn_select_disk(a);
if (!a->result || storage_get_selected_disk(a->s) == NULL) {
a->result = 0;
return;
}
}
if (confirm_dangerous_action(a->c,
_("WARNING! ALL data in ALL partitions on the disk\n\n"
"%s\n\nwill be IRREVOCABLY ERASED!\n\nAre you ABSOLUTELY "
"SURE you wish to take this action? This is your "
"LAST CHANCE to cancel!"), disk_get_desc(storage_get_selected_disk(a->s)))) {
cmds = commands_new();
command_add(cmds,
"%s%s if=/dev/zero of=/dev/%s bs=32k count=16",
a->os_root, cmd_name(a, "DD"),
disk_get_device_name(storage_get_selected_disk(a->s)));
command_add(cmds, "%s%s destroy %s",
a->os_root, cmd_name(a, "GPT"),
disk_get_device_name(storage_get_selected_disk(a->s)));
command_add(cmds, "%s%s create -f %s",
a->os_root, cmd_name(a, "GPT"),
disk_get_device_name(storage_get_selected_disk(a->s)));
command_add(cmds, "%s%s add -i 0 -s 262144 -t efi %s",
a->os_root, cmd_name(a, "GPT"),
disk_get_device_name(storage_get_selected_disk(a->s)));
command_add(cmds, "%s%s add -i 1 -t dragonfly %s",
a->os_root, cmd_name(a, "GPT"),
disk_get_device_name(storage_get_selected_disk(a->s)));
command_add(cmds, "%s%s -F 32 -c 2 -L EFI -m 0xf8 %ss0",
a->os_root, cmd_name(a, "NEWFS_MSDOS"),
disk_get_device_name(storage_get_selected_disk(a->s)));
command_add(cmds, "%s%s /dev/%ss0 %smnt",
a->os_root, cmd_name(a, "MOUNT_MSDOS"),
disk_get_device_name(storage_get_selected_disk(a->s)),
a->os_root);
command_add(cmds, "%s%s -p %smnt/EFI/BOOT",
a->os_root, cmd_name(a, "MKDIR"), a->os_root);
command_add(cmds,
"%s%s %s/boot/boot1.efi %smnt/EFI/BOOT/BOOTX64.EFI",
a->os_root, cmd_name(a, "CP"),
a->os_root, a->os_root);
command_add(cmds, "%s%s %smnt",
a->os_root, cmd_name(a, "UMOUNT"), a->os_root);
if (!commands_execute(a, cmds)) {
inform(a->c, _("The disk\n\n%s\n\nwas "
"not correctly formatted, and may "
"now be in an inconsistent state. "
"We recommend re-formatting it "
"before attempting to install "
"%s on it."),
disk_get_desc(storage_get_selected_disk(a->s)),
OPERATING_SYSTEM_NAME);
commands_free(cmds);
a->result = 0;
return;
}
commands_free(cmds);
selected_disk_string = aura_strdup(
disk_get_device_name(storage_get_selected_disk(a->s)));
if (!survey_storage(a)) {
inform(a->c, _("Errors occurred while probing "
"the system for its storage capabilities."));
}
storage_set_selected_disk(a->s,
disk_find(a->s, selected_disk_string));
free(selected_disk_string);
disk_set_formatted(storage_get_selected_disk(a->s), 1);
storage_set_selected_slice(a->s,
disk_slice_first(storage_get_selected_disk(a->s)));
inform(a->c, _("The disk\n\n%s\n\nwas formatted."),
disk_get_desc(storage_get_selected_disk(a->s)));
a->result = 1;
} else {
inform(a->c, _("Action cancelled - no disks were formatted."));
a->result = 0;
}
}
void
fn_wipe_start_of_disk(struct i_fn_args *a)
{
struct commands *cmds;
a->short_desc = _("If you are having problems formatting a disk, "
"it may be because of junk that has accumulated "
"in the boot block and the partition table. "
"A cure for this is to wipe out everything on "
"the first few sectors of the disk. However, this "
"is a rather drastic action to take, so it is not "
"recommended unless you are otherwise "
"encountering problems.");
a->cancel_desc = _("Return to Utilities Menu");
fn_select_disk(a);
if (!a->result)
return;
if (storage_get_selected_disk(a->s) != NULL && confirm_dangerous_action(a->c,
_("WARNING! ALL data in ALL partitions on the disk\n\n"
"%s\n\nwill be IRREVOCABLY ERASED!\n\nAre you ABSOLUTELY "
"SURE you wish to take this action? This is your "
"LAST CHANCE to cancel!"), disk_get_desc(storage_get_selected_disk(a->s)))) {
cmds = commands_new();
command_add(cmds,
"%s%s if=/dev/zero of=/dev/%s bs=32k count=16",
a->os_root, cmd_name(a, "DD"),
disk_get_device_name(storage_get_selected_disk(a->s)));
if (commands_execute(a, cmds)) {
inform(a->c, _("Start of disk was successfully wiped."));
} else {
inform(a->c, _("Some errors occurred. "
"Start of disk was not successfully wiped."));
}
commands_free(cmds);
}
}
void
fn_wipe_start_of_slice(struct i_fn_args *a)
{
struct commands *cmds;
a->short_desc =
_("If you are having problems formatting a primary partition, "
"it may be because of junk that has accumulated in the "
"partition's `disklabel'. A cure for this is to wipe out "
"everything on the first few sectors of the primary partition. "
"However, this is a rather drastic action to take, so it is not "
"recommended unless you are otherwise encountering problems.");
a->cancel_desc = _("Return to Utilities Menu");
fn_select_slice(a);
if (!a->result)
return;
if (confirm_dangerous_action(a->c,
_("WARNING! ALL data in primary partition #%d,\n\n%s\n\non the "
"disk\n\n%s\n\n will be IRREVOCABLY ERASED!\n\nAre you "
"ABSOLUTELY SURE you wish to take this action? This is "
"your LAST CHANCE to cancel!"),
slice_get_number(storage_get_selected_slice(a->s)),
slice_get_desc(storage_get_selected_slice(a->s)),
disk_get_desc(storage_get_selected_disk(a->s)))) {
cmds = commands_new();
command_add(cmds, "%s%s if=/dev/zero of=/dev/%s bs=32k count=16",
a->os_root, cmd_name(a, "DD"),
slice_get_device_name(storage_get_selected_slice(a->s)));
if (commands_execute(a, cmds)) {
inform(a->c, _("Start of primary partition was successfully wiped."));
} else {
inform(a->c, _("Some errors occurred. "
"Start of primary partition was not successfully wiped."));
}
commands_free(cmds);
}
}
static void
ask_to_wipe_boot_sector(struct i_fn_args *a, struct commands *fcmds)
{
struct commands *cmds;
struct command *cmd;
char *disk;
for (cmd = command_get_first(fcmds); cmd != NULL;
cmd = command_get_next(cmd)) {
disk = command_get_tag(cmd);
if (disk != NULL &&
command_get_result(cmd) > 0 &&
command_get_result(cmd) < 256) {
switch (dfui_be_present_dialog(a->c,
_("Bootblock Install Failed"),
_("Re-Initialize Bootblock|Cancel"),
_("Warning: bootblocks were not successfully "
"installed on the disk `%s'. This may be "
"because the disk is new and not yet "
"formatted. If this is the case, it might "
"help to re-initialize the boot sector, "
"then try installing the bootblock again. "
"Note that this should not affect the "
"partition table of the disk."),
disk)) {
case 1:
cmds = commands_new();
command_add(cmds,
"%s%s | %s%s -B /dev/%s",
a->os_root, cmd_name(a, "YES"),
a->os_root, cmd_name(a, "FDISK"),
disk);
if (commands_execute(a, cmds)) {
inform(a->c, _("Boot sector successfully initialized."));
} else {
inform(a->c, _("Some errors occurred. "
"Boot sector was not successfully initialized."));
}
commands_free(cmds);
break;
default:
break;
}
}
}
}
void
fn_install_bootblocks(struct i_fn_args *a, const char *device)
{
struct dfui_form *f;
struct dfui_response *r;
struct dfui_dataset *ds;
struct disk *d;
struct commands *cmds;
struct command *cmd;
char disk[64], boot0cfg[32], packet[32];
char msg_buf[1][1024];
snprintf(msg_buf[0], sizeof(msg_buf[0]),
"'Packet Mode' refers to using newer BIOS calls to boot "
"from a partition of the disk. It is generally not "
"required unless:\n\n"
"- your BIOS does not support legacy mode; or\n"
"- your %s primary partition resides on a "
"cylinder of the disk beyond cylinder 1024; or\n"
"- you just can't get it to boot without it.",
OPERATING_SYSTEM_NAME);
f = dfui_form_create(
"install_bootstrap",
_("Install Bootblock(s)"),
a->short_desc,
msg_buf[0],
"p", "special", "dfinstaller_install_bootstrap",
"f", "disk", _("Disk Drive"),
_("The disk on which you wish to install a bootblock"), "",
"p", "editable", "false",
"f", "boot0cfg", _("Install Bootblock?"),
_("Install a bootblock on this disk"), "",
"p", "control", "checkbox",
"f", "packet", _("Packet Mode?"),
_("Select this to use 'packet mode' to boot the disk"), "",
"p", "control", "checkbox",
"a", "ok", _("Accept and Install Bootblocks"), "", "",
"a", "cancel", a->cancel_desc, "", "",
"p", "accelerator", "ESC",
NULL
);
dfui_form_set_multiple(f, 1);
if (device != NULL) {
ds = dfui_dataset_new();
dfui_dataset_celldata_add(ds, "disk", device);
dfui_dataset_celldata_add(ds, "boot0cfg", "Y");
dfui_dataset_celldata_add(ds, "packet", "Y");
dfui_form_dataset_add(f, ds);
} else {
for (d = storage_disk_first(a->s); d != NULL; d = disk_next(d)) {
ds = dfui_dataset_new();
dfui_dataset_celldata_add(ds, "disk",
disk_get_device_name(d));
dfui_dataset_celldata_add(ds, "boot0cfg", "Y");
dfui_dataset_celldata_add(ds, "packet", "Y");
dfui_form_dataset_add(f, ds);
}
}
if (!dfui_be_present(a->c, f, &r))
abort_backend();
a->result = 0;
if (strcmp(dfui_response_get_action_id(r), "ok") == 0) {
cmds = commands_new();
for (ds = dfui_response_dataset_get_first(r); ds != NULL;
ds = dfui_dataset_get_next(ds)) {
strlcpy(disk, dfui_dataset_get_value(ds, "disk"), 64);
strlcpy(boot0cfg, dfui_dataset_get_value(ds, "boot0cfg"), 32);
strlcpy(packet, dfui_dataset_get_value(ds, "packet"), 32);
if (strcasecmp(boot0cfg, "Y") == 0) {
cmd = command_add(cmds, "%s%s -B -o %spacket %s",
a->os_root, cmd_name(a, "BOOT0CFG"),
strcasecmp(packet, "Y") == 0 ? "" : "no",
disk);
command_set_failure_mode(cmd, COMMAND_FAILURE_WARN);
command_set_tag(cmd, "%s", disk);
cmd = command_add(cmds, "%s%s -v %s",
a->os_root, cmd_name(a, "BOOT0CFG"),
disk);
command_set_failure_mode(cmd, COMMAND_FAILURE_WARN);
command_set_tag(cmd, "%s", disk);
}
}
if (!commands_execute(a, cmds)) {
ask_to_wipe_boot_sector(a, cmds);
} else {
inform(a->c, _("Bootblocks were successfully installed!"));
a->result = 1;
}
commands_free(cmds);
}
dfui_form_free(f);
dfui_response_free(r);
}
void
fn_format_msdos_floppy(struct i_fn_args *a)
{
struct commands *cmds;
switch (dfui_be_present_dialog(a->c, _("Format MSDOS Floppy"),
_("Format Floppy|Return to Utilities Menu"),
_("Please insert the floppy to be formatted "
"in unit 0 (``drive A:'')."))) {
case 1:
cmds = commands_new();
command_add(cmds, "%s%s -y -f 1440 /dev/fd0",
a->os_root, cmd_name(a, "FDFORMAT"));
command_add(cmds, "%s%s -f 1440 fd0",
a->os_root, cmd_name(a, "NEWFS_MSDOS"));
if (commands_execute(a, cmds))
inform(a->c, _("Floppy successfully formatted!"));
else
inform(a->c, _("Floppy was not successfully formatted."));
break;
case 2:
return;
default:
abort_backend();
}
}
void
fn_create_cdboot_floppy(struct i_fn_args *a)
{
struct commands *cmds;
char msg_buf[1][1024];
snprintf(msg_buf[0], sizeof(msg_buf[0]),
"%s cannot be installed from a floppy; "
"it must be installed from a booted CD-ROM. "
"However, many older systems do not support booting "
"from a CD-ROM. For these systems, a boot disk can be "
"created. This boot disk contains the Smart Boot "
"Manager program, which can boot a CD-ROM even "
"on systems with BIOSes which do not support booting "
"from the CD-ROM.\n\n"
"Smart Boot Manager is not a part of %s; "
"the Smart Boot Manager project can be found here:\n\n"
"http://btmgr.sourceforge.net/\n\n"
"To create a CDBoot floppy, insert a blank floppy "
"in unit 0 (``drive A:'') before proceeding."
"",
OPERATING_SYSTEM_NAME, OPERATING_SYSTEM_NAME);
switch (dfui_be_present_dialog(a->c, _("Create CDBoot Floppy"),
_("Create CDBoot Floppy|Return to Utilities Menu"),
"%s", msg_buf[0])) {
case 1:
cmds = commands_new();
command_add(cmds, "%s%s -c %sboot/cdboot.flp.bz2 | "
"%s%s of=/dev/fd0 bs=32k",
a->os_root, cmd_name(a, "BUNZIP2"),
a->os_root,
a->os_root, cmd_name(a, "DD"));
if (commands_execute(a, cmds))
inform(a->c, _("CDBoot floppy successfully created!"));
else
inform(a->c, _("CDBoot floppy was not successfully created."));
break;
case 2:
return;
default:
abort_backend();
}
}
int
format_slice(struct i_fn_args *a)
{
struct commands *cmds;
struct command *cmd;
int result;
int cyl, hd, sec;
cmds = commands_new();
if ((storage_get_selected_disk(a->s) == NULL) ||
(storage_get_selected_slice(a->s) == NULL))
return 0;
disk_get_geometry(storage_get_selected_disk(a->s), &cyl, &hd, &sec);
command_add(cmds, "%s%s 'g c%d h%d s%d' >%snew.fdisk",
a->os_root, cmd_name(a, "ECHO"),
cyl, hd, sec,
a->tmp);
command_add(cmds, "%s%s 'p %d %d %lu %lu' >>%snew.fdisk",
a->os_root, cmd_name(a, "ECHO"),
slice_get_number(storage_get_selected_slice(a->s)),
DOSPTYP_DFLYBSD,
slice_get_start(storage_get_selected_slice(a->s)),
slice_get_size(storage_get_selected_slice(a->s)),
a->tmp);
if (slice_get_flags(storage_get_selected_slice(a->s)) & 0x80) {
command_add(cmds, "%s%s 'a %d' >>%snew.fdisk",
a->os_root, cmd_name(a, "ECHO"),
slice_get_number(storage_get_selected_slice(a->s)),
a->tmp);
}
command_add(cmds, "%s%s %snew.fdisk",
a->os_root, cmd_name(a, "CAT"), a->tmp);
temp_file_add(a, "new.fdisk");
cmd = command_add(cmds, "%s%s -v -f %snew.fdisk %s",
a->os_root, cmd_name(a, "FDISK"), a->tmp,
disk_get_device_name(storage_get_selected_disk(a->s)));
if (slice_get_size(storage_get_selected_slice(a->s)) == 0xFFFFFFFFU)
command_set_failure_mode(cmd, COMMAND_FAILURE_IGNORE);
command_add(cmds, "%s%s -f %sinstall.disklabel.%s",
a->os_root, cmd_name(a, "RM"),
a->tmp,
slice_get_device_name(storage_get_selected_slice(a->s)));
result = commands_execute(a, cmds);
commands_free(cmds);
return(result);
}