1
/*******************************************************************************
2
* Copyright (c) 2006-2009 Wind River Systems, Inc. and others.
3
* All rights reserved. This program and the accompanying materials
4
* are made available under the terms of the Eclipse Public License v1.0
5
* which accompanies this distribution, and is available at
6
* http://www.eclipse.org/legal/epl-v10.html
9
* Ted R Williams (Wind River Systems, Inc.) - initial implementation
10
*******************************************************************************/
12
package org.eclipse.cdt.debug.ui.memory.transport;
15
import java.io.FileWriter;
16
import java.io.IOException;
17
import java.math.BigInteger;
18
import java.util.Properties;
20
import org.eclipse.cdt.debug.ui.memory.transport.model.IMemoryExporter;
21
import org.eclipse.core.runtime.IProgressMonitor;
22
import org.eclipse.core.runtime.IStatus;
23
import org.eclipse.core.runtime.Status;
24
import org.eclipse.core.runtime.jobs.Job;
25
import org.eclipse.debug.core.DebugException;
26
import org.eclipse.debug.core.model.IMemoryBlock;
27
import org.eclipse.debug.core.model.IMemoryBlockExtension;
28
import org.eclipse.debug.core.model.MemoryByte;
29
import org.eclipse.swt.SWT;
30
import org.eclipse.swt.events.KeyEvent;
31
import org.eclipse.swt.events.KeyListener;
32
import org.eclipse.swt.events.SelectionEvent;
33
import org.eclipse.swt.events.SelectionListener;
34
import org.eclipse.swt.layout.FormAttachment;
35
import org.eclipse.swt.layout.FormData;
36
import org.eclipse.swt.layout.FormLayout;
37
import org.eclipse.swt.widgets.Button;
38
import org.eclipse.swt.widgets.Composite;
39
import org.eclipse.swt.widgets.Control;
40
import org.eclipse.swt.widgets.Display;
41
import org.eclipse.swt.widgets.FileDialog;
42
import org.eclipse.swt.widgets.Label;
43
import org.eclipse.swt.widgets.Text;
45
public class SRecordExporter implements IMemoryExporter
48
BigInteger fStartAddress;
49
BigInteger fEndAddress;
51
private Text fStartText;
52
private Text fEndText;
53
private Text fLengthText;
54
private Text fFileText;
56
private IMemoryBlock fMemoryBlock;
58
private ExportMemoryDialog fParentDialog;
60
private Properties fProperties;
62
public Control createControl(final Composite parent, IMemoryBlock memBlock, Properties properties, ExportMemoryDialog parentDialog)
64
fMemoryBlock = memBlock;
65
fParentDialog = parentDialog;
66
fProperties = properties;
68
Composite composite = new Composite(parent, SWT.NONE)
72
fProperties.setProperty(TRANSFER_FILE, fFileText.getText());
73
fProperties.setProperty(TRANSFER_START, fStartText.getText());
74
fProperties.setProperty(TRANSFER_END, fEndText.getText());
76
fStartAddress = getStartAddress();
77
fEndAddress = getEndAddress();
78
fOutputFile = getFile();
83
FormLayout formLayout = new FormLayout();
84
formLayout.spacing = 5;
85
formLayout.marginWidth = formLayout.marginHeight = 9;
86
composite.setLayout(formLayout);
90
Label startLabel = new Label(composite, SWT.NONE);
91
startLabel.setText("Start address: ");
92
FormData data = new FormData();
93
startLabel.setLayoutData(data);
95
fStartText = new Text(composite, SWT.NONE);
96
data = new FormData();
97
data.left = new FormAttachment(startLabel);
99
fStartText.setLayoutData(data);
103
Label endLabel = new Label(composite, SWT.NONE);
104
endLabel.setText("End address: ");
105
data = new FormData();
106
data.top = new FormAttachment(fStartText, 0, SWT.CENTER);
107
data.left = new FormAttachment(fStartText);
108
endLabel.setLayoutData(data);
110
fEndText = new Text(composite, SWT.NONE);
111
data = new FormData();
112
data.top = new FormAttachment(fStartText, 0, SWT.CENTER);
113
data.left = new FormAttachment(endLabel);
115
fEndText.setLayoutData(data);
119
Label lengthLabel = new Label(composite, SWT.NONE);
120
lengthLabel.setText("Length: ");
121
data = new FormData();
122
data.top = new FormAttachment(fStartText, 0, SWT.CENTER);
123
data.left = new FormAttachment(fEndText);
124
lengthLabel.setLayoutData(data);
126
fLengthText = new Text(composite, SWT.NONE);
127
data = new FormData();
128
data.top = new FormAttachment(fStartText, 0, SWT.CENTER);
129
data.left = new FormAttachment(lengthLabel);
131
fLengthText.setLayoutData(data);
135
Label fileLabel = new Label(composite, SWT.NONE);
136
fFileText = new Text(composite, SWT.NONE);
137
Button fileButton = new Button(composite, SWT.PUSH);
139
fileLabel.setText("File name: ");
140
data = new FormData();
141
data.top = new FormAttachment(fileButton, 0, SWT.CENTER);
142
fileLabel.setLayoutData(data);
144
data = new FormData();
145
data.top = new FormAttachment(fileButton, 0, SWT.CENTER);
146
data.left = new FormAttachment(fileLabel);
148
fFileText.setLayoutData(data);
150
fileButton.setText("Browse...");
151
data = new FormData();
152
data.top = new FormAttachment(fLengthText);
153
data.left = new FormAttachment(fFileText);
154
fileButton.setLayoutData(data);
156
fFileText.setText(properties.getProperty(TRANSFER_FILE, ""));
159
BigInteger startAddress = null;
160
if(fMemoryBlock instanceof IMemoryBlockExtension)
161
startAddress = ((IMemoryBlockExtension) fMemoryBlock).getBigBaseAddress(); // FIXME use selection/caret address?
163
startAddress = BigInteger.valueOf(fMemoryBlock.getStartAddress());
165
if(properties.getProperty(TRANSFER_START) != null)
166
fStartText.setText(properties.getProperty(TRANSFER_START));
168
fStartText.setText("0x" + startAddress.toString(16));
170
if(properties.getProperty(TRANSFER_END) != null)
171
fEndText.setText(properties.getProperty(TRANSFER_END));
173
fEndText.setText("0x" + startAddress.toString(16));
175
fLengthText.setText(getEndAddress().subtract(getStartAddress()).toString());
179
MemoryTransportPlugin.getDefault().getLog().log(new Status(IStatus.ERROR, MemoryTransportPlugin.getUniqueIdentifier(),
180
DebugException.INTERNAL_ERROR, "Failure", e));
183
fileButton.addSelectionListener(new SelectionListener() {
185
public void widgetDefaultSelected(SelectionEvent e) {
186
// TODO Auto-generated method stub
190
public void widgetSelected(SelectionEvent e) {
191
FileDialog dialog = new FileDialog(parent.getShell(), SWT.SAVE);
192
dialog.setText("Choose memory export file");
193
dialog.setFilterExtensions(new String[] { "*.*;*" } );
194
dialog.setFilterNames(new String[] { "All Files" } );
195
dialog.setFileName(fFileText.getText());
198
String filename = dialog.getFileName();
199
if(filename != null && filename.length() != 0 )
201
fFileText.setText(dialog.getFilterPath() + File.separator + filename);
209
fStartText.addKeyListener(new KeyListener() {
210
public void keyReleased(KeyEvent e) {
211
boolean valid = true;
221
fStartText.setForeground(valid ? Display.getDefault().getSystemColor(SWT.COLOR_BLACK) :
222
Display.getDefault().getSystemColor(SWT.COLOR_RED));
226
BigInteger endAddress = getEndAddress();
227
BigInteger startAddress = getStartAddress();
229
fLengthText.setText(endAddress.subtract(startAddress).toString());
234
public void keyPressed(KeyEvent e) {}
237
fEndText.addKeyListener(new KeyListener() {
238
public void keyReleased(KeyEvent e) {
242
fEndText.setForeground(Display.getDefault().getSystemColor(SWT.COLOR_BLACK));
244
BigInteger endAddress = getEndAddress();
245
BigInteger startAddress = getStartAddress();
247
String lengthString = endAddress.subtract(startAddress).toString();
249
if(!fLengthText.getText().equals(lengthString))
250
fLengthText.setText(lengthString);
254
fEndText.setForeground(Display.getDefault().getSystemColor(SWT.COLOR_RED));
260
public void keyPressed(KeyEvent e) {}
264
fLengthText.addKeyListener(new KeyListener() {
265
public void keyReleased(KeyEvent e) {
268
BigInteger length = getLength();
269
fLengthText.setForeground(Display.getDefault().getSystemColor(SWT.COLOR_BLACK));
270
BigInteger startAddress = getStartAddress();
271
String endString = "0x" + startAddress.add(length).toString(16);
272
if(!fEndText.getText().equals(endString))
273
fEndText.setText(endString);
277
fLengthText.setForeground(Display.getDefault().getSystemColor(SWT.COLOR_RED));
285
public void keyPressed(KeyEvent e) {
290
fFileText.addKeyListener(new KeyListener() {
291
public void keyReleased(KeyEvent e) {
295
public void keyPressed(KeyEvent e) {
304
* We need to perform a validation. If we do it immediately we will get an exception
305
* because things are not totally setup. So we schedule an immediate running of the
306
* validation. For a very brief time the view logically may show a state which does
307
* not reflect the true state of affairs. But the validate immediately corrects the
308
* info. In practice the user never sees the invalid state displayed, because of the
309
* speed of the draw of the dialog.
311
Display.getDefault().asyncExec(new Runnable(){
321
public BigInteger getEndAddress()
323
String text = fEndText.getText();
324
boolean hex = text.startsWith("0x");
325
BigInteger endAddress = new BigInteger(hex ? text.substring(2) : text,
331
public BigInteger getStartAddress()
333
String text = fStartText.getText();
334
boolean hex = text.startsWith("0x");
335
BigInteger startAddress = new BigInteger(hex ? text.substring(2) : text,
341
public BigInteger getLength()
343
String text = fLengthText.getText();
344
boolean hex = text.startsWith("0x");
345
BigInteger lengthAddress = new BigInteger(hex ? text.substring(2) : text,
348
return lengthAddress;
351
public File getFile()
353
return new File(fFileText.getText());
356
private void validate()
358
boolean isValid = true;
366
BigInteger length = getLength();
368
if(length.compareTo(BigInteger.ZERO) <= 0)
371
if(!getFile().getParentFile().exists())
379
fParentDialog.setValid(isValid);
383
public String getId()
388
public String getName()
393
public void exportMemory()
395
Job job = new Job("Memory Export to S-Record File"){ //$NON-NLS-1$
396
public IStatus run(IProgressMonitor monitor) {
399
// FIXME 4 byte default
401
BigInteger DATA_PER_RECORD = BigInteger.valueOf(16);
403
BigInteger transferAddress = fStartAddress;
405
FileWriter writer = new FileWriter(fOutputFile);
407
BigInteger jobs = fEndAddress.subtract(transferAddress).divide(DATA_PER_RECORD);
408
BigInteger factor = BigInteger.ONE;
409
if(jobs.compareTo(BigInteger.valueOf(0x7FFFFFFF)) > 0)
411
factor = jobs.divide(BigInteger.valueOf(0x7FFFFFFF));
412
jobs = jobs.divide(factor);
415
monitor.beginTask("Transferring Data", jobs.intValue());
417
BigInteger jobCount = BigInteger.ZERO;
418
while(transferAddress.compareTo(fEndAddress) < 0 && !monitor.isCanceled())
420
BigInteger length = DATA_PER_RECORD;
421
if(fEndAddress.subtract(transferAddress).compareTo(length) < 0)
422
length = fEndAddress.subtract(transferAddress);
424
monitor.subTask(String.format("Transfering %s bytes at address 0x%s", length.toString(10), transferAddress.toString(16)));
426
writer.write("S3"); // FIXME 4 byte address
428
StringBuffer buf = new StringBuffer();
430
BigInteger sRecordLength = BigInteger.valueOf(4); // address size
431
sRecordLength = sRecordLength.add(length);
432
sRecordLength = sRecordLength.add(BigInteger.ONE); // checksum
434
String transferAddressString = transferAddress.toString(16);
436
String lengthString = sRecordLength.toString(16);
437
if(lengthString.length() == 1)
439
buf.append(lengthString);
440
for(int i = 0; i < 8 - transferAddressString.length(); i++)
442
buf.append(transferAddressString);
446
MemoryByte bytes[] = ((IMemoryBlockExtension) fMemoryBlock).getBytesFromAddress(transferAddress,
447
length.longValue() / ((IMemoryBlockExtension) fMemoryBlock).getAddressableSize());
448
for(int byteIndex = 0; byteIndex < bytes.length; byteIndex++)
450
String bString = BigInteger.valueOf(0xFF & bytes[byteIndex].getValue()).toString(16);
451
if(bString.length() == 1)
457
* The least significant byte of the one's complement of the sum of the values
458
* represented by the pairs of characters making up the records length, address,
459
* and the code/data fields.
463
for(int i = 0; i < buf.length(); i+=2)
465
BigInteger value = new BigInteger(buf.substring(i, i+2), 16);
466
checksum += value.byteValue();
469
String bString = BigInteger.valueOf(0xFF - checksum).and(BigInteger.valueOf(0xFF)).toString(16);
470
if(bString.length() == 1)
474
writer.write(buf.toString().toUpperCase());
477
transferAddress = transferAddress.add(length);
479
jobCount = jobCount.add(BigInteger.ONE);
480
if(jobCount.compareTo(factor) == 0)
482
jobCount = BigInteger.ZERO;
489
} catch (IOException ex) {
490
MemoryTransportPlugin.getDefault().getLog().log(new Status(IStatus.ERROR, MemoryTransportPlugin.getUniqueIdentifier(),
491
DebugException.REQUEST_FAILED, "Could not write to file.", ex));
492
return new Status(IStatus.ERROR, MemoryTransportPlugin.getUniqueIdentifier(),
493
DebugException.REQUEST_FAILED, "Could not write to file.", ex);
495
} catch (DebugException ex) {
496
MemoryTransportPlugin.getDefault().getLog().log(new Status(IStatus.ERROR, MemoryTransportPlugin.getUniqueIdentifier(),
497
DebugException.REQUEST_FAILED, "Could not read from target.", ex));
498
return new Status(IStatus.ERROR, MemoryTransportPlugin.getUniqueIdentifier(),
499
DebugException.REQUEST_FAILED, "Could not read from target.", ex);
500
} catch (Exception ex) {
501
MemoryTransportPlugin.getDefault().getLog().log(new Status(IStatus.ERROR, MemoryTransportPlugin.getUniqueIdentifier(),
502
DebugException.INTERNAL_ERROR, "Failure exporting memory", ex));
503
return new Status(IStatus.ERROR, MemoryTransportPlugin.getUniqueIdentifier(),
504
DebugException.INTERNAL_ERROR, "Failure exporting memory", ex);
506
return Status.OK_STATUS;