/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package com.atolsystems.memop;
import com.atolsystems.atolutilities.*;
import com.atolsystems.atolutilities.CommandLine.Arg;
import com.atolsystems.atolutilities.CommandLine.ArgDef;
import com.atolsystems.atolutilities.CommandLine.BooleanValueArgHandler;
import com.atolsystems.atolutilities.CommandLine.IntegerNumericArgHandler;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintStream;
import java.net.MalformedURLException;
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.filechooser.FileNameExtensionFilter;
/**
*
* @author sebastien.riou
*/
public final class MemEnc {
static private final String DSTFILE_PATH_PREFERENCE_KEY = "com.samsung.lsi.scard.dstFilePath";
static private final String INPUTFILE_PATH_PREFERENCE_KEY = "com.samsung.lsi.scard.inputFilePath";
/**
* An utility to concatenate several files into one
* @param args
*/
public static void main(String[] args){
sayHello();
MemEnc u=new MemEnc(args);
}
public static void sayHello(){
java.util.ResourceBundle bundle1 = java.util.ResourceBundle.getBundle("com/atolsystems/memop/resources/BuildNumber");
System.out.println("\n\nMemEnc v0.2 ("+"build "+bundle1.getString("build.number")+"), Samsung Electronics, 2010 - 2011");
System.out.println("Utility to encrypt/decrypt memory images of smart card devices");
System.out.println("\nAuthor: sebastien.riou@samsung.com");
}
public static void showHelp(CommandLine cl){
System.out.println("\nCommand line usage:");
System.out.println(cl.help());
System.out.println();
}
Boolean nonLinearity=false;
Boolean compressionTest=false;
int nlOutputWidth;
int nlStorageSize;
int nlInputWidth;
File dstFile;
File binDstFile;
File verilogDstFile;
File coeDstFile;
File baseDstFile;
File templateFile;
File maskImageFile;
ArrayList<File> files=new ArrayList<File>();
ArrayList<MemRange> dataKeysMap=new ArrayList<MemRange>();
ArrayList<MemRange> addressKeysMap=new ArrayList<MemRange>();
Boolean encrypt=null;
MutableInteger orRedWidth=new MutableInteger(-1);
boolean skipDataScrambling=false;
boolean skipAddrScrambling=false;
MemScrambler memScrambler=null;
Boolean directExit=true;
public MemEnc(String[] args) {
try {
CommandLine cl=new CommandLine();
HelpArgHandler helpArgHandler=new HelpArgHandler();
cl.addArgDef(helpArgHandler.argDef);
HexInArgHandler hexInArgHandler=new HexInArgHandler();
cl.addArgDef(hexInArgHandler.argDef);
HexOutArgHandler hexOutArgHandler=new HexOutArgHandler();
cl.addArgDef(hexOutArgHandler.argDef);
BinOutArgHandler binOutArgHandler=new BinOutArgHandler();
cl.addArgDef(binOutArgHandler.argDef);
VerilogOutArgHandler verilogOutArgHandler=new VerilogOutArgHandler();
cl.addArgDef(verilogOutArgHandler.argDef);
CoeOutArgHandler coeOutArgHandler=new CoeOutArgHandler();
cl.addArgDef(coeOutArgHandler.argDef);
VerilogPrependAddressArgHandler verilogPrependAddressArgHandler=new VerilogPrependAddressArgHandler();
cl.addArgDef(verilogPrependAddressArgHandler.argDef);
AddDataKeyArgHandler addDataKeyArgHandler=new AddDataKeyArgHandler();
cl.addArgDef(addDataKeyArgHandler.argDef);
AddAddressKeyArgHandler addAddressKeyArgHandler=new AddAddressKeyArgHandler();
cl.addArgDef(addAddressKeyArgHandler.argDef);
EncryptArgHandler encryptArgHandler=new EncryptArgHandler();
cl.addArgDef(encryptArgHandler.argDef);
DecryptArgHandler decryptArgHandler=new DecryptArgHandler();
cl.addArgDef(decryptArgHandler.argDef);
RecMaxSizeArgHandler recMaxSizeArgHandler=new RecMaxSizeArgHandler();
cl.addArgDef(recMaxSizeArgHandler.argDef);
ForceImageSizeArgHandler forceImageSizeArgHandler=new ForceImageSizeArgHandler();
cl.addArgDef(forceImageSizeArgHandler.argDef);
OutBitsPerWordArgHandler outBitsPerWordArgHandler=new OutBitsPerWordArgHandler();
cl.addArgDef(outBitsPerWordArgHandler.argDef);
TemplateArgHandler templateArgHandler=new TemplateArgHandler();
cl.addArgDef(templateArgHandler.argDef);
MemScramblerArgHandler memScramblerArgHandler=new MemScramblerArgHandler();
cl.addArgDef(memScramblerArgHandler.argDef);
NonLinearityArgHandler nonLinearityArgHandler=new NonLinearityArgHandler();
cl.addArgDef(nonLinearityArgHandler.argDef);
CompressionTestArgHandler compressionTestArgHandler=new CompressionTestArgHandler();
cl.addArgDef(compressionTestArgHandler.argDef);
DirectExitArgHandler directExitArgHandler=new DirectExitArgHandler();
cl.addArgDef(directExitArgHandler.argDef);
XorArgHandler xorArgHandler=new XorArgHandler();
cl.addArgDef(xorArgHandler.argDef);
OrReductionArgHandler orReductionArgHandler=new OrReductionArgHandler();
cl.addArgDef(orReductionArgHandler.argDef);
cl.addArgDef((new SkipDataScramblingArgHandler()).argDef);
cl.addArgDef((new SkipAddrScramblingArgHandler()).argDef);
if(0==args.length){
FileNameExtensionFilter filter = new FileNameExtensionFilter("MemEnc arg files", "MemEnc");
cl.askForArgFile(filter, true, true, true);
}else
cl.addNewArgs(args);
if(cl.isEmpty()){
showHelp(cl);
System.out.println("Hit a key to exit");
System.in.read();
return;
}
System.out.println("Command line before parsing:");
System.out.println(cl.toString());
//gather and check arguments
System.out.println("Command line after parsing:");
cl.processArgs();
System.out.println(cl.toString());
if((null!=templateFile) & (0!=recMaxSize.value)) throw new ExitException("\""+templateArgHandler.mark+"\" and \""+
recMaxSizeArgHandler.mark+"\" are mutually exclusive\n"+
"Please remove one of them from command line.");
boolean doOrRed=false;
if(orRedWidth.value>0) doOrRed=true;
if((null==encrypt) && (false==nonLinearity) && (null==maskImageFile) && (false==doOrRed)) throw new ExitException("Operation not set.");
if((null==dstFile) && (null==binDstFile) && (null==verilogDstFile)&& (null==coeDstFile)) throw new ExitException("Destination file not set.");
//build header for log files
StringBuilder sb=new StringBuilder();
sb.append("Input file(s): ");
//read input files
List<ProgrammingChunk> image=new ArrayList<ProgrammingChunk>();
for(File f:files){
image.addAll(IntelHexFileReader.hexFile2ProgrammingChunks(f));
sb.append("\t");
sb.append(f.getName());
sb.append(AStringUtilities.systemNewLine);
}
if(requestedImageSize.value!=-1){
image = ProgrammingChunk.resizeImage(image,requestedImageSize.value,(byte)0);
}
if(null!=memScrambler){
sb.append("MemScrambler class: ").append(memScrambler.getClass().getName()).append(AStringUtilities.systemNewLine);
sb.append("Data key map:");
sb.append(AStringUtilities.systemNewLine);
sb.append(MemRange.dump(dataKeysMap));
sb.append("Address key map:");
sb.append(AStringUtilities.systemNewLine);
sb.append(MemRange.dump(addressKeysMap));
} else
sb.append("No MemScrambler set.").append(AStringUtilities.systemNewLine);
byte[] input = ProgrammingChunk.list2Bytes(image);
sb.append(AStringUtilities.systemNewLine);
sb.append("Input data: (").append(input.length).append(" bytes)");
sb.append(AStringUtilities.systemNewLine);
if(input.length<=0x200){
sb.append(AStringUtilities.bytesToHex(input));
sb.append(AStringUtilities.systemNewLine);
}
String logHeader=sb.toString();
boolean writeOutput=false;
//apply operation
if(null!=memScrambler){
memScrambler.setScramblingContext(encrypt, dataKeysMap, addressKeysMap, skipDataScrambling, skipAddrScrambling);
memScrambler.apply(image);
}else{
System.out.println("WARNING: "+logHeader);
}
if(null!=maskImageFile){
List<ProgrammingChunk> maskImage=IntelHexFileReader.hexFile2ProgrammingChunks(maskImageFile);
image=ProgrammingChunk.xor(image,maskImage);
writeOutput=true;
}
if(doOrRed){
byte []orRed=ProgrammingChunk.orRed(image, orRedWidth.value);
System.out.println("Or reduction result: "+AStringUtilities.bytesToHex(orRed));
}
if(compressionTest){
String nlFileName=baseDstFile.getCanonicalPath()+"_compressionTestReport.log";
File nlFile=new File(nlFileName);
PrintStream ps = new PrintStream(nlFile);
ps.append(logHeader);
CompressionTest ct=new CompressionTest(ps);
ct.compressionTest(input,image);
ps.close();
}
if(nonLinearity){
String nlFileName=baseDstFile.getCanonicalPath()+"_nonLinearityReport.log";
File nlFile=new File(nlFileName);
PrintStream ps = new PrintStream(nlFile);
ps.append(logHeader);
NonLinearity nl=new NonLinearity(ps,nlInputWidth, nlOutputWidth, nlStorageSize);
nl.computeNonLinearity(image);
ps.close();
}
if(null!=templateFile){
List<ProgrammingChunk> template=new ArrayList<ProgrammingChunk>();
template.addAll(IntelHexFileReader.hexFile2ProgrammingChunks(templateFile));
ProgrammingChunk.format(image, template);
}else{
if(0<recMaxSize.value){
ProgrammingChunk.pack(image, recMaxSize.value);
}
}
if(null!=encrypt) writeOutput=true;
if(writeOutput){
if(null!=dstFile){
//write output file
IntelHexFileWriter hexWriter = new IntelHexFileWriter();
PrintStream ps = new PrintStream(dstFile);
hexWriter.writeHexFile(ps, image);
ps.close();
}
if(null!=binDstFile){
//write output file
FileOutputStream fos = new FileOutputStream(binDstFile);
BinFileWriter.writeBinFile(fos, image);
fos.close();
}
if(null!=verilogDstFile){
//write output file
VerilogMemFileWriter.writeMemFile(verilogDstFile, image, bytesPerWord(), verilogPrependAddress.value);
}
if(null!=coeDstFile){
//write output file
XilinxCoeMemInitFileWriter.writeMemFile(coeDstFile, image, bytesPerWord());
}
}
} catch(ExitException e){
System.out.println(e.getMessage());
} catch (StopRequestFromUserException e) {
} catch (IOException ex) {
Logger.getLogger(CommandLine.class.getName()).log(Level.SEVERE, null, ex);
} catch (Throwable ex) {
Logger.getLogger(CommandLine.class.getName()).log(Level.SEVERE, null, ex);
}
if(false==directExit){
Scanner keyIn = new Scanner(System.in);
System.out.print("Press the enter key to continue");
keyIn.nextLine();
}
}
class HelpArgHandler extends SimpleArgHandler implements SelfDocumented{
final public String mark="help";
final public ArgDef argDef=new ArgDef(mark, this);
@Override
public String help() {
return mark+"\n"+
" Show this help";
}
@Override
public boolean processArg(Arg arg, CommandLine cl) {
showHelp(cl);
return true;
}
}
class DirectExitArgHandler extends SimpleArgHandler implements SelfDocumented{
final public String mark="directExit";
final public ArgDef argDef=new ArgDef(mark, this);
@Override
public String help() {
return mark+"\n"+
" Don't ask user to hit enter before exit.";
}
@Override
public boolean processArg(Arg arg, CommandLine cl) {
directExit=true;
return true;
}
}
class MemScramblerArgHandler extends SimpleArgHandler implements SelfDocumented{
static final String mark="memScrambler:";
final public ArgDef argDef=new ArgDef(mark, this);
@Override
public String help() {
return mark+"<identifier>\n"+
" Set the memory scrambler type.";
}
@Override
public boolean processArg(Arg arg, CommandLine cl) {
if(null!=memScrambler) throw new RuntimeException("Memory scrambler already set.");
String identifier=arg.getString(mark);
try {
Class theClass = arg.getPlugInClass(identifier);
memScrambler = (MemScrambler) theClass.newInstance();
} catch (InstantiationException ex) {
Logger.getLogger(MemEnc.class.getName()).log(Level.SEVERE, null, ex);
} catch (IllegalAccessException ex) {
Logger.getLogger(MemEnc.class.getName()).log(Level.SEVERE, null, ex);
} catch (MalformedURLException ex) {
Logger.getLogger(MemEnc.class.getName()).log(Level.SEVERE, null, ex);
} catch (ClassNotFoundException ex) {
Logger.getLogger(MemEnc.class.getName()).log(Level.SEVERE, null, ex);
}
return true;
}
}
MutableInteger recMaxSize=new MutableInteger(0);
class RecMaxSizeArgHandler extends IntegerNumericArgHandler implements SelfDocumented{
static final String privateMark="recMaxSize:";
final public ArgDef argDef=new ArgDef(privateMark, this);
public RecMaxSizeArgHandler(){
super(recMaxSize,privateMark);
}
@Override
public String help() {
return mark+"<size>\n"+
" Set the maximum length of records in output file.";
}
}
MutableInteger requestedImageSize=new MutableInteger(-1);
class ForceImageSizeArgHandler extends IntegerNumericArgHandler implements SelfDocumented{
static final String privateMark="forceImageSize:";
final public ArgDef argDef=new ArgDef(privateMark, this);
public ForceImageSizeArgHandler(){
super(requestedImageSize,privateMark);
}
@Override
public String help() {
return mark+"<size>\n"+
" Force the image size before processing. If padding is needed, 0 is used as padding value";
}
}
class EncryptArgHandler extends SimpleArgHandler implements SelfDocumented{
final public String mark="encrypt";
final public ArgDef argDef=new ArgDef(mark, this);
@Override
public String help() {
return mark+"\n"+
" Set operation to \"encryption\": output is the encrypted version of input image.";
}
@Override
public boolean processArg(Arg arg, CommandLine cl) {
if(null!=encrypt) throw new RuntimeException("Operation already set.");
encrypt=true;
return true;
}
}
class DecryptArgHandler extends SimpleArgHandler implements SelfDocumented{
final public String mark="decrypt";
final public ArgDef argDef=new ArgDef(mark, this);
@Override
public String help() {
return mark+"\n"+
" Set operation to \"decryption\": output is the decrypted version of input image.";
}
@Override
public boolean processArg(Arg arg, CommandLine cl) {
if(null!=encrypt) throw new RuntimeException("Operation already set.");
encrypt=false;
return true;
}
}
class SkipDataScramblingArgHandler extends SimpleArgHandler implements SelfDocumented{
static final String mark="skipDataScrambling";
final public ArgDef argDef=new ArgDef(mark, this);
@Override
public String help() {
return mark+"\n"+
" Skip data scrambling on the whole address space.";
}
@Override
public boolean processArg(Arg arg, CommandLine cl) {
skipDataScrambling=true;
return true;
}
}
class SkipAddrScramblingArgHandler extends SimpleArgHandler implements SelfDocumented{
static final String mark="skipAddrScrambling";
final public ArgDef argDef=new ArgDef(mark, this);
@Override
public String help() {
return mark+"\n"+
" Skip address scrambling on the whole address space.";
}
@Override
public boolean processArg(Arg arg, CommandLine cl) {
skipAddrScrambling=true;
return true;
}
}
class XorArgHandler extends SimpleArgHandler implements SelfDocumented{
final public String mark="xor:";
final public ArgDef argDef=new ArgDef(mark, this);
@Override
public String help() {
return mark+"<maskImage>\n"+
" Set operation to \"image xor\": output is the result of input image xor <maskImage>.\n"+
" <maskImage>: file containing the image to xor. If maskImage is omitted, a dialog box ask for it.";
}
@Override
public boolean processArg(Arg arg, CommandLine cl) {
if(null!=maskImageFile) throw new RuntimeException("maskImage file already set.");
maskImageFile=arg.getOptionalFile(mark, null, "Indicate maskImage file (intel-hex format)", INPUTFILE_PATH_PREFERENCE_KEY, false);
if(null==maskImageFile) throw new RuntimeException("Cannot set maskImage file");
return true;
}
}
class OrReductionArgHandler extends IntegerNumericArgHandler implements SelfDocumented{
static final String privateMark="orReduction:";
final public ArgDef argDef=new ArgDef(privateMark, this);
public OrReductionArgHandler(){
super(orRedWidth,privateMark);
}
@Override
public String help() {
return mark+"<widthInBytes>\n"+
" Perform \"image or reduction\": output is the result of bitwise or on all memory words.\n"+
" <widthInBytes>: width of a word, in bytes.";
}
}
class NonLinearityArgHandler extends SimpleArgHandler implements SelfDocumented{
final public String mark="nonLinearity:";
final public ArgDef argDef=new ArgDef(mark, this);
@Override
public String help() {
return mark+"<input width>, <output width>, [storage size]\n"+
" Compute non linearity of a sbox stored in memory.\n"+
" <input width>: number of bits of sbox's input"+
" <output width>: number of bits of sbox's output.\n"+
" [storage size]: output values storage alignement in bytes.If omitted, minimal value is assumed\n"+
" All must be written in decimal.";
}
@Override
public boolean processArg(Arg arg, CommandLine cl) {
if(nonLinearity) throw new RuntimeException("nonLinearity operation already requested.");
String rawParams=arg.getString(mark);
String [] params=rawParams.split(",");
if((3!=params.length) && (2!=params.length)){
throw new RuntimeException(mark+" takes 2 or 3 parameters, but "+params.length+" have been found");
}
nlInputWidth=Integer.parseInt(params[0], 10);
nlOutputWidth=Integer.parseInt(params[1], 10);
if(2==params.length){
nlStorageSize=1+((nlOutputWidth-1)/8);
} else
nlStorageSize=Integer.parseInt(params[2], 10);
nonLinearity=true;
return true;
}
}
class CompressionTestArgHandler extends SimpleArgHandler implements SelfDocumented{
final public String mark="compressionTest";
final public ArgDef argDef=new ArgDef(mark, this);
@Override
public String help() {
return mark+"\n"+
" Generate compression test report.";
}
@Override
public boolean processArg(Arg arg, CommandLine cl) {
if(compressionTest) throw new RuntimeException("compressionTest operation already requested.");
compressionTest=true;
return true;
}
}
class AddDataKeyArgHandler extends SimpleArgHandler implements SelfDocumented{
final public String mark="addDataKey:";
final public ArgDef argDef=new ArgDef(mark, this);
@Override
public String help() {
return mark+"<start address>,<last address>,<key>\n"+
" Add <key> for data encryption to process data from <start address> to <last address>.\n"+
" All must be written in hexadecimal.\n"+
" <key> must have an even number of hex digits. Space, '-' and '_' might be inserted to separate bytes\n"+
" Ex: addKey:0,7FF,ABCD12";
}
@Override
public boolean processArg(Arg arg, CommandLine cl) {
String rawParams=arg.getString(mark);
String [] params=rawParams.split(",");
if(3!=params.length){
throw new RuntimeException(mark+" takes stricly 3 parameters, but "+params.length+" have been found");
}
long start=Long.parseLong(params[0], 16);
long end=Long.parseLong(params[1], 16);
byte []key=AStringUtilities.hexToBytesRightToLeft(params[2], " -_");
dataKeysMap.add(new MemRange(start,end,key));
return true;
}
}
class AddAddressKeyArgHandler extends SimpleArgHandler implements SelfDocumented{
final public String mark="addAddressKey:";
final public ArgDef argDef=new ArgDef(mark, this);
@Override
public String help() {
return mark+"<start address>,<last address>,<key>\n"+
" Add <key> for address scrambling to process data from <start address> to <last address>.\n"+
" All must be written in hexadecimal.\n"+
" <key> must have an even number of hex digits. Space, '-' and '_' might be inserted to separate bytes\n"+
" Ex: addKey:0,7FF,ABCD12";
}
@Override
public boolean processArg(Arg arg, CommandLine cl) {
String rawParams=arg.getString(mark);
String [] params=rawParams.split(",");
if(3!=params.length){
throw new RuntimeException("addAddressKey takes stricly 3 parameters, but "+params.length+" have been found");
}
long start=Long.parseLong(params[0], 16);
long end=Long.parseLong(params[1], 16);
byte []key=AStringUtilities.hexToBytesRightToLeft(params[2], " -_");
addressKeysMap.add(new MemRange(start,end,key));
return true;
}
}
class BinOutArgHandler extends SimpleArgHandler implements SelfDocumented{
final public String mark="binOut:";
final public ArgDef argDef=new ArgDef(mark, this);
@Override
public String help() {
return mark+"[file]\n"+
" Set destination file as binary file. If file is omitted, a dialog box ask for it.";
}
@Override
public boolean processArg(Arg arg, CommandLine cl) {
if(null!=binDstFile) throw new RuntimeException("Binary destination file already set.");
binDstFile=arg.getOptionalFile(mark, null, "Indicate destination file (raw binary format)", DSTFILE_PATH_PREFERENCE_KEY, true);
if(null==binDstFile) throw new RuntimeException("Cannot set destination file");
baseDstFile=binDstFile;
return true;
}
}
class VerilogOutArgHandler extends SimpleArgHandler implements SelfDocumented{
final public String mark="verilogOut:";
final public ArgDef argDef=new ArgDef(mark, this);
@Override
public String help() {
return mark+"[file]\n"+
" Set destination file as verilog file. If file is omitted, a dialog box ask for it.";
}
@Override
public boolean processArg(Arg arg, CommandLine cl) {
if(null!=verilogDstFile) throw new RuntimeException("Verilog destination file already set.");
verilogDstFile=arg.getOptionalFile(mark, null, "Indicate destination file (mem verilog format)", DSTFILE_PATH_PREFERENCE_KEY, true);
if(null==verilogDstFile) throw new RuntimeException("Cannot set destination file");
baseDstFile=verilogDstFile;
return true;
}
}
class CoeOutArgHandler extends SimpleArgHandler implements SelfDocumented{
final public String mark="coeOut:";
final public ArgDef argDef=new ArgDef(mark, this);
@Override
public String help() {
return mark+"[file]\n"+
" Set destination file as Xilinx COE memory initialization file. If file is omitted, a dialog box ask for it.";
}
@Override
public boolean processArg(Arg arg, CommandLine cl) {
if(null!=coeDstFile) throw new RuntimeException("COE destination file already set.");
coeDstFile=arg.getOptionalFile(mark, null, "Indicate destination file (Xilinx COE memory initialization format)", DSTFILE_PATH_PREFERENCE_KEY, true);
if(null==coeDstFile) throw new RuntimeException("Cannot set destination file");
baseDstFile=coeDstFile;
return true;
}
}
MutableBoolean verilogPrependAddress=new MutableBoolean(true);
class VerilogPrependAddressArgHandler extends BooleanValueArgHandler implements SelfDocumented{
static final String privateMark="verilogPrependAddress:";
final public ArgDef argDef=new ArgDef(privateMark, this);
public VerilogPrependAddressArgHandler(){
super(verilogPrependAddress,privateMark);
}
@Override
public String help() {
return mark+"<boolean value>\n"+
" If true, verilog mem file is generated with addresses on each line";
}
}
MutableInteger outBitsPerWord=new MutableInteger(8);
int bytesPerWord(){
int out = outBitsPerWord.value/8;
if(0!=(outBitsPerWord.value%8)) out++;
return out;
}
class OutBitsPerWordArgHandler extends IntegerNumericArgHandler implements SelfDocumented{
static final String privateMark="outBitsPerWord:";
final public ArgDef argDef=new ArgDef(privateMark, this);
public OutBitsPerWordArgHandler(){
super(outBitsPerWord,privateMark);
}
@Override
public String help() {
return mark+"<size>\n"+
" Set the number of bits per word in output files with \"memory word oriented format\" such as verilog mem files.";
}
}
class HexOutArgHandler extends SimpleArgHandler implements SelfDocumented{
final public String mark="hexOut:";
final public ArgDef argDef=new ArgDef(mark, this);
@Override
public String help() {
return mark+"[file]\n"+
" Set destination file. If file is omitted, a dialog box ask for it.";
}
@Override
public boolean processArg(Arg arg, CommandLine cl) {
if(null!=dstFile) throw new RuntimeException("Destination file already set.");
dstFile=arg.getOptionalFile(mark, null, "Indicate destination file (intel-hex format)", DSTFILE_PATH_PREFERENCE_KEY, true);
if(null==dstFile) throw new RuntimeException("Cannot set destination file");
baseDstFile=dstFile;
return true;
}
}
class HexInArgHandler extends SimpleArgHandler implements SelfDocumented{
final public String mark="hexIn:";
final public ArgDef argDef=new ArgDef(mark, this);
@Override
public String help() {
return mark+"[file]\n"+
" Add an input file. It must be in intel-hex format. If file is omitted, a dialog box ask for it";
}
@Override
public boolean processArg(Arg arg, CommandLine cl) {
File toAdd=arg.getOptionalFile(mark, null, "Add an input file (intel-hex format)", INPUTFILE_PATH_PREFERENCE_KEY, false);
files.add(toAdd);
return true;
}
}
class TemplateArgHandler extends SimpleArgHandler implements SelfDocumented{
final public String mark="template:";
final public ArgDef argDef=new ArgDef(mark, this);
@Override
public String help() {
return mark+"[file]\n"+
" Set template for output file. It must be in intel-hex format. If file is omitted, a dialog box ask for it";
}
@Override
public boolean processArg(Arg arg, CommandLine cl) {
if(null!=templateFile) throw new RuntimeException("Template file already set.");
templateFile=arg.getOptionalFile(mark, null, "Add an input file (intel-hex format)", INPUTFILE_PATH_PREFERENCE_KEY, false);
if(null==templateFile) throw new RuntimeException("Cannot set template file");
return true;
}
}
}