improvements... except now arm mode set_register for r15 doesn't work right... prolly...
[goodfet] / client / GoodFETARM.py
diff --git a/client/GoodFETARM.py b/client/GoodFETARM.py
deleted file mode 100644 (file)
index a2212d3..0000000
+++ /dev/null
@@ -1,556 +0,0 @@
-#!/usr/bin/env python
-# GoodFET ARM Client Library
-# 
-#
-# Good luck with alpha / beta code.
-# Contributions and bug reports welcome.
-#
-
-
-
-raise Exception("DEPRECATED.  USE GoodFETARM7")
-
-import sys, binascii, struct, time
-import atlasutils.smartprint as asp
-from GoodFET import GoodFET
-from intelhex import IntelHex
-
-platforms = {
-    "at91sam7": {0:(0x100000, "Flash before remap, SRAM after remap"),
-                 0x100000: (0x100000, "Internal Flash"),
-                 0x200000: (0x100000, "Internal SRAM"),
-                 },
-    }
-                
-
-#Global Commands
-READ  = 0x00
-WRITE = 0x01
-PEEK  = 0x02
-POKE  = 0x03
-SETUP = 0x10
-START = 0x20
-STOP  = 0x21
-CALL  = 0x30
-EXEC  = 0x31
-NOK   = 0x7E
-OK    = 0x7F
-
-# ARM7TDMI JTAG commands
-GET_DEBUG_CTRL      = 0x80
-SET_DEBUG_CTRL      = 0x81
-GET_PC              = 0x82
-SET_PC              = 0x83
-GET_CHIP_ID         = 0x84
-GET_DEBUG_STATE     = 0x85
-GET_WATCHPOINT      = 0x86
-SET_WATCHPOINT      = 0x87
-GET_REGISTER        = 0x88
-SET_REGISTER        = 0x89
-GET_REGISTERS       = 0x8a
-SET_REGISTERS       = 0x8b
-HALTCPU             = 0x8c
-RESUMECPU           = 0x8d
-DEBUG_INSTR         = 0x8e      #
-STEP_INSTR          = 0x8f      #
-STEP_REPLACE        = 0x90      #
-PROGRAM_FLASH       = 0x95
-LOCKCHIP            = 0x96      # ??
-CHIP_ERASE          = 0x97      # can do?
-# Really ARM specific stuff
-GET_CPSR            = 0x98
-SET_CPSR            = 0x99
-GET_SPSR            = 0x9a
-SET_SPSR            = 0x9b
-SET_MODE_THUMB      = 0x9c
-SET_MODE_ARM        = 0x9d
-SET_IR              = 0x9e
-WAIT_DBG            = 0x9f
-SHIFT_DR            = 0xa0
-SETWATCH0           = 0xa1
-SETWATCH1           = 0xa2
-CHAIN0              = 0xa3
-
-
-MSB         = 0
-LSB         = 1
-NOEND       = 2
-NORETIDLE   = 4
-
-PM_usr = 0b10000
-PM_fiq = 0b10001
-PM_irq = 0b10010
-PM_svc = 0b10011
-PM_abt = 0b10111
-PM_und = 0b11011
-PM_sys = 0b11111
-proc_modes = {
-    PM_usr: ("User Processor Mode", "usr", "Normal program execution mode"),
-    PM_fiq: ("FIQ Processor Mode", "fiq", "Supports a high-speed data transfer or channel process"),
-    PM_irq: ("IRQ Processor Mode", "irq", "Used for general-purpose interrupt handling"),
-    PM_svc: ("Supervisor Processor Mode", "svc", "A protected mode for the operating system"),
-    PM_irq: ("Abort Processor Mode", "irq", "Implements virtual memory and/or memory protection"),
-    PM_und: ("Undefined Processor Mode", "und", "Supports software emulation of hardware coprocessor"),
-    PM_sys: ("System Processor Mode", "sys", "Runs privileged operating system tasks (ARMv4 and above)"),
-}
-
-PSR_bits = [ 
-    None,
-    None,
-    None,
-    None,
-    None,
-    "Thumb",
-    "nFIQ_int",
-    "nIRQ_int",
-    "nImprDataAbort_int",
-    "BIGendian",
-    None,
-    None,
-    None,
-    None,
-    None,
-    None,
-    "GE_0",
-    "GE_1",
-    "GE_2",
-    "GE_3",
-    None,
-    None,
-    None,
-    None,
-    "Jazelle",
-    None,
-    None,
-    "Q (DSP-overflow)",
-    "oVerflow",
-    "Carry",
-    "Zero",
-    "Neg",
-    ]
-
-
-
-ARM_INSTR_NOP =             0xe1a00000L
-ARM_INSTR_BX_R0 =           0xe12fff10L
-ARM_INSTR_STR_Rx_r14 =      0xe58f0000L # from atmel docs
-ARM_READ_REG =              ARM_INSTR_STR_Rx_r14
-ARM_INSTR_LDR_Rx_r14 =      0xe59f0000L # from atmel docs
-ARM_WRITE_REG =             ARM_INSTR_LDR_Rx_r14
-ARM_INSTR_LDR_R1_r0_4 =     0xe4901004L
-ARM_READ_MEM =              ARM_INSTR_LDR_R1_r0_4
-ARM_INSTR_STR_R1_r0_4 =     0xe4801004L
-ARM_WRITE_MEM =             ARM_INSTR_STR_R1_r0_4
-ARM_INSTR_MRS_R0_CPSR =     0xe10f0000L
-ARM_INSTR_MSR_cpsr_cxsf_R0 =0xe12ff000L
-ARM_INSTR_STMIA_R14_r0_rx = 0xE88E0000L      # add up to 65k to indicate which registers...
-ARM_STORE_MULTIPLE =        ARM_INSTR_STMIA_R14_r0_rx
-ARM_INSTR_SKANKREGS =       0xE88F7fffL
-ARM_INSTR_CLOBBEREGS =      0xE89F7fffL
-
-ARM_INSTR_B_PC =            0xea000000L
-ARM_INSTR_BX_PC =           0xe1200010L      # need to set r0 to the desired address
-THUMB_INSTR_STR_R0_r0 =     0x60006000L
-THUMB_INSTR_MOV_R0_PC =     0x46b846b8L
-THUMB_INSTR_BX_PC =         0x47784778L
-THUMB_INSTR_NOP =           0x1c001c00L
-ARM_REG_PC =                15
-
-ARM7TDMI_IR_EXTEST =            0x0
-ARM7TDMI_IR_SCAN_N =            0x2
-ARM7TDMI_IR_SAMPLE =            0x3
-ARM7TDMI_IR_RESTART =           0x4
-ARM7TDMI_IR_CLAMP =             0x5
-ARM7TDMI_IR_HIGHZ =             0x7
-ARM7TDMI_IR_CLAMPZ =            0x9
-ARM7TDMI_IR_INTEST =            0xC
-ARM7TDMI_IR_IDCODE =            0xE
-ARM7TDMI_IR_BYPASS =            0xF
-
-
-def PSRdecode(psrval):
-    output = [ "(%s mode)"%proc_modes[psrval&0x1f][1] ]
-    for x in xrange(5,32):
-        if psrval & (1<<x):
-            output.append(PSR_bits[x])
-    return " ".join(output)
-   
-fmt = [None, "B", "<H", None, "<L", None, None, None, "<Q"]
-def chop(val,byts):
-    s = struct.pack(fmt[byts], val)
-    return [ord(b) for b in s ]
-        
-class GoodFETARM(GoodFET):
-    """A GoodFET variant for use with ARM7TDMI microprocessor."""
-    def ARMhaltcpu(self):
-        """Halt the CPU."""
-        self.writecmd(0x13,HALTCPU,0,self.data)
-        print "CPSR: (%s) %s"%(self.ARMget_regCPSRstr())
-    halt=ARMhaltcpu
-    def ARMreleasecpu(self):
-        """Resume the CPU."""
-        self.writecmd(0x13,RESUMECPU,0,self.data)
-    def ARMsetModeArm(self, restart=0):
-        self.writecmd(0x13,SET_MODE_ARM,0,[restart])
-    def ARMsetModeThumb(self, restart=0):
-        self.writecmd(0x13,SET_MODE_THUMB,0,[restart])
-    def ARMtest(self):
-        #self.ARMreleasecpu()
-        #self.ARMhaltcpu()
-        print "Status: %s" % self.ARMstatusstr()
-        
-        #Grab ident three times, should be equal.
-        ident1=self.ARMident()
-        ident2=self.ARMident()
-        ident3=self.ARMident()
-        if(ident1!=ident2 or ident2!=ident3):
-            print "Error, repeated ident attempts unequal."
-            print "%04x, %04x, %04x" % (ident1, ident2, ident3)
-        
-        #Set and Check Registers
-        regs = [1024+x for x in range(0,15)]
-        regr = []
-        for x in range(len(regs)):
-            self.ARMset_register(x, regs[x])
-
-        for x in range(len(regs)):
-            regr.append(self.ARMget_register(x))
-        
-        for x in range(len(regs)):
-            if regs[x] != regr[x]:
-                print "Error, R%d fail: %x != %x"%(x,regs[x],regr[x])
-
-        return
-
-
-
-
-        #Single step, printing PC.
-        print "Tracing execution at startup."
-        for i in range(15):
-            pc=self.ARMgetPC()
-            byte=self.ARMpeekcodebyte(i)
-            #print "PC=%04x, %02x" % (pc, byte)
-            self.ARMstep_instr()
-        
-        print "Verifying that debugging a NOP doesn't affect the PC."
-        for i in range(1,15):
-            pc=self.ARMgetPC()
-            self.ARMdebuginstr([NOP])
-            if(pc!=self.ARMgetPC()):
-                print "ERROR: PC changed during ARMdebuginstr([NOP])!"
-        
-        print "Checking pokes to XRAM."
-        for i in range(0xf000,0xf020):
-            self.ARMpokedatabyte(i,0xde)
-            if(self.ARMpeekdatabyte(i)!=0xde):
-                print "Error in DATA at 0x%04x" % i
-        
-        #print "Status: %s." % self.ARMstatusstr()
-        #Exit debugger
-        self.stop()
-        print "Done."
-
-    def setup(self):
-        """Move the FET into the JTAG ARM application."""
-        #print "Initializing ARM."
-        self.writecmd(0x13,SETUP,0,self.data)
-    def ARMget_dbgstate(self):
-        """Read the config register of an ARM."""
-        self.writecmd(0x13,GET_DEBUG_STATE,0,self.data)
-        retval = struct.unpack("<L", self.data[:4])[0]
-        return retval
-    def ARMget_dbgctrl(self):
-        """Read the config register of an ARM."""
-        self.writecmd(0x13,GET_DEBUG_CTRL,0,self.data)
-        retval = struct.unpack("B", self.data)[0]
-        return retval
-    def ARMset_dbgctrl(self,config):
-        """Write the config register of an ARM."""
-        self.writecmd(0x13,SET_DEBUG_CTRL,1,[config&7])
-    def ARMlockchip(self):
-        """Set the flash lock bit in info mem.
-        Chip-Specific.  Not implemented"""
-        #self.writecmd(0x13, LOCKCHIP, 0, [])
-        raise Exception("Unimplemented: lockchip.  This is chip specific and must be implemented for each chip.")
-    
-
-    def ARMidentstr(self):
-        ident=self.ARMident()
-        ver     = ident >> 28
-        partno  = (ident >> 12) & 0x10
-        mfgid   = ident & 0xfff
-        return "mfg: %x\npartno: %x\nver: %x\n(%x)" % (ver, partno, mfgid, ident); 
-    def ARMident(self):
-        """Get an ARM's ID."""
-        self.writecmd(0x13,GET_CHIP_ID,0,[])
-        retval = struct.unpack("<L", "".join(self.data[0:4]))[0]
-        return retval
-    def ARMsetPC(self, val):
-        """Set an ARM's PC.  Note: real PC gets all wonky in debug mode, this changes the "saved" PC which is used when exiting debug mode"""
-        self.writecmd(0x13,SET_PC,0,chop(val,4))
-    def ARMgetPC(self):
-        """Get an ARM's PC. Note: real PC gets all wonky in debug mode, this is the "saved" PC"""
-        self.writecmd(0x13,GET_PC,0,[])
-        retval = struct.unpack("<L", "".join(self.data[0:4]))[0]
-        return retval
-    def ARMget_register(self, reg):
-        """Get an ARM's Register"""
-        self.writecmd(0x13,GET_REGISTER,1,[reg&0xff])
-        retval = struct.unpack("<L", "".join(self.data[0:4]))[0]
-        return retval
-    def ARMset_register(self, reg, val):
-        """Get an ARM's Register"""
-        self.writecmd(0x13,SET_REGISTER,8,[val&0xff, (val>>8)&0xff, (val>>16)&0xff, val>>24, reg,0,0,0])
-        #self.writecmd(0x13,SET_REGISTER,8,[reg,0,0,0, (val>>16)&0xff, val>>24, val&0xff, (val>>8)&0xff])
-        retval = struct.unpack("<L", "".join(self.data[0:4]))[0]
-        return retval
-    def ARMget_registers(self):
-        """Get ARM Registers"""
-        regs = [ self.ARMget_register(x) for x in range(15) ]
-        regs.append(self.ARMgetPC())            # make sure we snag the "static" version of PC
-        return regs
-    def ARMset_registers(self, regs, mask):
-        """Set ARM Registers"""
-        for x in xrange(15):
-          if (1<<x) & mask:
-            self.ARMset_register(x,regs.pop())
-        if (1<<15) & mask:                      # make sure we set the "static" version of PC or changes will be lost
-          self.ARMsetPC(regs.pop())
-    def ARMget_regCPSRstr(self):
-        psr = self.ARMget_regCPSR()
-        return hex(psr), PSRdecode(psr)
-    def ARMget_regCPSR(self):
-        """Get an ARM's Register"""
-        self.writecmd(0x13,GET_CPSR,0,[])
-        retval = struct.unpack("<L", "".join(self.data[0:4]))[0]
-        return retval
-    def ARMset_regCPSR(self, val):
-        """Get an ARM's Register"""
-        self.writecmd(0x13,SET_CPSR,4,[val&0xff, (val>>8)&0xff, (val>>16)&0xff, val>>24])
-    def ARMcmd(self,phrase):
-        self.writecmd(0x13,READ,len(phrase),phrase)
-        val=ord(self.data[0])
-        print "Got %02x" % val
-        return val
-    def ARMdebuginstr(self,instr,bkpt):
-        if type (instr) == int or type(instr) == long:
-            instr = struct.pack("<L", instr)
-        instr = [int("0x%x"%ord(x),16) for x in instr]
-        instr.extend([bkpt])
-        self.writecmd(0x13,DEBUG_INSTR,len(instr),instr)
-        return (self.data)
-    def ARM_nop(self, bkpt):
-        return self.ARMdebuginstr(ARM_INSTR_NOP, bkpt)
-    def ARMset_IR(self, IR, noretidle=0):
-        self.writecmd(0x13,SET_IR,2, [IR, LSB|noretidle])
-        return self.data
-    def ARMshiftDR(self, data, bits, flags):
-        self.writecmd(0x13,SHIFT_DR,8,[bits&0xff, flags&0xff, 0, 0, data&0xff,(data>>8)&0xff,(data>>16)&0xff,(data>>24)&0xff])
-        return self.data
-    def ARMwaitDBG(self, timeout=0xff):
-        self.writecmd(0x13,WAIT_DBG,2,[timeout&0xf,timeout>>8])
-        return self.data
-    def ARMrestart(self):
-        #self.ARMset_IR(ARM7TDMI_IR_BYPASS)
-        self.ARMset_IR(ARM7TDMI_IR_RESTART)
-    def ARMset_watchpoint0(self, addr, addrmask, data, datamask, ctrl, ctrlmask):
-        self.data = []
-        self.data.extend(chop(addr,4))
-        self.data.extend(chop(addrmask,4))
-        self.data.extend(chop(data,4))
-        self.data.extend(chop(datamask,4))
-        self.data.extend(chop(ctrl,4))
-        self.data.extend(chop(ctrlmask,4))
-        self.writecmd(0x13,SETWATCH0,24,self.data)
-        return self.data
-    def ARMset_watchpoint1(self, addr, addrmask, data, datamask, ctrl, ctrlmask):
-        self.data = []
-        self.data.extend(chop(addr,4))
-        self.data.extend(chop(addrmask,4))
-        self.data.extend(chop(data,4))
-        self.data.extend(chop(datamask,4))
-        self.data.extend(chop(ctrl,4))
-        self.data.extend(chop(ctrlmask,4))
-        self.writecmd(0x13,SETWATCH1,24,self.data)
-        return self.data
-    def ARMreadMem(self, adr, wrdcount):
-        retval = [] 
-        r0 = self.ARMget_register(0);        # store R0 and R1
-        r1 = self.ARMget_register(1);
-        #print >>sys.stderr,("CPSR:\t%x"%self.ARMget_regCPSR())
-        for word in range(adr, adr+(wrdcount*4), 4):
-            sys.stdin.readline()
-            self.ARMset_register(0, word);        # write address into R0
-            #time.sleep(1)
-            self.ARMset_register(1, 0xdeadbeef)
-            #time.sleep(1)
-            self.ARM_nop(0)
-            #time.sleep(1)
-            self.ARM_nop(1)
-            #time.sleep(1)
-            self.ARMdebuginstr(ARM_READ_MEM, 0); # push LDR R1, [R0], #4 into instruction pipeline  (autoincrements for consecutive reads)
-            #time.sleep(1)
-            self.ARM_nop(0)
-            #time.sleep(1)
-            self.ARMrestart()
-            #time.sleep(1)
-            self.ARMwaitDBG()
-            #time.sleep(1)
-            print hex(self.ARMget_register(1))
-
-
-            # FIXME: this may end up changing te current debug-state.  should we compare to current_dbgstate?
-            #print repr(self.data[4])
-            if (len(self.data)>4 and self.data[4] == '\x00'):
-              print >>sys.stderr,("FAILED TO READ MEMORY/RE-ENTER DEBUG MODE")
-              raise Exception("FAILED TO READ MEMORY/RE-ENTER DEBUG MODE")
-              return (-1);
-            else:
-              retval.append( self.ARMget_register(1) )  # read memory value from R1 register
-              #print >>sys.stderr,("CPSR: %x\t\tR0: %x\t\tR1: %x"%(self.ARMget_regCPSR(),self.ARMget_register(0),self.ARMget_register(1)))
-        self.ARMset_register(1, r1);       # restore R0 and R1 
-        self.ARMset_register(0, r0);
-        return retval
-
-    def ARMwriteMem(self, adr, wordarray):
-        r0 = self.ARMget_register(0);        # store R0 and R1
-        r1 = self.ARMget_register(1);
-        #print >>sys.stderr,("CPSR:\t%x"%self.ARMget_regCPSR())
-        for word in xrange(adr, adr+len(string), 4):
-            self.ARMset_register(0, word);        # write address into R0
-            self.ARM_nop(0)
-            self.ARM_nop(1)
-            self.ARMdebuginstr(ARM_WRITE_MEM, 0); # push STR R1, [R0], #4 into instruction pipeline  (autoincrements for consecutive writes)
-            self.ARM_nop(0)
-            self.ARMrestart()
-            self.ARMwaitDBG()
-            print hex(self.ARMget_register(1))
-
-
-            # FIXME: this may end up changing te current debug-state.  should we compare to current_dbgstate?
-            #print repr(self.data[4])
-            if (len(self.data)>4 and self.data[4] == '\x00'):
-              print >>sys.stderr,("FAILED TO READ MEMORY/RE-ENTER DEBUG MODE")
-              raise Exception("FAILED TO READ MEMORY/RE-ENTER DEBUG MODE")
-              return (-1);
-            else:
-              retval.append( self.ARMget_register(1) )  # read memory value from R1 register
-              #print >>sys.stderr,("CPSR: %x\t\tR0: %x\t\tR1: %x"%(self.ARMget_regCPSR(),self.ARMget_register(0),self.ARMget_register(1)))
-        self.ARMset_register(1, r1);       # restore R0 and R1 
-        self.ARMset_register(0, r0);
-        return retval
-
-    def ARMpeekcodewords(self,adr,words):
-        """Read the contents of code memory at an address."""
-        self.data=[adr&0xff, (adr>>8)&0xff, (adr>>16)&0xff, (adr>>24)&0xff, words&0xff, (words>>8)&0xff, (words>>16)&0xff, (words>>24)&0xff ]
-        self.writecmd(0x13,READ_CODE_MEMORY,8,self.data)
-        retval = []
-        retval.append(self.serialport.read(words*4))
-        #retval = struct.unpack("<L", "".join(self.data[0:4]))[0]
-        return "".join(retval)
-    def ARMpeekdatabyte(self,adr):
-        """Read the contents of data memory at an address."""
-        self.data=[ adr&0xff, (adr>>8)&0xff, (adr>>16)&0xff, (adr>>24)&0xff ]
-        self.writecmd(0x13, PEEK, 4, self.data)
-        #retval.append(self.serialport.read(words*4))
-        retval = struct.unpack("<L", "".join(self.data[0:4]))[0]
-        return retval
-    def ARMpokedatabyte(self,adr,val):
-        """Write a byte to data memory."""
-        self.data=[adr&0xff, (adr>>8)&0xff, (adr>>16)&0xff, (adr>>24)&0xff, val&0xff, (val>>8)&0xff, (val>>16)&0xff, (val>>24)&0xff ]
-        self.writecmd(0x13, POKE, 8, self.data)
-        retval = struct.unpack("<L", "".join(self.data[0:4]))[0]
-        return retval
-    #def ARMchiperase(self):
-    #    """Erase all of the target's memory."""
-    #    self.writecmd(0x13,CHIP_ERASE,0,[])
-    def ARMstatus(self):
-        """Check the status."""
-        self.writecmd(0x13,GET_DEBUG_STATE,0,[])
-        return ord(self.data[0])
-    ARMstatusbits={
-                  0x10 : "TBIT",
-                  0x08 : "cgenL",
-                  0x04 : "Interrupts Enabled (or not?)",
-                  0x02 : "DBGRQ",
-                  0x01 : "DGBACK"
-                  }
-    ARMctrlbits={
-                  0x04 : "disable interrupts",
-                  0x02 : "force dbgrq",
-                  0x01 : "force dbgack"
-                  }
-                  
-    def ARMstatusstr(self):
-        """Check the status as a string."""
-        status=self.ARMstatus()
-        str=""
-        i=1
-        while i<0x100:
-            if(status&i):
-                str="%s %s" %(self.ARMstatusbits[i],str)
-            i*=2
-        return str
-    def ARMchain0(self, address, bits, data):
-        bulk = chop(address,4)
-        bulk.extend(chop(bits,8))
-        bulk.extend(chop(data,4))
-        print (repr(bulk))
-        self.writecmd(0x13,CHAIN0,16,bulk)
-        d1,b1,a1 = struct.unpack("<LQL",self.data)
-        return (a1,b1,d1)
-    def start(self):
-        """Start debugging."""
-        self.writecmd(0x13,START,0,self.data)
-        ident=self.ARMidentstr()
-        print "Target identifies as %s." % ident
-        print "Debug Status: %s." % self.ARMstatusstr()
-        #print "System State: %x." % self.ARMget_regCPSRstr()
-        #self.ARMreleasecpu()
-        #self.ARMhaltcpu()
-        
-    def stop(self):
-        """Stop debugging."""
-        self.writecmd(0x13,STOP,0,self.data)
-    #def ARMstep_instr(self):
-    #    """Step one instruction."""
-    #    self.writecmd(0x13,STEP_INSTR,0,self.data)
-    #def ARMflashpage(self,adr):
-    #    """Flash 2kB a page of flash from 0xF000 in XDATA"""
-    #    data=[adr&0xFF,
-    #          (adr>>8)&0xFF,
-    #          (adr>>16)&0xFF,
-    #          (adr>>24)&0xFF]
-    #    print "Flashing buffer to 0x%06x" % adr
-    #    self.writecmd(0x13,MASS_FLASH_PAGE,4,data)
-
-    def writecmd(self, app, verb, count=0, data=[]):
-        """Write a command and some data to the GoodFET."""
-        self.serialport.write(chr(app))
-        self.serialport.write(chr(verb))
-        count = len(data)
-        #if data!=None:
-        #    count=len(data); #Initial count ignored.
-
-        #print "TX %02x %02x %04x" % (app,verb,count)
-
-        #little endian 16-bit length
-        self.serialport.write(chr(count&0xFF))
-        self.serialport.write(chr(count>>8))
-
-        #print "count=%02x, len(data)=%04x" % (count,len(data))
-
-        if count!=0:
-            if(isinstance(data,list)):
-                for i in range(0,count):
-                    #print "Converting %02x at %i" % (data[i],i)
-                    data[i]=chr(data[i])
-            #print type(data)
-            outstr=''.join(data)
-            self.serialport.write(outstr)
-        if not self.besilent:
-            self.readcmd()
-
-
-