xref: /haiku/src/bin/writembr/writembr.cpp (revision 46b7da1f4f40f7157d74fc7fb26ff9ec7f2416f2)
11a7322a0SAleksas Pantechovskis /*
21a7322a0SAleksas Pantechovskis  * Copyright 2012 Aleksas Pantechovskis, <alexp.frl@gmail.com>
31a7322a0SAleksas Pantechovskis  * All rights reserved. Distributed under the terms of the MIT License.
41a7322a0SAleksas Pantechovskis  */
51a7322a0SAleksas Pantechovskis 
61a7322a0SAleksas Pantechovskis #include <fstream>
71a7322a0SAleksas Pantechovskis #include <iostream>
81a7322a0SAleksas Pantechovskis #include <sstream>
91a7322a0SAleksas Pantechovskis #include <string.h>
101a7322a0SAleksas Pantechovskis #include <string>
111a7322a0SAleksas Pantechovskis 
12a2647907SMichael Lotz #include <Debug.h>
131a7322a0SAleksas Pantechovskis #include <DiskDevice.h>
141a7322a0SAleksas Pantechovskis #include <DiskDeviceRoster.h>
151a7322a0SAleksas Pantechovskis #include <Path.h>
161a7322a0SAleksas Pantechovskis #include <Volume.h>
171a7322a0SAleksas Pantechovskis #include <VolumeRoster.h>
181a7322a0SAleksas Pantechovskis 
191a7322a0SAleksas Pantechovskis #include "MBR.h"
201a7322a0SAleksas Pantechovskis 
211a7322a0SAleksas Pantechovskis 
221a7322a0SAleksas Pantechovskis using namespace std;
231a7322a0SAleksas Pantechovskis 
241a7322a0SAleksas Pantechovskis const char* kUsageMessage = \
251a7322a0SAleksas Pantechovskis 	"Usage: writembr [ device ] \n"
261a7322a0SAleksas Pantechovskis 	"#\tRewrites the MBR for the specified device.\n"
271a7322a0SAleksas Pantechovskis 	"#\tIf no device is specified, the boot device is used.\n"
281a7322a0SAleksas Pantechovskis 	"#\t--help shows this usage message\n";
291a7322a0SAleksas Pantechovskis 
301a7322a0SAleksas Pantechovskis 
311a7322a0SAleksas Pantechovskis int
main(int argc,char ** argv)321a7322a0SAleksas Pantechovskis main(int argc, char** argv)
331a7322a0SAleksas Pantechovskis {
341a7322a0SAleksas Pantechovskis 	if ((argc == 2 && strcmp(argv[1], "--help") == 0) || argc > 2) {
351a7322a0SAleksas Pantechovskis 		cerr << kUsageMessage;
36db3aecc8SSiarzhuk Zharski 		return B_ERROR;
371a7322a0SAleksas Pantechovskis 	}
381a7322a0SAleksas Pantechovskis 
391a7322a0SAleksas Pantechovskis 	BPath device;
401a7322a0SAleksas Pantechovskis 
411a7322a0SAleksas Pantechovskis 	if (argc == 2)
421a7322a0SAleksas Pantechovskis 		// user specified device for rewriting
431a7322a0SAleksas Pantechovskis 		device.SetTo(argv[1]);
441a7322a0SAleksas Pantechovskis 
451a7322a0SAleksas Pantechovskis 	else if (argc == 1) {
461a7322a0SAleksas Pantechovskis 		// no parameters specified, rewrite boot device
471a7322a0SAleksas Pantechovskis 		BVolumeRoster volumeRoster;
481a7322a0SAleksas Pantechovskis 		BVolume bootVolume;
491a7322a0SAleksas Pantechovskis 		if (volumeRoster.GetBootVolume(&bootVolume) != B_OK) {
501a7322a0SAleksas Pantechovskis 			cerr << "Can not find boot device" << endl;
51db3aecc8SSiarzhuk Zharski 			return B_ERROR;
521a7322a0SAleksas Pantechovskis 		}
531a7322a0SAleksas Pantechovskis 
541a7322a0SAleksas Pantechovskis 		BDiskDeviceRoster roster;
551a7322a0SAleksas Pantechovskis 		BDiskDevice bootDevice;
561a7322a0SAleksas Pantechovskis 		if(roster.FindPartitionByVolume(bootVolume, &bootDevice, NULL) != B_OK) {
571a7322a0SAleksas Pantechovskis 			cerr << "Can not find boot device" << endl;
58db3aecc8SSiarzhuk Zharski 			return B_ERROR;
591a7322a0SAleksas Pantechovskis 		}
601a7322a0SAleksas Pantechovskis 
611a7322a0SAleksas Pantechovskis 		bootDevice.GetPath(&device);
621a7322a0SAleksas Pantechovskis 	}
631a7322a0SAleksas Pantechovskis 
641a7322a0SAleksas Pantechovskis 
651a7322a0SAleksas Pantechovskis 	if (strcmp(device.Leaf(), "raw") != 0) {
661a7322a0SAleksas Pantechovskis 		cerr << device.Path() << " is not a raw device" << endl;
67db3aecc8SSiarzhuk Zharski 		return B_ERROR;
681a7322a0SAleksas Pantechovskis 	}
691a7322a0SAleksas Pantechovskis 
701a7322a0SAleksas Pantechovskis 	fstream fs;
711a7322a0SAleksas Pantechovskis 	fs.open(device.Path(), fstream::in | fstream::out | fstream::binary);
72db3aecc8SSiarzhuk Zharski 	if (!fs.is_open()) {
73db3aecc8SSiarzhuk Zharski 		cerr << "Can't open " << device.Path() << endl;
74db3aecc8SSiarzhuk Zharski 		return B_ERROR;
75db3aecc8SSiarzhuk Zharski 	}
761a7322a0SAleksas Pantechovskis 
77a2647907SMichael Lotz 	STATIC_ASSERT(kMBRSize == 512);
78a2647907SMichael Lotz 
791a7322a0SAleksas Pantechovskis 	unsigned char MBR[kMBRSize];
801a7322a0SAleksas Pantechovskis 	fs.read((char*)MBR, kMBRSize);
81*ad398477SAdrien Destugues 	if (fs.fail() || fs.gcount() < (off_t)kMBRSize ) {
82db3aecc8SSiarzhuk Zharski 		cerr << "Cannot read " << kMBRSize
83db3aecc8SSiarzhuk Zharski 			<< " bytes from " << device.Path() << endl;
84db3aecc8SSiarzhuk Zharski 		fs.close();
85db3aecc8SSiarzhuk Zharski 		return B_ERROR;
861a7322a0SAleksas Pantechovskis 	}
871a7322a0SAleksas Pantechovskis 
881a7322a0SAleksas Pantechovskis 	// update only the code area and the MBR signature
891a7322a0SAleksas Pantechovskis 	memcpy(MBR, kMBR, 0x1be);
901a7322a0SAleksas Pantechovskis 	MBR[0x1FE] = kMBR[0x1FE];
911a7322a0SAleksas Pantechovskis 	MBR[0x1FF] = kMBR[0x1FF];
921a7322a0SAleksas Pantechovskis 
931a7322a0SAleksas Pantechovskis 	cerr << "About to overwrite the MBR boot code on " << device.Path()
941a7322a0SAleksas Pantechovskis 		<< "\nThis may disable any partition managers you have installed.\n"
951a7322a0SAleksas Pantechovskis 		<< "Are you sure you want to continue?\nyes/[no]: ";
961a7322a0SAleksas Pantechovskis 
971a7322a0SAleksas Pantechovskis 	string choice;
981a7322a0SAleksas Pantechovskis 	getline(cin, choice, '\n');
99db3aecc8SSiarzhuk Zharski 	if (choice == "no" || choice == "" || choice != "yes") {
100db3aecc8SSiarzhuk Zharski 		cerr << "MBR was NOT written" << endl;
101db3aecc8SSiarzhuk Zharski 		fs.close();
102db3aecc8SSiarzhuk Zharski 		return B_ERROR;
103db3aecc8SSiarzhuk Zharski 	}
1041a7322a0SAleksas Pantechovskis 
1051a7322a0SAleksas Pantechovskis 	cerr << "Rewriting MBR for " << device.Path() << endl;
1061a7322a0SAleksas Pantechovskis 
1071a7322a0SAleksas Pantechovskis 	fs.seekg(0, ios::beg);
1081a7322a0SAleksas Pantechovskis 	fs.write((char*)MBR, kMBRSize);
109db3aecc8SSiarzhuk Zharski 	if (fs.fail()) {
110db3aecc8SSiarzhuk Zharski 		cerr << "Cannot write " << kMBRSize
111db3aecc8SSiarzhuk Zharski 			<< " bytes to " << device.Path() << endl;
112db3aecc8SSiarzhuk Zharski 		fs.close();
113db3aecc8SSiarzhuk Zharski 		return B_ERROR;
1141a7322a0SAleksas Pantechovskis 	}
1151a7322a0SAleksas Pantechovskis 
1161a7322a0SAleksas Pantechovskis 	fs.close();
1171a7322a0SAleksas Pantechovskis 
118db3aecc8SSiarzhuk Zharski 	cerr << "MBR was written OK" << endl;
119db3aecc8SSiarzhuk Zharski 	return B_OK;
1201a7322a0SAleksas Pantechovskis }
1211a7322a0SAleksas Pantechovskis 
122