2 * Copyright 2008-2011, Haiku, Inc. All rights reserved.
3 * Distributed under the terms of the MIT License.
6 * Axel Dörfler, axeld@pinc-software.de
7 * Michael Pfeiffer <laplace@users.sourceforge.net>
11 #include "BootManagerController.h"
14 #include <Application.h>
17 #include <FindDirectory.h>
22 #include "BootDrive.h"
23 #include "DefaultPartitionPage.h"
24 #include "DescriptionPage.h"
25 #include "DrivesPage.h"
26 #include "FileSelectionPage.h"
27 #include "LegacyBootMenu.h"
28 #include "PartitionsPage.h"
29 #include "WizardView.h"
32 #undef B_TRANSLATION_CONTEXT
33 #define B_TRANSLATION_CONTEXT "BootManagerController"
36 BootManagerController::BootManagerController()
42 fSettings
.AddBool("install", true);
43 fSettings
.AddInt32("defaultPartition", 0);
44 fSettings
.AddInt32("timeout", -1);
47 if (find_directory(B_USER_SETTINGS_DIRECTORY
, &path
, true) == B_OK
) {
48 path
.Append("bootman/MBR");
49 fSettings
.AddString("file", path
.Path());
52 if (path
.GetParent(&parent
) == B_OK
) {
54 directory
.CreateDirectory(parent
.Path(), NULL
);
57 fSettings
.AddString("file", "");
60 // That's the only boot menu we support at the moment.
61 fBootMenus
.AddItem(new LegacyBootMenu());
65 BootManagerController::~BootManagerController()
71 BootManagerController::Previous(WizardView
* wizard
)
73 if (CurrentState() != kStateEntry
)
74 WizardController::Previous(wizard
);
76 fSettings
.ReplaceBool("install", false);
77 WizardController::Next(wizard
);
83 BootManagerController::InitialState()
90 BootManagerController::NextState(int32 state
)
96 if (fSettings
.FindString("disk", &path
) != B_OK
)
97 return kStateErrorEntry
;
101 fBootDrive
= new BootDrive(path
);
102 fBootMenu
= fBootDrive
->InstalledMenu(fBootMenus
);
104 if (fSettings
.FindBool("install")) {
105 int32 nextState
= fBootMenu
!= NULL
106 ? kStatePartitions
: kStateSaveMBR
;
108 // TODO: call BootDrive::AddSupportedMenus() once we support
109 // more than one type of boot menu - we'll probably need a
110 // requester to choose from them then as well.
111 if (fBootMenu
== NULL
)
112 fBootMenu
= fBootMenus
.ItemAt(0);
114 fCollectPartitionsStatus
= fBootMenu
->CollectPartitions(
115 *fBootDrive
, fSettings
);
120 return kStateUninstall
;
123 case kStateErrorEntry
:
124 be_app
->PostMessage(B_QUIT_REQUESTED
);
129 return kStateMBRSaved
;
133 return kStatePartitions
;
135 case kStatePartitions
:
136 if (_HasSelectedPartitions())
137 return kStateDefaultPartitions
;
140 case kStateDefaultPartitions
:
141 return kStateInstallSummary
;
143 case kStateInstallSummary
:
144 if (_WriteBootMenu())
145 return kStateInstalled
;
148 case kStateInstalled
:
149 be_app
->PostMessage(B_QUIT_REQUESTED
);
152 case kStateUninstall
:
154 return kStateUninstalled
;
157 case kStateUninstalled
:
158 be_app
->PostMessage(B_QUIT_REQUESTED
);
161 // cannot leave the current state/page
167 BootManagerController::_HasSelectedPartitions()
170 for (int32 i
= 0; fSettings
.FindMessage("partition", i
, &message
) == B_OK
;
173 if (message
.FindBool("show", &show
) == B_OK
&& show
)
177 BAlert
* alert
= new BAlert("info",
178 B_TRANSLATE("At least one partition must be selected!"),
179 B_TRANSLATE_COMMENT("OK", "Button"));
180 alert
->SetFlags(alert
->Flags() | B_CLOSE_ON_ESCAPE
);
188 BootManagerController::_WriteBootMenu()
190 BAlert
* alert
= new BAlert("confirm", B_TRANSLATE("About to write the "
191 "boot menu to disk. Are you sure you want to continue?"),
192 B_TRANSLATE_COMMENT("Write boot menu", "Button"),
193 B_TRANSLATE_COMMENT("Back", "Button"), NULL
, B_WIDTH_AS_USUAL
,
196 if (alert
->Go() == 1)
199 fWriteBootMenuStatus
= fBootMenu
->Install(*fBootDrive
, fSettings
);
205 BootManagerController::_SaveMBR()
208 fSettings
.FindString("file", &path
);
209 BFile
file(path
.String(), B_READ_WRITE
| B_CREATE_FILE
| B_ERASE_FILE
);
210 fSaveMBRStatus
= fBootMenu
->SaveMasterBootRecord(&fSettings
, &file
);
216 BootManagerController::_RestoreMBR()
220 fSettings
.FindString("disk", &disk
);
221 fSettings
.FindString("file", &path
);
224 message
<< B_TRANSLATE_COMMENT("About to restore the Master Boot Record "
225 "(MBR) of %disk from %file. Do you wish to continue?",
226 "Don't translate the place holders: %disk and %file");
227 message
.ReplaceFirst("%disk", disk
);
228 message
.ReplaceFirst("%file", path
);
230 BAlert
* alert
= new BAlert("confirm", message
.String(),
231 B_TRANSLATE_COMMENT("Restore MBR", "Button"),
232 B_TRANSLATE_COMMENT("Back", "Button"),
233 NULL
, B_WIDTH_AS_USUAL
, B_WARNING_ALERT
);
234 if (alert
->Go() == 1)
237 BFile
file(path
.String(), B_READ_ONLY
);
238 fRestoreMBRStatus
= fBootMenu
->RestoreMasterBootRecord(&fSettings
, &file
);
244 BootManagerController::CreatePage(int32 state
, WizardView
* wizard
)
246 WizardPageView
* page
= NULL
;
247 BRect
frame(0, 0, 300, 250);
251 fSettings
.ReplaceBool("install", true);
252 page
= new DrivesPage(wizard
, fBootMenus
, &fSettings
, "drives");
254 case kStateErrorEntry
:
255 page
= _CreateErrorEntryPage();
256 wizard
->SetPreviousButtonHidden(true);
257 wizard
->SetNextButtonLabel(B_TRANSLATE_COMMENT("Done", "Button"));
260 page
= _CreateSaveMBRPage(frame
);
261 wizard
->SetPreviousButtonHidden(false);
264 page
= _CreateMBRSavedPage();
266 case kStatePartitions
:
267 page
= new PartitionsPage(&fSettings
, "partitions");
268 wizard
->SetPreviousButtonHidden(false);
270 case kStateDefaultPartitions
:
271 page
= new DefaultPartitionPage(&fSettings
, frame
, "default");
273 case kStateInstallSummary
:
274 page
= _CreateInstallSummaryPage();
276 case kStateInstalled
:
277 page
= _CreateInstalledPage();
278 wizard
->SetNextButtonLabel(B_TRANSLATE_COMMENT("Done", "Button"));
280 case kStateUninstall
:
281 page
= _CreateUninstallPage(frame
);
282 wizard
->SetPreviousButtonHidden(false);
284 case kStateUninstalled
:
285 // TODO prevent overwriting MBR after clicking "Previous"
286 page
= _CreateUninstalledPage();
287 wizard
->SetNextButtonLabel(B_TRANSLATE_COMMENT("Done", "Button"));
296 BootManagerController::_CreateErrorEntryPage()
300 if (fCollectPartitionsStatus
== B_ENTRY_NOT_FOUND
) {
301 description
<< B_TRANSLATE_COMMENT("Partition table not compatible",
303 << B_TRANSLATE("The partition table of the first hard disk is not "
304 "compatible with Boot Manager.\n"
305 "Boot Manager only works with IBM PC MBR partitions.");
306 } else if (fCollectPartitionsStatus
== B_PARTITION_TOO_SMALL
) {
307 description
<< B_TRANSLATE_COMMENT("First partition starts too early",
309 << B_TRANSLATE("The first partition on the disk starts too early "
310 "and does not leave enough space free for a boot menu.\n"
311 "Boot Manager needs 2 KiB available space before the first "
314 description
<< B_TRANSLATE_COMMENT("Error reading partition table",
316 << B_TRANSLATE("Boot Manager is unable to read the partition "
320 return new DescriptionPage("errorEntry", description
.String(), true);
325 BootManagerController::_CreateSaveMBRPage(BRect frame
)
329 fSettings
.FindString("disk", &disk
);
331 description
<< B_TRANSLATE_COMMENT("Backup Master Boot Record", "Title")
332 << "\n" << B_TRANSLATE("The Master Boot Record (MBR) of the boot "
335 "will now be saved to disk. Please select a file to "
336 "save the MBR into.\n\n"
337 "If something goes wrong with the installation or if "
338 "you later wish to remove the boot menu, simply run the "
339 "bootman program and choose the 'Uninstall' option.");
340 description
.ReplaceFirst("%s", disk
);
342 return new FileSelectionPage(&fSettings
, frame
, "saveMBR",
343 description
.String(),
349 BootManagerController::_CreateMBRSavedPage()
353 fSettings
.FindString("file", &file
);
355 if (fSaveMBRStatus
== B_OK
) {
356 description
<< B_TRANSLATE_COMMENT("Old Master Boot Record saved",
358 << B_TRANSLATE("The old Master Boot Record was successfully "
359 "saved to %s.") << "\n";
361 description
<< B_TRANSLATE_COMMENT("Old Master Boot Record backup "
362 "failure", "Title") << "\n"
363 << B_TRANSLATE("The old Master Boot Record could not be saved "
364 "to %s. You can continue the installation but there will be no "
365 "way to uninstall the boot menu.") << "\n";
367 description
.ReplaceFirst("%s", file
);
369 return new DescriptionPage("summary", description
.String(), true);
374 BootManagerController::_CreateInstallSummaryPage()
378 fSettings
.FindString("disk", &disk
);
380 description
<< B_TRANSLATE_COMMENT("Summary", "Title") << "\n"
381 << B_TRANSLATE("About to write the following boot menu to the boot "
382 "disk (%s). Please verify the information below before continuing.")
384 description
.ReplaceFirst("%s", disk
);
387 for (int32 i
= 0; fSettings
.FindMessage("partition", i
, &message
) == B_OK
;
390 if (message
.FindBool("show", &show
) != B_OK
|| !show
)
395 message
.FindString("name", &name
);
396 message
.FindString("path", &path
);
399 if (fBootMenu
->GetDisplayText(name
.String(), displayName
) == B_OK
)
400 description
<< displayName
<< "\t(" << path
<< ")\n";
402 description
<< name
<< "\t(" << path
<< ")\n";
405 return new DescriptionPage("summary", description
.String(), true);
410 BootManagerController::_CreateInstalledPage()
414 if (fWriteBootMenuStatus
== B_OK
) {
415 description
<< B_TRANSLATE_COMMENT("Installation of boot menu "
416 "completed", "Title") << "\n"
417 << B_TRANSLATE("The boot manager has been successfully installed "
420 description
<< B_TRANSLATE_COMMENT("Installation of boot menu failed",
422 << B_TRANSLATE("An error occurred writing the boot menu. "
423 "The Master Boot Record might be destroyed, "
424 "you should restore the MBR now!");
427 return new DescriptionPage("done", description
, true);
432 BootManagerController::_CreateUninstallPage(BRect frame
)
435 description
<< B_TRANSLATE_COMMENT("Uninstall boot manager", "Title")
437 << B_TRANSLATE("Please locate the Master Boot Record (MBR) save file "
438 "to restore from. This is the file that was created when the "
439 "boot manager was first installed.");
441 return new FileSelectionPage(&fSettings
, frame
, "restoreMBR",
442 description
.String(), B_OPEN_PANEL
);
447 BootManagerController::_CreateUninstalledPage()
452 fSettings
.FindString("disk", &disk
);
453 fSettings
.FindString("file", &file
);
455 if (fRestoreMBRStatus
== B_OK
) {
456 description
<< B_TRANSLATE_COMMENT("Uninstallation of boot menu "
457 "completed", "Title") << "\n"
458 << B_TRANSLATE("The Master Boot Record of the boot device "
459 "(%DISK) has been successfully restored from %FILE.");
460 description
.ReplaceFirst("%DISK", disk
);
461 description
.ReplaceFirst("%FILE", file
);
463 description
<< B_TRANSLATE_COMMENT("Uninstallation of boot menu "
464 "failed", "Title") << "\n"
465 << B_TRANSLATE("The Master Boot Record could not be restored!");
468 return new DescriptionPage("summary", description
.String(), true);