/// <summary> /// Ask the kernel which OS is installed, fail if it doesn't match the one in the file. /// </summary> public async Task <bool> IsSameOperatingSystemAccordingToKernel(FileValidator validator, CancellationToken cancellationToken) { Response <uint> osidResponse = await this.QueryOperatingSystemIdFromKernel(cancellationToken); if (osidResponse.Status != ResponseStatus.Success) { // The kernel seems broken. This shouldn't happen, but if it does, halt. this.logger.AddUserMessage("The kernel did not respond to operating system ID query."); return(false); } if (!validator.IsSameOperatingSystem(osidResponse.Value)) { return(false); } return(true); }
/// <summary> /// Write changes to the PCM's flash memory. /// </summary> private async void write_BackgroundThread(WriteType writeType) { using (new AwayMode()) { try { this.currentWriteType = writeType; if (this.Vehicle == null) { // This shouldn't be possible - it would mean the buttons // were enabled when they shouldn't be. return; } this.cancellationTokenSource = new CancellationTokenSource(); string path = null; this.Invoke((MethodInvoker) delegate() { this.DisableUserInput(); this.cancelButton.Enabled = true; path = this.ShowOpenDialog(); }); if (path == null) { return; } this.AddUserMessage(path); byte[] image; using (Stream stream = File.OpenRead(path)) { image = new byte[stream.Length]; int bytesRead = await stream.ReadAsync(image, 0, (int)stream.Length); if (bytesRead != stream.Length) { // If this happens too much, we should try looping rather than reading the whole file in one shot. this.AddUserMessage("Unable to load file."); return; } } // Sanity checks. FileValidator validator = new FileValidator(image, this); if (!validator.IsValid()) { this.AddUserMessage("This file is corrupt. It would render your PCM unusable."); return; } UInt32 kernelVersion = 0; bool needUnlock; int keyAlgorithm = 1; UInt32 pcmOperatingSystemId = 0; bool needToCheckOperatingSystem = writeType != WriteType.Full; this.AddUserMessage("Requesting operating system ID..."); Response <uint> osidResponse = await this.Vehicle.QueryOperatingSystemId(this.cancellationTokenSource.Token); if (osidResponse.Status == ResponseStatus.Success) { pcmOperatingSystemId = osidResponse.Value; PcmInfo info = new PcmInfo(pcmOperatingSystemId); keyAlgorithm = info.KeyAlgorithm; needUnlock = true; if (needToCheckOperatingSystem && !validator.IsSameOperatingSystem(pcmOperatingSystemId)) { this.AddUserMessage("Flashing this file could render your PCM unusable."); return; } needToCheckOperatingSystem = false; } else { if (this.cancellationTokenSource.Token.IsCancellationRequested) { return; } this.AddUserMessage("Operating system request failed, checking for a live kernel..."); kernelVersion = await this.Vehicle.GetKernelVersion(); if (kernelVersion == 0) { this.AddUserMessage("Checking for recovery mode..."); bool recoveryMode = await this.Vehicle.IsInRecoveryMode(); if (recoveryMode) { this.AddUserMessage("PCM is in recovery mode."); needUnlock = true; } else { this.AddUserMessage("PCM is not responding to OSID, kernel version, or recovery mode checks."); this.AddUserMessage("Unlock may not work, but we'll try..."); needUnlock = true; } } else { needUnlock = false; this.AddUserMessage("Kernel version: " + kernelVersion.ToString("X8")); this.AddUserMessage("Asking kernel for the PCM's operating system ID..."); if (needToCheckOperatingSystem && !await this.Vehicle.IsSameOperatingSystemAccordingToKernel(validator, this.cancellationTokenSource.Token)) { this.AddUserMessage("Flashing this file could render your PCM unusable."); return; } needToCheckOperatingSystem = false; } } await this.Vehicle.SuppressChatter(); if (needUnlock) { bool unlocked = await this.Vehicle.UnlockEcu(keyAlgorithm); if (!unlocked) { this.AddUserMessage("Unlock was not successful."); return; } this.AddUserMessage("Unlock succeeded."); } DateTime start = DateTime.Now; CKernelWriter writer = new CKernelWriter( this.Vehicle, new Protocol(), this); await writer.Write( image, writeType, kernelVersion, validator, needToCheckOperatingSystem, this.cancellationTokenSource.Token); this.AddUserMessage("Elapsed time " + DateTime.Now.Subtract(start)); } catch (IOException exception) { this.AddUserMessage(exception.ToString()); } finally { this.currentWriteType = WriteType.None; this.Invoke((MethodInvoker) delegate() { this.EnableUserInput(); this.cancelButton.Enabled = false; }); // The token / token-source can only be cancelled once, so we need to make sure they won't be re-used. this.cancellationTokenSource = null; } } }
/// <summary> /// Write changes to the PCM's flash memory, or just test writing (Without /// making changes) to evaluate the connection quality. /// </summary> public async Task <bool> Write( byte[] image, UInt32 kernelVersion, FileValidator validator, bool needToCheckOperatingSystem, CancellationToken cancellationToken) { bool success = false; try { // Start with known state. await this.vehicle.ForceSendToolPresentNotification(); this.vehicle.ClearDeviceMessageQueue(); // TODO: install newer version if available. if (kernelVersion == 0) { // Switch to 4x, if possible. But continue either way. if (Configuration.Enable4xReadWrite) { // if the vehicle bus switches but the device does not, the bus will need to time out to revert back to 1x, and the next steps will fail. if (!await this.vehicle.VehicleSetVPW4x(VpwSpeed.FourX)) { this.logger.AddUserMessage("Stopping here because we were unable to switch to 4X."); return(false); } } else { this.logger.AddUserMessage("4X communications disabled by configuration."); } Response <byte[]> response = await this.vehicle.LoadKernelFromFile("kernel.bin"); if (response.Status != ResponseStatus.Success) { logger.AddUserMessage("Failed to load kernel from file."); return(false); } if (cancellationToken.IsCancellationRequested) { return(false); } // TODO: instead of this hard-coded address, get the base address from the PcmInfo object. if (!await this.vehicle.PCMExecute(response.Value, 0xFF8000, cancellationToken)) { logger.AddUserMessage("Failed to upload kernel to PCM"); return(false); } logger.AddUserMessage("Kernel uploaded to PCM succesfully."); } // Confirm operating system match await this.vehicle.SendToolPresentNotification(); await this.vehicle.SetDeviceTimeout(TimeoutScenario.ReadProperty); Response <UInt32> osidResponse = await this.vehicle.QueryOperatingSystemIdFromKernel(cancellationToken); if (needToCheckOperatingSystem && (osidResponse.Status != ResponseStatus.Success)) { // The kernel seems broken. This shouldn't happen, but if it does, halt. this.logger.AddUserMessage("The kernel did not respond to operating system ID query."); return(false); } bool shouldHalt; Utility.ReportOperatingSystems(validator.GetOsidFromImage(), osidResponse.Value, this.writeType, this.logger, out shouldHalt); if (needToCheckOperatingSystem && shouldHalt) { return(false); } success = await this.Write(cancellationToken, image); // We only do cleanup after a successful write. // If the kernel remains running, the user can try to flash again without rebooting and reloading. // TODO: kernel version should be stored at a fixed location in the bin file. // TODO: app should check kernel version (not just "is present") and reload only if version is lower than version in kernel file. if (success) { await this.vehicle.Cleanup(); } return(success); } catch (Exception exception) { if (!success) { switch (this.writeType) { case WriteType.None: case WriteType.Compare: case WriteType.TestWrite: await this.vehicle.Cleanup(); this.logger.AddUserMessage("Something has gone wrong. Please report this error."); this.logger.AddUserMessage("Errors during comparisons or test writes indicate a"); this.logger.AddUserMessage("problem with the PCM, interface, cable, or app. Don't"); this.logger.AddUserMessage("try to do any actual writing until you are certain that"); this.logger.AddUserMessage("the underlying problem has been completely corrected."); break; default: this.logger.AddUserMessage("Something went wrong. " + exception.Message); this.logger.AddUserMessage("Do not power off the PCM! Do not exit this program!"); this.logger.AddUserMessage("Try flashing again. If errors continue, seek help online."); break; } this.logger.AddUserMessage("https://pcmhacking.net/forums/viewtopic.php?f=42&t=6080"); this.logger.AddUserMessage(string.Empty); this.logger.AddUserMessage(exception.ToString()); } return(success); } }
/// <summary> /// Write changes to the IPC's flash memory, or just test writing (Without /// making changes) to evaluate the connection quality. /// </summary> public async Task <bool> Write( byte[] image, UInt32 kernelVersion, FileValidator validator, bool needToCheckOperatingSystem, CancellationToken cancellationToken) { bool success = false; try { // Start with known state. await this.vehicle.ForceSendToolPresentNotification(); this.vehicle.ClearDeviceMessageQueue(); // TODO: install newer version if available. if (kernelVersion == 0) { // Switch to 4x, if possible. But continue either way. if (Configuration.Enable4xReadWrite) { // if the vehicle bus switches but the device does not, the bus will need to time out to revert back to 1x, and the next steps will fail. if (!await this.vehicle.VehicleSetVPW4x(VpwSpeed.FourX)) { this.logger.AddUserMessage("Stopping here because we were unable to switch to 4X."); return(false); } } else { this.logger.AddUserMessage("4X communications disabled by configuration."); } } ///var sweepResponse = await this.vehicle.startProgram(); // TODO: instead of this hard-coded address, get the base address from the PcmInfo object. int address1 = 0x020000; int claimedSize1 = 0x000002; if (!await this.vehicle.PCMStartProgram(address1, claimedSize1, cancellationToken)) { logger.AddUserMessage("Start Program to IPC denied"); return(false); } logger.AddUserMessage("Start Program to IPC allowed."); /// var modeResponse = await this.vehicle.requestmode34(); // TODO: instead of this hard-coded address, get the base address from the PcmInfo object. int address = 0x00E000; int claimedSize = 0x0400; if (!await this.vehicle.PCMExecute1(address, claimedSize, cancellationToken)) { logger.AddUserMessage("Upload to IPC denied"); return(false); } logger.AddUserMessage("Upload to IPC allowed."); success = await this.Write(cancellationToken, image); // We only do cleanup after a successful write. // If the kernel remains running, the user can try to flash again without rebooting and reloading. // TODO: kernel version should be stored at a fixed location in the bin file. // TODO: app should check kernel version (not just "is present") and reload only if version is lower than version in kernel file. if (success) { await this.vehicle.Cleanup(); } return(success); } catch (Exception exception) { if (!success) { switch (this.writeTypeIpc) { case WriteTypeIpc.None: case WriteTypeIpc.Compare: case WriteTypeIpc.TestWrite: await this.vehicle.Cleanup(); this.logger.AddUserMessage("Something has gone wrong. Please report this error."); this.logger.AddUserMessage("Errors during comparisons or test writes indicate a"); this.logger.AddUserMessage("problem with the PCM, interface, cable, or app. Don't"); this.logger.AddUserMessage("try to do any actual writing until you are certain that"); this.logger.AddUserMessage("the underlying problem has been completely corrected."); break; default: this.logger.AddUserMessage("Something went wrong. " + exception.Message); this.logger.AddUserMessage("Do not power off the PCM! Do not exit this program!"); this.logger.AddUserMessage("Try flashing again. If errors continue, seek help online."); break; } ///this.logger.AddUserMessage("https://pcmhacking.net/forums/viewtopic.php?f=42&t=6080"); this.logger.AddUserMessage(string.Empty); this.logger.AddUserMessage(exception.ToString()); } return(success); } }
/// <summary> /// Write changes to the PCM's flash memory, or just test writing (Without /// making changes) to evaluate the connection quality. /// </summary> public async Task <bool> Write( byte[] image, WriteType writeType, UInt32 kernelVersion, FileValidator validator, bool needToCheckOperatingSystem, CancellationToken cancellationToken) { bool success = false; try { await notifier.Notify(); this.device.ClearMessageQueue(); // TODO: install newer version if available. if (kernelVersion == 0) { // switch to 4x, if possible. But continue either way. // if the vehicle bus switches but the device does not, the bus will need to time out to revert back to 1x, and the next steps will fail. if (!await this.VehicleSetVPW4x(VpwSpeed.FourX, notifier)) { this.logger.AddUserMessage("Stopping here because we were unable to switch to 4X."); return(false); } Response <byte[]> response = await LoadKernelFromFile("write-kernel.bin"); if (response.Status != ResponseStatus.Success) { logger.AddUserMessage("Failed to load kernel from file."); return(false); } if (cancellationToken.IsCancellationRequested) { return(false); } // TODO: instead of this hard-coded address, get the base address from the PcmInfo object. if (!await PCMExecute(response.Value, 0xFF8000, notifier, cancellationToken)) { logger.AddUserMessage("Failed to upload kernel to PCM"); return(false); } logger.AddUserMessage("Kernel uploaded to PCM succesfully."); } if (needToCheckOperatingSystem) { if (!await this.IsSameOperatingSystemAccordingToKernel(validator, cancellationToken)) { this.logger.AddUserMessage("Flashing this file could render your PCM unusable."); return(false); } } success = await Write(cancellationToken, image, writeType, notifier); // We only do cleanup after a successful write. // If the kernel remains running, the user can try to flash again without rebooting and reloading. // TODO: kernel version should be stored at a fixed location in the bin file. // TODO: app should check kernel version (not just "is present") and reload only if version is lower than version in kernel file. if (success) { await this.Cleanup(); } return(success); } catch (Exception exception) { if (!success) { this.logger.AddUserMessage("Something went wrong. " + exception.Message); this.logger.AddUserMessage("Do not power off the PCM! Do not exit this program!"); this.logger.AddUserMessage("Try flashing again. If errors continue, seek help online."); this.logger.AddUserMessage("https://pcmhacking.net/forums/viewtopic.php?f=3&t=6080"); this.logger.AddUserMessage(string.Empty); this.logger.AddUserMessage(exception.ToString()); } return(success); } }