// Write the concatonated header and configuration data to the Flash config sector private void WriteConfig(string configName, byte[] data, bool staticSize, bool updateConfigSector) { _DBG.Engine engine = m_device.DbgEngine; if (!m_init) { InitializeConfigData(); } // updating the config if (m_cfgHash.ContainsKey(configName)) { ConfigIndexData cid = (ConfigIndexData)m_cfgHash[configName]; // If old and new data are different sizes if (cid.Size != data.Length) { // If data comes from a well defined structure, its size cannot vary if (staticSize) { throw new MFInvalidConfigurationDataException(); } uint newNextIndex, oldNextIndex; byte[] temp; int diff = 0; // Figure out where any following configuration data will start newNextIndex = (uint)(cid.Index + data.Length); while (0 != (newNextIndex % 4)) { newNextIndex++; // Force a 4 byte boundary } // Figure out where any following configuration data previously started oldNextIndex = (uint)(cid.Index + cid.Size); while (0 != (oldNextIndex % 4)) { oldNextIndex++; // Force a 4 byte boundary } diff = (int)newNextIndex - (int)oldNextIndex; // Find the adjusted difference in size between old and new config data temp = new byte[m_lastCfgIndex + diff]; // Create a new byte array to contain all the configuration data Array.Copy(m_all_cfg_data, temp, cid.Index); // Copy all preceding data to new array Array.Copy(data, 0, temp, cid.Index, data.Length); // Copy new configuration to new array if (oldNextIndex < m_lastCfgIndex) // Copy all following data (if it exists) to new array { Array.Copy(m_all_cfg_data, oldNextIndex, temp, newNextIndex, (m_all_cfg_data.Length - oldNextIndex)); } // Update the local copy of the configuration list m_all_cfg_data = temp; m_lastCfgIndex += diff; } else { // Copy the new configuration data on top of the old Array.Copy(data, 0, m_all_cfg_data, cid.Index, data.Length); } } else // adding a new configuration to the end of the current list { uint newLastIndex; if (m_lastCfgIndex == -1) { throw new MFConfigurationSectorOutOfMemoryException(); } // Find the new size of the whole configuration list newLastIndex = (uint)(m_lastCfgIndex + data.Length); while (0 != (newLastIndex % 4)) { newLastIndex++; // Force a 4 byte boundary } byte[] temp = new byte[m_lastCfgIndex >= m_all_cfg_data.Length ? m_lastCfgIndex + data.Length : m_all_cfg_data.Length]; Array.Copy(m_all_cfg_data, 0, temp, 0, m_all_cfg_data.Length); Array.Copy(data, 0, temp, m_lastCfgIndex, data.Length); // Update the local copy of the configuration list m_all_cfg_data = temp; m_lastCfgIndex = (int)newLastIndex; } if (!updateConfigSector) { return; } // Rewrite entire configuration list to Flash if (!engine.EraseMemory(m_cfg_sector.m_address, (uint)m_all_cfg_data.Length)) { throw new MFConfigSectorEraseFailureException(); } if (!engine.WriteMemory(m_cfg_sector.m_address, m_all_cfg_data)) { throw new MFConfigSectorWriteFailureException(); } // Rebuild hash table m_cfgHash.Clear(); uint hal_config_block_size = 0; unsafe { hal_config_block_size = (uint)sizeof(HAL_CONFIG_BLOCK); } int index = (int)m_StaticConfig.ConfigurationLength; byte[] headerData = new byte[hal_config_block_size]; HAL_CONFIG_BLOCK cfg_header; while (index < m_lastCfgIndex) { // Read in next configuration header Array.Copy(m_all_cfg_data, index, headerData, 0, hal_config_block_size); cfg_header = (HAL_CONFIG_BLOCK)UnmarshalData(headerData, typeof(HAL_CONFIG_BLOCK)); m_cfgHash[cfg_header.DriverNameString] = new ConfigIndexData(index, (int)(cfg_header.Size + hal_config_block_size)); // Index of next configuration header must lie on a 4 byte boundary index += (int)(cfg_header.Size + hal_config_block_size); while (0 != (index % 4)) { index++; // Force a 4 byte boundary } } // we need to perform signature check regardless of key update, in order for the device to write from ram buffer to flash if (!engine.CheckSignature(new byte[TINYBOOTER_KEY_CONFIG.c_KeySignatureLength], 0)) { if (engine.ConnectionSource == Microsoft.SPOT.Debugger.ConnectionSource.TinyBooter) { throw new MFConfigSectorWriteFailureException(); } } if (engine.ConnectionSource == Microsoft.SPOT.Debugger.ConnectionSource.TinyBooter && m_fRestartClr) { engine.ExecuteMemory(c_EnumerateAndLaunchAddr); } }
/// <summary> /// Attempts to deploy an SREC (.hex) file to the connected .Net Micro Framework device. The /// signatureFile is used to validate the image once it has been deployed to the device. If /// the signature does not match the image is erased. /// </summary> /// <param name="filePath">Full path to the SREC (.hex) file</param> /// <param name="signatureFile">Full path to the signature file (.sig) for the SREC file identified by the filePath parameter</param> /// <param name="entrypoint">Out parameter that is set to the entry point address for the given SREC file</param> /// <returns>Returns false if the deployment fails, true otherwise /// Possible exceptions: MFFileNotFoundException, MFDeviceNoResponseException, MFUserExitException /// </returns> public bool Deploy(string filePath, string signatureFile, ref uint entryPoint) { entryPoint = 0; if (!File.Exists(filePath)) { throw new FileNotFoundException(filePath); } if (m_eng == null) { throw new MFDeviceNoResponseException(); } // make sure we know who we are talking to m_eng.TryToConnect(1, 100, true, _DBG.ConnectionSource.Unknown); bool sigExists = File.Exists(signatureFile); FileInfo fi = new FileInfo(filePath); ArrayList blocks = new ArrayList(); entryPoint = _DBG.SRecordFile.Parse(filePath, blocks, sigExists? signatureFile: null); if (blocks.Count > 0) { long total = 0; long value = 0; for (int i = 0; i < blocks.Count; i++) { total += (blocks[i] as _DBG.SRecordFile.Block).data.Length; } PrepareForDeploy(blocks); foreach (_DBG.SRecordFile.Block block in blocks) { long len = block.data.Length; uint addr = block.address; if (EventCancel.WaitOne(0, false)) { throw new MFUserExitException(); } block.data.Seek(0, SeekOrigin.Begin); if (OnProgress != null) { OnProgress(0, total, string.Format(Properties.Resources.StatusEraseSector, block.address)); } // the clr requires erase before writing if (!m_eng.EraseMemory(block.address, (uint)len)) { return(false); } while (len > 0) { if (EventCancel.WaitOne(0, false)) { throw new MFUserExitException(); } int buflen = len > 1024? 1024: (int)len; byte[] data = new byte[buflen]; if (block.data.Read(data, 0, buflen) <= 0) { return(false); } if (!m_eng.WriteMemory(addr, data)) { return(false); } value += buflen; addr += (uint)buflen; len -= buflen; if (OnProgress != null) { OnProgress(value, total, string.Format(Properties.Resources.StatusFlashing, fi.Name)); } } if (_DBG.ConnectionSource.TinyCLR != m_eng.ConnectionSource) { byte[] emptySig = new byte[128]; if (OnProgress != null) { OnProgress(value, total, Properties.Resources.StatusCheckingSignature); } if (!m_eng.CheckSignature(((block.signature == null || block.signature.Length == 0)? emptySig: block.signature), 0)) { throw new MFSignatureFailureException(signatureFile); } } } } return(true); }
private void UploadWithTinyBooter() { m_eng.OnNoise -= new _DBG.NoiseEventHandler(OnNoise); foreach (_DBG.SRecordFile.Block bl in m_blocks) { long offset = 0; uint location = bl.address; byte[] buf = bl.data.ToArray(); long count = bl.data.Length; OnProgress(bl, (int)offset, false); byte[] chunk = new byte[4096]; while (count != 0) { long length = System.Math.Min(4096, count); if (length != 4096) { chunk = new byte[length]; } Array.Copy(buf, offset, chunk, 0, length); if (!m_eng.WriteMemory(location, chunk)) { return; } location += (uint)length; offset += length; count -= length; OnProgress(bl, (int)offset, false); } if (!m_eng.CheckSignature(bl.signature, 0)) { this.NewText("Check Signature failed!"); return; } OnProgress(bl, (int)count, true); } uint address = uint.MaxValue; foreach (_DBG.SRecordFile.Block bl in m_blocks) { if (bl.executable) { address = bl.address; } } if (address != uint.MaxValue) { m_eng.ExecuteMemory(address); } m_eng.OnNoise += new _DBG.NoiseEventHandler(OnNoise); if (m_fDisconnect) { this.Invoke(new Callback_Bool(this.StartOrStop), new object[] { false }); } }