Save and restore MBR and write boot menu.

git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@24935 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Michael Pfeiffer
2008-04-12 08:25:38 +00:00
parent 7437e205be
commit dff9173818
9 changed files with 566 additions and 100 deletions
+11 -5
View File
@@ -23,17 +23,23 @@
"path" String (path to partition in /dev/...) "path" String (path to partition in /dev/...)
"size" long (size of partition in bytes) "size" long (size of partition in bytes)
*/ */
enum {
// Not enough space free before first partition for boot loader
kErrorBootSectorTooSmall = B_ERRORS_END + 1,
};
class BootDrive class BootDrive
{ {
public: public:
BootDrive() {} BootDrive() {}
virtual ~BootDrive() {} virtual ~BootDrive() {}
virtual bool IsBootMenuInstalled() = 0; virtual bool IsBootMenuInstalled(BMessage* settings) = 0;
virtual status_t ReadPartitions(BMessage *message) = 0; virtual status_t ReadPartitions(BMessage* settings) = 0;
virtual status_t WriteBootMenu(BMessage *message) = 0; virtual status_t WriteBootMenu(BMessage* settings) = 0;
virtual status_t SaveMasterBootRecord(BFile *file) = 0; virtual status_t SaveMasterBootRecord(BMessage* settings, BFile* file) = 0;
virtual status_t RestoreMasterBootRecord(BFile *file) = 0; virtual status_t RestoreMasterBootRecord(BMessage* settings, BFile* file) = 0;
}; };
#endif // BOOT_DRIVE_H #endif // BOOT_DRIVE_H
+69
View File
@@ -0,0 +1,69 @@
// THIS FILE WAS GENERATED WITH
// ./make_array kBootLoader bootman.bin
static const uint8 kBootLoader[] = {
0xb8, 0xc0, 0x07, 0x8e, 0xd8, 0x8e, 0xc0, 0x8e, 0xd0, 0xbc, 0xff, 0xff, 0xfc, 0xb4, 0x06, 0x30,
0xc0, 0xb7, 0x0f, 0x31, 0xc9, 0xba, 0x4f, 0x18, 0xcd, 0x10, 0xb7, 0x00, 0xb4, 0x02, 0xba, 0x1f,
0x01, 0xcd, 0x10, 0xbe, 0x83, 0x00, 0xb3, 0x0f, 0xe8, 0x2c, 0x00, 0xb4, 0x02, 0xba, 0x1b, 0x17,
0xb3, 0x07, 0xcd, 0x10, 0xbe, 0x96, 0x00, 0xe8, 0x1d, 0x00, 0xb4, 0x42, 0xb2, 0x80, 0xbe, 0x73,
0x00, 0xcd, 0x13, 0x72, 0x03, 0xe9, 0xb8, 0x01, 0xbe, 0xb1, 0x00, 0xb3, 0x04, 0xe8, 0x07, 0x00,
0xb4, 0x00, 0xcd, 0x16, 0xf4, 0xeb, 0xf9, 0x51, 0xe9, 0x11, 0x00, 0xb9, 0x01, 0x00, 0xb4, 0x09,
0xcd, 0x10, 0xb4, 0x03, 0xcd, 0x10, 0xfe, 0xc2, 0xb4, 0x02, 0xcd, 0x10, 0xac, 0x3c, 0x00, 0x75,
0xea, 0x59, 0xc3, 0x10, 0x00, 0x03, 0x00, 0x00, 0x02, 0xc0, 0x07, 0x01, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x48, 0x61, 0x69, 0x6b, 0x75, 0x20, 0x42, 0x6f, 0x6f, 0x74, 0x20, 0x4d, 0x61,
0x6e, 0x61, 0x67, 0x65, 0x72, 0x00, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x20, 0x61, 0x6e, 0x20,
0x4f, 0x53, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6d, 0x65, 0x6e, 0x75,
0x00, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x20, 0x6c, 0x6f, 0x61, 0x64, 0x69, 0x6e, 0x67, 0x20, 0x73,
0x65, 0x63, 0x74, 0x6f, 0x72, 0x73, 0x21, 0x00, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42,
0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42,
0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42,
0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42,
0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42,
0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42,
0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42,
0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42,
0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42,
0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42,
0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42,
0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42,
0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42,
0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42,
0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42,
0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42,
0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42,
0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42,
0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42,
0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x55, 0xaa,
0xa1, 0x99, 0x03, 0xa3, 0x46, 0x03, 0xb8, 0x13, 0x00, 0xf7, 0x26, 0x9b, 0x03, 0x89, 0xd3, 0x50,
0xb4, 0x00, 0xcd, 0x1a, 0x58, 0x01, 0xd0, 0x11, 0xcb, 0xa3, 0x4a, 0x03, 0x89, 0x1e, 0x4c, 0x03,
0xa0, 0x97, 0x03, 0xd0, 0xe8, 0xb3, 0x0c, 0x28, 0xc3, 0x88, 0x1e, 0x48, 0x03, 0xe8, 0x65, 0x00,
0x81, 0x3e, 0x9b, 0x03, 0xff, 0xff, 0x74, 0x27, 0xb4, 0x01, 0xcd, 0x16, 0x75, 0x21, 0xe8, 0x05,
0x00, 0x73, 0xf5, 0xe9, 0x9b, 0x00, 0xb4, 0x00, 0xcd, 0x1a, 0x3b, 0x0e, 0x4c, 0x03, 0x72, 0x08,
0x77, 0x08, 0x3b, 0x16, 0x4a, 0x03, 0x77, 0x02, 0xf8, 0xc3, 0xf9, 0xc3, 0xe8, 0x36, 0x00, 0xb4,
0x00, 0xcd, 0x16, 0x80, 0xfc, 0x50, 0x74, 0x0c, 0x80, 0xfc, 0x48, 0x74, 0x18, 0x80, 0xfc, 0x1c,
0x74, 0x6f, 0xeb, 0xeb, 0xa1, 0x46, 0x03, 0x40, 0x3b, 0x06, 0x97, 0x03, 0x75, 0x02, 0x31, 0xc0,
0xa3, 0x46, 0x03, 0xeb, 0xd7, 0xa1, 0x46, 0x03, 0x09, 0xc0, 0x75, 0x03, 0xa1, 0x97, 0x03, 0x48,
0xa3, 0x46, 0x03, 0xeb, 0xc7, 0xa0, 0x48, 0x03, 0xa2, 0x49, 0x03, 0xbe, 0x9d, 0x03, 0x31, 0xc9,
0xac, 0xfe, 0xc8, 0xd0, 0xe8, 0xb2, 0x28, 0x28, 0xc2, 0x8a, 0x36, 0x49, 0x03, 0xb4, 0x02, 0xcd,
0x10, 0x89, 0xcf, 0x81, 0xe7, 0x03, 0x00, 0x8a, 0x9d, 0x5e, 0x03, 0x3b, 0x0e, 0x46, 0x03, 0x75,
0x03, 0x80, 0xf3, 0x08, 0xe8, 0x56, 0x00, 0x81, 0xc6, 0x08, 0x00, 0xfe, 0x06, 0x49, 0x03, 0x41,
0x3b, 0x0e, 0x97, 0x03, 0x75, 0xca, 0xb4, 0x02, 0xba, 0x1a, 0x15, 0xba, 0x1c, 0x18, 0xcd, 0x10,
0xc3, 0xbe, 0x9d, 0x03, 0x8b, 0x0e, 0x46, 0x03, 0x41, 0x30, 0xe4, 0xe9, 0x04, 0x00, 0x81, 0xc6,
0x08, 0x00, 0xac, 0x01, 0xc6, 0xe2, 0xf7, 0xbf, 0x56, 0x03, 0xb9, 0x04, 0x00, 0xad, 0xab, 0xe2,
0xfc, 0xb4, 0x42, 0xb2, 0x80, 0xbe, 0x4e, 0x03, 0xcd, 0x13, 0xbe, 0x62, 0x03, 0x72, 0x2a, 0xa1,
0xfe, 0x01, 0x3d, 0x55, 0xaa, 0xbe, 0x78, 0x03, 0x75, 0x1f, 0xe9, 0xe3, 0xfc, 0x51, 0xe9, 0x11,
0x00, 0xb9, 0x01, 0x00, 0xb4, 0x09, 0xcd, 0x10, 0xb4, 0x03, 0xcd, 0x10, 0xfe, 0xc2, 0xb4, 0x02,
0xcd, 0x10, 0xac, 0x3c, 0x00, 0x75, 0xea, 0x59, 0xc3, 0xbb, 0x0f, 0x00, 0xe8, 0xde, 0xff, 0xb4,
0x00, 0xcd, 0x16, 0xf4, 0xeb, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00,
0x01, 0x00, 0x00, 0x00, 0xc0, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x04,
0x03, 0x02, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x20, 0x6c, 0x6f, 0x61, 0x64, 0x69, 0x6e, 0x67, 0x20,
0x73, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x73, 0x00, 0x4e, 0x6f, 0x74, 0x20, 0x61, 0x20, 0x62, 0x6f,
0x6f, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x20, 0x70, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e,
0x00, 0x42, 0x6f, 0x6f, 0x74, 0x21, 0x00, 0x06, 0x00, 0x02, 0x00, 0x05, 0x00, 0x06, 0x48, 0x41,
0x49, 0x4b, 0x55, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x46, 0x72, 0x65,
0x65, 0x42, 0x53, 0x44, 0x00, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x44, 0x4f,
0x53, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x4c, 0x49, 0x4e, 0x55, 0x58,
0x00, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x42, 0x65, 0x4f, 0x53, 0x20, 0x52,
0x35, 0x00, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x4f, 0x70, 0x65, 0x6e, 0x42,
0x53, 0x44, 0x00, 0xaa, 0xaa, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
+62 -43
View File
@@ -61,7 +61,7 @@ BootManagerController::BootManagerController()
fSettings.AddString("file", ""); fSettings.AddString("file", "");
} }
fBootDrive->ReadPartitions(&fSettings); fReadPartitionsStatus = fBootDrive->ReadPartitions(&fSettings);
} }
@@ -73,7 +73,9 @@ BootManagerController::~BootManagerController()
int32 int32
BootManagerController::InitialState() BootManagerController::InitialState()
{ {
return kStateEntry; if (fReadPartitionsStatus == B_OK)
return kStateEntry;
return kStateErrorEntry;
} }
@@ -86,7 +88,7 @@ BootManagerController::NextState(int32 state)
bool install; bool install;
fSettings.FindBool("install", &install); fSettings.FindBool("install", &install);
if (install) { if (install) {
if (fBootDrive->IsBootMenuInstalled()) if (fBootDrive->IsBootMenuInstalled(&fSettings))
return kStatePartitions; return kStatePartitions;
else else
return kStateSaveMBR; return kStateSaveMBR;
@@ -94,6 +96,10 @@ BootManagerController::NextState(int32 state)
else else
return kStateUninstall; return kStateUninstall;
} }
case kStateErrorEntry:
be_app->PostMessage(B_QUIT_REQUESTED);
break;
case kStateSaveMBR: case kStateSaveMBR:
if (_SaveMBR()) if (_SaveMBR())
@@ -162,10 +168,7 @@ BootManagerController::_WriteBootMenu()
if (alert->Go() == 1) if (alert->Go() == 1)
return false; return false;
status_t status = fBootDrive->WriteBootMenu(&fSettings); fWriteBootMenuStatus = fBootDrive->WriteBootMenu(&fSettings);
fSettings.RemoveName("installStatus");
fSettings.AddInt32("installStatus", status);
return true; return true;
} }
@@ -173,11 +176,10 @@ BootManagerController::_WriteBootMenu()
bool bool
BootManagerController::_SaveMBR() BootManagerController::_SaveMBR()
{ {
BFile file("", B_READ_WRITE | B_CREATE_FILE | B_ERASE_FILE); BString path;
status_t state = fBootDrive->SaveMasterBootRecord(&file); fSettings.FindString("file", &path);
fSettings.RemoveName("saveMBRStatus"); BFile file(path.String(), B_READ_WRITE | B_CREATE_FILE | B_ERASE_FILE);
fSettings.AddInt32("saveMBRStatus", state); fSaveMBRStatus = fBootDrive->SaveMasterBootRecord(&fSettings, &file);
return true; return true;
} }
@@ -201,10 +203,7 @@ BootManagerController::_RestoreMBR()
return false; return false;
BFile file(path.String(), B_READ_ONLY); BFile file(path.String(), B_READ_ONLY);
status_t state = fBootDrive->RestoreMasterBootRecord(&file); fRestoreMBRStatus = fBootDrive->RestoreMasterBootRecord(&fSettings, &file);
fSettings.RemoveName("restoreMBRStatus");
fSettings.AddInt32("restoreMBRStatus", state);
return true; return true;
} }
@@ -220,6 +219,11 @@ BootManagerController::CreatePage(int32 state, WizardView* wizard)
page = new EntryPage(&fSettings, frame, "entry"); page = new EntryPage(&fSettings, frame, "entry");
wizard->SetPreviousButtonHidden(true); wizard->SetPreviousButtonHidden(true);
break; break;
case kStateErrorEntry:
page = _CreateErrorEntryPage(frame);
wizard->SetPreviousButtonHidden(true);
wizard->SetNextButtonLabel("Done");
break;
case kStateSaveMBR: case kStateSaveMBR:
page = _CreateSaveMBRPage(frame); page = _CreateSaveMBRPage(frame);
wizard->SetPreviousButtonHidden(false); wizard->SetPreviousButtonHidden(false);
@@ -258,6 +262,26 @@ BootManagerController::CreatePage(int32 state, WizardView* wizard)
} }
WizardPageView*
BootManagerController::_CreateErrorEntryPage(BRect frame)
{
BString description;
if (fReadPartitionsStatus == kErrorBootSectorTooSmall)
description <<
"Partition Table Not Compatible\n\n"
"The partition table of the first hard disk is not compatible "
"with Boot Manager.\n"
"Boot Manager needs 2 KB available space before the first partition.";
else
description <<
"Error Reading Partition Table\n\n"
"Boot Manager is unable to read the partition table!";
return new DescriptionPage(frame, "errorEntry", description.String(), true);
}
WizardPageView* WizardPageView*
BootManagerController::_CreateSaveMBRPage(BRect frame) BootManagerController::_CreateSaveMBRPage(BRect frame)
{ {
@@ -275,9 +299,8 @@ BootManagerController::_CreateSaveMBRPage(BRect frame)
"you later wish to remove the boot menu, simply run the " "you later wish to remove the boot menu, simply run the "
"bootman program and choose to 'Uninstall' option."; "bootman program and choose to 'Uninstall' option.";
FileSelectionPage* page = new FileSelectionPage(&fSettings, frame, "saveMBR", description.String(), return new FileSelectionPage(&fSettings, frame, "saveMBR", description.String(),
B_SAVE_PANEL); B_SAVE_PANEL);
return page;
} }
@@ -288,13 +311,19 @@ BootManagerController::_CreateMBRSavedPage(BRect frame)
BString file; BString file;
fSettings.FindString("file", &file); fSettings.FindString("file", &file);
description << if (fSaveMBRStatus == B_OK) {
"Old Master Boot Record Saved\n\n" description <<
"The old Master Boot Record was successfully save to " "Old Master Boot Record Saved\n\n"
<< file << ".\n"; "The old Master Boot Record was successfully save to "
<< file << ".\n";
} else {
description <<
"Old Master Boot Record Saved Failure\n\n"
"The old Master Boot Record could not be saved to "
<< file << ".\n";
}
DescriptionPage* page = new DescriptionPage(frame, "summary", description.String(), true); return new DescriptionPage(frame, "summary", description.String(), true);
return page;
} }
@@ -325,8 +354,7 @@ BootManagerController::_CreateInstallSummaryPage(BRect frame)
description << name << "\t(" << path << ")\n"; description << name << "\t(" << path << ")\n";
} }
DescriptionPage* page = new DescriptionPage(frame, "summary", description.String(), true); return new DescriptionPage(frame, "summary", description.String(), true);
return page;
} }
@@ -335,20 +363,17 @@ BootManagerController::_CreateInstalledPage(BRect frame)
{ {
const char* description; const char* description;
int32 status; if (fWriteBootMenuStatus == B_OK) {
fSettings.FindInt32("installStatus", &status);
if (status == B_OK) {
description = "Installation Boot Menu Completed\n\n" description = "Installation Boot Menu Completed\n\n"
"The boot manager has been successfully installed " "The boot manager has been successfully installed "
"on your system."; "on your system.";
} else { } else {
// TODO
description = "Installation Boot Menu Failed\n\n" description = "Installation Boot Menu Failed\n\n"
"TODO"; "An error occured writing the boot menu. The Master Boot Record "
"might be destroyed, you should restore the MBR now!";
} }
DescriptionPage* page = new DescriptionPage(frame, "done", description, true); return new DescriptionPage(frame, "done", description, true);
return page;
} }
@@ -363,9 +388,8 @@ BootManagerController::_CreateUninstallPage(BRect frame)
"restore from. This is the file that was created when the " "restore from. This is the file that was created when the "
"boot manager was first installed."; "boot manager was first installed.";
FileSelectionPage* page = new FileSelectionPage(&fSettings, frame, "restoreMBR", description.String(), return new FileSelectionPage(&fSettings, frame, "restoreMBR", description.String(),
B_OPEN_PANEL); B_OPEN_PANEL);
return page;
} }
@@ -378,22 +402,17 @@ BootManagerController::_CreateUninstalledPage(BRect frame)
fSettings.FindString("disk", &disk); fSettings.FindString("disk", &disk);
fSettings.FindString("file", &file); fSettings.FindString("file", &file);
int32 status; if (fRestoreMBRStatus == B_OK) {
fSettings.FindInt32("restoreMBRStatus", &status);
if (status == B_OK) {
description << description <<
"Uninstallation Boot Menu Completed\n\n" "Uninstallation Boot Menu Completed\n\n"
"The Master Boot Record of the boot device " "The Master Boot Record of the boot device "
"(" << disk << ") has been successfully restored from " "(" << disk << ") has been successfully restored from "
<< file << "."; << file << ".";
} else { } else {
// TODO
description << description <<
"Uninstallation Boot Menu Failed\n\n" "Uninstallation Boot Menu Failed\n\n"
"TODO"; "The Master Boot Record could not be restored!";
} }
DescriptionPage* page = new DescriptionPage(frame, "summary", description.String(), true); return new DescriptionPage(frame, "summary", description.String(), true);
return page;
} }
+7 -3
View File
@@ -25,9 +25,6 @@ class BRect;
"file" String (the file where the backup of the MBR is saved) "file" String (the file where the backup of the MBR is saved)
"defaultPartition" int32 (index of default partition) "defaultPartition" int32 (index of default partition)
"timeout" int32 (timeout in seconds, -1 for no timeout) "timeout" int32 (timeout in seconds, -1 for no timeout)
"installStatus" int32 (status_t)
"saveMBRStatus" int32 (status_t)
"restoreMBRStatus" int32 (status_t)
*/ */
class BootManagerController : public WizardController class BootManagerController : public WizardController
@@ -45,6 +42,7 @@ private:
enum State { enum State {
kStateEntry, kStateEntry,
kStateErrorEntry,
// Install states // Install states
kStateSaveMBR, kStateSaveMBR,
@@ -64,6 +62,7 @@ private:
bool _SaveMBR(); bool _SaveMBR();
bool _RestoreMBR(); bool _RestoreMBR();
WizardPageView* _CreateErrorEntryPage(BRect frame);
WizardPageView* _CreateSaveMBRPage(BRect frame); WizardPageView* _CreateSaveMBRPage(BRect frame);
WizardPageView* _CreateMBRSavedPage(BRect frame); WizardPageView* _CreateMBRSavedPage(BRect frame);
WizardPageView* _CreateInstallSummaryPage(BRect frame); WizardPageView* _CreateInstallSummaryPage(BRect frame);
@@ -73,6 +72,11 @@ private:
BMessage fSettings; BMessage fSettings;
BootDrive* fBootDrive; BootDrive* fBootDrive;
status_t fReadPartitionsStatus;
status_t fWriteBootMenuStatus;
status_t fSaveMBRStatus;
status_t fRestoreMBRStatus;
}; };
-1
View File
@@ -13,7 +13,6 @@ Application bootman :
FileSelectionPage.cpp FileSelectionPage.cpp
LegacyBootDrive.cpp LegacyBootDrive.cpp
PartitionsPage.cpp PartitionsPage.cpp
TestBootDrive.cpp
UninstallPage.cpp UninstallPage.cpp
WizardController.cpp WizardController.cpp
WizardPageView.cpp WizardPageView.cpp
+355 -25
View File
@@ -17,7 +17,93 @@
#include <Path.h> #include <Path.h>
#include <String.h> #include <String.h>
#include <errno.h>
#include <fcntl.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <ByteOrder.h>
#include <DataIO.h>
#include <File.h>
#include <String.h>
#include "BootLoader.h"
#define USE_SECOND_DISK 0
class Buffer : public BMallocIO
{
public:
Buffer() : BMallocIO() {}
bool WriteInt8(int8 value);
bool WriteInt16(int16 value);
bool WriteInt32(int32 value);
bool WriteInt64(int64 value);
bool WriteString(const char* value);
bool Align(int16 alignment);
bool Fill(int16 size, int8 fillByte);
};
bool
Buffer::WriteInt8(int8 value)
{
return Write(&value, sizeof(value)) == sizeof(value);
}
bool
Buffer::WriteInt16(int16 value)
{
return WriteInt8(value & 0xff) && WriteInt8(value >> 8);
}
bool
Buffer::WriteInt32(int32 value)
{
return WriteInt8(value & 0xff) && WriteInt8(value >> 8) &&
WriteInt8(value >> 16) && WriteInt8(value >> 24);
}
bool
Buffer::WriteInt64(int64 value)
{
return WriteInt32(value) && WriteInt32(value >> 32);
}
bool
Buffer::WriteString(const char* value)
{
int len = strlen(value) + 1;
return WriteInt8(len) && Write(value, len) == len;
}
bool
Buffer::Align(int16 alignment)
{
if ((Position() % alignment) == 0)
return true;
return Fill(alignment - (Position() % alignment), 0);
}
bool
Buffer::Fill(int16 size, int8 fillByte)
{
for (int i = 0; i < size; i ++) {
if (!WriteInt8(fillByte))
return false;
}
return true;
}
class PartitionRecorder : public BDiskDeviceVisitor class PartitionRecorder : public BDiskDeviceVisitor
@@ -28,16 +114,22 @@ public:
virtual bool Visit(BDiskDevice* device); virtual bool Visit(BDiskDevice* device);
virtual bool Visit(BPartition* partition, int32 level); virtual bool Visit(BPartition* partition, int32 level);
bool HasPartitions() const;
off_t FirstOffset() const;
private: private:
bool _Record(BPartition* partition); bool _Record(BPartition* partition);
BMessage* fSettings; BMessage* fSettings;
int32 fIndex; int32 fIndex;
off_t fFirstOffset;
}; };
PartitionRecorder::PartitionRecorder(BMessage* settings) PartitionRecorder::PartitionRecorder(BMessage* settings)
: fSettings(settings) : fSettings(settings)
, fIndex(0)
, fFirstOffset((off_t)-1)
{ {
} }
@@ -56,6 +148,20 @@ PartitionRecorder::Visit(BPartition* partition, int32 level)
} }
bool
PartitionRecorder::HasPartitions() const
{
return fFirstOffset != (off_t)-1;
}
off_t
PartitionRecorder::FirstOffset() const
{
return fFirstOffset;
}
bool bool
PartitionRecorder::_Record(BPartition* partition) PartitionRecorder::_Record(BPartition* partition)
{ {
@@ -75,13 +181,20 @@ PartitionRecorder::_Record(BPartition* partition)
type = "Unknown"; type = "Unknown";
BMessage message; BMessage message;
// Data as required by BootLoader.h
message.AddBool("show", true); message.AddBool("show", true);
message.AddString("name", name); message.AddString("name", name);
message.AddString("type", type); message.AddString("type", type);
message.AddString("path", partitionPath.Path()); message.AddString("path", partitionPath.Path());
message.AddInt64("size", partition->ContentSize()); message.AddInt64("size", partition->ContentSize());
fSettings->AddMessage("partition", &message); // Specific data
message.AddInt64("offset", partition->Offset());
fSettings->AddMessage("partition", &message);
if (partition->Offset() < fFirstOffset)
fFirstOffset = partition->Offset();
return false; return false;
} }
@@ -97,62 +210,279 @@ LegacyBootDrive::~LegacyBootDrive()
bool bool
LegacyBootDrive::IsBootMenuInstalled() LegacyBootDrive::IsBootMenuInstalled(BMessage* settings)
{ {
// TODO detect bootman
return false; return false;
} }
status_t status_t
LegacyBootDrive::ReadPartitions(BMessage *message) LegacyBootDrive::ReadPartitions(BMessage *settings)
{ {
BDiskDeviceRoster diskDeviceRoster; BDiskDeviceRoster diskDeviceRoster;
BDiskDevice device; BDiskDevice device;
// first disk only bool diskFound = false;
if (diskDeviceRoster.GetNextDevice(&device) == B_OK) { while (diskDeviceRoster.GetNextDevice(&device) == B_OK) {
BPath path; BPath path;
if (device.GetPath(&path) != B_OK) if (device.GetPath(&path) != B_OK)
return B_ERROR; return B_ERROR;
message->AddString("disk", path.Path()); PartitionRecorder recorder(settings);
PartitionRecorder recorder(message);
device.VisitEachDescendant(&recorder); device.VisitEachDescendant(&recorder);
if (!diskFound) {
settings->AddString("disk", path.Path());
diskFound = true;
#if not USE_SECOND_DISK
// ignored in test build
off_t size = sizeof(kBootLoader);
if (!recorder.HasPartitions() || recorder.FirstOffset() < size)
return kErrorBootSectorTooSmall;
#endif
}
} }
return B_OK;
#if USE_SECOND_DISK
// for testing only write boot menu to second hdd
settings->ReplaceString("disk", "/dev/disk/ata/1/master/raw");
#endif
if (diskFound)
return B_OK;
else
return B_ERROR;
} }
status_t status_t
LegacyBootDrive::WriteBootMenu(BMessage *message) LegacyBootDrive::WriteBootMenu(BMessage *settings)
{ {
// TODO
printf("WriteBootMenu:\n"); printf("WriteBootMenu:\n");
message->PrintToStream(); settings->PrintToStream();
BString path;
if (settings->FindString("disk", &path) != B_OK)
return B_BAD_VALUE;
BMessage partition; int32 defaultPartitionIndex;
int32 index = 0; if (settings->FindInt32("defaultPartition", &defaultPartitionIndex) != B_OK)
for (; message->FindMessage("partition", index, &partition) == B_OK; index ++) { return B_BAD_VALUE;
printf("Partition %d:\n", (int)index);
partition.PrintToStream(); int32 timeout;
if (settings->FindInt32("timeout", &timeout) != B_OK)
return B_BAD_VALUE;
int fd = open(path.String(), O_RDWR);
if (fd < 0)
return B_IO_ERROR;
MasterBootRecord oldMBR;
if (read(fd, &oldMBR, sizeof(oldMBR)) != sizeof(oldMBR)) {
close(fd);
return B_IO_ERROR;
} }
if (!_IsValid(&oldMBR)) {
close(fd);
return B_BAD_VALUE;
}
Buffer newBootLoader;
ssize_t size = sizeof(kBootLoader);
if (newBootLoader.Write(kBootLoader, size) != size) {
close(fd);
return B_NO_MEMORY;
}
MasterBootRecord* newMBR = (MasterBootRecord*)newBootLoader.BMallocIO::Buffer();
_CopyPartitionTable(newMBR, &oldMBR);
int menuEntries = 0;
BMessage partition;
int32 index;
for (index = 0; settings->FindMessage("partition", index, &partition) == B_OK; index ++) {
bool show;
partition.FindBool("show", &show);
if (!show)
continue;
menuEntries ++;
}
newBootLoader.WriteInt16(menuEntries);
newBootLoader.WriteInt16(defaultPartitionIndex);
newBootLoader.WriteInt16(timeout);
for (index = 0; settings->FindMessage("partition", index, &partition) == B_OK; index ++) {
bool show;
BString name;
BString path;
int64 offset;
partition.FindBool("show", &show);
partition.FindString("name", &name);
partition.FindString("path", &path);
// LegacyBootDrive provides offset in message as well
partition.FindInt64("offset", &offset);
if (!show)
continue;
newBootLoader.WriteString(name.String());
newBootLoader.WriteInt64(offset / kBlockSize);
}
if (!newBootLoader.Align(kBlockSize)) {
close(fd);
return B_ERROR;
}
lseek(fd, 0, SEEK_SET);
const uint8* buffer = (uint8*)newBootLoader.BMallocIO::Buffer();
status_t status = _WriteBlocks(fd, buffer, newBootLoader.Position());
close(fd);
return status;
}
status_t
LegacyBootDrive::SaveMasterBootRecord(BMessage* settings, BFile* file)
{
BString path;
if (settings->FindString("disk", &path) != B_OK)
return B_BAD_VALUE;
int fd = open(path.String(), O_RDONLY);
if (fd < 0)
return B_IO_ERROR;
ssize_t size = kBlockSize * kNumberOfBootLoaderBlocks;
uint8* buffer = new uint8[size];
if (buffer == NULL) {
close(fd);
return B_NO_MEMORY;
}
status_t status = _ReadBlocks(fd, buffer, size);
if (status != B_OK) {
close(fd);
delete buffer;
return B_IO_ERROR;
}
MasterBootRecord* mbr = (MasterBootRecord*)buffer;
if (!_IsValid(mbr)) {
close(fd);
delete buffer;
return B_BAD_VALUE;
}
if (file->Write(buffer, size) != size)
status = B_IO_ERROR;
delete buffer;
close(fd);
return status;
}
status_t
LegacyBootDrive::RestoreMasterBootRecord(BMessage* settings, BFile* file)
{
BString path;
if (settings->FindString("disk", &path) != B_OK)
return B_BAD_VALUE;
int fd = open(path.String(), O_RDWR);
if (fd < 0)
return B_IO_ERROR;
MasterBootRecord oldMBR;
if (read(fd, &oldMBR, sizeof(oldMBR)) != sizeof(oldMBR)) {
close(fd);
return B_IO_ERROR;
}
if (!_IsValid(&oldMBR)) {
close(fd);
return B_BAD_VALUE;
}
lseek(fd, 0, SEEK_SET);
size_t size = kBlockSize * kNumberOfBootLoaderBlocks;
uint8* buffer = new uint8[size];
if (buffer == NULL) {
close(fd);
return B_NO_MEMORY;
}
if (file->Read(buffer, size) != (ssize_t)size) {
close(fd);
delete buffer;
return B_IO_ERROR;
}
MasterBootRecord* newMBR = (MasterBootRecord*)buffer;
if (!_IsValid(newMBR)) {
close(fd);
delete buffer;
return B_BAD_VALUE;
}
_CopyPartitionTable(newMBR, &oldMBR);
status_t status = _WriteBlocks(fd, buffer, size);
delete buffer;
close(fd);
return status;
}
status_t
LegacyBootDrive::_ReadBlocks(int fd, uint8* buffer, size_t size)
{
if (size % kBlockSize != 0) {
fprintf(stderr, "_ReadBlocks buffer size must be a multiple of %d\n", (int)kBlockSize);
return B_BAD_VALUE;
}
const size_t blocks = size / kBlockSize;
uint8* block = buffer;
for (size_t i = 0; i < blocks; i ++, block += kBlockSize) {
if (read(fd, block, kBlockSize) != (ssize_t)kBlockSize)
return B_IO_ERROR;
}
return B_OK; return B_OK;
} }
status_t status_t
LegacyBootDrive::SaveMasterBootRecord(BFile *file) LegacyBootDrive::_WriteBlocks(int fd, const uint8* buffer, size_t size)
{ {
// TODO implement if (size % kBlockSize != 0) {
fprintf(stderr, "_WriteBlocks buffer size must be a multiple of %d\n", (int)kBlockSize);
return B_BAD_VALUE;
}
const size_t blocks = size / kBlockSize;
const uint8* block = buffer;
for (size_t i = 0; i < blocks; i ++, block += kBlockSize) {
if (write(fd, block, kBlockSize) != (ssize_t)kBlockSize)
return B_IO_ERROR;
}
return B_OK; return B_OK;
} }
status_t void
LegacyBootDrive::RestoreMasterBootRecord(BFile *file) LegacyBootDrive::_CopyPartitionTable(MasterBootRecord* destination,
const MasterBootRecord* source)
{ {
// TODO implement memcpy(destination->partition, source->partition, sizeof(source->partition));
return B_OK; }
bool
LegacyBootDrive::_IsValid(const MasterBootRecord* mbr)
{
return mbr->signature[0] == (kMBRSignature & 0xff) &&
mbr->signature[1] == (kMBRSignature >> 8);
} }
+29 -5
View File
@@ -10,17 +10,41 @@
#include "BootDrive.h" #include "BootDrive.h"
#include <SupportDefs.h>
const uint32 kBlockSize = 512;
// The number of blocks required to store the
// MBR including the Haiku boot loader.
const uint32 kNumberOfBootLoaderBlocks = 4;
const uint32 kMBRSignature = 0xAA55;
typedef struct {
uint8 bootLoader[440];
uint8 diskSignature[4];
uint8 reserved[2];
uint8 partition[64];
uint8 signature[2];
} MasterBootRecord;
class LegacyBootDrive : public BootDrive class LegacyBootDrive : public BootDrive
{ {
public: public:
LegacyBootDrive(); LegacyBootDrive();
virtual ~LegacyBootDrive(); virtual ~LegacyBootDrive();
virtual bool IsBootMenuInstalled(); virtual bool IsBootMenuInstalled(BMessage* settings);
virtual status_t ReadPartitions(BMessage *message); virtual status_t ReadPartitions(BMessage* settings);
virtual status_t WriteBootMenu(BMessage *message); virtual status_t WriteBootMenu(BMessage* settings);
virtual status_t SaveMasterBootRecord(BFile *file); virtual status_t SaveMasterBootRecord(BMessage* settings, BFile* file);
virtual status_t RestoreMasterBootRecord(BFile *file); virtual status_t RestoreMasterBootRecord(BMessage* settings, BFile* file);
private:
status_t _ReadBlocks(int fd, uint8* buffer, size_t size);
status_t _WriteBlocks(int fd, const uint8* buffer, size_t size);
void _CopyPartitionTable(MasterBootRecord* destination,
const MasterBootRecord* source);
bool _IsValid(const MasterBootRecord* mbr);
}; };
#endif // LEGACY_BOOT_DRIVE_H #endif // LEGACY_BOOT_DRIVE_H
+28 -13
View File
@@ -9,8 +9,19 @@
#include "TestBootDrive.h" #include "TestBootDrive.h"
#include <errno.h>
#include <fcntl.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <ByteOrder.h>
#include <DataIO.h>
#include <File.h>
#include <String.h>
#include "BootLoader.h"
TestBootDrive::TestBootDrive() TestBootDrive::TestBootDrive()
@@ -24,16 +35,16 @@ TestBootDrive::~TestBootDrive()
bool bool
TestBootDrive::IsBootMenuInstalled() TestBootDrive::IsBootMenuInstalled(BMessage* settings)
{ {
return false; return false;
} }
status_t status_t
TestBootDrive::ReadPartitions(BMessage *message) TestBootDrive::ReadPartitions(BMessage *settings)
{ {
message->AddString("disk", "/dev/disk/ide/ata/0/master/0/raw"); settings->AddString("disk", "bootcylinder");
BMessage partition; BMessage partition;
@@ -42,7 +53,7 @@ TestBootDrive::ReadPartitions(BMessage *message)
partition.AddString("type", "bfs"); partition.AddString("type", "bfs");
partition.AddString("path", "/dev/disk/ide/ata/0/master/0/0_0"); partition.AddString("path", "/dev/disk/ide/ata/0/master/0/0_0");
partition.AddInt64("size", 3 * (int64)1024 * 1024 * 1024); partition.AddInt64("size", 3 * (int64)1024 * 1024 * 1024);
message->AddMessage("partition", &partition); settings->AddMessage("partition", &partition);
partition.MakeEmpty(); partition.MakeEmpty();
@@ -51,7 +62,7 @@ TestBootDrive::ReadPartitions(BMessage *message)
partition.AddString("type", "dos"); partition.AddString("type", "dos");
partition.AddString("path", "/dev/disk/ide/ata/0/slave/0/0_0"); partition.AddString("path", "/dev/disk/ide/ata/0/slave/0/0_0");
partition.AddInt64("size", 10 * (int64)1024 * 1024 * 1024); partition.AddInt64("size", 10 * (int64)1024 * 1024 * 1024);
message->AddMessage("partition", &partition); settings->AddMessage("partition", &partition);
partition.MakeEmpty(); partition.MakeEmpty();
partition.AddBool("show", true); partition.AddBool("show", true);
@@ -59,21 +70,21 @@ TestBootDrive::ReadPartitions(BMessage *message)
partition.AddString("type", "unknown"); partition.AddString("type", "unknown");
partition.AddString("path", "/dev/disk/ide/ata/0/slave/0/0_1"); partition.AddString("path", "/dev/disk/ide/ata/0/slave/0/0_1");
partition.AddInt64("size", 250 * (int64)1024 * 1024 * 1024); partition.AddInt64("size", 250 * (int64)1024 * 1024 * 1024);
message->AddMessage("partition", &partition); settings->AddMessage("partition", &partition);
return B_OK; return B_OK;
} }
status_t status_t
TestBootDrive::WriteBootMenu(BMessage *message) TestBootDrive::WriteBootMenu(BMessage *settings)
{ {
printf("WriteBootMenu:\n"); printf("WriteBootMenu:\n");
message->PrintToStream(); settings->PrintToStream();
BMessage partition; BMessage partition;
int32 index = 0; int32 index = 0;
for (; message->FindMessage("partition", index, &partition) == B_OK; index ++) { for (; settings->FindMessage("partition", index, &partition) == B_OK; index ++) {
printf("Partition %d:\n", (int)index); printf("Partition %d:\n", (int)index);
partition.PrintToStream(); partition.PrintToStream();
} }
@@ -83,14 +94,18 @@ TestBootDrive::WriteBootMenu(BMessage *message)
status_t status_t
TestBootDrive::SaveMasterBootRecord(BFile *file) TestBootDrive::SaveMasterBootRecord(BMessage* settings, BFile* file)
{ {
return B_OK; return B_OK;
} }
status_t status_t
TestBootDrive::RestoreMasterBootRecord(BFile *file) TestBootDrive::RestoreMasterBootRecord(BMessage* settings, BFile* file)
{ {
return B_OK; return B_OK;
} }
+5 -5
View File
@@ -16,11 +16,11 @@ public:
TestBootDrive(); TestBootDrive();
virtual ~TestBootDrive(); virtual ~TestBootDrive();
virtual bool IsBootMenuInstalled(); virtual bool IsBootMenuInstalled(BMessage* settings);
virtual status_t ReadPartitions(BMessage *message); virtual status_t ReadPartitions(BMessage* settings);
virtual status_t WriteBootMenu(BMessage *message); virtual status_t WriteBootMenu(BMessage* settings);
virtual status_t SaveMasterBootRecord(BFile *file); virtual status_t SaveMasterBootRecord(BMessage* settings, BFile* file);
virtual status_t RestoreMasterBootRecord(BFile *file); virtual status_t RestoreMasterBootRecord(BMessage* settings, BFile* file);
}; };
#endif // TEST_BOOT_DRIVE_H #endif // TEST_BOOT_DRIVE_H