From 1a7322a09e825d2445ca88a47cd1d5cd06d3811b Mon Sep 17 00:00:00 2001 From: Aleksas Pantechovskis Date: Sun, 15 Jan 2012 14:51:33 +0000 Subject: [PATCH] Command line 'writembr' tool implemented * Implemented writembr tool used to update MBR area with easy boot loader starting the system from currently active partition; * This work fixes #5595; * This is result of GCI2011 task. Signed-off-by: Siarzhuk Zharski --- build/jam/HaikuImage | 3 +- src/bin/Jamfile | 1 + src/bin/writembr/Jamfile | 28 ++++++++ src/bin/writembr/writembr.cpp | 125 ++++++++++++++++++++++++++++++++++ 4 files changed, 156 insertions(+), 1 deletion(-) create mode 100644 src/bin/writembr/Jamfile create mode 100644 src/bin/writembr/writembr.cpp diff --git a/build/jam/HaikuImage b/build/jam/HaikuImage index 972856dfda..3573caa635 100644 --- a/build/jam/HaikuImage +++ b/build/jam/HaikuImage @@ -60,7 +60,8 @@ SYSTEM_BIN = "[" addattr alert arp base64 basename bash bc beep bzip2 tput tr traceroute translate trash true truncate tsort tty uname unchop unexpand unmount uniq unlink unrar unshar unzip unzipsfx updatedb uptime urlwrapper useradd uudecode uuencode - vdir version vmstat waitfor watch wc wget whoami xargs xres yes + vdir version vmstat + waitfor watch wc wget whoami $(X86_ONLY)writembr xargs xres yes zdiff zforce zgrep zip zipcloak zipgrep zipnote zipsplit zmore znew ; diff --git a/src/bin/Jamfile b/src/bin/Jamfile index 4dc153e86e..ffa2844f92 100644 --- a/src/bin/Jamfile +++ b/src/bin/Jamfile @@ -276,6 +276,7 @@ SubInclude HAIKU_TOP src bin screen_blanker ; SubInclude HAIKU_TOP src bin screenmode ; SubInclude HAIKU_TOP src bin sharutils ; SubInclude HAIKU_TOP src bin unrar ; +SubInclude HAIKU_TOP src bin writembr ; SubInclude HAIKU_TOP src bin zic ; # RCS commands diff --git a/src/bin/writembr/Jamfile b/src/bin/writembr/Jamfile new file mode 100644 index 0000000000..1979c605cf --- /dev/null +++ b/src/bin/writembr/Jamfile @@ -0,0 +1,28 @@ +SubDir HAIKU_TOP src bin writembr ; + +UsePrivateHeaders shared storage ; + +Application writembr : + writembr.cpp + + : be $(TARGET_LIBSUPC+++) $(TARGET_LIBSTDC++) +; + +# Assemble the MBR code, and convert it into a header file + +rule AssembleYasmBin object : source +{ + SEARCH on $(source) = $(SUBDIR) ; + MakeLocateDebug $(object) ; + Depends $(object) : $(source) ; +} + +actions AssembleYasmBin +{ + $(HAIKU_YASM) -f bin -O5 -o $(1) $(2) +} + +AssembleYasmBin [ FGristFiles mbr.bin ] : mbr.S ; + +DataFileToSourceFile [ FGristFiles MBR.h ] : [ FGristFiles mbr.bin ] + : kMBR : kMBRSize ; diff --git a/src/bin/writembr/writembr.cpp b/src/bin/writembr/writembr.cpp new file mode 100644 index 0000000000..269edec21b --- /dev/null +++ b/src/bin/writembr/writembr.cpp @@ -0,0 +1,125 @@ +/* + * Copyright 2012 Aleksas Pantechovskis, + * All rights reserved. Distributed under the terms of the MIT License. + */ + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "MBR.h" + + +using namespace std; + +const char* kUsageMessage = \ + "Usage: writembr [ device ] \n" + "#\tRewrites the MBR for the specified device.\n" + "#\tIf no device is specified, the boot device is used.\n" + "#\t--help shows this usage message\n"; + + +int +main(int argc, char** argv) +{ + status_t result = B_ERROR; + + if ((argc == 2 && strcmp(argv[1], "--help") == 0) || argc > 2) { + cerr << kUsageMessage; + return result; + } + + BPath device; + + if (argc == 2) + // user specified device for rewriting + device.SetTo(argv[1]); + + else if (argc == 1) { + // no parameters specified, rewrite boot device + BVolumeRoster volumeRoster; + BVolume bootVolume; + if (volumeRoster.GetBootVolume(&bootVolume) != B_OK) { + cerr << "Can not find boot device" << endl; + return result; + } + + BDiskDeviceRoster roster; + BDiskDevice bootDevice; + if(roster.FindPartitionByVolume(bootVolume, &bootDevice, NULL) != B_OK) { + cerr << "Can not find boot device" << endl; + return result; + } + + bootDevice.GetPath(&device); + } + + + if (strcmp(device.Leaf(), "raw") != 0) { + cerr << device.Path() << " is not a raw device" << endl; + return result; + } + + fstream fs; + fs.exceptions(ios::failbit | ios::badbit); + + try { + + fs.open(device.Path(), fstream::in | fstream::out | fstream::binary); + + unsigned char MBR[kMBRSize]; + fs.read((char*)MBR, kMBRSize); + if (fs.gcount() < kMBRSize ) { + stringstream error; + error << "only " << fs.gcount() << " of " << kMBRSize + << " bytes was read from " << device.Path(); + throw fstream::failure(error.str()); + } + + // update only the code area and the MBR signature + memcpy(MBR, kMBR, 0x1be); + MBR[0x1FE] = kMBR[0x1FE]; + MBR[0x1FF] = kMBR[0x1FF]; + + cerr << "About to overwrite the MBR boot code on " << device.Path() + << "\nThis may disable any partition managers you have installed.\n" + << "Are you sure you want to continue?\nyes/[no]: "; + + string choice; + getline(cin, choice, '\n'); + if (choice == "no" || choice == "" || choice != "yes") + throw fstream::failure("users cancel"); + + cerr << "Rewriting MBR for " << device.Path() << endl; + + fs.seekg(0, ios::beg); + fs.write((char*)MBR, kMBRSize); + fs.flush(); + + cerr << "MBR was written OK" << endl; + result = B_OK; + + } catch (fstream::failure exception) { + cerr << "MBR was NOT written" << endl; + cerr << "Error: "; + if (fs.is_open()) + cerr << exception.what(); + else + cerr << "Can't open " << device.Path(); + cerr << endl; + } + + if (fs.is_open()) + fs.close(); + + return result; +} +