diff options
Diffstat (limited to 'heimdall/source')
-rw-r--r-- | heimdall/source/BridgeManager.cpp | 307 | ||||
-rw-r--r-- | heimdall/source/BridgeManager.h | 7 | ||||
-rw-r--r-- | heimdall/source/Interface.cpp | 409 | ||||
-rw-r--r-- | heimdall/source/Interface.h | 255 | ||||
-rw-r--r-- | heimdall/source/InterfaceManager.cpp | 325 | ||||
-rw-r--r-- | heimdall/source/InterfaceManager.h | 123 | ||||
-rw-r--r-- | heimdall/source/OutboundPacket.h | 2 | ||||
-rwxr-xr-x | heimdall/source/PitData.cpp | 284 | ||||
-rwxr-xr-x | heimdall/source/PitData.h | 345 | ||||
-rw-r--r-- | heimdall/source/main.cpp | 342 |
10 files changed, 1021 insertions, 1378 deletions
diff --git a/heimdall/source/BridgeManager.cpp b/heimdall/source/BridgeManager.cpp index caa3978..204d87f 100644 --- a/heimdall/source/BridgeManager.cpp +++ b/heimdall/source/BridgeManager.cpp @@ -27,6 +27,8 @@ // Heimdall #include "BeginDumpPacket.h" #include "BridgeManager.h" +#include "DeviceInfoPacket.h" +#include "DeviceInfoResponse.h" #include "DumpPartFileTransferPacket.h" #include "DumpPartPitFilePacket.h" #include "DumpResponse.h" @@ -37,7 +39,7 @@ #include "FlashPartFileTransferPacket.h" #include "FlashPartPitFilePacket.h" #include "InboundPacket.h" -#include "InterfaceManager.h" +#include "Interface.h" #include "OutboundPacket.h" #include "PitFilePacket.h" #include "PitFileResponse.h" @@ -92,7 +94,7 @@ BridgeManager::~BridgeManager() if (detachedDriver) { - InterfaceManager::Print("Re-attaching kernel driver...\n"); + Interface::Print("Re-attaching kernel driver...\n"); libusb_attach_kernel_driver(deviceHandle, interfaceIndex); } @@ -108,13 +110,50 @@ BridgeManager::~BridgeManager() libusb_exit(libusbContext); } +bool BridgeManager::DetectDevice(void) +{ + // Initialise libusb-1.0 + int result = libusb_init(&libusbContext); + if (result != LIBUSB_SUCCESS) + { + Interface::PrintError("Failed to initialise libusb. Error: %i\n", result); + return (false); + } + + // Get handle to Galaxy S device + struct libusb_device **devices; + int deviceCount = libusb_get_device_list(libusbContext, &devices); + + for (int deviceIndex = 0; deviceIndex < deviceCount; deviceIndex++) + { + libusb_device_descriptor descriptor; + libusb_get_device_descriptor(devices[deviceIndex], &descriptor); + + for (int i = 0; i < BridgeManager::kSupportedDeviceCount; i++) + { + if (descriptor.idVendor == supportedDevices[i].vendorId && descriptor.idProduct == supportedDevices[i].productId) + { + libusb_free_device_list(devices, deviceCount); + + Interface::Print("Device detected"); + return (true); + } + } + } + + libusb_free_device_list(devices, deviceCount); + + Interface::Print("Failed to detect compatible device\n"); + return (false); +} + bool BridgeManager::Initialise(void) { // Initialise libusb-1.0 int result = libusb_init(&libusbContext); if (result != LIBUSB_SUCCESS) { - InterfaceManager::PrintError("Failed to initialise libusb. Error: %i\n", result); + Interface::PrintError("Failed to initialise libusb. Error: %i\n", result); return (false); } @@ -145,14 +184,14 @@ bool BridgeManager::Initialise(void) if (!heimdallDevice) { - InterfaceManager::PrintError("Failed to detect compatible device\n"); + Interface::PrintError("Failed to detect compatible device\n"); return (false); } result = libusb_open(heimdallDevice, &deviceHandle); if (result != LIBUSB_SUCCESS) { - InterfaceManager::PrintError("Failed to access device. Error: %i\n", result); + Interface::PrintError("Failed to access device. Error: %i\n", result); return (false); } @@ -160,7 +199,7 @@ bool BridgeManager::Initialise(void) result = libusb_get_device_descriptor(heimdallDevice, &deviceDescriptor); if (result != LIBUSB_SUCCESS) { - InterfaceManager::PrintError("Failed to retrieve device description\n"); + Interface::PrintError("Failed to retrieve device description\n"); return (false); } @@ -170,36 +209,36 @@ bool BridgeManager::Initialise(void) if (libusb_get_string_descriptor_ascii(deviceHandle, deviceDescriptor.iManufacturer, stringBuffer, 128) >= 0) { - InterfaceManager::Print(" Manufacturer: \"%s\"\n", stringBuffer); + Interface::Print(" Manufacturer: \"%s\"\n", stringBuffer); } if (libusb_get_string_descriptor_ascii(deviceHandle, deviceDescriptor.iProduct, stringBuffer, 128) >= 0) { - InterfaceManager::Print(" Product: \"%s\"\n", stringBuffer); + Interface::Print(" Product: \"%s\"\n", stringBuffer); } if (libusb_get_string_descriptor_ascii(deviceHandle, deviceDescriptor.iSerialNumber, stringBuffer, 128) >= 0) { - InterfaceManager::Print(" Serial No: \"%s\"\n", stringBuffer); + Interface::Print(" Serial No: \"%s\"\n", stringBuffer); } - InterfaceManager::Print("\n length: %d\n", deviceDescriptor.bLength); - InterfaceManager::Print(" device class: %d\n", deviceDescriptor.bDeviceClass); - InterfaceManager::Print(" S/N: %d\n", deviceDescriptor.iSerialNumber); - InterfaceManager::Print(" VID:PID: %04X:%04X\n", deviceDescriptor.idVendor, deviceDescriptor.idProduct); - InterfaceManager::Print(" bcdDevice: %04X\n", deviceDescriptor.bcdDevice); - InterfaceManager::Print(" iMan:iProd:iSer: %d:%d:%d\n", deviceDescriptor.iManufacturer, deviceDescriptor.iProduct, + Interface::Print("\n length: %d\n", deviceDescriptor.bLength); + Interface::Print(" device class: %d\n", deviceDescriptor.bDeviceClass); + Interface::Print(" S/N: %d\n", deviceDescriptor.iSerialNumber); + Interface::Print(" VID:PID: %04X:%04X\n", deviceDescriptor.idVendor, deviceDescriptor.idProduct); + Interface::Print(" bcdDevice: %04X\n", deviceDescriptor.bcdDevice); + Interface::Print(" iMan:iProd:iSer: %d:%d:%d\n", deviceDescriptor.iManufacturer, deviceDescriptor.iProduct, deviceDescriptor.iSerialNumber); - InterfaceManager::Print(" nb confs: %d\n", deviceDescriptor.bNumConfigurations); + Interface::Print(" nb confs: %d\n", deviceDescriptor.bNumConfigurations); } libusb_config_descriptor *configDescriptor; result = libusb_get_config_descriptor(heimdallDevice, 0, &configDescriptor); if (result != LIBUSB_SUCCESS || !configDescriptor) { - InterfaceManager::PrintError("Failed to retrieve config descriptor\n"); + Interface::PrintError("Failed to retrieve config descriptor\n"); return (false); } @@ -212,9 +251,9 @@ bool BridgeManager::Initialise(void) { if (verbose) { - InterfaceManager::Print("\ninterface[%d].altsetting[%d]: num endpoints = %d\n", + Interface::Print("\ninterface[%d].altsetting[%d]: num endpoints = %d\n", i, j, configDescriptor->usb_interface[i].altsetting[j].bNumEndpoints); - InterfaceManager::Print(" Class.SubClass.Protocol: %02X.%02X.%02X\n", + Interface::Print(" Class.SubClass.Protocol: %02X.%02X.%02X\n", configDescriptor->usb_interface[i].altsetting[j].bInterfaceClass, configDescriptor->usb_interface[i].altsetting[j].bInterfaceSubClass, configDescriptor->usb_interface[i].altsetting[j].bInterfaceProtocol); @@ -230,9 +269,9 @@ bool BridgeManager::Initialise(void) if (verbose) { - InterfaceManager::Print(" endpoint[%d].address: %02X\n", k, endpoint->bEndpointAddress); - InterfaceManager::Print(" max packet size: %04X\n", endpoint->wMaxPacketSize); - InterfaceManager::Print(" polling interval: %02X\n", endpoint->bInterval); + Interface::Print(" endpoint[%d].address: %02X\n", k, endpoint->bEndpointAddress); + Interface::Print(" max packet size: %04X\n", endpoint->wMaxPacketSize); + Interface::Print(" polling interval: %02X\n", endpoint->bInterval); } if (endpoint->bEndpointAddress & LIBUSB_ENDPOINT_IN) @@ -258,11 +297,11 @@ bool BridgeManager::Initialise(void) if (result != LIBUSB_SUCCESS) { - InterfaceManager::PrintError("Failed to find correct interface configuration\n"); + Interface::PrintError("Failed to find correct interface configuration\n"); return (false); } - InterfaceManager::Print("\nClaiming interface..."); + Interface::Print("\nClaiming interface..."); result = libusb_claim_interface(deviceHandle, interfaceIndex); #ifdef OS_LINUX @@ -270,9 +309,9 @@ bool BridgeManager::Initialise(void) if (result != LIBUSB_SUCCESS) { detachedDriver = true; - InterfaceManager::Print(" Failed. Attempting to detach driver...\n"); + Interface::Print(" Failed. Attempting to detach driver...\n"); libusb_detach_kernel_driver(deviceHandle, interfaceIndex); - InterfaceManager::Print("Claiming interface again..."); + Interface::Print("Claiming interface again..."); result = libusb_claim_interface(deviceHandle, interfaceIndex); } @@ -280,28 +319,28 @@ bool BridgeManager::Initialise(void) if (result != LIBUSB_SUCCESS) { - InterfaceManager::PrintError(" Failed!\n"); + Interface::PrintError(" Failed!\n"); return (false); } - InterfaceManager::Print(" Success\n"); + Interface::Print(" Success\n"); - InterfaceManager::Print("Setting up interface..."); + Interface::Print("Setting up interface..."); result = libusb_set_interface_alt_setting(deviceHandle, interfaceIndex, altSettingIndex); if (result != LIBUSB_SUCCESS) { - InterfaceManager::PrintError(" Failed!\n"); + Interface::PrintError(" Failed!\n"); return (false); } - InterfaceManager::Print(" Success\n"); + Interface::Print(" Success\n"); return (true); } bool BridgeManager::BeginSession(void) const { - InterfaceManager::Print("Beginning session...\n"); + Interface::Print("Beginning session...\n"); unsigned char *dataBuffer = new unsigned char[7]; @@ -309,7 +348,7 @@ bool BridgeManager::BeginSession(void) const if (result < 0) { - InterfaceManager::PrintError("Failed to initialise usb communication!\n"); + Interface::PrintError("Failed to initialise usb communication!\n"); delete [] dataBuffer; return (false); } @@ -322,7 +361,7 @@ bool BridgeManager::BeginSession(void) const result = libusb_control_transfer(deviceHandle, LIBUSB_REQUEST_TYPE_CLASS, 0x20, 0x0, 0, dataBuffer, 7, 1000); if (result < 0) { - InterfaceManager::PrintError("Failed to initialise usb communication!\n"); + Interface::PrintError("Failed to initialise usb communication!\n"); delete [] dataBuffer; return (false); } @@ -330,7 +369,7 @@ bool BridgeManager::BeginSession(void) const result = libusb_control_transfer(deviceHandle, LIBUSB_REQUEST_TYPE_CLASS, 0x22, 0x3, 0, nullptr, 0, 1000); if (result < 0) { - InterfaceManager::PrintError("Failed to initialise usb communication!\n"); + Interface::PrintError("Failed to initialise usb communication!\n"); delete [] dataBuffer; return (false); } @@ -338,7 +377,7 @@ bool BridgeManager::BeginSession(void) const result = libusb_control_transfer(deviceHandle, LIBUSB_REQUEST_TYPE_CLASS, 0x22, 0x2, 0, nullptr, 0, 1000); if (result < 0) { - InterfaceManager::PrintError("Failed to initialise usb communication!\n"); + Interface::PrintError("Failed to initialise usb communication!\n"); delete [] dataBuffer; return (false); } @@ -351,7 +390,7 @@ bool BridgeManager::BeginSession(void) const result = libusb_control_transfer(deviceHandle, LIBUSB_REQUEST_TYPE_CLASS, 0x20, 0x0, 0, dataBuffer, 7, 1000); if (result < 0) { - InterfaceManager::PrintError("Failed to initialise usb communication!\n"); + Interface::PrintError("Failed to initialise usb communication!\n"); delete [] dataBuffer; return (false); } @@ -359,12 +398,12 @@ bool BridgeManager::BeginSession(void) const result = libusb_control_transfer(deviceHandle, LIBUSB_REQUEST_TYPE_CLASS, 0x22, 0x2, 0, nullptr, 0, 1000); if (result < 0) { - InterfaceManager::PrintError("Failed to initialise usb communication!\n"); + Interface::PrintError("Failed to initialise usb communication!\n"); delete [] dataBuffer; return (false); } - InterfaceManager::Print("Handshaking with Loke..."); + Interface::Print("Handshaking with Loke..."); int dataTransferred; @@ -374,10 +413,10 @@ bool BridgeManager::BeginSession(void) const result = libusb_bulk_transfer(deviceHandle, outEndpoint, dataBuffer, 4, &dataTransferred, 1000); if (result < 0) { - InterfaceManager::PrintError(" Failed!\n"); + Interface::PrintError(" Failed!\n"); if (verbose) - InterfaceManager::PrintError("ERROR: Failed to send data: \"%s\"\n", dataBuffer); + Interface::PrintError("ERROR: Failed to send data: \"%s\"\n", dataBuffer); delete [] dataBuffer; return (false); @@ -385,10 +424,10 @@ bool BridgeManager::BeginSession(void) const if (dataTransferred != 4) { - InterfaceManager::PrintError(" Failed!\n"); + Interface::PrintError(" Failed!\n"); if (verbose) - InterfaceManager::PrintError("ERROR: Failed to complete sending data: \"%s\"\n", dataBuffer); + Interface::PrintError("ERROR: Failed to complete sending data: \"%s\"\n", dataBuffer); delete [] dataBuffer; return (false); @@ -400,32 +439,32 @@ bool BridgeManager::BeginSession(void) const result = libusb_bulk_transfer(deviceHandle, inEndpoint, dataBuffer, 7, &dataTransferred, 1000); if (result < 0) { - InterfaceManager::PrintError(" Failed!\n"); + Interface::PrintError(" Failed!\n"); if (verbose) - InterfaceManager::PrintError("ERROR: Failed to receive response\n"); + Interface::PrintError("ERROR: Failed to receive response\n"); delete [] dataBuffer; return (false);; } if (dataTransferred != 4 || memcmp(dataBuffer, "LOKE", 4) != 0) { - InterfaceManager::PrintError(" Failed!\n"); + Interface::PrintError(" Failed!\n"); if (verbose) - InterfaceManager::PrintError("ERROR: Unexpected communication.\nExpected: \"%s\"\nReceived: \"%s\"\n", "LOKE", dataBuffer); + Interface::PrintError("ERROR: Unexpected communication.\nExpected: \"%s\"\nReceived: \"%s\"\n", "LOKE", dataBuffer); delete [] dataBuffer; return (false); } - InterfaceManager::Print(" Success\n\n"); + Interface::Print(" Success\n\n"); return (true); } -bool BridgeManager::EndSession(void) const +bool BridgeManager::EndSession(bool reboot) const { - InterfaceManager::Print("Ending session...\n"); + Interface::Print("Ending session...\n"); EndSessionPacket *endSessionPacket = new EndSessionPacket(EndSessionPacket::kRequestEndSession); bool success = SendPacket(endSessionPacket); @@ -433,7 +472,7 @@ bool BridgeManager::EndSession(void) const if (!success) { - InterfaceManager::PrintError("Failed to send end session packet!\n"); + Interface::PrintError("Failed to send end session packet!\n"); return (false); } @@ -443,10 +482,35 @@ bool BridgeManager::EndSession(void) const if (!success) { - InterfaceManager::PrintError("Failed to receive session end confirmation!\n"); + Interface::PrintError("Failed to receive session end confirmation!\n"); return (false); } + if (reboot) + { + Interface::Print("Rebooting device...\n"); + + EndSessionPacket *rebootDevicePacket = new EndSessionPacket(EndSessionPacket::kRequestRebootDevice); + bool success = SendPacket(rebootDevicePacket); + delete rebootDevicePacket; + + if (!success) + { + Interface::PrintError("Failed to send reboot device packet!\n"); + return (false); + } + + ResponsePacket *rebootDeviceResponse = new ResponsePacket(ResponsePacket::kResponseTypeEndSession); + success = ReceivePacket(rebootDeviceResponse); + delete rebootDeviceResponse; + + if (!success) + { + Interface::PrintError("Failed to receive reboot confirmation!\n"); + return (false); + } + } + return (true); } @@ -464,13 +528,13 @@ bool BridgeManager::SendPacket(OutboundPacket *packet, int timeout) const int retryDelay = (communicationDelay > 250) ? communicationDelay : 250; if (verbose) - InterfaceManager::PrintError("Error %i whilst sending packet. ", result); + Interface::PrintError("Error %i whilst sending packet. ", result); // Retry for (int i = 0; i < 5; i++) { if (verbose) - InterfaceManager::PrintError(" Retrying...\n"); + Interface::PrintError(" Retrying...\n"); // Wait longer each retry Sleep(retryDelay * (i + 1)); @@ -482,11 +546,11 @@ bool BridgeManager::SendPacket(OutboundPacket *packet, int timeout) const break; if (verbose) - InterfaceManager::PrintError("Error %i whilst sending packet. ", result); + Interface::PrintError("Error %i whilst sending packet. ", result); } if (verbose) - InterfaceManager::PrintError("\n"); + Interface::PrintError("\n"); } if (communicationDelay != 0) @@ -510,13 +574,13 @@ bool BridgeManager::ReceivePacket(InboundPacket *packet, int timeout) const int retryDelay = (communicationDelay > 250) ? communicationDelay : 250; if (verbose) - InterfaceManager::PrintError("Error %i whilst receiving packet. ", result); + Interface::PrintError("Error %i whilst receiving packet. ", result); // Retry for (int i = 0; i < 5; i++) { if (verbose) - InterfaceManager::PrintError(" Retrying\n"); + Interface::PrintError(" Retrying\n"); // Wait longer each retry Sleep(retryDelay * (i + 1)); @@ -528,7 +592,7 @@ bool BridgeManager::ReceivePacket(InboundPacket *packet, int timeout) const break; if (verbose) - InterfaceManager::PrintError("Error %i whilst receiving packet. ", result); + Interface::PrintError("Error %i whilst receiving packet. ", result); if (i >= 3) { @@ -538,7 +602,7 @@ bool BridgeManager::ReceivePacket(InboundPacket *packet, int timeout) const } if (verbose) - InterfaceManager::PrintError("\n"); + Interface::PrintError("\n"); } if (communicationDelay != 0) @@ -552,6 +616,24 @@ bool BridgeManager::ReceivePacket(InboundPacket *packet, int timeout) const return (packet->Unpack()); } +bool BridgeManager::RequestDeviceInfo(unsigned int request, int *result) const +{ + DeviceInfoPacket deviceInfoPacket(request); + bool success = SendPacket(&deviceInfoPacket); + + if (!success) + { + Interface::PrintError("Failed to request device info packet!\nFailed Request: %d\n"); + return (false); + } + + DeviceInfoResponse deviceInfoResponse; + success = ReceivePacket(&deviceInfoResponse); + *result = deviceInfoResponse.GetUnknown(); + + return (true); +} + bool BridgeManager::SendPitFile(FILE *file) const { fseek(file, 0, SEEK_END); @@ -565,7 +647,7 @@ bool BridgeManager::SendPitFile(FILE *file) const if (!success) { - InterfaceManager::PrintError("Failed to request sending of PIT file!\n"); + Interface::PrintError("Failed to request sending of PIT file!\n"); return (false); } @@ -575,7 +657,7 @@ bool BridgeManager::SendPitFile(FILE *file) const if (!success) { - InterfaceManager::PrintError("Failed to confirm sending of PIT file!\n"); + Interface::PrintError("Failed to confirm sending of PIT file!\n"); return (false); } @@ -586,7 +668,7 @@ bool BridgeManager::SendPitFile(FILE *file) const if (!success) { - InterfaceManager::PrintError("Failed to send PIT file part information!\n"); + Interface::PrintError("Failed to send PIT file part information!\n"); return (false); } @@ -596,7 +678,7 @@ bool BridgeManager::SendPitFile(FILE *file) const if (!success) { - InterfaceManager::PrintError("Failed to confirm sending of PIT file part information!\n"); + Interface::PrintError("Failed to confirm sending of PIT file part information!\n"); return (false); } @@ -607,7 +689,7 @@ bool BridgeManager::SendPitFile(FILE *file) const if (!success) { - InterfaceManager::PrintError("Failed to send file part packet!\n"); + Interface::PrintError("Failed to send file part packet!\n"); return (false); } @@ -617,7 +699,7 @@ bool BridgeManager::SendPitFile(FILE *file) const if (!success) { - InterfaceManager::PrintError("Failed to receive PIT file transfer count!\n"); + Interface::PrintError("Failed to receive PIT file transfer count!\n"); return (false); } @@ -637,7 +719,7 @@ int BridgeManager::ReceivePitFile(unsigned char **pitBuffer) const if (!success) { - InterfaceManager::PrintError("Failed to request receival of PIT file!\n"); + Interface::PrintError("Failed to request receival of PIT file!\n"); return (0); } @@ -648,7 +730,7 @@ int BridgeManager::ReceivePitFile(unsigned char **pitBuffer) const if (!success) { - InterfaceManager::PrintError("Failed to receive PIT file size!\n"); + Interface::PrintError("Failed to receive PIT file size!\n"); return (0); } @@ -668,7 +750,7 @@ int BridgeManager::ReceivePitFile(unsigned char **pitBuffer) const if (!success) { - InterfaceManager::PrintError("Failed to request PIT file part #%i!\n", i); + Interface::PrintError("Failed to request PIT file part #%i!\n", i); delete [] buffer; return (0); } @@ -678,7 +760,7 @@ int BridgeManager::ReceivePitFile(unsigned char **pitBuffer) const if (!success) { - InterfaceManager::PrintError("Failed to receive PIT file part #%i!\n", i); + Interface::PrintError("Failed to receive PIT file part #%i!\n", i); delete receiveFilePartPacket; delete [] buffer; return (0); @@ -698,7 +780,7 @@ int BridgeManager::ReceivePitFile(unsigned char **pitBuffer) const if (!success) { - InterfaceManager::PrintError("Failed to send request to end PIT file transfer!\n"); + Interface::PrintError("Failed to send request to end PIT file transfer!\n"); delete [] buffer; return (0); } @@ -709,7 +791,7 @@ int BridgeManager::ReceivePitFile(unsigned char **pitBuffer) const if (!success) { - InterfaceManager::PrintError("Failed to receive end PIT file transfer verification!\n"); + Interface::PrintError("Failed to receive end PIT file transfer verification!\n"); delete [] buffer; return (0); } @@ -722,13 +804,13 @@ bool BridgeManager::SendFile(FILE *file, int destination, int fileIdentifier) co { if (destination != EndFileTransferPacket::kDestinationModem && destination != EndFileTransferPacket::kDestinationPhone) { - InterfaceManager::PrintError("ERROR: Attempted to send file to unknown destination!\n"); + Interface::PrintError("ERROR: Attempted to send file to unknown destination!\n"); return (false); } if (destination == EndFileTransferPacket::kDestinationModem && fileIdentifier != -1) { - InterfaceManager::PrintError("ERROR: The modem file does not have an identifier!\n"); + Interface::PrintError("ERROR: The modem file does not have an identifier!\n"); return (false); } @@ -738,7 +820,7 @@ bool BridgeManager::SendFile(FILE *file, int destination, int fileIdentifier) co if (!success) { - InterfaceManager::PrintError("Failed to initialise transfer!\n"); + Interface::PrintError("Failed to initialise transfer!\n"); return (false); } @@ -752,7 +834,7 @@ bool BridgeManager::SendFile(FILE *file, int destination, int fileIdentifier) co if (!success) { - InterfaceManager::PrintError("Failed to confirm transfer initialisation!\n"); + Interface::PrintError("Failed to confirm transfer initialisation!\n"); return (false); } @@ -772,7 +854,7 @@ bool BridgeManager::SendFile(FILE *file, int destination, int fileIdentifier) co long bytesTransferred = 0; int currentPercent; int previousPercent = 0; - InterfaceManager::Print("0%%"); + Interface::Print("0%%"); for (int sequenceIndex = 0; sequenceIndex < sequenceCount; sequenceIndex++) { @@ -786,7 +868,7 @@ bool BridgeManager::SendFile(FILE *file, int destination, int fileIdentifier) co if (!success) { - InterfaceManager::PrintError("\nFailed to begin file transfer sequence!\n"); + Interface::PrintError("\nFailed to begin file transfer sequence!\n"); return (false); } @@ -796,7 +878,7 @@ bool BridgeManager::SendFile(FILE *file, int destination, int fileIdentifier) co if (!success) { - InterfaceManager::PrintError("\nFailed to confirm beginning of file transfer sequence!\n"); + Interface::PrintError("\nFailed to confirm beginning of file transfer sequence!\n"); return (false); } @@ -812,7 +894,7 @@ bool BridgeManager::SendFile(FILE *file, int destination, int fileIdentifier) co if (!success) { - InterfaceManager::PrintError("\nFailed to send file part packet!\n"); + Interface::PrintError("\nFailed to send file part packet!\n"); return (false); } @@ -824,7 +906,7 @@ bool BridgeManager::SendFile(FILE *file, int destination, int fileIdentifier) co if (verbose) { const unsigned char *data = sendFilePartResponse->GetData(); - InterfaceManager::Print("File Part #%i... Response: %X %X %X %X %X %X %X %X \n", filePartIndex, + Interface::Print("File Part #%i... Response: %X %X %X %X %X %X %X %X \n", filePartIndex, data[0], data[1], data[2], data[3], data[4], data[5], data[6], data[7]); } @@ -832,11 +914,11 @@ bool BridgeManager::SendFile(FILE *file, int destination, int fileIdentifier) co if (!success) { - InterfaceManager::PrintError("\nFailed to receive file part response!\n"); + Interface::PrintError("\nFailed to receive file part response!\n"); for (int retry = 0; retry < 4; retry++) { - InterfaceManager::PrintError("\nRetrying..."); + Interface::PrintError("\nRetrying..."); // Send sendFilePartPacket = new SendFilePartPacket(file); @@ -845,7 +927,7 @@ bool BridgeManager::SendFile(FILE *file, int destination, int fileIdentifier) co if (!success) { - InterfaceManager::PrintError("\nFailed to send file part packet!\n"); + Interface::PrintError("\nFailed to send file part packet!\n"); return (false); } @@ -857,7 +939,7 @@ bool BridgeManager::SendFile(FILE *file, int destination, int fileIdentifier) co if (verbose) { const unsigned char *data = sendFilePartResponse->GetData(); - InterfaceManager::Print("File Part #%i... Response: %X %X %X %X %X %X %X %X \n", filePartIndex, + Interface::Print("File Part #%i... Response: %X %X %X %X %X %X %X %X \n", filePartIndex, data[0], data[1], data[2], data[3], data[4], data[5], data[6], data[7]); } @@ -865,7 +947,7 @@ bool BridgeManager::SendFile(FILE *file, int destination, int fileIdentifier) co if (receivedPartIndex != filePartIndex) { - InterfaceManager::PrintError("\nERROR: Expected file part index: %i Received: %i\n", + Interface::PrintError("\nERROR: Expected file part index: %i Received: %i\n", filePartIndex, receivedPartIndex); return (false); } @@ -880,7 +962,7 @@ bool BridgeManager::SendFile(FILE *file, int destination, int fileIdentifier) co if (receivedPartIndex != filePartIndex) { - InterfaceManager::PrintError("\nERROR: Expected file part index: %i Received: %i\n", + Interface::PrintError("\nERROR: Expected file part index: %i Received: %i\n", filePartIndex, receivedPartIndex); return (false); } @@ -896,9 +978,9 @@ bool BridgeManager::SendFile(FILE *file, int destination, int fileIdentifier) co if (currentPercent != previousPercent) { if (previousPercent < 10) - InterfaceManager::Print("\b\b%i%%", currentPercent); + Interface::Print("\b\b%i%%", currentPercent); else - InterfaceManager::Print("\b\b\b%i%%", currentPercent); + Interface::Print("\b\b\b%i%%", currentPercent); } } @@ -917,7 +999,7 @@ bool BridgeManager::SendFile(FILE *file, int destination, int fileIdentifier) co if (!success) { - InterfaceManager::PrintError("\nFailed to end phone file transfer sequence!\n"); + Interface::PrintError("\nFailed to end phone file transfer sequence!\n"); return (false); } } @@ -931,7 +1013,7 @@ bool BridgeManager::SendFile(FILE *file, int destination, int fileIdentifier) co if (!success) { - InterfaceManager::PrintError("\nFailed to end modem file transfer sequence!\n"); + Interface::PrintError("\nFailed to end modem file transfer sequence!\n"); return (false); } } @@ -942,13 +1024,13 @@ bool BridgeManager::SendFile(FILE *file, int destination, int fileIdentifier) co if (!success) { - InterfaceManager::PrintError("\nFailed to confirm end of file transfer sequence!\n"); + Interface::PrintError("\nFailed to confirm end of file transfer sequence!\n"); return (false); } } if (!verbose) - InterfaceManager::Print("\n"); + Interface::Print("\n"); return (true); } @@ -964,7 +1046,7 @@ bool BridgeManager::ReceiveDump(int chipType, int chipId, FILE *file) const if (!success) { - InterfaceManager::PrintError("Failed to request dump!\n"); + Interface::PrintError("Failed to request dump!\n"); return (false); } @@ -975,7 +1057,7 @@ bool BridgeManager::ReceiveDump(int chipType, int chipId, FILE *file) const if (!success) { - InterfaceManager::PrintError("Failed to receive dump size!\n"); + Interface::PrintError("Failed to receive dump size!\n"); return (false); } @@ -994,7 +1076,7 @@ bool BridgeManager::ReceiveDump(int chipType, int chipId, FILE *file) const if (!success) { - InterfaceManager::PrintError("Failed to request dump part #%i!\n", i); + Interface::PrintError("Failed to request dump part #%i!\n", i); delete [] buffer; return (false); } @@ -1004,7 +1086,7 @@ bool BridgeManager::ReceiveDump(int chipType, int chipId, FILE *file) const if (!success) { - InterfaceManager::PrintError("Failed to receive dump part #%i!\n", i); + Interface::PrintError("Failed to receive dump part #%i!\n", i); continue; delete receiveFilePartPacket; delete [] buffer; @@ -1040,7 +1122,7 @@ bool BridgeManager::ReceiveDump(int chipType, int chipId, FILE *file) const if (!success) { - InterfaceManager::PrintError("Failed to send request to end dump transfer!\n"); + Interface::PrintError("Failed to send request to end dump transfer!\n"); return (false); } @@ -1050,34 +1132,7 @@ bool BridgeManager::ReceiveDump(int chipType, int chipId, FILE *file) const if (!success) { - InterfaceManager::PrintError("Failed to receive end dump transfer verification!\n"); - return (false); - } - - return (true); -} - -bool BridgeManager::RebootDevice(void) const -{ - InterfaceManager::Print("Rebooting device...\n"); - - EndSessionPacket *rebootDevicePacket = new EndSessionPacket(EndSessionPacket::kRequestRebootDevice); - bool success = SendPacket(rebootDevicePacket); - delete rebootDevicePacket; - - if (!success) - { - InterfaceManager::PrintError("Failed to send reboot device packet!\n"); - return (false); - } - - ResponsePacket *rebootDeviceResponse = new ResponsePacket(ResponsePacket::kResponseTypeEndSession); - success = ReceivePacket(rebootDeviceResponse); - delete rebootDeviceResponse; - - if (!success) - { - InterfaceManager::PrintError("Failed to receive reboot confirmation!\n"); + Interface::PrintError("Failed to receive end dump transfer verification!\n"); return (false); } diff --git a/heimdall/source/BridgeManager.h b/heimdall/source/BridgeManager.h index 06e4d61..c28cd9c 100644 --- a/heimdall/source/BridgeManager.h +++ b/heimdall/source/BridgeManager.h @@ -97,22 +97,23 @@ namespace Heimdall BridgeManager(bool verbose, int communicationDelay);
~BridgeManager();
+ bool DetectDevice(void);
bool Initialise(void);
bool BeginSession(void) const;
- bool EndSession(void) const;
+ bool EndSession(bool reboot) const;
bool SendPacket(OutboundPacket *packet, int timeout = 3000) const;
bool ReceivePacket(InboundPacket *packet, int timeout = 3000) const;
+ bool RequestDeviceInfo(unsigned int request, int *result) const;
+
bool SendPitFile(FILE *file) const;
int ReceivePitFile(unsigned char **pitBuffer) const;
bool SendFile(FILE *file, int destination, int fileIdentifier = -1) const;
bool ReceiveDump(int chipType, int chipId, FILE *file) const;
- bool RebootDevice(void) const;
-
bool IsVerbose(void) const
{
return (verbose);
diff --git a/heimdall/source/Interface.cpp b/heimdall/source/Interface.cpp new file mode 100644 index 0000000..5f0942d --- /dev/null +++ b/heimdall/source/Interface.cpp @@ -0,0 +1,409 @@ +/* Copyright (c) 2010 Benjamin Dobell, Glass Echidna + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE.*/ + +// C/C++ Standard Library +#include <cstdarg> +#include <cstdlib> +#include <stdio.h> + +// Heimdall +#include "Heimdall.h" +#include "Interface.h" + +using namespace std; +using namespace libpit; +using namespace Heimdall; + +const char *Interface::version = "v1.3.0"; + +const char *Interface::usage = "Usage: heimdall <action> <arguments> [--verbose] [--no-reboot] [--delay <ms>]\n\ +\n\ +action: flash\n\ +arguments:\n\ + --repartition --pit <filename> [--factoryfs <filename>]\n\ + [--cache <filename>] [--dbdata <filename>] [--primary-boot <filename>]\n\ + [--secondary-boot <filename>] [--param <filename>] [--kernel <filename>]\n\ + [--modem <filename>] [--normal-boot <filename>] [--system <filename>]\n\ + [--user-data <filename>] [--fota <filename>] [--hidden <filename>]\n\ + [--movinand <filename>] [--data <filename>] [--ums <filename>]\n\ + [--emmc <filename>] [--<partition identifier> <filename>]\n\ + or:\n\ + [--factoryfs <filename>] [--cache <filename>] [--dbdata <filename>]\n\ + [--primary-boot <filename>] [--secondary-boot <filename>]\n\ + [--secondary-boot-backup <filename>] [--param <filename>]\n\ + [--kernel <filename>] [--recovery <filename>] [--efs <filename>]\n\ + [--modem <filename>] [--normal-boot <filename>] [--system <filename>]\n\ + [--user-data <filename>] [--fota <filename>] [--hidden <filename>]\n\ + [--movinand <filename>] [--data <filename>] [--ums <filename>]\n\ + [--emmc <filename>] [--<partition identifier> <filename>]\n\ +description: Flashes firmware files to your phone.\n\ +WARNING: If you're repartitioning it's strongly recommended you specify\n\ + all files at your disposal, including bootloaders.\n\ +\n\ +action: close-pc-screen\n\ +description: Attempts to get rid off the \"connect phone to PC\" screen.\n\ +\n\ +action: detect\n\ +description: Indicates whether or not a download mode device can be detected.\n\ +\n\ +action: dump\n\ +arguments: --chip-type <NAND | RAM> --chip-id <integer> --output <filename>\n\ +description: Attempts to dump data from the phone corresponding to the\n\ + specified chip type and chip ID.\n\ +NOTE: Galaxy S phones don't appear to properly support this functionality.\n\ +\n\ +action: print-pit\n\ +description: Dumps the PIT file from the connected device and prints it in\n\ + a human readable format.\n\ +\n\ +action version\n\ +description: Displays the version number of this binary.\n\ +\n\ +action: help\n\ +description: Displays this dialogue.\n"; + +const char *Interface::releaseInfo = "Heimdall %s, Copyright (c) 2010-2011, Benjamin Dobell, Glass Echidna\n\ +http://www.glassechidna.com.au\n\n\ +This software is provided free of charge. Copying and redistribution is\nencouraged.\n\n\ +If you appreciate this software and you would like to support future\ndevelopment please consider donating:\n\ +http://www.glassechidna.com.au/donate/\n\n"; + +// Flash arguments +string Interface::flashValueArguments[kFlashValueArgCount] = { + "-pit", "-factoryfs", "-cache", "-dbdata", "-primary-boot", "-secondary-boot", "-secondary-boot-backup", "-param", "-kernel", "-recovery", "-efs", "-modem", + "-normal-boot", "-system", "-user-data", "-fota", "-hidden", "-movinand", "-data", "-ums", "-emmc", "-%d" +}; + +string Interface::flashValueShortArguments[kFlashValueArgCount] = { + "pit", "fs", "cache", "db", "boot", "sbl", "sbl2", "param", "z", "rec", "efs", "m", + "norm", "sys", "udata", "fota", "hide", "nand", "data", "ums", "emmc", "%d" +}; + +string Interface::flashValuelessArguments[kFlashValuelessArgCount] = { + "-repartition" +}; + +string Interface::flashValuelessShortArguments[kFlashValuelessArgCount] = { + "r" +}; + +// Dump arguments +string Interface::dumpValueArguments[kDumpValueArgCount] = { + "-chip-type", "-chip-id", "-output" +}; + +string Interface::dumpValueShortArguments[kDumpValueArgCount] = { + "type", "id", "out" +}; + +// Common arguments +string Interface::commonValueArguments[kCommonValueArgCount] = { + "-delay" +}; + +string Interface::commonValueShortArguments[kCommonValueArgCount] = { + "d" +}; + +string Interface::commonValuelessArguments[kCommonValuelessArgCount] = { + "-verbose", "-no-reboot" +}; + +string Interface::commonValuelessShortArguments[kCommonValuelessArgCount] = { + "v", "nobt" +}; + +Action Interface::actions[Interface::kActionCount] = { + // kActionFlash + Action("flash", flashValueArguments, flashValueShortArguments, kFlashValueArgCount, + flashValuelessArguments, flashValuelessShortArguments, kFlashValuelessArgCount), + + // kActionClosePcScreen + Action("close-pc-screen", nullptr, nullptr, kClosePcScreenValueArgCount, + nullptr, nullptr, kClosePcScreenValuelessArgCount), + + // kActionDump + Action("dump", dumpValueArguments, dumpValueShortArguments, kDumpValueArgCount, + nullptr, nullptr, kDumpValuelessArgCount), + + // kActionPrintPit + Action("print-pit", nullptr, nullptr, kPrintPitValueArgCount, + nullptr, nullptr, kPrintPitValuelessArgCount), + + // kActionVersion + Action("version", nullptr, nullptr, kVersionValueArgCount, + nullptr, nullptr, kVersionValuelessArgCount), + + // kActionHelp + Action("help", nullptr, nullptr, kHelpValueArgCount, + nullptr, nullptr, kHelpValuelessArgCount), + + // kActionDetect + Action("detect", nullptr, nullptr, kDetectValueArgCount, + nullptr, nullptr, kDetectValuelessArgCount) +}; + +bool Interface::GetArguments(int argc, char **argv, map<string, string>& argumentMap, int *actionIndex) +{ + if (argc < 2) + { + Print(usage, version); + return (false); + } + + const char *actionName = argv[1]; + *actionIndex = -1; + + for (int i = 0; i < kActionCount; i++) + { + if (actions[i].name == actionName) + { + *actionIndex = i; + break; + } + } + + if (*actionIndex < 0) + { + Print("Unknown action \"%s\"\n\n", actionName); + Print(usage, version); + return (false); + } + + const Action& action = actions[*actionIndex]; + + for (int argIndex = 2; argIndex < argc; argIndex++) + { + if (*(argv[argIndex]) != '-') + { + Print(usage, version); + return (false); + } + + string argumentName = (char *)(argv[argIndex] + 1); + + // Check if the argument is a valid valueless argument + bool valid = false; + + for (unsigned int i = 0; i < action.valuelessArgumentCount; i++) + { + if (argumentName == action.valuelessArguments[i] || argumentName == action.valuelessShortArguments[i]) + { + argumentName = action.valuelessArguments[i]; + valid = true; + break; + } + } + + if (!valid) + { + // Check if it's a common valueless argument + for (unsigned int i = 0; i < kCommonValuelessArgCount; i++) + { + if (argumentName == commonValuelessArguments[i] || argumentName == commonValuelessShortArguments[i]) + { + argumentName = commonValuelessArguments[i]; + valid = true; + break; + } + } + } + + if (valid) + { + // The argument is valueless + argumentMap.insert(pair<string, string>(argumentName, "")); + continue; + } + + // Check if the argument is a valid value argument + for (unsigned int i = 0; i < action.valueArgumentCount; i++) + { + // Support for --<integer> and -<integer> parameters. + if (argumentName.length() > 1 && action.valueArguments[i] == "-%d") + { + if (atoi(argumentName.substr(1).c_str()) > 0 || argumentName == "-0") + { + valid = true; + break; + } + } + else if (action.valueArguments[i] == "%d") + { + if (atoi(argumentName.c_str()) > 0 || argumentName == "0") + { + argumentName = "-" + argumentName; + valid = true; + break; + } + } + + if (argumentName == action.valueArguments[i] || argumentName == action.valueShortArguments[i]) + { + argumentName = action.valueArguments[i]; + valid = true; + break; + } + } + + if (!valid) + { + // Check if it's a common value argument + for (unsigned int i = 0; i < kCommonValueArgCount; i++) + { + // Support for --<integer> and -<integer> parameters. + if (argumentName.length() > 1 && commonValueArguments[i] == "-%d") + { + if (atoi(argumentName.substr(1).c_str()) > 0 || argumentName == "-0") + { + valid = true; + break; + } + } + else if (commonValueArguments[i] == "%d") + { + if (atoi(argumentName.c_str()) > 0 || argumentName == "0") + { + argumentName = "-" + argumentName; + valid = true; + break; + } + } + + if (argumentName == commonValueArguments[i] || argumentName == commonValueShortArguments[i]) + { + argumentName = commonValueArguments[i]; + valid = true; + break; + } + } + } + + if (!valid) + { + PrintError("\"%s\" is not a valid argument\n", argumentName.c_str()); + return (false); + } + + argIndex++; + + if (argIndex >= argc) + { + PrintError("\"%s\" is missing a value\n", argumentName.c_str()); + return (false); + } + + argumentMap.insert(pair<string, string>(argumentName, argv[argIndex])); + } + + return (true); +} + +void Interface::Print(const char *format, ...) +{ + va_list args; + + va_start(args, format); + vfprintf(stdout, format, args); + va_end(args); + + fflush(stdout); // Make sure output isn't buffered. +} + +void Interface::PrintError(const char *format, ...) +{ + va_list args; + + va_start(args, format); + vfprintf(stderr, format, args); + va_end(args); + + fflush(stderr); // Make sure output isn't buffered. +} + +void Interface::PrintVersion(void) +{ + Print("%s\n", version); +} + +void Interface::PrintUsage(void) +{ + Print(usage); +} + +void Interface::PrintReleaseInfo(void) +{ + Print(releaseInfo, version); +} + +void Interface::PrintPit(const PitData *pitData) +{ + Interface::Print("Entry Count: %d\n", pitData->GetEntryCount()); + + Interface::Print("Unknown 1: %d\n", pitData->GetUnknown1()); + Interface::Print("Unknown 2: %d\n", pitData->GetUnknown2()); + Interface::Print("Unknown 3: %d\n", pitData->GetUnknown3()); + Interface::Print("Unknown 4: %d\n", pitData->GetUnknown4()); + Interface::Print("Unknown 5: %d\n", pitData->GetUnknown5()); + Interface::Print("Unknown 6: %d\n", pitData->GetUnknown6()); + Interface::Print("Unknown 7: %d\n", pitData->GetUnknown7()); + Interface::Print("Unknown 8: %d\n", pitData->GetUnknown8()); + + for (unsigned int i = 0; i < pitData->GetEntryCount(); i++) + { + const PitEntry *entry = pitData->GetEntry(i); + + Interface::Print("\n\n--- Entry #%d ---\n", i); + Interface::Print("Unused: %s\n", (entry->GetUnused()) ? "Yes" : "No"); + + const char *partitionTypeText = "Unknown"; + + if (entry->GetPartitionType() == PitEntry::kPartitionTypeRfs) + partitionTypeText = "RFS"; + else if (entry->GetPartitionType() == PitEntry::kPartitionTypeExt4) + partitionTypeText = "EXT4"; + + Interface::Print("Partition Type: %d (%s)\n", entry->GetPartitionType(), partitionTypeText); + + Interface::Print("Partition Identifier: %d\n", entry->GetPartitionIdentifier()); + + Interface::Print("Partition Flags: %d (", entry->GetPartitionFlags()); + + if (entry->GetPartitionFlags() & PitEntry::kPartitionFlagWrite) + Interface::Print("R/W"); + else + Interface::Print("R"); + + Interface::Print(")\n"); + + Interface::Print("Unknown 1: %d\n", entry->GetUnknown1()); + + Interface::Print("Partition Block Size: %d\n", entry->GetPartitionBlockSize()); + Interface::Print("Partition Block Count: %d\n", entry->GetPartitionBlockCount()); + + Interface::Print("Unknown 2: %d\n", entry->GetUnknown2()); + Interface::Print("Unknown 3: %d\n", entry->GetUnknown3()); + + Interface::Print("Partition Name: %s\n", entry->GetPartitionName()); + Interface::Print("Filename: %s\n", entry->GetFilename()); + } + + Interface::Print("\n"); +} diff --git a/heimdall/source/Interface.h b/heimdall/source/Interface.h new file mode 100644 index 0000000..c6bdef3 --- /dev/null +++ b/heimdall/source/Interface.h @@ -0,0 +1,255 @@ +/* Copyright (c) 2010 Benjamin Dobell, Glass Echidna + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE.*/ + +#ifndef INTERFACE_H +#define INTERFACE_H + +// C/C++ Standard Library +#include <map> +#include <string> + +// libpit +#include "libpit.h" + +using namespace std; +using namespace libpit; + +namespace Heimdall +{ + struct Action + { + public: + + string name; + + string *valueArguments; + string *valueShortArguments; + unsigned int valueArgumentCount; + + string *valuelessArguments; + string *valuelessShortArguments; + unsigned int valuelessArgumentCount; + + Action(const char *name, string *valueArguments, string *valueShortArguments, unsigned int valueArgumentCount, + string *valuelessArguments, string *valuelessShortArguments, unsigned int valuelessArgumentCount) + { + this->name = name; + + this->valueArguments = valueArguments; + this->valueShortArguments = valueShortArguments; + this->valueArgumentCount = valueArgumentCount; + + this->valuelessArguments = valuelessArguments; + this->valuelessShortArguments = valuelessShortArguments; + this->valuelessArgumentCount = valuelessArgumentCount; + } + }; + + class Interface + { + public: + + // Actions + enum + { + kActionFlash = 0, + kActionClosePcScreen, + kActionDump, + kActionPrintPit, + kActionVersion, + kActionHelp, + kActionDetect, + kActionCount + }; + + // Flash value arguments + enum + { + kFlashValueArgPit, + kFlashValueArgFactoryFs, + kFlashValueArgCache, + kFlashValueArgDatabaseData, + kFlashValueArgPrimaryBootloader, + kFlashValueArgSecondaryBootloader, + kFlashValueArgSecondaryBootloaderBackup, + kFlashValueArgParam, + kFlashValueArgKernel, + kFlashValueArgRecovery, + kFlashValueArgEfs, + kFlashValueArgModem, + + kFlashValueArgNormalBoot, + kFlashValueArgSystem, + kFlashValueArgUserData, + kFlashValueArgFota, + kFlashValueArgHidden, + kFlashValueArgMovinand, + kFlashValueArgData, + kFlashValueArgUms, + kFlashValueArgEmmc, + + kFlashValueArgPartitionIndex, + + kFlashValueArgCount + }; + + // Flash valueless arguments + enum + { + kFlashValuelessArgRepartition = 0, + + kFlashValuelessArgCount + }; + + // Close PC Screen value arguments + enum + { + kClosePcScreenValueArgCount = 0 + }; + + // Close PC Screen valueless arguments + enum + { + kClosePcScreenValuelessArgCount = 0 + }; + + // Dump value arguments + enum + { + kDumpValueArgChipType = 0, + kDumpValueArgChipId, + kDumpValueArgOutput, + + kDumpValueArgCount + }; + + // Dump valueless arguments + enum + { + kDumpValuelessArgCount = 0 + }; + + // Print PIT value arguments + enum + { + kPrintPitValueArgCount = 0 + }; + + // Print PIT valueless arguments + enum + { + kPrintPitValuelessArgCount = 0 + }; + + // Version value arguments + enum + { + kVersionValueArgCount = 0 + }; + + // Version valueless arguments + enum + { + kVersionValuelessArgCount = 0 + }; + + // Help value arguments + enum + { + kHelpValueArgCount = 0 + }; + + // Help valueless arguments + enum + { + kHelpValuelessArgCount = 0 + }; + + // Detect value arguments + enum + { + kDetectValueArgCount = 0 + }; + + // Detect valueless arguments + enum + { + kDetectValuelessArgCount = 0 + }; + + // Common value arguments + enum + { + kCommonValueArgDelay = 0, + + kCommonValueArgCount + }; + + // Comon valueless arguments + enum + { + kCommonValuelessArgVerbose = 0, + kCommonValuelessArgNoReboot, + + kCommonValuelessArgCount + }; + + private: + + static const char *version; + static const char *usage; + static const char *releaseInfo; + + // Flash arguments + static string flashValueArguments[kFlashValueArgCount]; + static string flashValueShortArguments[kFlashValueArgCount]; + + static string flashValuelessArguments[kFlashValuelessArgCount]; + static string flashValuelessShortArguments[kFlashValuelessArgCount]; + + // Dump arguments + static string dumpValueArguments[kDumpValueArgCount]; + static string dumpValueShortArguments[kDumpValueArgCount]; + + public: + + // Common arguments + static string commonValueArguments[kCommonValueArgCount]; + static string commonValueShortArguments[kCommonValueArgCount]; + + static string commonValuelessArguments[kCommonValuelessArgCount]; + static string commonValuelessShortArguments[kCommonValuelessArgCount]; + + static Action actions[kActionCount]; + + static bool GetArguments(int argc, char **argv, map<string, string>& argumentMap, int *actionIndex); + + static void Print(const char *format, ...); + static void PrintError(const char *format, ...); + + static void PrintVersion(void); + static void PrintUsage(void); + static void PrintReleaseInfo(void); + + static void PrintPit(const PitData *pitData); + }; +} + +#endif diff --git a/heimdall/source/InterfaceManager.cpp b/heimdall/source/InterfaceManager.cpp deleted file mode 100644 index 26ef028..0000000 --- a/heimdall/source/InterfaceManager.cpp +++ /dev/null @@ -1,325 +0,0 @@ -/* Copyright (c) 2010 Benjamin Dobell, Glass Echidna
-
- Permission is hereby granted, free of charge, to any person obtaining a copy
- of this software and associated documentation files (the "Software"), to deal
- in the Software without restriction, including without limitation the rights
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- copies of the Software, and to permit persons to whom the Software is
- furnished to do so, subject to the following conditions:
-
- The above copyright notice and this permission notice shall be included in
- all copies or substantial portions of the Software.
-
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- THE SOFTWARE.*/
-
-// C/C++ Standard Library
-#include <cstdarg>
-#include <cstdlib>
-#include <stdio.h>
-
-// Heimdall
-#include "Heimdall.h"
-#include "InterfaceManager.h"
-
-using namespace std;
-using namespace Heimdall;
-
-string InterfaceManager::actionNames[kActionCount] = { "flash", "close-pc-screen", "dump", "print-pit", "help" };
-
-string InterfaceManager::flashArgumentNames[kFlashArgCount * 2] = {
- // --- Long Names ---
- "-repartition",
-
- "-pit", "-factoryfs", "-cache", "-dbdata", "-primary-boot", "-secondary-boot", "-secondary-boot-backup", "-param", "-kernel", "-recovery", "-efs", "-modem",
- "-normal-boot", "-system", "-user-data", "-fota", "-hidden", "-movinand", "-data", "-ums", "-emmc", "-%d",
-
- // --- Short Names ---
- "r",
-
- "pit", "fs", "cache", "db", "boot", "sbl", "sbl2", "param", "z", "rec", "efs", "m",
- "norm", "sys", "udata", "fota", "hide", "nand", "data", "ums", "emmc", "%d"
-};
-
-string InterfaceManager::dumpArgumentNames[kDumpArgCount * 2] = {
- // --- Long Names ---
- "-chip-type", "-chip-id", "-output",
-
- // --- Short Names ---
- "type", "id", "out"
-};
-
-string InterfaceManager::commonArgumentNames[kCommonArgCount * 2] = {
- // --- Long Names ---
- "-verbose", "-no-reboot",
-
- "-delay",
-
- // --- Short Names ---
- "v", "nobt",
-
- "d"
-};
-
-// argumentNames[kActionCount][] stores common arguments.
-string *InterfaceManager::actionArgumentNames[kActionCount + 1] = {
- // kActionFlash
- flashArgumentNames,
-
- // kActionClosePcScreen
- nullptr,
-
- // kActionDump
- dumpArgumentNames,
-
- // kActionPrintPit
- nullptr,
-
- // kActionHelp
- nullptr,
-
- // Common (kActionCount)
- commonArgumentNames
-};
-
-int InterfaceManager::actionArgumentCounts[kActionCount + 1] = {
- kFlashArgCount, 0, kDumpArgCount, 0, 0, kCommonArgCount
-};
-
-int InterfaceManager::actionValuelessArgumentCounts[kActionCount + 1] = {
- kFlashArgPit, 0, kDumpArgChipType, 0, 0, kCommonArgDelay
-};
-
-const char *InterfaceManager::usage = "\nHeimdall v1.2.0, Copyright (c) 2010-2011, Benjamin Dobell, Glass Echidna\n\n\
-Usage: heimdall <action> <arguments> [--verbose] [--no-reboot] [--delay <ms>]\n\
-\n\
-action: flash\n\
-arguments:\n\
- --repartition --pit <filename> [--factoryfs <filename>]\n\
- [--cache <filename>] [--dbdata <filename>] [--primary-boot <filename>]\n\
- [--secondary-boot <filename>] [--param <filename>] [--kernel <filename>]\n\
- [--modem <filename>] [--normal-boot <filename>] [--system <filename>]\n\
- [--user-data <filename>] [--fota <filename>] [--hidden <filename>]\n\
- [--movinand <filename>] [--data <filename>] [--ums <filename>]\n\
- [--emmc <filename>] [--<partition identifier> <filename>]\n\
- or:\n\
- [--factoryfs <filename>] [--cache <filename>] [--dbdata <filename>]\n\
- [--primary-boot <filename>] [--secondary-boot <filename>]\n\
- [--secondary-boot-backup <filename>] [--param <filename>]\n\
- [--kernel <filename>] [--recovery <filename>] [--efs <filename>]\n\
- [--modem <filename>] [--normal-boot <filename>] [--system <filename>]\n\
- [--user-data <filename>] [--fota <filename>] [--hidden <filename>]\n\
- [--movinand <filename>] [--data <filename>] [--ums <filename>]\n\
- [--emmc <filename>] [--<partition identifier> <filename>]\n\
-description: Flashes firmware files to your phone.\n\
-WARNING: If you're repartitioning it's strongly recommended you specify\n\
- all files at your disposal, including bootloaders.\n\
-\n\
-action: close-pc-screen\n\
-description: Attempts to get rid off the \"connect phone to PC\" screen.\n\
-\n\
-action: dump\n\
-arguments: --chip-type <NAND | RAM> --chip-id <integer> --output <filename>\n\
-description: Attempts to dump data from the phone corresponding to the\n\
- specified chip type and chip ID.\n\
-NOTE: Galaxy S phones don't appear to properly support this functionality.\n\
-\n\
-action: print-pit\n\
-description: Dumps the PIT file from the connected device and prints it in\n\
- a human readable format.\n\
-\n\
-action: help\n\
-description: Display this dialogue.\n";
-
-bool InterfaceManager::GetArguments(int argc, char **argv, map<string, string>& argumentMap, int *actionIndex)
-{
- if (argc < 2)
- {
- Print(usage);
- return (false);
- }
-
- const char *actionName = argv[1];
- *actionIndex = -1;
-
- for (int i = 0; i < kActionCount; i++)
- {
- if (actionNames[i] == actionName)
- {
- *actionIndex = i;
- break;
- }
- }
-
- if (*actionIndex < 0)
- {
- Print("Unknown action \"%s\"\n\n", actionName);
- Print(usage);
- return (false);
- }
-
- int actionArgumentCount = actionArgumentCounts[*actionIndex];
- int commonArgumentCount = actionArgumentCounts[kActionCount];
-
- int actionValuelessArgumentCount = actionValuelessArgumentCounts[*actionIndex];
- int commonValuelessArgumentCount = actionValuelessArgumentCounts[kActionCount];
-
- string *argumentNames = actionArgumentNames[*actionIndex];
- string *commonArgumentNames = actionArgumentNames[kActionCount];
-
- for (int argIndex = 2; argIndex < argc; argIndex++)
- {
- if (*(argv[argIndex]) != '-')
- {
- Print(usage);
- return (false);
- }
-
- string argumentName = (char *)(argv[argIndex] + 1);
-
- // Check if the argument is a valid valueless argument
- bool valid = false;
-
- for (int i = 0; i < actionValuelessArgumentCount; i++)
- {
- if (argumentName == argumentNames[i] || argumentName == argumentNames[actionArgumentCount + i])
- {
- argumentName = argumentNames[i];
- valid = true;
- break;
- }
- }
-
- if (!valid)
- {
- // Check if it's a common valueless argument
- for (int i = 0; i < commonValuelessArgumentCount; i++)
- {
- if (argumentName == commonArgumentNames[i] || argumentName == commonArgumentNames[commonArgumentCount + i])
- {
- argumentName = commonArgumentNames[i];
- valid = true;
- break;
- }
- }
- }
-
- if (valid)
- {
- // The argument is valueless
- argumentMap.insert(pair<string, string>(argumentName, ""));
- continue;
- }
-
- if (argumentNames != nullptr)
- {
- // Check if the argument is a valid regular argument
- for (int i = actionValuelessArgumentCount; i < actionArgumentCount; i++)
- {
- // Support for --<integer> and -<integer> parameters.
- if (argumentName.length() > 1 && argumentNames[i].compare("-%d") == 0)
- {
- if (atoi(argumentName.substr(1).c_str()) > 0 || argumentName.compare("-0") == 0)
- {
- valid = true;
- break;
- }
- }
- else if (argumentNames[i].compare("%d") == 0)
- {
- if (atoi(argumentName.c_str()) > 0 || argumentName.compare("0") == 0)
- {
- argumentName = "-" + argumentName;
- valid = true;
- break;
- }
- }
-
- if (argumentName == argumentNames[i] || argumentName == argumentNames[actionArgumentCount + i])
- {
- argumentName = argumentNames[i];
- valid = true;
- break;
- }
- }
- }
-
- if (!valid)
- {
- // Check if it's a common regular argument
- for (int i = commonValuelessArgumentCount; i < commonArgumentCount; i++)
- {
- // Support for --<integer> and -<integer> parameters.
- if (argumentName.length() > 1 && commonArgumentNames[i].compare("-%d"))
- {
- if (atoi(argumentName.substr(1).c_str()) > 0 || argumentName.compare("-0") == 0)
- {
- valid = true;
- break;
- }
- }
- else if (commonArgumentNames[i].compare("%d"))
- {
- if (atoi(argumentName.c_str()) > 0 || argumentName.compare("0") == 0)
- {
- argumentName = "-" + argumentName;
- valid = true;
- break;
- }
- }
-
- if (argumentName == commonArgumentNames[i] || argumentName == commonArgumentNames[commonArgumentCount + i])
- {
- argumentName = commonArgumentNames[i];
- valid = true;
- break;
- }
- }
- }
-
- if (!valid)
- {
- PrintError("\"%s\" is not a valid argument\n", argumentName.c_str());
- return (false);
- }
-
- argIndex++;
-
- if (argIndex >= argc)
- {
- PrintError("\"%s\" is missing a value\n", argumentName.c_str());
- return (false);
- }
-
- argumentMap.insert(pair<string, string>(argumentName, argv[argIndex]));
- }
-
- return (true);
-}
-
-void InterfaceManager::Print(const char *format, ...)
-{
- va_list args;
-
- va_start(args, format);
- vfprintf(stdout, format, args);
- va_end(args);
-
- fflush(stdout); // Make sure output isn't buffered.
-}
-
-void InterfaceManager::PrintError(const char *format, ...)
-{
- va_list args;
-
- va_start(args, format);
- vfprintf(stderr, format, args);
- va_end(args);
-
- fflush(stderr); // Make sure output isn't buffered.
-}
diff --git a/heimdall/source/InterfaceManager.h b/heimdall/source/InterfaceManager.h deleted file mode 100644 index 1f5ba94..0000000 --- a/heimdall/source/InterfaceManager.h +++ /dev/null @@ -1,123 +0,0 @@ -/* Copyright (c) 2010 Benjamin Dobell, Glass Echidna - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE.*/ - -#ifndef INTERFACEMANAGER_H -#define INTERFACEMANAGER_H - -// C/C++ Standard Library -#include <map> -#include <string> - -using namespace std; - -namespace Heimdall -{ - class InterfaceManager - { - public: - - enum - { - kActionFlash = 0, - kActionClosePcScreen, - kActionDump, - kActionPrintPit, - kActionHelp, - kActionCount - }; - - enum - { - // Valueless arguments - kFlashArgRepartition = 0, - - // Regular arguments - kFlashArgPit, - kFlashArgFactoryFs, - kFlashArgCache, - kFlashArgDatabaseData, - kFlashArgPrimaryBootloader, - kFlashArgSecondaryBootloader, - kFlashArgSecondaryBootloaderBackup, - kFlashArgParam, - kFlashArgKernel, - kFlashArgRecovery, - kFlashArgEfs, - kFlashArgModem, - - kFlashArgNormalBoot, - kFlashArgSystem, - kFlashArgUserData, - kFlashArgFota, - kFlashArgHidden, - kFlashArgMovinand, - kFlashArgData, - kFlashArgUms, - kFlashArgEmmc, - - kFlashArgPartitionIndex, - - kFlashArgCount - }; - - enum - { - // Regular arguments - kDumpArgChipType = 0, - kDumpArgChipId, - kDumpArgOutput, - - kDumpArgCount - }; - - enum - { - // Valueless arguments - kCommonArgVerbose = 0, - kCommonArgNoReboot, - - // Regular arguments - kCommonArgDelay, - - kCommonArgCount - }; - - static string actionNames[kActionCount]; - - static string flashArgumentNames[kFlashArgCount * 2]; - static string dumpArgumentNames[kDumpArgCount * 2]; - static string commonArgumentNames[kCommonArgCount * 2]; - - // argumentNames[kActionCount][] defines common arguments. - static string *actionArgumentNames[kActionCount + 1]; - - static int actionArgumentCounts[kActionCount + 1]; - static int actionValuelessArgumentCounts[kActionCount + 1]; - - static const char *usage; - - static bool GetArguments(int argc, char **argv, map<string, string>& argumentMap, int *actionIndex); - - static void Print(const char *format, ...); - static void PrintError(const char *format, ...); - }; -} - -#endif diff --git a/heimdall/source/OutboundPacket.h b/heimdall/source/OutboundPacket.h index dbe3f8a..8f8e6c6 100644 --- a/heimdall/source/OutboundPacket.h +++ b/heimdall/source/OutboundPacket.h @@ -21,7 +21,7 @@ #ifndef OUTBOUNDPACKET_H
#define OUTBOUNDPACKET_H
-// Heimdall include
+// Heimdall
#include "Packet.h"
namespace Heimdall
diff --git a/heimdall/source/PitData.cpp b/heimdall/source/PitData.cpp deleted file mode 100755 index 10e88b7..0000000 --- a/heimdall/source/PitData.cpp +++ /dev/null @@ -1,284 +0,0 @@ -/* Copyright (c) 2010 Benjamin Dobell, Glass Echidna - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE.*/ - -// Heimdall -#include "Heimdall.h" -#include "InterfaceManager.h" -#include "PitData.h" - -using namespace Heimdall; - -PitEntry::PitEntry() -{ - unused = false; - partitionType = 0; - partitionIdentifier = 0; - partitionFlags = 0; - unknown2 = 0; - partitionBlockSize = 0; - partitionBlockCount = 0; - unknown3 = 0; - unknown4 = 0; - - memset(partitionName, 0, 32); - memset(filename, 0, 64); -} - -PitEntry::~PitEntry() -{ -} - -void PitEntry::Print(void) const -{ - InterfaceManager::Print("Unused: %s\n", (unused) ? "Yes" : "No"); - - const char *partitionTypeText = "Unknown"; - - if (partitionType == PitEntry::kPartitionTypeRfs) - partitionTypeText = "RFS"; - else if (partitionType == PitEntry::kPartitionTypeExt4) - partitionTypeText = "EXT4"; - - InterfaceManager::Print("Partition Type: %d (%s)\n", partitionType, partitionTypeText); - - InterfaceManager::Print("Partition Identifier: %d\n", partitionIdentifier); - - InterfaceManager::Print("Partition Flags: %d (", partitionFlags); - - if (partitionFlags & PitEntry::kPartitionFlagWrite) - InterfaceManager::Print("R/W"); - else - InterfaceManager::Print("R"); - - InterfaceManager::Print(")\n"); - - InterfaceManager::Print("Unknown 2: %d\n", unknown2); - - InterfaceManager::Print("Partition Block Size: %d\n", partitionBlockSize); - InterfaceManager::Print("Partition Block Count: %d\n", partitionBlockCount); - - InterfaceManager::Print("Unknown 3: %d\n", unknown3); - InterfaceManager::Print("Unknown 4: %d\n", unknown4); - - InterfaceManager::Print("Partition Name: %s\n", partitionName); - InterfaceManager::Print("Filename: %s\n", filename); -} - - - -PitData::PitData() -{ - entryCount = 0; - - unknown1 = 0; - unknown2 = 0; - - unknown3 = 0; - unknown4 = 0; - - unknown5 = 0; - unknown6 = 0; - - unknown7 = 0; - unknown8 = 0; -} - -PitData::~PitData() -{ - for (unsigned int i = 0; i < entries.size(); i++) - delete entries[i]; -} - -bool PitData::Unpack(const unsigned char *data) -{ - if (PitData::UnpackInteger(data, 0) != PitData::kFileIdentifier) - return (false); - - // Remove existing entries - for (unsigned int i = 0; i < entries.size(); i++) - delete entries[i]; - - entryCount = PitData::UnpackInteger(data, 4); - - entries.resize(entryCount); - - unknown1 = PitData::UnpackInteger(data, 8); - unknown2 = PitData::UnpackInteger(data, 12); - - unknown3 = PitData::UnpackShort(data, 16); - unknown4 = PitData::UnpackShort(data, 18); - - unknown5 = PitData::UnpackShort(data, 20); - unknown6 = PitData::UnpackShort(data, 22); - - unknown7 = PitData::UnpackShort(data, 24); - unknown8 = PitData::UnpackShort(data, 26); - - unsigned int integerValue; - unsigned int entryOffset; - - for (unsigned int i = 0; i < entryCount; i++) - { - entryOffset = PitData::kHeaderDataSize + i * PitEntry::kDataSize; - - entries[i] = new PitEntry(); - - integerValue = PitData::UnpackInteger(data, entryOffset); - entries[i]->SetUnused((integerValue != 0) ? true : false); - - integerValue = PitData::UnpackInteger(data, entryOffset + 4); - entries[i]->SetPartitionType(integerValue); - - integerValue = PitData::UnpackInteger(data, entryOffset + 8); - entries[i]->SetPartitionIdentifier(integerValue); - - integerValue = PitData::UnpackInteger(data, entryOffset + 12); - entries[i]->SetPartitionFlags(integerValue); - - integerValue = PitData::UnpackInteger(data, entryOffset + 16); - entries[i]->SetUnknown2(integerValue); - - integerValue = PitData::UnpackInteger(data, entryOffset + 20); - entries[i]->SetPartitionBlockSize(integerValue); - - integerValue = PitData::UnpackInteger(data, entryOffset + 24); - entries[i]->SetPartitionBlockCount(integerValue); - - integerValue = PitData::UnpackInteger(data, entryOffset + 28); - entries[i]->SetUnknown3(integerValue); - - integerValue = PitData::UnpackInteger(data, entryOffset + 32); - entries[i]->SetUnknown4(integerValue); - - entries[i]->SetPartitionName((const char *)data + entryOffset + 36); - entries[i]->SetFilename((const char *)data + entryOffset + 36 + PitEntry::kPartitionNameMaxLength); - } - - return (true); -} - -void PitData::Pack(unsigned char *data) const -{ - PitData::PackInteger(data, 0, PitData::kFileIdentifier); - - PitData::PackInteger(data, 4, entryCount); - - PitData::PackInteger(data, 8, unknown1); - PitData::PackInteger(data, 12, unknown2); - - PitData::PackShort(data, 16, unknown3); - PitData::PackShort(data, 18, unknown4); - - PitData::PackShort(data, 20, unknown5); - PitData::PackShort(data, 22, unknown6); - - PitData::PackShort(data, 24, unknown7); - PitData::PackShort(data, 26, unknown8); - - int entryOffset; - - for (unsigned int i = 0; i < entryCount; i++) - { - entryOffset = PitData::kHeaderDataSize + i * PitEntry::kDataSize; - - PitData::PackInteger(data, entryOffset, (entries[i]->GetUnused()) ? 1 : 0); - - PitData::PackInteger(data, entryOffset + 4, entries[i]->GetPartitionType()); - PitData::PackInteger(data, entryOffset + 8, entries[i]->GetPartitionIdentifier()); - PitData::PackInteger(data, entryOffset + 12, entries[i]->GetPartitionFlags()); - - PitData::PackInteger(data, entryOffset + 16, entries[i]->GetUnknown2()); - - PitData::PackInteger(data, entryOffset + 20, entries[i]->GetPartitionBlockSize()); - PitData::PackInteger(data, entryOffset + 24, entries[i]->GetPartitionBlockCount()); - - PitData::PackInteger(data, entryOffset + 28, entries[i]->GetUnknown3()); - PitData::PackInteger(data, entryOffset + 32, entries[i]->GetUnknown4()); - - memcpy(data + entryOffset + 36, entries[i]->GetPartitionName(), PitEntry::kPartitionNameMaxLength); - memcpy(data + entryOffset + 36 + PitEntry::kPartitionNameMaxLength, entries[i]->GetPartitionName(), PitEntry::kFilenameMaxLength); - } -} - -PitEntry *PitData::FindEntry(const char *partitionName) -{ - for (unsigned int i = 0; i < entries.size(); i++) - { - if (strcmp(entries[i]->GetPartitionName(), partitionName) == 0) - return (entries[i]); - } - - return (nullptr); -} - -const PitEntry *PitData::FindEntry(const char *partitionName) const -{ - for (unsigned int i = 0; i < entries.size(); i++) - { - if (strcmp(entries[i]->GetPartitionName(), partitionName) == 0) - return (entries[i]); - } - - return (nullptr); -} - -PitEntry *PitData::FindEntry(unsigned int partitionIdentifier) -{ - for (unsigned int i = 0; i < entries.size(); i++) - { - if (entries[i]->GetPartitionIdentifier() == partitionIdentifier) - return (entries[i]); - } - - return (nullptr); -} - -const PitEntry *PitData::FindEntry(unsigned int partitionIdentifier) const -{ - for (unsigned int i = 0; i < entries.size(); i++) - { - if (entries[i]->GetPartitionIdentifier() == partitionIdentifier) - return (entries[i]); - } - - return (nullptr); -} - -void PitData::Print(void) const -{ - InterfaceManager::Print("Entry Count: %d\n", entryCount); - - InterfaceManager::Print("Unknown 1: %d\n", unknown1); - InterfaceManager::Print("Unknown 2: %d\n", unknown2); - InterfaceManager::Print("Unknown 3: %d\n", unknown3); - InterfaceManager::Print("Unknown 4: %d\n", unknown4); - InterfaceManager::Print("Unknown 5: %d\n", unknown5); - InterfaceManager::Print("Unknown 6: %d\n", unknown6); - InterfaceManager::Print("Unknown 7: %d\n", unknown7); - InterfaceManager::Print("Unknown 8: %d\n", unknown8); - - for (unsigned int i = 0; i < entryCount; i++) - { - InterfaceManager::Print("\n\n--- Entry #%d ---\n", i); - entries[i]->Print(); - } - - InterfaceManager::Print("\n"); -} diff --git a/heimdall/source/PitData.h b/heimdall/source/PitData.h deleted file mode 100755 index b6a0d2f..0000000 --- a/heimdall/source/PitData.h +++ /dev/null @@ -1,345 +0,0 @@ -/* Copyright (c) 2010 Benjamin Dobell, Glass Echidna - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE.*/ - -#ifndef PITDATA_H -#define PITDATA_H - -// C Standard Library -#include <string.h> -#include <vector> - -namespace Heimdall -{ - class PitEntry - { - public: - - enum - { - kDataSize = 132, - kPartitionNameMaxLength = 32, - kFilenameMaxLength = 64 - }; - - enum - { - kPartitionTypeRfs = 0, - kPartitionTypeBlank = 1, // ? - kPartitionTypeExt4 = 2 - }; - - enum - { - kPartitionFlagWrite = 1 << 1 - }; - - private: - - bool unused; - - unsigned int partitionType; - unsigned int partitionIdentifier; - unsigned int partitionFlags; - - unsigned int unknown2; - - unsigned int partitionBlockSize; - unsigned int partitionBlockCount; - - unsigned int unknown3; - unsigned int unknown4; - - char partitionName[kPartitionNameMaxLength]; - char filename[kFilenameMaxLength]; - - public: - - PitEntry(); - ~PitEntry(); - - void Print(void) const; - - bool GetUnused(void) const - { - return unused; - } - - void SetUnused(bool unused) - { - this->unused = unused; - } - - unsigned int GetPartitionType(void) const - { - return partitionType; - } - - void SetPartitionType(unsigned int partitionType) - { - this->partitionType = partitionType; - } - - unsigned int GetPartitionIdentifier(void) const - { - return partitionIdentifier; - } - - void SetPartitionIdentifier(unsigned int partitionIdentifier) - { - this->partitionIdentifier = partitionIdentifier; - } - - unsigned int GetPartitionFlags(void) const - { - return partitionFlags; - } - - void SetPartitionFlags(unsigned int partitionFlags) - { - this->partitionFlags = partitionFlags; - } - - unsigned int GetUnknown2(void) const - { - return unknown2; - } - - void SetUnknown2(unsigned int unknown2) - { - this->unknown2 = unknown2; - } - - unsigned int GetPartitionBlockSize(void) const - { - return partitionBlockSize; - } - - void SetPartitionBlockSize(unsigned int partitionBlockSize) - { - this->partitionBlockSize = partitionBlockSize; - } - - unsigned int GetPartitionBlockCount(void) const - { - return partitionBlockCount; - } - - void SetPartitionBlockCount(unsigned int partitionBlockCount) - { - this->partitionBlockCount = partitionBlockCount; - } - - unsigned int GetUnknown3(void) const - { - return unknown3; - } - - void SetUnknown3(unsigned int unknown3) - { - this->unknown3 = unknown3; - } - - unsigned int GetUnknown4(void) const - { - return unknown4; - } - - void SetUnknown4(unsigned int unknown4) - { - this->unknown4 = unknown4; - } - - const char *GetPartitionName(void) const - { - return partitionName; - } - - void SetPartitionName(const char *partitionName) - { - // This isn't strictly necessary but ensures no junk is left in our PIT file. - memset(this->partitionName, 0, 64); - - if (strlen(partitionName) < 64) - strcpy(this->partitionName, partitionName); - else - memcpy(this->partitionName, partitionName, 63); - } - - const char *GetFilename(void) const - { - return filename; - } - - void SetFilename(const char *filename) - { - // This isn't strictly necessary but ensures no junk is left in our PIT file. - memset(this->filename, 0, 32); - - if (strlen(partitionName) < 32) - strcpy(this->filename, filename); - else - memcpy(this->filename, filename, 31); - } - }; - - class PitData - { - public: - - enum - { - kFileIdentifier = 0x12349876, - kHeaderDataSize = 28 - }; - - private: - - unsigned int entryCount; // 0x04 - unsigned int unknown1; // 0x08 - unsigned int unknown2; // 0x0C - - unsigned short unknown3; // 0x10 (7508 = I9000, 7703 = I9100 & P1000)? - unsigned short unknown4; // 0x12 (Always 65, probably flags of some sort) - - unsigned short unknown5; // 0x14 - unsigned short unknown6; // 0x16 - - unsigned short unknown7; // 0x18 - unsigned short unknown8; // 0x1A - - // Entries start at 0x1C - std::vector<PitEntry *> entries; - - static int UnpackInteger(const unsigned char *data, unsigned int offset) - { -#ifdef WORDS_BIGENDIAN - int value = (data[offset] << 24) | (data[offset + 1] << 16) | - (data[offset + 2] << 8) | data[offset + 3]; -#else - // Flip endianness - int value = data[offset] | (data[offset + 1] << 8) | - (data[offset + 2] << 16) | (data[offset + 3] << 24); -#endif - return (value); - } - - static int UnpackShort(const unsigned char *data, unsigned int offset) - { -#ifdef WORDS_BIGENDIAN - short value = (data[offset] << 8) | data[offset + 1]; -#else - // Flip endianness - short value = data[offset] | (data[offset + 1] << 8); -#endif - return (value); - } - - static void PackInteger(unsigned char *data, unsigned int offset, unsigned int value) - { -#ifdef WORDS_BIGENDIAN - data[offset] = (value & 0xFF000000) >> 24; - data[offset + 1] = (value & 0x00FF0000) >> 16; - data[offset + 2] = (value & 0x0000FF00) >> 8; - data[offset + 3] = value & 0x000000FF; -#else - // Flip endianness - data[offset] = value & 0x000000FF; - data[offset + 1] = (value & 0x0000FF00) >> 8; - data[offset + 2] = (value & 0x00FF0000) >> 16; - data[offset + 3] = (value & 0xFF000000) >> 24; -#endif - } - - static void PackShort(unsigned char *data, unsigned int offset, unsigned short value) - { -#ifdef WORDS_BIGENDIAN - data[offset] = (value & 0xFF00) >> 8; - data[offset + 1] = value & 0x00FF; -#else - // Flip endianness - data[offset] = value & 0x00FF; - data[offset + 1] = (value & 0xFF00) >> 8; -#endif - } - - public: - - PitData(); - ~PitData(); - - bool Unpack(const unsigned char *data); - void Pack(unsigned char *data) const; - - PitEntry *FindEntry(const char *partitionName); - const PitEntry *FindEntry(const char *partitionName) const; - - PitEntry *FindEntry(unsigned int partitionIdentifier); - const PitEntry *FindEntry(unsigned int partitionIdentifier) const; - - void Print(void) const; - - unsigned int GetEntryCount(void) const - { - return entryCount; - } - - unsigned int GetUnknown1(void) const - { - return unknown1; - } - - unsigned int GetUnknown2(void) const - { - return unknown2; - } - - unsigned short GetUnknown3(void) const - { - return unknown3; - } - - unsigned short GetUnknown4(void) const - { - return unknown4; - } - - unsigned short GetUnknown5(void) const - { - return unknown5; - } - - unsigned short GetUnknown6(void) const - { - return unknown6; - } - - unsigned short GetUnknown7(void) const - { - return unknown7; - } - - unsigned short GetUnknown8(void) const - { - return unknown8; - } - }; -} - -#endif diff --git a/heimdall/source/main.cpp b/heimdall/source/main.cpp index 84260f0..64cc553 100644 --- a/heimdall/source/main.cpp +++ b/heimdall/source/main.cpp @@ -24,14 +24,16 @@ #include <stdio.h> #include <string> +// libpit +#include "libpit.h" + // Heimdall #include "BridgeManager.h" #include "DeviceInfoPacket.h" #include "DeviceInfoResponse.h" #include "EndModemFileTransferPacket.h" #include "EndPhoneFileTransferPacket.h" -#include "InterfaceManager.h" -#include "PitData.h" +#include "Interface.h" using namespace std; using namespace Heimdall; @@ -110,6 +112,26 @@ void initialiseKnownPartitionNames(void) knownPartitionNames[kKnownPartitionEmmc].push_back("GANG"); } +bool isKnownPartition(const char *partitionName, unsigned int knownPartitionIndex) +{ + for (unsigned int i = 0; i < knownPartitionNames[knownPartitionIndex].size(); i++) + { + if (strcmp(partitionName, knownPartitionNames[knownPartitionIndex][i]) == 0) + return (true); + } + + return (false); +} + +bool isKnownBootPartition(const char *partitionName) +{ + return (isKnownPartition(partitionName, kKnownPartitionPrimaryBootloader) || + isKnownPartition(partitionName, kKnownPartitionSecondaryBootloader) || + isKnownPartition(partitionName, kKnownPartitionSecondaryBootloaderBackup) || + isKnownPartition(partitionName, kKnownPartitionParam) || + isKnownPartition(partitionName, kKnownPartitionNormalBoot)); +} + bool openFiles(const map<string, string>& argumentMap, map<string, FILE *>& argumentFileMap) { map<string, string>::const_iterator it = argumentMap.begin(); @@ -130,7 +152,7 @@ bool openFiles(const map<string, string>& argumentMap, map<string, FILE *>& argu // The argument wasn't a partition index, check if it's a known partition name. for (int knownPartition = 0; knownPartition < kKnownPartitionCount; knownPartition++) { - if (it->first.compare(InterfaceManager::flashArgumentNames[InterfaceManager::kFlashArgPit + knownPartition]) == 0) + if (it->first == Interface::actions[Interface::kActionFlash].valueArguments[knownPartition]) { isFileArgument = true; break; @@ -147,7 +169,7 @@ bool openFiles(const map<string, string>& argumentMap, map<string, FILE *>& argu if (!argumentFilePair.second) { - InterfaceManager::PrintError("Failed to open file \"%s\"\n", it->second.c_str()); + Interface::PrintError("Failed to open file \"%s\"\n", it->second.c_str()); return (false); } @@ -179,7 +201,7 @@ bool mapFilesToPartitions(const map<string, FILE *>& argumentFileMap, const PitD for (knownPartition = 0; knownPartition < kKnownPartitionCount; knownPartition++) { - if (it->first.compare(InterfaceManager::flashArgumentNames[InterfaceManager::kFlashArgPit + knownPartition]) == 0) + if (it->first == Interface::actions[Interface::kActionFlash].valueArguments[knownPartition]) break; } @@ -195,7 +217,7 @@ bool mapFilesToPartitions(const map<string, FILE *>& argumentFileMap, const PitD if (!pitEntry) { - InterfaceManager::PrintError("Partition corresponding to %s argument could not be located\n", it->first.c_str()); + Interface::PrintError("Partition corresponding to %s argument could not be located\n", it->first.c_str()); return (false); } @@ -216,18 +238,18 @@ void closeFiles(map<string, FILE *> argumentfileMap) int downloadPitFile(BridgeManager *bridgeManager, unsigned char **pitBuffer) { - InterfaceManager::Print("Downloading device's PIT file...\n"); + Interface::Print("Downloading device's PIT file...\n"); int devicePitFileSize = bridgeManager->ReceivePitFile(pitBuffer); if (!*pitBuffer) { - InterfaceManager::PrintError("Failed to download PIT file!\n"); + Interface::PrintError("Failed to download PIT file!\n"); return (-1); } - InterfaceManager::Print("PIT file download sucessful\n\n"); + Interface::Print("PIT file download sucessful\n\n"); return devicePitFileSize; } @@ -247,16 +269,16 @@ bool flashFile(BridgeManager *bridgeManager, unsigned int partitionIndex, const if (isPit) { - InterfaceManager::Print("Uploading %s\n", partitionName); + Interface::Print("Uploading %s\n", partitionName); if (bridgeManager->SendPitFile(file)) { - InterfaceManager::Print("%s upload successful\n", partitionName); + Interface::Print("%s upload successful\n", partitionName); return (true); } else { - InterfaceManager::PrintError("%s upload failed!\n", partitionName); + Interface::PrintError("%s upload failed!\n", partitionName); return (false); } } @@ -276,34 +298,34 @@ bool flashFile(BridgeManager *bridgeManager, unsigned int partitionIndex, const if (isModem) { - InterfaceManager::Print("Uploading %s\n", partitionName); + Interface::Print("Uploading %s\n", partitionName); //if (bridgeManager->SendFile(file, EndPhoneFileTransferPacket::kDestinationPhone, // <-- Kies method. WARNING: Doesn't work on Galaxy Tab! // EndPhoneFileTransferPacket::kFileModem)) if (bridgeManager->SendFile(file, EndModemFileTransferPacket::kDestinationModem)) // <-- Odin method { - InterfaceManager::Print("%s upload successful\n", partitionName); + Interface::Print("%s upload successful\n", partitionName); return (true); } else { - InterfaceManager::PrintError("%s upload failed!\n", partitionName); + Interface::PrintError("%s upload failed!\n", partitionName); return (false); } } else { // We're uploading to a phone partition - InterfaceManager::Print("Uploading %s\n", partitionName); + Interface::Print("Uploading %s\n", partitionName); if (bridgeManager->SendFile(file, EndPhoneFileTransferPacket::kDestinationPhone, partitionIndex)) { - InterfaceManager::Print("%s upload successful\n", partitionName); + Interface::Print("%s upload successful\n", partitionName); return (true); } else { - InterfaceManager::PrintError("%s upload failed!\n", partitionName); + Interface::PrintError("%s upload failed!\n", partitionName); return (false); } } @@ -318,63 +340,31 @@ bool attemptFlash(BridgeManager *bridgeManager, map<string, FILE *> argumentFile // ---------- GET DEVICE INFORMATION ---------- - DeviceInfoPacket *deviceInfoPacket = new DeviceInfoPacket(DeviceInfoPacket::kUnknown1); - success = bridgeManager->SendPacket(deviceInfoPacket); - delete deviceInfoPacket; - - if (!success) - { - InterfaceManager::PrintError("Failed to send device info packet!\nFailed Request: kUnknown1\n"); - return (false); - } - - DeviceInfoResponse *deviceInfoResponse = new DeviceInfoResponse(); - success = bridgeManager->ReceivePacket(deviceInfoResponse); - int unknown = deviceInfoResponse->GetUnknown(); - delete deviceInfoResponse; - - if (!success) - { - InterfaceManager::PrintError("Failed to receive device info response!\n"); + int deviceInfoResult; + + if (!bridgeManager->RequestDeviceInfo(DeviceInfoPacket::kUnknown1, &deviceInfoResult)) return (false); - } // 131072 for Galaxy S II, 0 for other devices. - if (unknown != 0 && unknown != 131072) + if (deviceInfoResult != 0 && deviceInfoResult != 131072) { - InterfaceManager::PrintError("Unexpected device info response!\nExpected: 0\nReceived:%i\n", unknown); + Interface::PrintError("Unexpected device info response!\nExpected: 0\nReceived:%i\n", deviceInfoResult); return (false); } // -------------------- KIES DOESN'T DO THIS -------------------- - deviceInfoPacket = new DeviceInfoPacket(DeviceInfoPacket::kUnknown2); - success = bridgeManager->SendPacket(deviceInfoPacket); - delete deviceInfoPacket; - if (!success) - { - InterfaceManager::PrintError("Failed to send device info packet!\nFailed Request: kUnknown2\n"); + if (!bridgeManager->RequestDeviceInfo(DeviceInfoPacket::kUnknown2, &deviceInfoResult)) return (false); - } - - deviceInfoResponse = new DeviceInfoResponse(); - success = bridgeManager->ReceivePacket(deviceInfoResponse); - unknown = deviceInfoResponse->GetUnknown(); - delete deviceInfoResponse; - - if (!success) - { - InterfaceManager::PrintError("Failed to receive device info response!\n"); - return (false); - } // TODO: Work out what this value is... it has been either 180 or 0 for Galaxy S phones, 3 on the Galaxy Tab, 190 for SHW-M110S. - if (unknown != 180 && unknown != 0 && unknown != 3 && unknown != 190) + if (deviceInfoResult != 180 && deviceInfoResult != 0 && deviceInfoResult != 3 && deviceInfoResult != 190) { - InterfaceManager::PrintError("Unexpected device info response!\nExpected: 180, 0 or 3\nReceived:%i\n", unknown); + Interface::PrintError("Unexpected device info response!\nExpected: 180, 0 or 3\nReceived:%i\n", deviceInfoResult); return (false); } - // -------------------------------------------------------------- + + // ------------- SEND TOTAL BYTES TO BE TRANSFERRED ------------- int totalBytes = 0; for (map<string, FILE *>::const_iterator it = argumentFileMap.begin(); it != argumentFileMap.end(); it++) @@ -384,30 +374,30 @@ bool attemptFlash(BridgeManager *bridgeManager, map<string, FILE *> argumentFile rewind(it->second); } - deviceInfoPacket = new DeviceInfoPacket(DeviceInfoPacket::kTotalBytes, totalBytes); + DeviceInfoPacket *deviceInfoPacket = new DeviceInfoPacket(DeviceInfoPacket::kTotalBytes, totalBytes); success = bridgeManager->SendPacket(deviceInfoPacket); delete deviceInfoPacket; if (!success) { - InterfaceManager::PrintError("Failed to send total bytes device info packet!\n"); + Interface::PrintError("Failed to send total bytes device info packet!\n"); return (false); } - deviceInfoResponse = new DeviceInfoResponse(); + DeviceInfoResponse *deviceInfoResponse = new DeviceInfoResponse(); success = bridgeManager->ReceivePacket(deviceInfoResponse); - unknown = deviceInfoResponse->GetUnknown(); + deviceInfoResult = deviceInfoResponse->GetUnknown(); delete deviceInfoResponse; if (!success) { - InterfaceManager::PrintError("Failed to receive device info response!\n"); + Interface::PrintError("Failed to receive device info response!\n"); return (false); } - if (unknown != 0) + if (deviceInfoResult != 0) { - InterfaceManager::PrintError("Unexpected device info response!\nExpected: 0\nReceived:%i\n", unknown); + Interface::PrintError("Unexpected device info response!\nExpected: 0\nReceived:%i\n", deviceInfoResult); return (false); } @@ -419,13 +409,12 @@ bool attemptFlash(BridgeManager *bridgeManager, map<string, FILE *> argumentFile if (repartition) { // If we're repartitioning then we need to unpack the information from the specified PIT file. - - map<string, FILE *>::iterator it = argumentFileMap.find(InterfaceManager::flashArgumentNames[InterfaceManager::kFlashArgPit]); + map<string, FILE *>::iterator it = argumentFileMap.find(Interface::actions[Interface::kActionFlash].valueArguments[Interface::kFlashValueArgPit]); // This shouldn't ever happen due to early checks, but we'll check again just in case... if (it == argumentFileMap.end()) { - InterfaceManager::PrintError("Attempt was made to repartition without specifying a PIT file!\n"); + Interface::PrintError("Attempt was made to repartition without specifying a PIT file!\n"); return (false); } @@ -451,7 +440,6 @@ bool attemptFlash(BridgeManager *bridgeManager, map<string, FILE *> argumentFile else { // If we're not repartitioning then we need to retrieve the device's PIT file and unpack it. - unsigned char *pitFileBuffer; downloadPitFile(bridgeManager, &pitFileBuffer); @@ -463,9 +451,13 @@ bool attemptFlash(BridgeManager *bridgeManager, map<string, FILE *> argumentFile map<unsigned int, PartitionNameFilePair> partitionFileMap; - // Map the files being flashed to partitions stored in PIT file. - mapFilesToPartitions(argumentFileMap, pitData, partitionFileMap); - + // Map the files being flashed to partitions stored in the PIT file. + if (!mapFilesToPartitions(argumentFileMap, pitData, partitionFileMap)) + { + delete pitData; + return (false); + } + delete pitData; // If we're repartitioning then we need to flash the PIT file first. @@ -477,14 +469,26 @@ bool attemptFlash(BridgeManager *bridgeManager, map<string, FILE *> argumentFile { if (!flashFile(bridgeManager, it->first, it->second.partitionName.c_str(), it->second.file)) return (false); + + break; } } } - // Flash all other files + // Flash partitions not involved in the boot process second. for (map<unsigned int, PartitionNameFilePair>::iterator it = partitionFileMap.begin(); it != partitionFileMap.end(); it++) { - if (it->second.file != localPitFile) + if (!isKnownPartition(it->second.partitionName.c_str(), kKnownPartitionPit) && !isKnownBootPartition(it->second.partitionName.c_str())) + { + if (!flashFile(bridgeManager, it->first, it->second.partitionName.c_str(), it->second.file)) + return (false); + } + } + + // Flash boot partitions last. + for (map<unsigned int, PartitionNameFilePair>::iterator it = partitionFileMap.begin(); it != partitionFileMap.end(); it++) + { + if (isKnownBootPartition(it->second.partitionName.c_str())) { if (!flashFile(bridgeManager, it->first, it->second.partitionName.c_str(), it->second.file)) return (false); @@ -499,7 +503,7 @@ int main(int argc, char **argv) map<string, string> argumentMap; int actionIndex; - if (!InterfaceManager::GetArguments(argc, argv, argumentMap, &actionIndex)) + if (!Interface::GetArguments(argc, argv, argumentMap, &actionIndex)) { Sleep(250); return (0); @@ -507,83 +511,95 @@ int main(int argc, char **argv) initialiseKnownPartitionNames(); - if (actionIndex == InterfaceManager::kActionHelp) - { - InterfaceManager::Print(InterfaceManager::usage); - return (0); - } - else if (actionIndex == InterfaceManager::kActionFlash) + switch (actionIndex) { - if (argumentMap.find(InterfaceManager::flashArgumentNames[InterfaceManager::kFlashArgRepartition]) != argumentMap.end() - && argumentMap.find(InterfaceManager::flashArgumentNames[InterfaceManager::kFlashArgPit]) == argumentMap.end()) - { - InterfaceManager::Print("If you wish to repartition then a PIT file must be specified.\n"); - return (0); - } + case Interface::kActionFlash: + if (argumentMap.find(Interface::actions[Interface::kActionFlash].valuelessArguments[Interface::kFlashValuelessArgRepartition]) != argumentMap.end() + && argumentMap.find(Interface::actions[Interface::kActionFlash].valueArguments[Interface::kFlashValueArgPit]) == argumentMap.end()) + { + Interface::Print("If you wish to repartition then a PIT file must be specified.\n"); + return (0); + } - if (argumentMap.find(InterfaceManager::flashArgumentNames[InterfaceManager::kFlashArgPit]) != argumentMap.end() - && argumentMap.find(InterfaceManager::flashArgumentNames[InterfaceManager::kFlashArgRepartition]) == argumentMap.end()) - { - InterfaceManager::Print("A PIT file should only be used when repartitioning.\n"); - return (0); - } - } - else if (actionIndex == InterfaceManager::kActionDump) - { - if (argumentMap.find(InterfaceManager::dumpArgumentNames[InterfaceManager::kDumpArgOutput]) == argumentMap.end()) - { - InterfaceManager::Print("Output file not specified.\n\n"); - InterfaceManager::Print(InterfaceManager::usage); - return (0); - } + if (argumentMap.find(Interface::actions[Interface::kActionFlash].valueArguments[Interface::kFlashValueArgPit]) != argumentMap.end() + && argumentMap.find(Interface::actions[Interface::kActionFlash].valuelessArguments[Interface::kFlashValuelessArgRepartition]) == argumentMap.end()) + { + Interface::Print("A PIT file should only be used when repartitioning.\n"); + return (0); + } - if (argumentMap.find(InterfaceManager::dumpArgumentNames[InterfaceManager::kDumpArgChipType]) == argumentMap.end()) - { - InterfaceManager::Print("You must specify a chip type.\n\n"); - InterfaceManager::Print(InterfaceManager::usage); - return (0); - } + break; - string chipType = argumentMap.find(InterfaceManager::dumpArgumentNames[InterfaceManager::kDumpArgChipType])->second; - if (!(chipType == "RAM" || chipType == "ram" || chipType == "NAND" || chipType == "nand")) + case Interface::kActionDump: { - InterfaceManager::Print("Unknown chip type: %s.\n\n", chipType.c_str()); - InterfaceManager::Print(InterfaceManager::usage); - return (0); + if (argumentMap.find(Interface::actions[Interface::kActionDump].valueArguments[Interface::kDumpValueArgOutput]) == argumentMap.end()) + { + Interface::Print("Output file not specified.\n\n"); + Interface::PrintUsage(); + return (0); + } + + if (argumentMap.find(Interface::actions[Interface::kActionDump].valueArguments[Interface::kDumpValueArgChipType]) == argumentMap.end()) + { + Interface::Print("You must specify a chip type.\n\n"); + Interface::PrintUsage(); + return (0); + } + + string chipType = argumentMap.find(Interface::actions[Interface::kActionDump].valueArguments[Interface::kDumpValueArgChipType])->second; + if (!(chipType == "RAM" || chipType == "ram" || chipType == "NAND" || chipType == "nand")) + { + Interface::Print("Unknown chip type: %s.\n\n", chipType.c_str()); + Interface::PrintUsage(); + return (0); + } + + if (argumentMap.find(Interface::actions[Interface::kActionDump].valueArguments[Interface::kDumpValueArgChipId]) == argumentMap.end()) + { + Interface::Print("You must specify a Chip ID.\n\n"); + Interface::PrintUsage(); + return (0); + } + + int chipId = atoi(argumentMap.find(Interface::actions[Interface::kActionDump].valueArguments[Interface::kDumpValueArgChipId])->second.c_str()); + if (chipId < 0) + { + Interface::Print("Chip ID must be a non-negative integer.\n"); + return (0); + } + + break; } - if (argumentMap.find(InterfaceManager::dumpArgumentNames[InterfaceManager::kDumpArgChipId]) == argumentMap.end()) - { - InterfaceManager::Print("You must specify a Chip ID.\n\n"); - InterfaceManager::Print(InterfaceManager::usage); + case Interface::kActionVersion: + Interface::PrintVersion(); return (0); - } - int chipId = atoi(argumentMap.find(InterfaceManager::dumpArgumentNames[InterfaceManager::kDumpArgChipId])->second.c_str()); - if (chipId < 0) - { - InterfaceManager::Print("Chip ID must be a non-negative integer.\n"); + case Interface::kActionHelp: + Interface::PrintUsage(); return (0); - } } - InterfaceManager::Print("\nHeimdall v1.2.0, Copyright (c) 2010-2011, Benjamin Dobell, Glass Echidna\n"); - InterfaceManager::Print("http://www.glassechidna.com.au\n\n"); - InterfaceManager::Print("This software is provided free of charge. Copying and redistribution is\nencouraged.\n\n"); - InterfaceManager::Print("If you appreciate this software and you would like to support future\ndevelopment please consider donating:\n"); - InterfaceManager::Print("http://www.glassechidna.com.au/donate/\n\n"); - - Sleep(1000); - - bool verbose = argumentMap.find(InterfaceManager::commonArgumentNames[InterfaceManager::kCommonArgVerbose]) != argumentMap.end(); - bool noReboot = argumentMap.find(InterfaceManager::commonArgumentNames[InterfaceManager::kCommonArgNoReboot]) != argumentMap.end(); + bool verbose = argumentMap.find(Interface::commonValuelessArguments[Interface::kCommonValuelessArgVerbose]) != argumentMap.end(); + bool reboot = argumentMap.find(Interface::commonValuelessArguments[Interface::kCommonValuelessArgNoReboot]) == argumentMap.end(); int communicationDelay = BridgeManager::kCommunicationDelayDefault; - if (argumentMap.find(InterfaceManager::commonArgumentNames[InterfaceManager::kCommonArgDelay]) != argumentMap.end()) - communicationDelay = atoi(argumentMap.find(InterfaceManager::commonArgumentNames[InterfaceManager::kCommonArgDelay])->second.c_str()); + if (argumentMap.find(Interface::commonValueArguments[Interface::kCommonValueArgDelay]) != argumentMap.end()) + communicationDelay = atoi(argumentMap.find(Interface::commonValueArguments[Interface::kCommonValueArgDelay])->second.c_str()); BridgeManager *bridgeManager = new BridgeManager(verbose, communicationDelay); + if (actionIndex == Interface::kActionDetect) + { + bridgeManager->DetectDevice(); + + delete bridgeManager; + return (0); + } + + Interface::PrintReleaseInfo(); + Sleep(1000); + if (!bridgeManager->Initialise()) { delete bridgeManager; @@ -594,7 +610,7 @@ int main(int argc, char **argv) switch (actionIndex) { - case InterfaceManager::kActionFlash: + case Interface::kActionFlash: { map<string, FILE *> argumentFileMap; @@ -615,20 +631,17 @@ int main(int argc, char **argv) return (-1); } - bool repartition = argumentMap.find(InterfaceManager::flashArgumentNames[InterfaceManager::kFlashArgRepartition]) != argumentMap.end(); + bool repartition = argumentMap.find(Interface::actions[Interface::kActionFlash].valuelessArguments[Interface::kFlashValuelessArgRepartition]) != argumentMap.end(); success = attemptFlash(bridgeManager, argumentFileMap, repartition); - if (noReboot) - success = bridgeManager->EndSession() && success; - else - success = bridgeManager->EndSession() && bridgeManager->RebootDevice() && success; + success = bridgeManager->EndSession(reboot) && success; closeFiles(argumentFileMap); break; } - case InterfaceManager::kActionClosePcScreen: + case Interface::kActionClosePcScreen: { if (!bridgeManager->BeginSession()) { @@ -636,37 +649,34 @@ int main(int argc, char **argv) return (-1); } - InterfaceManager::Print("Attempting to close connect to pc screen...\n"); + Interface::Print("Attempting to close connect to pc screen...\n"); - if (noReboot) - success = bridgeManager->EndSession(); - else - success = bridgeManager->EndSession() && bridgeManager->RebootDevice(); + success = bridgeManager->EndSession(reboot); if (success) - InterfaceManager::Print("Attempt complete\n"); + Interface::Print("Attempt complete\n"); break; } - case InterfaceManager::kActionDump: + case Interface::kActionDump: { - const char *outputFilename = argumentMap.find(InterfaceManager::dumpArgumentNames[InterfaceManager::kDumpArgOutput])->second.c_str(); + const char *outputFilename = argumentMap.find(Interface::actions[Interface::kActionDump].valueArguments[Interface::kDumpValueArgOutput])->second.c_str(); FILE *dumpFile = fopen(outputFilename, "wb"); if (!dumpFile) { - InterfaceManager::PrintError("Failed to open file \"%s\"\n", outputFilename); + Interface::PrintError("Failed to open file \"%s\"\n", outputFilename); delete bridgeManager; return (-1); } int chipType = 0; - string chipTypeName = argumentMap.find(InterfaceManager::dumpArgumentNames[InterfaceManager::kDumpArgChipType])->second; + string chipTypeName = argumentMap.find(Interface::actions[Interface::kActionDump].valueArguments[Interface::kDumpValueArgChipType])->second; if (chipTypeName == "NAND" || chipTypeName == "nand") chipType = 1; - int chipId = atoi(argumentMap.find(InterfaceManager::dumpArgumentNames[InterfaceManager::kDumpArgChipId])->second.c_str()); + int chipId = atoi(argumentMap.find(Interface::actions[Interface::kActionDump].valueArguments[Interface::kDumpValueArgChipId])->second.c_str()); if (!bridgeManager->BeginSession()) { @@ -680,15 +690,12 @@ int main(int argc, char **argv) fclose(dumpFile); - if (noReboot) - success = bridgeManager->EndSession() && success; - else - success = bridgeManager->EndSession() && bridgeManager->RebootDevice() && success; + success = bridgeManager->EndSession(reboot) && success; break; } - case InterfaceManager::kActionPrintPit: + case Interface::kActionPrintPit: { if (!bridgeManager->BeginSession()) { @@ -700,11 +707,7 @@ int main(int argc, char **argv) if (downloadPitFile(bridgeManager, &devicePit) < -1) { - if (!bridgeManager->EndSession()) - return (-1); - - if (!noReboot) - bridgeManager->RebootDevice(); + bridgeManager->EndSession(reboot); delete bridgeManager; return (-1); @@ -714,21 +717,18 @@ int main(int argc, char **argv) if (pitData->Unpack(devicePit)) { - pitData->Print(); + Interface::PrintPit(pitData); success = true; } else { - InterfaceManager::PrintError("Failed to unpack device's PIT file!\n"); + Interface::PrintError("Failed to unpack device's PIT file!\n"); success = false; } delete pitData; - if (noReboot) - success = bridgeManager->EndSession() && success; - else - success = bridgeManager->EndSession() && bridgeManager->RebootDevice() && success; + success = bridgeManager->EndSession(reboot) && success; break; } |