diff options
Diffstat (limited to '')
35 files changed, 3850 insertions, 0 deletions
diff --git a/heimdall/source/.DS_Store b/heimdall/source/.DS_Store Binary files differnew file mode 100644 index 0000000..b244d9f --- /dev/null +++ b/heimdall/source/.DS_Store diff --git a/heimdall/source/._.DS_Store b/heimdall/source/._.DS_Store Binary files differnew file mode 100644 index 0000000..338bd7b --- /dev/null +++ b/heimdall/source/._.DS_Store diff --git a/heimdall/source/._BridgeManager.cpp b/heimdall/source/._BridgeManager.cpp Binary files differnew file mode 100644 index 0000000..5b4b4a0 --- /dev/null +++ b/heimdall/source/._BridgeManager.cpp diff --git a/heimdall/source/._InterfaceManager.cpp b/heimdall/source/._InterfaceManager.cpp Binary files differnew file mode 100644 index 0000000..a322a67 --- /dev/null +++ b/heimdall/source/._InterfaceManager.cpp diff --git a/heimdall/source/._InterfaceManager.h b/heimdall/source/._InterfaceManager.h Binary files differnew file mode 100644 index 0000000..a322a67 --- /dev/null +++ b/heimdall/source/._InterfaceManager.h diff --git a/heimdall/source/.dirstamp b/heimdall/source/.dirstamp new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/heimdall/source/.dirstamp diff --git a/heimdall/source/BeginDumpPacket.h b/heimdall/source/BeginDumpPacket.h new file mode 100644 index 0000000..4bd6d88 --- /dev/null +++ b/heimdall/source/BeginDumpPacket.h @@ -0,0 +1,72 @@ +/* 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 BEGINDUMPPACKET_H
+#define BEGINDUMPPACKET_H
+
+// Heimdall
+#include "FileTransferPacket.h"
+
+namespace Heimdall
+{
+ class BeginDumpPacket : public FileTransferPacket
+ {
+ public:
+
+ enum
+ {
+ kChipTypeRam = 0,
+ kChipTypeNand = 1
+ };
+
+ private:
+
+ unsigned int chipType;
+ unsigned int chipId;
+
+ public:
+
+ BeginDumpPacket(unsigned int chipType, unsigned int chipId) : FileTransferPacket(FileTransferPacket::kRequestDump)
+ {
+ this->chipType = chipType;
+ this->chipId = chipId;
+ }
+
+ unsigned int GetChipType(void) const
+ {
+ return (chipType);
+ }
+
+ unsigned int GetChipId(void) const
+ {
+ return (chipId);
+ }
+
+ virtual void Pack(void)
+ {
+ FileTransferPacket::Pack();
+
+ PackInteger(FileTransferPacket::kDataSize, chipType);
+ PackInteger(FileTransferPacket::kDataSize + 4, chipId);
+ }
+ };
+}
+
+#endif
diff --git a/heimdall/source/BridgeManager.cpp b/heimdall/source/BridgeManager.cpp new file mode 100644 index 0000000..0b94dfb --- /dev/null +++ b/heimdall/source/BridgeManager.cpp @@ -0,0 +1,1086 @@ +/* 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 Standard Library +#include <stdio.h> + +// libusb +#include <libusb.h> + +// Heimdall +#include "BeginDumpPacket.h" +#include "BridgeManager.h" +#include "DumpPartFileTransferPacket.h" +#include "DumpPartPitFilePacket.h" +#include "DumpResponse.h" +#include "EndModemFileTransferPacket.h" +#include "EndPhoneFileTransferPacket.h" +#include "FileTransferPacket.h" +#include "FlashPartFileTransferPacket.h" +#include "FlashPartPitFilePacket.h" +#include "InboundPacket.h" +#include "InterfaceManager.h" +#include "OutboundPacket.h" +#include "PitFilePacket.h" +#include "PitFileResponse.h" +#include "ReceiveFilePartPacket.h" +#include "RebootDevicePacket.h" +#include "ResponsePacket.h" +#include "SendFilePartPacket.h" +#include "SendFilePartResponse.h" + +// Future versions of libusb will use usb_interface instead of interface. +#define usb_interface interface + +#define CLASS_CDC 0x0A + +using namespace Heimdall; + +const DeviceIdentifier BridgeManager::supportedDevices[BridgeManager::kSupportedDeviceCount] = { + DeviceIdentifier(BridgeManager::kVidSamsung, BridgeManager::kPidGalaxySDownloadMode)/*, + DeviceIdentifier(BridgeManager::kVidSamsung, BridgeManager::kPidGalaxySInternational), + DeviceIdentifier(BridgeManager::kVidSamsung, BridgeManager::kPidGalaxySNewInternational), + DeviceIdentifier(BridgeManager::kVidSamsung, BridgeManager::kPidVibrantCanadaBell)*/ +}; + +enum +{ + kMaxSequenceLength = 800 +}; + +BridgeManager::BridgeManager(bool verbose, int communicationDelay) +{ + this->verbose = verbose; + this->communicationDelay = communicationDelay; + + libusbContext = nullptr; + deviceHandle = nullptr; + heimdallDevice = nullptr; + inEndpoint = -1; + outEndpoint = -1; + interfaceIndex = -1; + +#ifdef OS_LINUX + + detachedDriver = false; + +#endif +} + +BridgeManager::~BridgeManager() +{ + if (interfaceIndex >= 0) + libusb_release_interface(deviceHandle, interfaceIndex); + +#ifdef OS_LINUX + + if (detachedDriver) + { + InterfaceManager::Print("Re-attaching kernel driver...\n"); + libusb_attach_kernel_driver(deviceHandle, interfaceIndex); + } + +#endif + + if (deviceHandle) + libusb_close(deviceHandle); + + if (heimdallDevice) + libusb_unref_device(heimdallDevice); + + if (libusbContext) + libusb_exit(libusbContext); +} + +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); + 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) + { + heimdallDevice = devices[deviceIndex]; + libusb_ref_device(heimdallDevice); + break; + } + } + + if (heimdallDevice) + break; + } + + libusb_free_device_list(devices, deviceCount); + + if (!heimdallDevice) + { + InterfaceManager::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); + return (false); + } + + libusb_device_descriptor deviceDescriptor; + result = libusb_get_device_descriptor(heimdallDevice, &deviceDescriptor); + if (result != LIBUSB_SUCCESS) + { + InterfaceManager::PrintError("Failed to retrieve device description\n"); + return (false); + } + + if (verbose) + { + unsigned char stringBuffer[128]; + if (libusb_get_string_descriptor_ascii(deviceHandle, deviceDescriptor.iManufacturer, + stringBuffer, 128) >= 0) + { + InterfaceManager::Print(" Manufacturer: \"%s\"\n", stringBuffer); + } + + if (libusb_get_string_descriptor_ascii(deviceHandle, deviceDescriptor.iProduct, + stringBuffer, 128) >= 0) + { + InterfaceManager::Print(" Product: \"%s\"\n", stringBuffer); + } + + if (libusb_get_string_descriptor_ascii(deviceHandle, deviceDescriptor.iSerialNumber, + stringBuffer, 128) >= 0) + { + InterfaceManager::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, + deviceDescriptor.iSerialNumber); + InterfaceManager::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"); + return (false); + } + + int interfaceIndex = -1; + int altSettingIndex; + + for (int i = 0; i < configDescriptor->bNumInterfaces; i++) + { + for (int j = 0 ; j < configDescriptor->usb_interface[i].num_altsetting; j++) + { + if (verbose) + { + InterfaceManager::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", + configDescriptor->usb_interface[i].altsetting[j].bInterfaceClass, + configDescriptor->usb_interface[i].altsetting[j].bInterfaceSubClass, + configDescriptor->usb_interface[i].altsetting[j].bInterfaceProtocol); + } + + int inEndpointAddress = -1; + int outEndpointAddress = -1; + + for (int k = 0; k < configDescriptor->usb_interface[i].altsetting[j].bNumEndpoints; k++) + { + const libusb_endpoint_descriptor *endpoint = + &configDescriptor->usb_interface[i].altsetting[j].endpoint[k]; + + 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); + } + + if (endpoint->bEndpointAddress & LIBUSB_ENDPOINT_IN) + inEndpointAddress = endpoint->bEndpointAddress; + else + outEndpointAddress = endpoint->bEndpointAddress; + } + + if (interfaceIndex < 0 + && configDescriptor->usb_interface[i].altsetting[j].bNumEndpoints == 2 + && configDescriptor->usb_interface[i].altsetting[j].bInterfaceClass == CLASS_CDC + && inEndpointAddress != -1 && outEndpointAddress != -1) + { + interfaceIndex = i; + altSettingIndex = j; + inEndpoint = inEndpointAddress; + outEndpoint = outEndpointAddress; + } + } + } + + libusb_free_config_descriptor(configDescriptor); + + if (result != LIBUSB_SUCCESS) + { + InterfaceManager::PrintError("Failed to find correct interface configuration\n"); + return (false); + } + + InterfaceManager::Print("\nClaiming interface..."); + result = libusb_claim_interface(deviceHandle, interfaceIndex); + +#ifdef OS_LINUX + + if (result != LIBUSB_SUCCESS) + { + detachedDriver = true; + InterfaceManager::Print(" Failed. Attempting to detach driver...\n"); + libusb_detach_kernel_driver(deviceHandle, interfaceIndex); + InterfaceManager::Print("Claiming interface again..."); + result = libusb_claim_interface(deviceHandle, interfaceIndex); + } + +#endif + + if (result != LIBUSB_SUCCESS) + { + InterfaceManager::PrintError(" Failed!\n"); + return (false); + } + + InterfaceManager::Print(" Success\n"); + + InterfaceManager::Print("Setting up interface..."); + result = libusb_set_interface_alt_setting(deviceHandle, interfaceIndex, altSettingIndex); + if (result != LIBUSB_SUCCESS) + { + InterfaceManager::PrintError(" Failed!\n"); + return (false); + } + + InterfaceManager::Print(" Success\n"); + + return (true); +} + +bool BridgeManager::BeginSession(void) const +{ + InterfaceManager::Print("Beginning session...\n"); + + unsigned char *dataBuffer = new unsigned char[7]; + + int 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"); + delete [] dataBuffer; + return (false); + } + + memset(dataBuffer, 0, 7); + dataBuffer[1] = 0xC2; + dataBuffer[2] = 0x01; + dataBuffer[6] = 0x07; + + 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"); + delete [] dataBuffer; + return (false); + } + + 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"); + delete [] dataBuffer; + return (false); + } + + 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"); + delete [] dataBuffer; + return (false); + } + + memset(dataBuffer, 0, 7); + dataBuffer[1] = 0xC2; + dataBuffer[2] = 0x01; + dataBuffer[6] = 0x08; + + 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"); + delete [] dataBuffer; + return (false); + } + + 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"); + delete [] dataBuffer; + return (false); + } + + InterfaceManager::Print("Handshaking with Loke..."); + + int dataTransferred; + + // Send "ODIN" + strcpy((char *)dataBuffer, "ODIN"); + + result = libusb_bulk_transfer(deviceHandle, outEndpoint, dataBuffer, 4, &dataTransferred, 1000); + if (result < 0) + { + InterfaceManager::PrintError(" Failed!\n"); + + if (verbose) + InterfaceManager::PrintError("ERROR: Failed to send data: \"%s\"\n", dataBuffer); + + delete [] dataBuffer; + return (false); + } + + if (dataTransferred != 4) + { + InterfaceManager::PrintError(" Failed!\n"); + + if (verbose) + InterfaceManager::PrintError("ERROR: Failed to complete sending data: \"%s\"\n", dataBuffer); + + delete [] dataBuffer; + return (false); + } + + // Expect "LOKE" + memset(dataBuffer, 0, 7); + + result = libusb_bulk_transfer(deviceHandle, inEndpoint, dataBuffer, 7, &dataTransferred, 1000); + if (result < 0) + { + InterfaceManager::PrintError(" Failed!\n"); + + if (verbose) + InterfaceManager::PrintError("ERROR: Failed to receive response\n"); + delete [] dataBuffer; + return (false);; + } + + if (dataTransferred != 4 || memcmp(dataBuffer, "LOKE", 4) != 0) + { + InterfaceManager::PrintError(" Failed!\n"); + + if (verbose) + InterfaceManager::PrintError("ERROR: Unexpected communication.\nExpected: \"%s\"\nReceived: \"%s\"\n", "LOKE", dataBuffer); + + delete [] dataBuffer; + return (false); + } + + InterfaceManager::Print(" Success\n\n"); + return (true); +} + +bool BridgeManager::EndSession(void) const +{ + InterfaceManager::Print("Ending session...\n"); + + RebootDevicePacket *rebootDevicePacket = new RebootDevicePacket(RebootDevicePacket::kRequestEndSession); + bool success = SendPacket(rebootDevicePacket); + delete rebootDevicePacket; + + if (!success) + { + InterfaceManager::PrintError("Failed to send end session packet!\n"); + return (false); + } + + ResponsePacket *rebootDeviceResponse = new ResponsePacket(ResponsePacket::kResponseTypeRebootDevice); + success = ReceivePacket(rebootDeviceResponse); + delete rebootDeviceResponse; + + if (!success) + { + InterfaceManager::PrintError("Failed to receive session end confirmation!\n"); + return (false); + } + + return (true); +} + +bool BridgeManager::SendPacket(OutboundPacket *packet, int timeout) const +{ + packet->Pack(); + + int dataTransferred; + int result = libusb_bulk_transfer(deviceHandle, outEndpoint, packet->GetData(), packet->GetSize(), + &dataTransferred, timeout); + + if (result < 0) + { + // max(250, communicationDelay) + int retryDelay = (communicationDelay > 250) ? communicationDelay : 250; + + if (verbose) + InterfaceManager::PrintError("Error %i whilst sending packet. ", result); + + // Retry + for (int i = 0; i < 5; i++) + { + if (verbose) + InterfaceManager::PrintError(" Retrying...\n"); + + // Wait longer each retry + Sleep(retryDelay * (i + 1)); + + result = libusb_bulk_transfer(deviceHandle, outEndpoint, packet->GetData(), packet->GetSize(), + &dataTransferred, timeout); + + if (result >= 0) + break; + + if (verbose) + InterfaceManager::PrintError("Error %i whilst sending packet. ", result); + } + + if (verbose) + InterfaceManager::PrintError("\n"); + } + + if (communicationDelay != 0) + Sleep(communicationDelay); + + if (result < 0 || dataTransferred != packet->GetSize()) + return (false); + + return (true); +} + +bool BridgeManager::ReceivePacket(InboundPacket *packet, int timeout) const +{ + int dataTransferred; + int result = libusb_bulk_transfer(deviceHandle, inEndpoint, packet->GetData(), packet->GetSize(), + &dataTransferred, timeout); + + if (result < 0) + { + // max(250, communicationDelay) + int retryDelay = (communicationDelay > 250) ? communicationDelay : 250; + + if (verbose) + InterfaceManager::PrintError("Error %i whilst receiving packet. ", result); + + // Retry + for (int i = 0; i < 5; i++) + { + if (verbose) + InterfaceManager::PrintError(" Retrying\n"); + + // Wait longer each retry + Sleep(retryDelay * (i + 1)); + + result = libusb_bulk_transfer(deviceHandle, inEndpoint, packet->GetData(), packet->GetSize(), + &dataTransferred, timeout); + + if (result >= 0) + break; + + if (verbose) + InterfaceManager::PrintError("Error %i whilst receiving packet. ", result); + + if (i >= 3) + { + int breakHere = 0; + breakHere++; + } + } + + if (verbose) + InterfaceManager::PrintError("\n"); + } + + if (communicationDelay != 0) + Sleep(communicationDelay); + + if (result < 0 || (dataTransferred != packet->GetSize() && !packet->IsSizeVariable())) + return (false); + + packet->SetReceivedSize(dataTransferred); + + return (packet->Unpack()); +} + +bool BridgeManager::SendPitFile(FILE *file) const +{ + fseek(file, 0, SEEK_END); + long fileSize = ftell(file); + rewind(file); + + // Start file transfer + PitFilePacket *pitFilePacket = new PitFilePacket(PitFilePacket::kRequestFlash); + bool success = SendPacket(pitFilePacket); + delete pitFilePacket; + + if (!success) + { + InterfaceManager::PrintError("Failed to request sending of PIT file!\n"); + return (false); + } + + PitFileResponse *pitFileResponse = new PitFileResponse(); + success = ReceivePacket(pitFileResponse); + delete pitFileResponse; + + if (!success) + { + InterfaceManager::PrintError("Failed to confirm sending of PIT file!\n"); + return (false); + } + + // Transfer file size + FlashPartPitFilePacket *flashPartPitFilePacket = new FlashPartPitFilePacket(fileSize); + success = SendPacket(flashPartPitFilePacket); + delete flashPartPitFilePacket; + + if (!success) + { + InterfaceManager::PrintError("Failed to send PIT file part information!\n"); + return (false); + } + + pitFileResponse = new PitFileResponse(); + success = ReceivePacket(pitFileResponse); + delete pitFileResponse; + + if (!success) + { + InterfaceManager::PrintError("Failed to confirm sending of PIT file part information!\n"); + return (false); + } + + // Flash pit file + SendFilePartPacket *sendFilePartPacket = new SendFilePartPacket(file, fileSize); + success = SendPacket(sendFilePartPacket); + delete sendFilePartPacket; + + if (!success) + { + InterfaceManager::PrintError("Failed to send file part packet!\n"); + return (false); + } + + pitFileResponse = new PitFileResponse(); + success = ReceivePacket(pitFileResponse); + delete pitFileResponse; + + if (!success) + { + InterfaceManager::PrintError("Failed to receive PIT file transfer count!\n"); + return (false); + } + + return (true); +} + +int BridgeManager::ReceivePitFile(unsigned char **pitBuffer) const +{ + *pitBuffer = nullptr; + + bool success; + + // Start file transfer + PitFilePacket *pitFilePacket = new PitFilePacket(PitFilePacket::kRequestDump); + success = SendPacket(pitFilePacket); + delete pitFilePacket; + + if (!success) + { + InterfaceManager::PrintError("Failed to request receival of PIT file!\n"); + return (0); + } + + PitFileResponse *pitFileResponse = new PitFileResponse(); + success = ReceivePacket(pitFileResponse); + int fileSize = pitFileResponse->GetFileSize(); + delete pitFileResponse; + + if (!success) + { + InterfaceManager::PrintError("Failed to receive PIT file size!\n"); + return (0); + } + + int transferCount = fileSize / ReceiveFilePartPacket::kDataSize; + if (fileSize % ReceiveFilePartPacket::kDataSize != 0) + transferCount++; + + unsigned char *buffer = new unsigned char[fileSize]; + int offset = 0; + + // NOTE: The PIT file appears to always be padded out to exactly 4 kilobytes. + for (int i = 0; i < transferCount; i++) + { + DumpPartPitFilePacket *requestPacket = new DumpPartPitFilePacket(i); + success = SendPacket(requestPacket); + delete requestPacket; + + if (!success) + { + InterfaceManager::PrintError("Failed to request PIT file part #%i!\n", i); + delete [] buffer; + return (0); + } + + ReceiveFilePartPacket *receiveFilePartPacket = new ReceiveFilePartPacket(); + success = ReceivePacket(receiveFilePartPacket); + + if (!success) + { + InterfaceManager::PrintError("Failed to receive PIT file part #%i!\n", i); + delete receiveFilePartPacket; + delete [] buffer; + return (0); + } + + // Copy the whole packet data into the buffer. + memcpy(buffer + offset, receiveFilePartPacket->GetData(), receiveFilePartPacket->GetReceivedSize()); + offset += receiveFilePartPacket->GetReceivedSize(); + + delete receiveFilePartPacket; + } + + // End file transfer + pitFilePacket = new PitFilePacket(PitFilePacket::kRequestEndTransfer); + success = SendPacket(pitFilePacket); + delete pitFilePacket; + + if (!success) + { + InterfaceManager::PrintError("Failed to send request to end PIT file transfer!\n"); + delete [] buffer; + return (0); + } + + pitFileResponse = new PitFileResponse(); + success = ReceivePacket(pitFileResponse); + delete pitFileResponse; + + if (!success) + { + InterfaceManager::PrintError("Failed to receive end PIT file transfer verification!\n"); + delete [] buffer; + return (0); + } + + *pitBuffer = buffer; + return (fileSize); +} + +bool BridgeManager::SendFile(FILE *file, int destination, int fileIdentifier) const +{ + if (destination != EndFileTransferPacket::kDestinationModem && destination != EndFileTransferPacket::kDestinationPhone) + { + InterfaceManager::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"); + return (false); + } + + FileTransferPacket *flashFileTransferPacket = new FileTransferPacket(FileTransferPacket::kRequestFlash); + bool success = SendPacket(flashFileTransferPacket); + delete flashFileTransferPacket; + + if (!success) + { + InterfaceManager::PrintError("Failed to initialise transfer!\n"); + return (false); + } + + fseek(file, 0, SEEK_END); + long fileSize = ftell(file); + rewind(file); + + ResponsePacket *fileTransferResponse = new ResponsePacket(ResponsePacket::kResponseTypeFileTransfer); + success = ReceivePacket(fileTransferResponse); + delete fileTransferResponse; + + if (!success) + { + InterfaceManager::PrintError("Failed to confirm transfer initialisation!\n"); + return (false); + } + + int sequenceCount = fileSize / (kMaxSequenceLength * SendFilePartPacket::kDefaultPacketSize); + int lastSequenceSize = kMaxSequenceLength; + int partialPacketLength = fileSize % SendFilePartPacket::kDefaultPacketSize; + if (fileSize % (kMaxSequenceLength * SendFilePartPacket::kDefaultPacketSize) != 0) + { + sequenceCount++; + + int lastSequenceBytes = fileSize % (kMaxSequenceLength * SendFilePartPacket::kDefaultPacketSize); + lastSequenceSize = lastSequenceBytes / SendFilePartPacket::kDefaultPacketSize; + if (partialPacketLength != 0) + lastSequenceSize++; + } + + long bytesTransferred = 0; + int currentPercent; + int previousPercent = 0; + InterfaceManager::Print("0%%"); + + for (int sequenceIndex = 0; sequenceIndex < sequenceCount; sequenceIndex++) + { + // Min(lastSequenceSize, 131072) + bool isLastSequence = sequenceIndex == sequenceCount - 1; + int sequenceSize = (isLastSequence) ? lastSequenceSize : kMaxSequenceLength; + + FlashPartFileTransferPacket *beginFileTransferPacket = new FlashPartFileTransferPacket(0, 2 * sequenceSize); + success = SendPacket(beginFileTransferPacket); + delete beginFileTransferPacket; + + if (!success) + { + InterfaceManager::PrintError("\nFailed to begin file transfer sequence!\n"); + return (false); + } + + fileTransferResponse = new ResponsePacket(ResponsePacket::kResponseTypeFileTransfer); + bool success = ReceivePacket(fileTransferResponse); + delete fileTransferResponse; + + if (!success) + { + InterfaceManager::PrintError("\nFailed to confirm beginning of file transfer sequence!\n"); + return (false); + } + + SendFilePartPacket *sendFilePartPacket; + SendFilePartResponse *sendFilePartResponse; + + for (int filePartIndex = 0; filePartIndex < sequenceSize; filePartIndex++) + { + // Send + sendFilePartPacket = new SendFilePartPacket(file); + success = SendPacket(sendFilePartPacket); + delete sendFilePartPacket; + + if (!success) + { + InterfaceManager::PrintError("\nFailed to send file part packet!\n"); + return (false); + } + + // Response + sendFilePartResponse = new SendFilePartResponse(); + success = ReceivePacket(sendFilePartResponse); + int receivedPartIndex = sendFilePartResponse->GetPartIndex(); + + if (verbose) + { + const unsigned char *data = sendFilePartResponse->GetData(); + InterfaceManager::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]); + } + + delete sendFilePartResponse; + + if (!success) + { + InterfaceManager::PrintError("\nFailed to receive file part response!\n"); + + for (int retry = 0; retry < 4; retry++) + { + InterfaceManager::PrintError("\nRetrying..."); + + // Send + sendFilePartPacket = new SendFilePartPacket(file); + success = SendPacket(sendFilePartPacket); + delete sendFilePartPacket; + + if (!success) + { + InterfaceManager::PrintError("\nFailed to send file part packet!\n"); + return (false); + } + + // Response + sendFilePartResponse = new SendFilePartResponse(); + success = ReceivePacket(sendFilePartResponse); + int receivedPartIndex = sendFilePartResponse->GetPartIndex(); + + if (verbose) + { + const unsigned char *data = sendFilePartResponse->GetData(); + InterfaceManager::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]); + } + + delete sendFilePartResponse; + + if (receivedPartIndex != filePartIndex) + { + InterfaceManager::PrintError("\nERROR: Expected file part index: %i Received: %i\n", + filePartIndex, receivedPartIndex); + return (false); + } + + if (success) + break; + } + + if (!success) + return (false); + } + + if (receivedPartIndex != filePartIndex) + { + InterfaceManager::PrintError("\nERROR: Expected file part index: %i Received: %i\n", + filePartIndex, receivedPartIndex); + return (false); + } + + bytesTransferred += SendFilePartPacket::kDefaultPacketSize; + if (bytesTransferred > fileSize) + bytesTransferred = fileSize; + + currentPercent = (int)(100.0f * ((float)bytesTransferred / (float)fileSize)); + + if (!verbose) + { + if (currentPercent != previousPercent) + { + if (previousPercent < 10) + InterfaceManager::Print("\b\b%i%%", currentPercent); + else + InterfaceManager::Print("\b\b\b%i%%", currentPercent); + } + } + + previousPercent = currentPercent; + } + + int lastFullPacketIndex = 2 * ((isLastSequence && partialPacketLength != 0) ? sequenceSize - 1 : sequenceSize); + + if (destination == EndFileTransferPacket::kDestinationPhone) + { + EndPhoneFileTransferPacket *endPhoneFileTransferPacket = new EndPhoneFileTransferPacket( + (isLastSequence) ? partialPacketLength : 0, lastFullPacketIndex, 0, 0, fileIdentifier, isLastSequence); + + success = SendPacket(endPhoneFileTransferPacket, 3000); + delete endPhoneFileTransferPacket; + + if (!success) + { + InterfaceManager::PrintError("\nFailed to end phone file transfer sequence!\n"); + return (false); + } + } + else // destination == EndFileTransferPacket::kDestinationModem + { + EndModemFileTransferPacket *endModemFileTransferPacket = new EndModemFileTransferPacket( + (isLastSequence) ? partialPacketLength : 0, lastFullPacketIndex, 0, 0, isLastSequence); + + success = SendPacket(endModemFileTransferPacket, 3000); + delete endModemFileTransferPacket; + + if (!success) + { + InterfaceManager::PrintError("\nFailed to end modem file transfer sequence!\n"); + return (false); + } + } + + fileTransferResponse = new ResponsePacket(ResponsePacket::kResponseTypeFileTransfer); + success = ReceivePacket(fileTransferResponse, 30000); + delete fileTransferResponse; + + if (!success) + { + InterfaceManager::PrintError("\nFailed to confirm end of file transfer sequence!\n"); + return (false); + } + } + + if (!verbose) + InterfaceManager::Print("\n"); + + return (true); +} + +bool BridgeManager::ReceiveDump(int chipType, int chipId, FILE *file) const +{ + bool success; + + // Start file transfer + BeginDumpPacket *beginDumpPacket = new BeginDumpPacket(chipType, chipId); + success = SendPacket(beginDumpPacket); + delete beginDumpPacket; + + if (!success) + { + InterfaceManager::PrintError("Failed to request dump!\n"); + return (false); + } + + DumpResponse *dumpResponse = new DumpResponse(); + success = ReceivePacket(dumpResponse); + unsigned int dumpSize = dumpResponse->GetDumpSize(); + delete dumpResponse; + + if (!success) + { + InterfaceManager::PrintError("Failed to receive dump size!\n"); + return (false); + } + + unsigned int transferCount = dumpSize / ReceiveFilePartPacket::kDataSize; + if (transferCount % ReceiveFilePartPacket::kDataSize != 0) + transferCount++; + + char *buffer = new char[kDumpBufferSize * ReceiveFilePartPacket::kDataSize]; + int bufferOffset = 0; + + for (unsigned int i = 0; i < transferCount; i++) + { + DumpPartFileTransferPacket *dumpPartPacket = new DumpPartFileTransferPacket(i); + success = SendPacket(dumpPartPacket); + delete dumpPartPacket; + + if (!success) + { + InterfaceManager::PrintError("Failed to request dump part #%i!\n", i); + delete [] buffer; + return (false); + } + + ReceiveFilePartPacket *receiveFilePartPacket = new ReceiveFilePartPacket(); + success = ReceivePacket(receiveFilePartPacket); + + if (!success) + { + InterfaceManager::PrintError("Failed to receive dump part #%i!\n", i); + continue; + delete receiveFilePartPacket; + delete [] buffer; + return (true); + } + + if (bufferOffset + receiveFilePartPacket->GetReceivedSize() > kDumpBufferSize * ReceiveFilePartPacket::kDataSize) + { + // Write the buffer to the output file + fwrite(buffer, 1, bufferOffset, file); + bufferOffset = 0; + } + + // Copy the packet data into pitFile. + memcpy(buffer + bufferOffset, receiveFilePartPacket->GetData(), receiveFilePartPacket->GetReceivedSize()); + bufferOffset += receiveFilePartPacket->GetReceivedSize(); + + delete receiveFilePartPacket; + } + + if (bufferOffset != 0) + { + // Write the buffer to the output file + fwrite(buffer, 1, bufferOffset, file); + } + + delete [] buffer; + + // End file transfer + FileTransferPacket *fileTransferPacket = new FileTransferPacket(FileTransferPacket::kRequestEnd); + success = SendPacket(fileTransferPacket); + delete fileTransferPacket; + + if (!success) + { + InterfaceManager::PrintError("Failed to send request to end dump transfer!\n"); + return (false); + } + + ResponsePacket *responsePacket = new ResponsePacket(ResponsePacket::kResponseTypeFileTransfer); + success = ReceivePacket(responsePacket); + delete responsePacket; + + 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"); + + RebootDevicePacket *rebootDevicePacket = new RebootDevicePacket(RebootDevicePacket::kRequestRebootDevice); + bool success = SendPacket(rebootDevicePacket); + delete rebootDevicePacket; + + if (!success) + { + InterfaceManager::PrintError("Failed to send end session packet!\n"); + return (false); + } + + ResponsePacket *rebootDeviceResponse = new ResponsePacket(ResponsePacket::kResponseTypeRebootDevice); + success = ReceivePacket(rebootDeviceResponse); + delete rebootDeviceResponse; + + if (!success) + { + InterfaceManager::PrintError("Failed to receive reboot confirmation!\n"); + return (false); + } + + return (true); +} diff --git a/heimdall/source/BridgeManager.h b/heimdall/source/BridgeManager.h new file mode 100644 index 0000000..40a7ceb --- /dev/null +++ b/heimdall/source/BridgeManager.h @@ -0,0 +1,124 @@ +/* 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 BRIDGEMANAGER_H
+#define BRIDGEMANAGER_H
+
+// Heimdall
+#include "Heimdall.h"
+
+struct libusb_context;
+struct libusb_device;
+struct libusb_device_handle;
+
+namespace Heimdall
+{
+ class InboundPacket;
+ class OutboundPacket;
+
+ class DeviceIdentifier
+ {
+ public:
+
+ const int vendorId;
+ const int productId;
+
+ DeviceIdentifier(int vid, int pid) :
+ vendorId(vid),
+ productId(pid)
+ {
+ }
+ };
+
+ class BridgeManager
+ {
+ public:
+
+ enum
+ {
+ kSupportedDeviceCount = 1,
+
+ kCommunicationDelayDefault = 0,
+ kDumpBufferSize = 4096
+ };
+
+ enum
+ {
+ kVidSamsung = 0x04E8
+ };
+
+ enum
+ {
+ kPidGalaxySDownloadMode = 0x6601/*,
+ kPidGalaxySInternational = 0x681C,
+ kPidGalaxySNewInternational = 0x681D,
+ kPidVibrantCanadaBell = 0x6877*/
+ };
+
+ private:
+
+ static const DeviceIdentifier supportedDevices[kSupportedDeviceCount];
+
+ bool verbose;
+
+ libusb_context *libusbContext;
+ libusb_device_handle *deviceHandle;
+ libusb_device *heimdallDevice;
+ int interfaceIndex;
+ int inEndpoint;
+ int outEndpoint;
+
+ int communicationDelay;
+
+#ifdef OS_LINUX
+
+ bool detachedDriver;
+
+#endif
+
+ public:
+
+ BridgeManager(bool verbose, int communicationDelay);
+ ~BridgeManager();
+
+ bool Initialise(void);
+
+ bool BeginSession(void) const;
+ bool EndSession(void) const;
+
+ bool SendPacket(OutboundPacket *packet, int timeout = 3000) const;
+ bool ReceivePacket(InboundPacket *packet, int timeout = 3000) 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);
+ }
+ };
+}
+
+#endif
diff --git a/heimdall/source/ControlPacket.h b/heimdall/source/ControlPacket.h new file mode 100644 index 0000000..2379073 --- /dev/null +++ b/heimdall/source/ControlPacket.h @@ -0,0 +1,71 @@ +/* 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 CONTROLPACKET_H
+#define CONTROLPACKET_H
+
+// Heimdall
+#include "OutboundPacket.h"
+
+namespace Heimdall
+{
+ class ControlPacket : public OutboundPacket
+ {
+ public:
+
+ enum
+ {
+ kControlTypeDeviceInfo = 0x64,
+ kControlTypePitFile = 0x65,
+ kControlTypeFileTransfer = 0x66,
+ kControlTypeRebootDevice = 0x67
+ };
+
+ protected:
+
+ enum
+ {
+ kDataSize = 4
+ };
+
+ private:
+
+ unsigned int controlType;
+
+ public:
+
+ ControlPacket(unsigned int controlType) : OutboundPacket(1024)
+ {
+ this->controlType = controlType;
+ }
+
+ unsigned int GetControlType(void) const
+ {
+ return (controlType);
+ }
+
+ virtual void Pack(void)
+ {
+ PackInteger(0, controlType);
+ }
+ };
+}
+
+#endif
diff --git a/heimdall/source/DeviceInfoPacket.h b/heimdall/source/DeviceInfoPacket.h new file mode 100644 index 0000000..153cdc5 --- /dev/null +++ b/heimdall/source/DeviceInfoPacket.h @@ -0,0 +1,74 @@ +/* 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 DEVICEINFOPACKET_H
+#define DEVICEINFOPACKET_H
+
+// Heimdall
+#include "ControlPacket.h"
+
+namespace Heimdall
+{
+ class DeviceInfoPacket : public ControlPacket
+ {
+ public:
+
+ enum
+ {
+ kUnknown1 = 0, // Begin device info?
+ kUnknown2 = 1, // End device info?
+ kTotalBytes = 2 // Total no. bytes that will be flashed, seems to be ignored though.
+ };
+
+ private:
+
+ unsigned int request;
+ unsigned int unknown3Parameter; // TODO: Subclass for unknown2.
+
+ public:
+
+ DeviceInfoPacket(unsigned int request, unsigned int unknown3Parameter = 0)
+ : ControlPacket(ControlPacket::kControlTypeDeviceInfo)
+ {
+ this->request = request;
+ this->unknown3Parameter = unknown3Parameter;
+ }
+
+ unsigned int GetRequest(void) const
+ {
+ return (request);
+ }
+
+ unsigned int GetUnknown3Parameter(void) const
+ {
+ return (unknown3Parameter);
+ }
+
+ void Pack(void)
+ {
+ ControlPacket::Pack();
+
+ PackInteger(ControlPacket::kDataSize, request);
+ PackInteger(ControlPacket::kDataSize + 4, unknown3Parameter);
+ }
+ };
+}
+
+#endif
diff --git a/heimdall/source/DeviceInfoResponse.h b/heimdall/source/DeviceInfoResponse.h new file mode 100644 index 0000000..3bf2d8f --- /dev/null +++ b/heimdall/source/DeviceInfoResponse.h @@ -0,0 +1,58 @@ +/* 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 DEVICEINFORESPONSE_H
+#define DEVICEINFORESPONSE_H
+
+// Heimdall
+#include "ResponsePacket.h"
+
+namespace Heimdall
+{
+ class DeviceInfoResponse : public ResponsePacket
+ {
+ private:
+
+ unsigned int unknown;
+
+ public:
+
+ DeviceInfoResponse() : ResponsePacket(ResponsePacket::kResponseTypeDeviceInfo)
+ {
+ }
+
+ int GetUnknown(void) const
+ {
+ return (unknown);
+ }
+
+ bool Unpack(void)
+ {
+ if (!ResponsePacket::Unpack())
+ return (false);
+
+ unknown = UnpackInteger(ResponsePacket::kDataSize);
+
+ return (true);
+ }
+ };
+}
+
+#endif
diff --git a/heimdall/source/DumpPartFileTransferPacket.h b/heimdall/source/DumpPartFileTransferPacket.h new file mode 100644 index 0000000..60fb8c5 --- /dev/null +++ b/heimdall/source/DumpPartFileTransferPacket.h @@ -0,0 +1,56 @@ +/* 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 DUMPPARTFILETRANSFERPACKET_H
+#define DUMPPARTFILETRANSFERPACKET_H
+
+// Heimdall
+#include "FileTransferPacket.h"
+
+namespace Heimdall
+{
+ class DumpPartFileTransferPacket : public FileTransferPacket
+ {
+ private:
+
+ unsigned int partIndex;
+
+ public:
+
+ DumpPartFileTransferPacket(unsigned int partIndex) : FileTransferPacket(FileTransferPacket::kRequestPart)
+ {
+ this->partIndex = partIndex;
+ }
+
+ unsigned int GetPartIndex(void) const
+ {
+ return (partIndex);
+ }
+
+ virtual void Pack(void)
+ {
+ FileTransferPacket::Pack();
+
+ PackInteger(FileTransferPacket::kDataSize, partIndex);
+ }
+ };
+}
+
+#endif
diff --git a/heimdall/source/DumpPartPitFilePacket.h b/heimdall/source/DumpPartPitFilePacket.h new file mode 100644 index 0000000..29025c2 --- /dev/null +++ b/heimdall/source/DumpPartPitFilePacket.h @@ -0,0 +1,56 @@ +/* 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 DUMPPARTPITFILEPACKET_H
+#define DUMPPARTPITFILEPACKET_H
+
+// Heimdall
+#include "PitFilePacket.h"
+
+namespace Heimdall
+{
+ class DumpPartPitFilePacket : public PitFilePacket
+ {
+ private:
+
+ unsigned int partIndex;
+
+ public:
+
+ DumpPartPitFilePacket(unsigned int partIndex) : PitFilePacket(PitFilePacket::kRequestPart)
+ {
+ this->partIndex = partIndex;
+ }
+
+ unsigned int GetPartIndex(void) const
+ {
+ return (partIndex);
+ }
+
+ void Pack(void)
+ {
+ PitFilePacket::Pack();
+
+ PackInteger(PitFilePacket::kDataSize, partIndex);
+ }
+ };
+}
+
+#endif
diff --git a/heimdall/source/DumpResponse.h b/heimdall/source/DumpResponse.h new file mode 100644 index 0000000..126982a --- /dev/null +++ b/heimdall/source/DumpResponse.h @@ -0,0 +1,58 @@ +/* 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 DUMPRESPONSE_H
+#define DUMPRESPONSE_H
+
+// Heimdall
+#include "ResponsePacket.h"
+
+namespace Heimdall
+{
+ class DumpResponse : public ResponsePacket
+ {
+ private:
+
+ unsigned int dumpSize;
+
+ public:
+
+ DumpResponse() : ResponsePacket(kResponseTypeFileTransfer)
+ {
+ }
+
+ unsigned int GetDumpSize(void) const
+ {
+ return (dumpSize);
+ }
+
+ bool Unpack(void)
+ {
+ if (!ResponsePacket::Unpack())
+ return (false);
+
+ dumpSize = UnpackInteger(ResponsePacket::kDataSize);
+
+ return (true);
+ }
+ };
+}
+
+#endif
diff --git a/heimdall/source/EndFileTransferPacket.h b/heimdall/source/EndFileTransferPacket.h new file mode 100644 index 0000000..3f3d689 --- /dev/null +++ b/heimdall/source/EndFileTransferPacket.h @@ -0,0 +1,120 @@ +/* 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 ENDFILETRANSFERPACKET_H
+#define ENDFILETRANSFERPACKET_H
+
+// Heimdall
+#include "FileTransferPacket.h"
+
+namespace Heimdall
+{
+ class EndFileTransferPacket : public FileTransferPacket
+ {
+ public:
+
+ enum
+ {
+ kDestinationPhone = 0x00,
+ kDestinationModem = 0x01
+ };
+
+ protected:
+
+ enum
+ {
+ kDataSize = FileTransferPacket::kDataSize + 16
+ };
+
+ private:
+
+ unsigned int destination; // Chip identifier perhaps
+ unsigned short partialPacketLength; // Length or (length - 65536) if lastFullPacket is odd.
+ unsigned int lastFullPacketIndex;
+ unsigned short unknown1;
+ unsigned int unknown2;
+
+ protected:
+
+ EndFileTransferPacket(unsigned int destination, unsigned int partialPacketLength, unsigned int lastFullPacketIndex,
+ unsigned short unknown1, unsigned int unknown2)
+ : FileTransferPacket(FileTransferPacket::kRequestEnd)
+ {
+ this->destination = destination;
+
+ if (partialPacketLength > 65535)
+ {
+ this->partialPacketLength = (partialPacketLength - 65536);
+ this->lastFullPacketIndex = lastFullPacketIndex + 1;
+ }
+ else
+ {
+ this->partialPacketLength = partialPacketLength;
+ this->lastFullPacketIndex = lastFullPacketIndex;
+ }
+
+ this->unknown1 = unknown1;
+ this->unknown2 = unknown2;
+ }
+
+ public:
+
+ unsigned int GetDestination(void) const
+ {
+ return (destination);
+ }
+
+ unsigned int GetPartialPacketLength(void) const
+ {
+ if (lastFullPacketIndex % 2 == 0)
+ return (partialPacketLength);
+ else
+ return (partialPacketLength + 65536);
+ }
+
+ unsigned int GetLastFullPacketIndex(void) const
+ {
+ return (lastFullPacketIndex - lastFullPacketIndex % 2);
+ }
+
+ unsigned short GetUnknown1(void) const
+ {
+ return (unknown1);
+ }
+
+ unsigned int GetUnknown2(void) const
+ {
+ return (unknown2);
+ }
+
+ virtual void Pack(void)
+ {
+ FileTransferPacket::Pack();
+
+ PackInteger(FileTransferPacket::kDataSize, destination);
+ PackShort(FileTransferPacket::kDataSize + 4, partialPacketLength);
+ PackInteger(FileTransferPacket::kDataSize + 6, lastFullPacketIndex);
+ PackShort(FileTransferPacket::kDataSize + 10, unknown1);
+ PackInteger(FileTransferPacket::kDataSize + 12, unknown2);
+ }
+ };
+}
+
+#endif
diff --git a/heimdall/source/EndModemFileTransferPacket.h b/heimdall/source/EndModemFileTransferPacket.h new file mode 100644 index 0000000..9dc4c78 --- /dev/null +++ b/heimdall/source/EndModemFileTransferPacket.h @@ -0,0 +1,59 @@ +/* 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 ENDMODEMFILETRANSFERPACKET_H
+#define ENDMODEMFILETRANSFERPACKET_H
+
+// Heimdall
+#include "EndFileTransferPacket.h"
+
+namespace Heimdall
+{
+ class EndModemFileTransferPacket : public EndFileTransferPacket
+ {
+ private:
+
+ unsigned int endOfFile;
+
+ public:
+
+ EndModemFileTransferPacket(unsigned int partialPacketLength, unsigned int lastFullPacketIndex, unsigned short unknown1,
+ unsigned int unknown2, bool endOfFile)
+ : EndFileTransferPacket(EndFileTransferPacket::kDestinationModem, partialPacketLength,
+ lastFullPacketIndex, unknown1, unknown2)
+ {
+ this->endOfFile = (endOfFile) ? 1 : 0;
+ }
+
+ bool IsEndOfFile(void) const
+ {
+ return (endOfFile == 1);
+ }
+
+ void Pack(void)
+ {
+ EndFileTransferPacket::Pack();
+
+ PackInteger(EndFileTransferPacket::kDataSize, endOfFile);
+ }
+ };
+}
+
+#endif
diff --git a/heimdall/source/EndPhoneFileTransferPacket.h b/heimdall/source/EndPhoneFileTransferPacket.h new file mode 100644 index 0000000..24650a2 --- /dev/null +++ b/heimdall/source/EndPhoneFileTransferPacket.h @@ -0,0 +1,86 @@ +/* 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 ENDPHONEFILETRANSFERPACKET_H
+#define ENDPHONEFILETRANSFERPACKET_H
+
+// Heimdall
+#include "EndFileTransferPacket.h"
+
+namespace Heimdall
+{
+ class EndPhoneFileTransferPacket : public EndFileTransferPacket
+ {
+ public:
+
+ enum
+ {
+ kFilePrimaryBootloader = 0x00,
+ kFilePit = 0x01, // New 1.1 - Don't flash the pit this way!
+ kFileSecondaryBootloader = 0x03,
+ kFileSecondaryBootloaderBackup = 0x04, // New 1.1
+ kFileKernel = 0x06,
+ kFileRecovery = 0x07, // New 1.1
+ kFileEfs = 0x14, // New 1.1
+ kFileParamLfs = 0x15,
+ kFileFactoryFilesystem = 0x16,
+ kFileDatabaseData = 0x17,
+ kFileCache = 0x18,
+
+ kFileModem = 0x0B // New 1.1 - Kies flashes the modem this way rather than using the EndModemFileTransferPacket.
+ };
+
+ private:
+
+ unsigned int fileIdentifier;
+ unsigned int endOfFile;
+
+ public:
+
+ EndPhoneFileTransferPacket(unsigned int partialPacketLength, unsigned int lastFullPacketIndex, unsigned short unknown1,
+ unsigned int unknown2, unsigned int fileIdentifier, bool endOfFile)
+ : EndFileTransferPacket(EndFileTransferPacket::kDestinationPhone, partialPacketLength,
+ lastFullPacketIndex, unknown1, unknown2)
+ {
+ this->fileIdentifier = fileIdentifier;
+ this->endOfFile = (endOfFile) ? 1 : 0;
+ }
+
+ unsigned int GetFileIdentifier(void)
+ {
+ return (fileIdentifier);
+ }
+
+ bool IsEndOfFile(void) const
+ {
+ return (endOfFile == 1);
+ }
+
+ void Pack(void)
+ {
+ EndFileTransferPacket::Pack();
+
+ PackInteger(EndFileTransferPacket::kDataSize, fileIdentifier);
+ PackInteger(EndFileTransferPacket::kDataSize + 4, endOfFile);
+ }
+ };
+}
+
+#endif
diff --git a/heimdall/source/FileTransferPacket.h b/heimdall/source/FileTransferPacket.h new file mode 100644 index 0000000..daa6a75 --- /dev/null +++ b/heimdall/source/FileTransferPacket.h @@ -0,0 +1,73 @@ +/* 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 FILETRANSFERPACKET_H
+#define FILETRANSFERPACKET_H
+
+// Heimdall
+#include "ControlPacket.h"
+
+namespace Heimdall
+{
+ class FileTransferPacket : public ControlPacket
+ {
+ public:
+
+ enum
+ {
+ kRequestFlash = 0x00,
+ kRequestDump = 0x01,
+ kRequestPart = 0x02,
+ kRequestEnd = 0x03
+ };
+
+ protected:
+
+ enum
+ {
+ kDataSize = ControlPacket::kDataSize + 4
+ };
+
+ private:
+
+ unsigned int request;
+
+ public:
+
+ FileTransferPacket(unsigned int request) : ControlPacket(ControlPacket::kControlTypeFileTransfer)
+ {
+ this->request = request;
+ }
+
+ unsigned int GetRequest(void) const
+ {
+ return (request);
+ }
+
+ virtual void Pack(void)
+ {
+ ControlPacket::Pack();
+
+ PackInteger(ControlPacket::kDataSize, request);
+ }
+ };
+}
+
+#endif
diff --git a/heimdall/source/FlashPartFileTransferPacket.h b/heimdall/source/FlashPartFileTransferPacket.h new file mode 100644 index 0000000..6aa57da --- /dev/null +++ b/heimdall/source/FlashPartFileTransferPacket.h @@ -0,0 +1,65 @@ +/* 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 FLASHPARTFILETRANSFERPACKET_H
+#define FLASHPARTFILETRANSFERPACKET_H
+
+// Heimdall
+#include "FileTransferPacket.h"
+
+namespace Heimdall
+{
+ class FlashPartFileTransferPacket : public FileTransferPacket
+ {
+ private:
+
+ unsigned short unknown;
+ unsigned int transferCount;
+
+ public:
+
+ FlashPartFileTransferPacket(unsigned short unknown, unsigned int transferCount)
+ : FileTransferPacket(FileTransferPacket::kRequestPart)
+ {
+ this->unknown = unknown;
+ this->transferCount = transferCount;
+ }
+
+ unsigned short GetUnknown(void) const
+ {
+ return (unknown);
+ }
+
+ unsigned int GetTransferCount(void) const
+ {
+ return (transferCount);
+ }
+
+ void Pack(void)
+ {
+ FileTransferPacket::Pack();
+
+ PackShort(FileTransferPacket::kDataSize, unknown);
+ PackInteger(FileTransferPacket::kDataSize + 2, transferCount);
+ }
+ };
+}
+
+#endif
diff --git a/heimdall/source/FlashPartPitFilePacket.h b/heimdall/source/FlashPartPitFilePacket.h new file mode 100644 index 0000000..3974c3c --- /dev/null +++ b/heimdall/source/FlashPartPitFilePacket.h @@ -0,0 +1,56 @@ +/* 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 FLASHPARTPITFILEPACKET_H
+#define FLASHPARTPITFILEPACKET_H
+
+// Heimdall
+#include "PitFilePacket.h"
+
+namespace Heimdall
+{
+ class FlashPartPitFilePacket : public PitFilePacket
+ {
+ private:
+
+ unsigned int partSize;
+
+ public:
+
+ FlashPartPitFilePacket(unsigned int partSize) : PitFilePacket(PitFilePacket::kRequestPart)
+ {
+ this->partSize = partSize;
+ }
+
+ unsigned int GetPartSize(void) const
+ {
+ return (partSize);
+ }
+
+ void Pack(void)
+ {
+ PitFilePacket::Pack();
+
+ PackInteger(PitFilePacket::kDataSize, partSize);
+ }
+ };
+}
+
+#endif
diff --git a/heimdall/source/Heimdall.h b/heimdall/source/Heimdall.h new file mode 100644 index 0000000..672cf14 --- /dev/null +++ b/heimdall/source/Heimdall.h @@ -0,0 +1,43 @@ +/* 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 HEIMDALL_H
+#define HEIMDALL_H
+
+#ifdef OS_WINDOWS +#include <Windows.h> +#else + +#include "../config.h" + +#if defined(OS_DARWIN) || defined(OS_LINUX) +#include <unistd.h> +#define Sleep(t) usleep(1000*t) +#else +#error operating system not supported +#endif + +#endif
+
+#ifndef nullptr
+#define nullptr 0
+#endif
+
+#endif
diff --git a/heimdall/source/InboundPacket.h b/heimdall/source/InboundPacket.h new file mode 100644 index 0000000..bf393fa --- /dev/null +++ b/heimdall/source/InboundPacket.h @@ -0,0 +1,77 @@ +/* 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 INBOUNDPACKET_H
+#define INBOUNDPACKET_H
+
+// Heimdall
+#include "Packet.h"
+
+namespace Heimdall
+{
+ class InboundPacket : public Packet
+ {
+ private:
+
+ bool sizeVariable;
+ unsigned int receivedSize;
+
+ protected:
+
+ int UnpackInteger(int offset)
+ {
+#ifdef PPC
+ 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);
+ }
+
+ public:
+
+ InboundPacket(unsigned int size, bool sizeVariable = false) : Packet(size)
+ {
+ this->sizeVariable = sizeVariable;
+ }
+
+ bool IsSizeVariable(void) const
+ {
+ return (sizeVariable);
+ }
+
+ unsigned int GetReceivedSize(void) const
+ {
+ return (receivedSize);
+ }
+
+ void SetReceivedSize(unsigned int receivedSize)
+ {
+ this->receivedSize = receivedSize;
+ }
+
+ virtual bool Unpack(void) = 0;
+ };
+}
+
+#endif
diff --git a/heimdall/source/InterfaceManager.cpp b/heimdall/source/InterfaceManager.cpp new file mode 100644 index 0000000..23791bc --- /dev/null +++ b/heimdall/source/InterfaceManager.cpp @@ -0,0 +1,265 @@ +/* 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 <stdio.h>
+
+// Heimdall
+#include "Heimdall.h"
+#include "InterfaceManager.h"
+
+using namespace std;
+using namespace Heimdall;
+
+string InterfaceManager::actionNames[kActionCount] = { "flash", "close-pc-screen", "dump", "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",
+
+ // --- Short Names ---
+ "r",
+
+ "pit", "fs", "cache", "db", "boot", "sbl", "sbl2", "param", "z", "rec", "efs", "m"
+};
+
+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",
+
+ "-delay",
+
+ // --- Short Names ---
+ "v",
+
+ "d"
+};
+
+// argumentNames[kActionCount][] stores common arguments.
+string *InterfaceManager::actionArgumentNames[kActionCount + 1] = {
+ // kActionFlash
+ flashArgumentNames,
+
+ // kActionClosePcScreen
+ nullptr,
+
+ // kActionDump
+ dumpArgumentNames,
+
+ // kActionHelp
+ nullptr,
+
+ // Common (kActionCount)
+ commonArgumentNames
+};
+
+int InterfaceManager::actionArgumentCounts[kActionCount + 1] = {
+ kFlashArgCount, 0, kDumpArgCount, 0, kCommonArgCount
+};
+
+int InterfaceManager::actionValuelessArgumentCounts[kActionCount + 1] = {
+ kFlashArgPit, 0, kDumpArgChipType, 0, kCommonArgDelay
+};
+
+const char *InterfaceManager::usage = "Usage: heimdall <action> <arguments> [--verbose] [--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>\n\
+ or:\n\
+ [--pit <filename>] [--factoryfs <filename>] [--cache <filename>]\n\
+ [--dbdata <filename>] [--primary-boot <filename>]\n\
+ [--secondary-boot <filename>] [--secondary-boot-backup <filename>]\n\
+ [--param <filename>] [--kernel <filename>] [--recovery <filename>]\n\
+ [--efs <filename>] [--modem <filename>]\n\
+description: Flashes firmware files to your phone.\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: 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;
+ }
+
+ // Check if the argument is a valid regular argument
+ for (int i = actionValuelessArgumentCount; i < actionArgumentCount; i++)
+ {
+ 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++)
+ {
+ 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 new file mode 100644 index 0000000..734c086 --- /dev/null +++ b/heimdall/source/InterfaceManager.h @@ -0,0 +1,109 @@ +/* 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, + kActionHelp, + kActionCount + }; + + enum + { + // Valueless arguments + kFlashArgRepartition = 0, + + // Regular arguments + kFlashArgPit, + kFlashArgFactoryFs, + kFlashArgCache, + kFlashArgData, + kFlashArgPrimaryBootloader, + kFlashArgSecondaryBootloader, + kFlashArgSecondaryBootloaderBackup, + kFlashArgParam, + kFlashArgKernel, + kFlashArgRecovery, + kFlashArgEfs, + kFlashArgModem, + + kFlashArgCount + }; + + enum + { + // Regular arguments + kDumpArgChipType = 0, + kDumpArgChipId, + kDumpArgOutput, + + kDumpArgCount + }; + + enum + { + // Valueless arguments + kCommonArgVerbose = 0, + + // 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 new file mode 100644 index 0000000..d433d84 --- /dev/null +++ b/heimdall/source/OutboundPacket.h @@ -0,0 +1,71 @@ +/* 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 OUTBOUNDPACKET_H
+#define OUTBOUNDPACKET_H
+
+// Heimdall include
+#include "Packet.h"
+
+namespace Heimdall
+{
+ class OutboundPacket : public Packet
+ {
+ protected:
+
+ void PackInteger(unsigned int offset, unsigned int value)
+ {
+#ifdef PPC
+ 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
+ }
+
+ void PackShort(unsigned int offset, unsigned short value)
+ {
+#ifdef PPC
+ 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:
+
+ OutboundPacket(unsigned int size) : Packet(size)
+ {
+ }
+
+ virtual void Pack(void) = 0;
+ };
+}
+
+#endif
diff --git a/heimdall/source/Packet.h b/heimdall/source/Packet.h new file mode 100644 index 0000000..33469f1 --- /dev/null +++ b/heimdall/source/Packet.h @@ -0,0 +1,65 @@ +/* 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 PACKET_H
+#define PACKET_H
+
+// C++ Standard Library
+#include <cstring>
+
+namespace Heimdall
+{
+ class Packet
+ {
+ private:
+
+ unsigned int size;
+
+ protected:
+
+ unsigned char *data;
+
+ public:
+
+ Packet(unsigned int size)
+ {
+ this->size = size;
+ data = new unsigned char[size];
+ memset(data, 0, size);
+ }
+
+ ~Packet()
+ {
+ delete [] data;
+ }
+
+ int GetSize(void) const
+ {
+ return (size);
+ }
+
+ unsigned char *GetData(void)
+ {
+ return (data);
+ }
+ };
+}
+
+#endif
diff --git a/heimdall/source/PitFilePacket.h b/heimdall/source/PitFilePacket.h new file mode 100644 index 0000000..d23314e --- /dev/null +++ b/heimdall/source/PitFilePacket.h @@ -0,0 +1,73 @@ +/* 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 PITFILEPACKET_H
+#define PITFILEPACKET_H
+
+// Heimdall
+#include "ControlPacket.h"
+
+namespace Heimdall
+{
+ class PitFilePacket : public ControlPacket
+ {
+ public:
+
+ enum
+ {
+ kRequestFlash = 0x00,
+ kRequestDump = 0x01,
+ kRequestPart = 0x02,
+ kRequestEndTransfer = 0x03
+ };
+
+ protected:
+
+ enum
+ {
+ kDataSize = ControlPacket::kDataSize + 4
+ };
+
+ private:
+
+ unsigned int request;
+
+ public:
+
+ PitFilePacket(unsigned int request) : ControlPacket(ControlPacket::kControlTypePitFile)
+ {
+ this->request = request;
+ }
+
+ unsigned int GetRequest(void) const
+ {
+ return (request);
+ }
+
+ void Pack(void)
+ {
+ ControlPacket::Pack();
+
+ PackInteger(ControlPacket::kDataSize, request);
+ }
+ };
+}
+
+#endif
diff --git a/heimdall/source/PitFileResponse.h b/heimdall/source/PitFileResponse.h new file mode 100644 index 0000000..bf8f6f6 --- /dev/null +++ b/heimdall/source/PitFileResponse.h @@ -0,0 +1,58 @@ +/* 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 PITFILERESPONSE_H
+#define PITFILERESPONSE_H
+
+// Heimdall
+#include "ResponsePacket.h"
+
+namespace Heimdall
+{
+ class PitFileResponse : public ResponsePacket
+ {
+ private:
+
+ unsigned int fileSize;
+
+ public:
+
+ PitFileResponse() : ResponsePacket(ResponsePacket::kResponseTypePitFile)
+ {
+ }
+
+ unsigned int GetFileSize(void) const
+ {
+ return (fileSize);
+ }
+
+ bool Unpack(void)
+ {
+ if (!ResponsePacket::Unpack())
+ return (false);
+
+ fileSize = UnpackInteger(ResponsePacket::kDataSize);
+
+ return (true);
+ }
+ };
+}
+
+#endif
diff --git a/heimdall/source/RebootDevicePacket.h b/heimdall/source/RebootDevicePacket.h new file mode 100644 index 0000000..f40a227 --- /dev/null +++ b/heimdall/source/RebootDevicePacket.h @@ -0,0 +1,64 @@ +/* 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 REBOOTDEVICEPACKET_H
+#define REBOOTDEVICEPACKET_H
+
+// Heimdall
+#include "ControlPacket.h"
+
+namespace Heimdall
+{
+ class RebootDevicePacket : public ControlPacket
+ {
+ public:
+
+ enum
+ {
+ kRequestEndSession = 0,
+ kRequestRebootDevice = 1
+ };
+
+ private:
+
+ unsigned int request;
+
+ public:
+
+ RebootDevicePacket(unsigned int request) : ControlPacket(ControlPacket::kControlTypeRebootDevice)
+ {
+ this->request = request;
+ }
+
+ unsigned int GetRequest(void) const
+ {
+ return (request);
+ }
+
+ void Pack(void)
+ {
+ ControlPacket::Pack();
+
+ PackInteger(ControlPacket::kDataSize, request);
+ }
+ };
+}
+
+#endif
diff --git a/heimdall/source/ReceiveFilePartPacket.h b/heimdall/source/ReceiveFilePartPacket.h new file mode 100644 index 0000000..5671ed4 --- /dev/null +++ b/heimdall/source/ReceiveFilePartPacket.h @@ -0,0 +1,49 @@ +/* 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 RECEIVEFILEPARTPACKET_H
+#define RECEIVEFILEPARTPACKET_H
+
+// Heimdall
+#include "InboundPacket.h"
+
+namespace Heimdall
+{
+ class ReceiveFilePartPacket : public InboundPacket
+ {
+ public:
+
+ enum
+ {
+ kDataSize = 500
+ };
+
+ ReceiveFilePartPacket() : InboundPacket(kDataSize, true)
+ {
+ }
+
+ bool Unpack(void)
+ {
+ return (true);
+ }
+ };
+}
+
+#endif
diff --git a/heimdall/source/ResponsePacket.h b/heimdall/source/ResponsePacket.h new file mode 100644 index 0000000..ce799b5 --- /dev/null +++ b/heimdall/source/ResponsePacket.h @@ -0,0 +1,81 @@ +/* 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 RESPONSEPACKET_H
+#define RESPONSEPACKET_H
+
+// Heimdall
+#include "InboundPacket.h"
+
+namespace Heimdall
+{
+ class ResponsePacket : public InboundPacket
+ {
+ public:
+
+ enum
+ {
+ kResponseTypeSendFilePart = 0x00,
+ kResponseTypeDeviceInfo = 0x64,
+ kResponseTypePitFile = 0x65,
+ kResponseTypeFileTransfer = 0x66,
+ kResponseTypeRebootDevice = 0x67
+ };
+
+ private:
+
+ unsigned int responseType;
+
+ protected:
+
+ enum
+ {
+ kDataSize = 4
+ };
+
+ public:
+
+ ResponsePacket(int responseType) : InboundPacket(8)
+ {
+ this->responseType = responseType;
+ }
+
+ unsigned int GetResponseType(void) const
+ {
+ return (responseType);
+ }
+
+ virtual bool Unpack(void)
+ {
+ const unsigned char *data = GetData();
+
+ unsigned int receivedResponseType = UnpackInteger(0);
+ if (receivedResponseType != responseType)
+ {
+ responseType = receivedResponseType;
+ return (false);
+ }
+
+ return (true);
+ }
+ };
+}
+
+#endif
diff --git a/heimdall/source/SendFilePartPacket.h b/heimdall/source/SendFilePartPacket.h new file mode 100644 index 0000000..0b41830 --- /dev/null +++ b/heimdall/source/SendFilePartPacket.h @@ -0,0 +1,63 @@ +/* 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 SENDFILEPARTPACKET_H
+#define SENDFILEPARTPACKET_H
+
+// C Standard Library
+#include <stdio.h>
+#include <string.h>
+
+// Heimdall
+#include "Packet.h"
+
+namespace Heimdall
+{
+ class SendFilePartPacket : public OutboundPacket
+ {
+ public:
+
+ enum
+ {
+ kDefaultPacketSize = 131072
+ };
+
+ SendFilePartPacket(FILE *file, int size = SendFilePartPacket::kDefaultPacketSize) : OutboundPacket(size)
+ {
+ memset(data, 0, size);
+
+ long position = ftell(file);
+
+ fseek(file, 0, SEEK_END);
+ long fileSize = ftell(file);
+ fseek(file, position, SEEK_SET);
+
+ // min(fileSize, size)
+ int bytesToRead = (fileSize < size) ? fileSize - position : size;
+ fread(data, 1, bytesToRead, file);
+ }
+
+ void Pack(void)
+ {
+ }
+ };
+}
+
+#endif
diff --git a/heimdall/source/SendFilePartResponse.h b/heimdall/source/SendFilePartResponse.h new file mode 100644 index 0000000..ba6eb6b --- /dev/null +++ b/heimdall/source/SendFilePartResponse.h @@ -0,0 +1,58 @@ +/* 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 SENDFILEPARTRESPONSE_H
+#define SENDFILEPARTRESPONSE_H
+
+// Heimdall
+#include "ResponsePacket.h"
+
+namespace Heimdall
+{
+ class SendFilePartResponse : public ResponsePacket
+ {
+ private:
+
+ unsigned int partIndex;
+
+ public:
+
+ SendFilePartResponse() : ResponsePacket(ResponsePacket::kResponseTypeSendFilePart)
+ {
+ }
+
+ unsigned int GetPartIndex(void) const
+ {
+ return (partIndex);
+ }
+
+ bool Unpack(void)
+ {
+ if (!ResponsePacket::Unpack())
+ return (false);
+
+ partIndex = UnpackInteger(ResponsePacket::kDataSize);
+
+ return (true);
+ }
+ };
+}
+
+#endif
diff --git a/heimdall/source/main.cpp b/heimdall/source/main.cpp new file mode 100644 index 0000000..037d097 --- /dev/null +++ b/heimdall/source/main.cpp @@ -0,0 +1,660 @@ +/* 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 <algorithm> +#include <map> +#include <stdio.h> +#include <string> + +// Heimdall +#include "BridgeManager.h" +#include "DeviceInfoPacket.h" +#include "DeviceInfoResponse.h" +#include "EndModemFileTransferPacket.h" +#include "EndPhoneFileTransferPacket.h" +#include "InterfaceManager.h" + +using namespace std; +using namespace Heimdall; + +enum +{ + kFilePit = 0, + kFileFactoryFs, + kFileCache, + kFileData, + kFilePrimaryBootloader, + kFileSecondaryBootloader, + kFileSecondaryBootloaderBackup, + kFileParam, + kFileKernel, + kFileRecovery, + kFileEfs, + kFileModem, + kFileCount +}; + +bool flashFile(BridgeManager *bridgeManager, FILE *file, int fileIndex) +{ + switch (fileIndex) + { + case kFilePit: + + InterfaceManager::Print("Uploading PIT file\n"); + if (bridgeManager->SendPitFile(file)) + { + InterfaceManager::Print("PIT file upload successful\n"); + return (true); + } + else + { + InterfaceManager::PrintError("PIT file upload failed!\n"); + return (false); + } + + case kFileFactoryFs: + + InterfaceManager::Print("Uploading factory filesytem\n"); + if (bridgeManager->SendFile(file, EndPhoneFileTransferPacket::kDestinationPhone, + EndPhoneFileTransferPacket::kFileFactoryFilesystem)) + { + InterfaceManager::Print("Factory filesytem upload successful\n"); + return (true); + } + else + { + InterfaceManager::PrintError("Factory filesytem upload failed!\n"); + return (false); + } + + case kFileCache: + + InterfaceManager::Print("Uploading cache\n"); + if (bridgeManager->SendFile(file, EndPhoneFileTransferPacket::kDestinationPhone, + EndPhoneFileTransferPacket::kFileCache)) + { + InterfaceManager::Print("Cache upload successful\n"); + return (true); + } + else + { + InterfaceManager::PrintError("Cache upload failed!\n"); + return (false); + } + + case kFileData: + + InterfaceManager::Print("Uploading data database\n"); + if (bridgeManager->SendFile(file, EndPhoneFileTransferPacket::kDestinationPhone, + EndPhoneFileTransferPacket::kFileDatabaseData)) + { + InterfaceManager::Print("Data database upload successful\n"); + return (true); + } + else + { + InterfaceManager::PrintError("Data database upload failed!\n"); + return (false); + } + + case kFilePrimaryBootloader: + + InterfaceManager::Print("Uploading primary bootloader\n"); + if (bridgeManager->SendFile(file, EndPhoneFileTransferPacket::kDestinationPhone, + EndPhoneFileTransferPacket::kFilePrimaryBootloader)) + { + InterfaceManager::Print("Primary bootloader upload successful\n"); + return (true); + } + else + { + InterfaceManager::PrintError("Primary bootloader upload failed!\n"); + return (false); + } + + case kFileSecondaryBootloader: + + InterfaceManager::Print("Uploading secondary bootloader\n"); + if (bridgeManager->SendFile(file, EndPhoneFileTransferPacket::kDestinationPhone, + EndPhoneFileTransferPacket::kFileSecondaryBootloader)) + { + InterfaceManager::Print("Secondary bootloader upload successful\n"); + return (true); + } + else + { + InterfaceManager::PrintError("Secondary bootloader upload failed!\n"); + return (false); + } + + case kFileSecondaryBootloaderBackup: + + InterfaceManager::Print("Uploading backup secondary bootloader\n"); + if (bridgeManager->SendFile(file, EndPhoneFileTransferPacket::kDestinationPhone, + EndPhoneFileTransferPacket::kFileSecondaryBootloaderBackup)) + { + InterfaceManager::Print("Backup secondary bootloader upload successful\n"); + return (true); + } + else + { + InterfaceManager::PrintError("Backup secondary bootloader upload failed!\n"); + return (false); + } + + case kFileParam: + InterfaceManager::Print("Uploading param.lfs\n"); + if (bridgeManager->SendFile(file, EndPhoneFileTransferPacket::kDestinationPhone, + EndPhoneFileTransferPacket::kFileParamLfs)) + { + InterfaceManager::Print("param.lfs upload successful\n"); + return (true); + } + else + { + InterfaceManager::PrintError("param.lfs upload failed!\n"); + return (false); + } + + case kFileKernel: + + InterfaceManager::Print("Uploading kernel\n"); + if (bridgeManager->SendFile(file, EndPhoneFileTransferPacket::kDestinationPhone, + EndPhoneFileTransferPacket::kFileKernel)) + { + InterfaceManager::Print("Kernel upload successful\n"); + return (true); + } + else + { + InterfaceManager::PrintError("Kernel upload failed!\n"); + return (false); + } + + case kFileModem: + + InterfaceManager::Print("Uploading modem\n"); + + /*if (bridgeManager->SendFile(file, EndModemFileTransferPacket::kDestinationModem))*/ // <-- Odin method + if (bridgeManager->SendFile(file, EndPhoneFileTransferPacket::kDestinationPhone, // <-- Kies method + EndPhoneFileTransferPacket::kFileModem)) + { + InterfaceManager::Print("Modem upload successful\n"); + return (true); + } + else + { + InterfaceManager::PrintError("Modem upload failed!\n"); + return (false); + } + + case kFileRecovery: + + InterfaceManager::Print("Uploading recovery\n"); + if (bridgeManager->SendFile(file, EndPhoneFileTransferPacket::kDestinationPhone, + EndPhoneFileTransferPacket::kFileRecovery)) + { + InterfaceManager::Print("Recovery upload successful\n"); + return (true); + } + else + { + InterfaceManager::PrintError("Recovery upload failed!\n"); + return (false); + } + + case kFileEfs: + + InterfaceManager::Print("Uploading EFS\n"); + if (bridgeManager->SendFile(file, EndPhoneFileTransferPacket::kDestinationPhone, + EndPhoneFileTransferPacket::kFileEfs)) + { + InterfaceManager::Print("EFS upload successful\n"); + return (true); + } + else + { + InterfaceManager::PrintError("EFS upload failed!\n"); + return (false); + } + + default: + + InterfaceManager::PrintError("ERROR: Attempted to flash unknown file!\n"); + return (false); + } +} + +bool attemptFlash(BridgeManager *bridgeManager, FILE **fileArray, bool repartition) +{ + bool success; + + // ---------- 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"); + return (false); + } + + if (unknown != 0) + { + InterfaceManager::PrintError("Unexpected device info response!\nExpected: 0\nReceived:%i\n", unknown); + + if (!bridgeManager->EndSession()) + return (false); + bridgeManager->RebootDevice(); + + 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"); + 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, and 3 on the Galaxy Tab. + if (unknown != 180 && unknown != 0 && unknown != 3) + { + InterfaceManager::PrintError("Unexpected device info response!\nExpected: 180, 0 or 3\nReceived:%i\n", unknown); + + if (!bridgeManager->EndSession()) + return (false); + bridgeManager->RebootDevice(); + + return (false); + } + // -------------------------------------------------------------- + + int totalBytes = 0; + for (int i = kFileFactoryFs; i < kFileCount; i++) + { + if (fileArray[i]) + { + fseek(fileArray[i], 0, SEEK_END); + totalBytes += ftell(fileArray[i]); + rewind(fileArray[i]); + } + } + + if (repartition) + { + // When repartitioning we send the PIT file to the device. + fseek(fileArray[kFilePit], 0, SEEK_END); + totalBytes += ftell(fileArray[kFilePit]); + rewind(fileArray[kFilePit]); + } + + 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"); + 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); + } + + if (unknown != 0) + { + InterfaceManager::PrintError("Unexpected device info response!\nExpected: 0\nReceived:%i\n", unknown); + + if (!bridgeManager->EndSession()) + return (false); + bridgeManager->RebootDevice(); + + return (false); + } + + // ----------------------------------------------------- + + if (fileArray[kFilePit]) + { + if (repartition) + { + flashFile(bridgeManager, fileArray[kFilePit], kFilePit); + } + else // We're performing a PIT check + { + // Load the local pit file into memory. + char *localPit = new char[4096]; + memset(localPit, 0, 4096); + + fseek(fileArray[kFilePit], 0, SEEK_END); + long localPitFileSize = ftell(fileArray[kFilePit]); + rewind(fileArray[kFilePit]); + + fread(localPit, 1, localPitFileSize, fileArray[kFilePit]); + + InterfaceManager::Print("Downloading device's PIT file...\n"); + + unsigned char *devicePit; + int devicePitFileSize = bridgeManager->ReceivePitFile(&devicePit); + + if (!devicePit) + { + InterfaceManager::PrintError("Failed to download PIT file!\n"); + + if (!bridgeManager->EndSession()) + return (false); + bridgeManager->RebootDevice(); + + return (false); + } + + InterfaceManager::Print("PIT file download sucessful\n\n"); + + bool pitFilesMatch = !memcmp(localPit, devicePit, localPitFileSize); + + delete [] localPit; + delete [] devicePit; + + if (!pitFilesMatch) + { + InterfaceManager::Print("Optional PIT check failed! To disable this check don't use the --pit parameter."); + + if (!bridgeManager->EndSession()) + return (false); + bridgeManager->RebootDevice(); + + return (false); + } + } + } + + // Flash specified files + for (int fileIndex = kFileFactoryFs; fileIndex < kFileCount; fileIndex++) + { + if (fileArray[fileIndex]) + { + if (!flashFile(bridgeManager, fileArray[fileIndex], fileIndex)) + return (false); + } + } + + return (bridgeManager->EndSession() && bridgeManager->RebootDevice()); +} + +bool openFiles(const map<string, string>& argumentMap, FILE **fileArray) +{ + for (int fileIndex = 0; fileIndex < kFileCount; fileIndex++) + { + // kFlashArgPit + kFile<Name> == kFlashArg<Name> + map<string, string>::const_iterator it = argumentMap.find(InterfaceManager::flashArgumentNames[InterfaceManager::kFlashArgPit + fileIndex]); + if (it == argumentMap.end()) + continue; + + fileArray[fileIndex] = fopen(it->second.c_str(), "rb"); + if (!fileArray[fileIndex]) + { + InterfaceManager::PrintError("Failed to open file \"%s\"\n", it->second.c_str()); + return (false); + } + } + + return (true); +} + +void closeFiles(FILE **fileArray) +{ + for (int fileIndex = 0; fileIndex < kFileCount; fileIndex++) + { + if (fileArray[fileIndex] != nullptr) + fclose(fileArray[fileIndex]); + } +} + +int main(int argc, char **argv) +{ + map<string, string> argumentMap; + int actionIndex; + + if (!InterfaceManager::GetArguments(argc, argv, argumentMap, &actionIndex)) + { + Sleep(1000); + return (0); + } + + if (actionIndex == InterfaceManager::kActionHelp) + { + InterfaceManager::Print(InterfaceManager::usage); + return (0); + } + else if (actionIndex == InterfaceManager::kActionFlash) + { + if (argumentMap.find(InterfaceManager::flashArgumentNames[InterfaceManager::kFlashArgRepartition]) != argumentMap.end() + && (argumentMap.find(InterfaceManager::flashArgumentNames[InterfaceManager::kFlashArgPit]) == argumentMap.end() + || argumentMap.find(InterfaceManager::flashArgumentNames[InterfaceManager::kFlashArgFactoryFs]) == argumentMap.end() + || argumentMap.find(InterfaceManager::flashArgumentNames[InterfaceManager::kFlashArgCache]) == argumentMap.end() + || argumentMap.find(InterfaceManager::flashArgumentNames[InterfaceManager::kFlashArgData]) == argumentMap.end() + || argumentMap.find(InterfaceManager::flashArgumentNames[InterfaceManager::kFlashArgPrimaryBootloader]) == argumentMap.end() + || argumentMap.find(InterfaceManager::flashArgumentNames[InterfaceManager::kFlashArgSecondaryBootloader]) == argumentMap.end() + || argumentMap.find(InterfaceManager::flashArgumentNames[InterfaceManager::kFlashArgParam]) == argumentMap.end() + || argumentMap.find(InterfaceManager::flashArgumentNames[InterfaceManager::kFlashArgKernel]) == argumentMap.end())) + { + InterfaceManager::Print("If you wish to repartition then factoryfs, cache, dbdata, primary and secondary\nbootloaders, param, kernel and a PIT file must all be specified.\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(InterfaceManager::dumpArgumentNames[InterfaceManager::kDumpArgChipType]) == argumentMap.end()) + { + InterfaceManager::Print("You must specify a chip type.\n\n"); + InterfaceManager::Print(InterfaceManager::usage); + return (0); + } + + string chipType = argumentMap.find(InterfaceManager::dumpArgumentNames[InterfaceManager::kDumpArgChipType])->second; + if (!(chipType == "RAM" || chipType == "ram" || chipType == "NAND" || chipType == "nand")) + { + InterfaceManager::Print("Unknown chip type: %s.\n\n", chipType.c_str()); + InterfaceManager::Print(InterfaceManager::usage); + return (0); + } + + if (argumentMap.find(InterfaceManager::dumpArgumentNames[InterfaceManager::kDumpArgChipId]) == argumentMap.end()) + { + InterfaceManager::Print("You must specify a Chip ID.\n\n"); + InterfaceManager::Print(InterfaceManager::usage); + 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"); + return (0); + } + } + + InterfaceManager::Print("\nHeimdall, Copyright (c) 2010, 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(); + + int communicationDelay = BridgeManager::kCommunicationDelayDefault; + if (argumentMap.find(InterfaceManager::commonArgumentNames[InterfaceManager::kCommonArgDelay]) != argumentMap.end()) + communicationDelay = atoi(argumentMap.find(InterfaceManager::commonArgumentNames[InterfaceManager::kCommonArgDelay])->second.c_str()); + + BridgeManager *bridgeManager = new BridgeManager(verbose, communicationDelay); + + if (!bridgeManager->Initialise()) + { + delete bridgeManager; + return (-2); + } + + bool success; + + switch (actionIndex) + { + case InterfaceManager::kActionFlash: + { + FILE **fileArray = new FILE *[kFileCount]; + for (int i = 0; i < kFileCount; i++) + fileArray[i] = nullptr; + + // We open the files before doing anything else to ensure they exist. + if (!openFiles(argumentMap, fileArray)) + { + closeFiles(fileArray); + delete [] fileArray; + + delete bridgeManager; + + return (0); + } + + if (!bridgeManager->BeginSession()) + { + closeFiles(fileArray); + delete [] fileArray; + + delete bridgeManager; + + return (-1); + } + + bool repartition = argumentMap.find(InterfaceManager::flashArgumentNames[InterfaceManager::kFlashArgRepartition]) != argumentMap.end(); + success = attemptFlash(bridgeManager, fileArray, repartition); + + closeFiles(fileArray); + delete [] fileArray; + + break; + } + + case InterfaceManager::kActionClosePcScreen: + { + if (!bridgeManager->BeginSession()) + { + delete bridgeManager; + return (-1); + } + + InterfaceManager::Print("Attempting to close connect to pc screen...\n"); + success = bridgeManager->EndSession() && bridgeManager->RebootDevice(); + + if (success) + InterfaceManager::Print("Attempt complete\n"); + + break; + } + + case InterfaceManager::kActionDump: + { + const char *outputFilename = argumentMap.find(InterfaceManager::dumpArgumentNames[InterfaceManager::kDumpArgOutput])->second.c_str(); + FILE *dumpFile = fopen(outputFilename, "wb"); + if (!dumpFile) + { + InterfaceManager::PrintError("Failed to open file \"%s\"\n", outputFilename); + + delete bridgeManager; + return (-1); + } + + int chipType = 0; + string chipTypeName = argumentMap.find(InterfaceManager::dumpArgumentNames[InterfaceManager::kDumpArgChipType])->second; + if (chipTypeName == "NAND" || chipTypeName == "nand") + chipType = 1; + + int chipId = atoi(argumentMap.find(InterfaceManager::dumpArgumentNames[InterfaceManager::kDumpArgChipId])->second.c_str()); + + if (!bridgeManager->BeginSession()) + { + fclose(dumpFile); + + delete bridgeManager; + + return (-1); + } + + success = bridgeManager->ReceiveDump(chipType, chipId, dumpFile); + + fclose(dumpFile); + + if (success) + success = bridgeManager->EndSession() && bridgeManager->RebootDevice(); + + break; + } + } + + delete bridgeManager; + + return ((success) ? 0 : -1); +}
\ No newline at end of file |