Beispiel #1
0
    def __init__(self):
        addr = toAddr('levent_table')
        if addr is None:
            raise ValueError('levent_table not found, check stubs or run ImportCHDKStubs.py')

        self.list=[]
        self.by_name = {}
        self.by_id = {}
        while True:
            evdef = get_levent_def_at(addr)
            if evdef is None:
                break

            self.list.append(evdef)

            if evdef['id'] not in self.by_id:
                self.by_id[evdef['id']] = evdef
            else:
                warn("dupe event id %x"%(evdef['id']))

            if evdef['name'] != '':
                if evdef['name'] not in self.by_name:
                    self.by_name[evdef['name']] = evdef
                else:
                    warn("dupe event name %s"%(evdef['name']))

            addr = addr.add(12)
Beispiel #2
0
    def create_bytemap(self, mbdef):
        addr = toAddr(mbdef['start'])
        src_addr = toAddr(mbdef['src'])
        mb_src = getMemoryBlock(src_addr)
        if not mb_src:
            warn("mblock %s bytemap no source block found" % (mbdef['name']))
            return

        infomsg(
            0, "Create bytemap mblock %s 0x%s 0x%x (%d) from %s %s\n" %
            (mbdef['name'], addr, mbdef['size'], mbdef['size'],
             mb_src.getName(), src_addr))
        if g_options['pretend']:
            return

        mem = getCurrentProgram().getMemory()
        # API changed in 9.2, added "overlay" bool
        if ghidra.framework.ApplicationVersion(getGhidraVersion(
        )) >= ghidra.framework.ApplicationVersion('9.2'):
            mem.createByteMappedBlock(mbdef['name'], addr, src_addr,
                                      mbdef['size'], False)
        else:
            mem.createByteMappedBlock(mbdef['name'], addr, src_addr,
                                      mbdef['size'])
        mb_new = getMemoryBlock(addr)
        self.set_attrs(mbdef, mb_new)
Beispiel #3
0
def do_after_pop_list(l):
    for v in l:
        # disassemble directly to force tmode, allow checking invalid
        idesc = get_insn_desc(v[0], disassemble=True, dis_tmode=v[2])
        r = idesc.is_likely_after_pop()
        if r != v[1]:
            warn('after_pop fail %s %s != %s %s' % (v[0], r, v[1], idesc.insn))
Beispiel #4
0
    def merge_blocks(self):
        '''merge adjacent blocks to reduce CHDK core data'''
        blocks = []
        pb = None
        for b in sorted(self.blocks, key=lambda b: b['offset']):
            if pb:
                infomsg(
                    2, '%s %s %x\n' % (pb['name'], b['name'], b['offset'] -
                                       (pb['offset'] + pb['size'])))
                pb_end = pb['offset'] + pb['size']
                # should be handled correctly, but may indicate incorrect block detection
                if pb_end > b['offset']:
                    warn('overlapping blocks %s %s\n' %
                         (pb['name'], b['name']))

                # allow a modest fudge, assuming Canon wouldn't put a varying chunk in a small space
                if b['offset'] <= pb['offset'] + pb['size'] + 32:
                    nb = pb
                    nb['name'] += ', ' + b['name']
                    nb['size'] += b['size'] + b['offset'] - (pb['offset'] +
                                                             pb['size'])
                    pb = nb
                    continue
            pb = b
            blocks.append(b)

        self.blocks = blocks
Beispiel #5
0
def init_levent_table():
    addr = toAddr('levent_table')
    if addr is None:
        raise ValueError('levent_table not found, check stubs or run ImportCHDKStubs.py')

    cnt = 0
    while True:
        try:
            pname = get_valid_pointer_at(addr)
            if pname is None or getInt(addr.add(4)) == -1:
                infomsg(0,'break\n')
                break

            clearListing(addr, addr.add(11))

            b = getByte(pname)
            # if it looks like a string
            if is_print_char(b):
                # if preceding is null, and address isn't already inside data, make string
                if getByte(pname.add(-1)) == 0 and getDataContaining(pname) == None:
                    createAsciiString(pname)

            createData(addr, Pointer32DataType())

            createDwords(addr.add(4),2)
            addr = addr.add(12)
            cnt += 1

        except(ghidra.program.model.mem.MemoryAccessException):
            warn("Memory access exception at %s"%(addr))
            break

    infomsg(0,'levent_table %s %d entries\n'%(toAddr('levent_table'),cnt))
Beispiel #6
0
def list_mzrm_create_calls():

    filename = str(askFile("mzrm id list", "select"))

    mzrmlist = MzrmMsgList(filename)

    cd = MzrmCallDescriber(mzrmlist)

    instr = str(askString("MZRM Messages", "Names, numbers or *")).upper()
    mzrm_ids = []
    do_all = False

    for s in re.split('[ ,]+', instr):
        if s == '*':
            do_all = True
        elif re.match('0x[0-9a-f]+$', s, re.I):
            mzrm_ids.append(int(s, 16))
        elif re.match('[0-9]+$', s):
            mzrm_ids.append(int(s, 10))
        else:
            mzrm_msg = mzrmlist.by_name.get(s)
            if mzrm_msg is None:
                # iterate over list for case insensitive compare
                for mzrm_id in mzrmlist.by_id:
                    if mzrmlist.by_id[mzrm_id].name.lower() == s.lower():
                        mzrm_msg = mzrmlist.by_id[mzrm_id]
                        break

            if mzrm_msg is None:
                warn('ignoring unknown mesasge id %s' % (s))
            else:
                mzrm_ids.append(mzrm_msg.mid)

    if len(mzrm_ids) == 0 and not do_all:
        warn('no valid IDs specified, exiting')
        return

    infomsg(0, "Searching for")
    msg = []
    if do_all:
        msg.append('all known')
    for mzrm_id in mzrm_ids:
        if mzrm_id in mzrmlist.by_id and not mzrmlist.by_id[mzrm_id].unk:
            msg.append("%s (%d)" % (mzrmlist.by_id[mzrm_id].name, mzrm_id))
        else:
            msg.append("%d" % (mzrm_id))

    infomsg(0, " %s\n" % (', '.join(msg)))

    for desc in cd.describe_all_calls():
        mzrm_id = desc.args[2].val
        if (do_all and mzrmlist.by_id.get(mzrm_id)) or mzrm_id in mzrm_ids:
            infomsg(
                0, '%s %s(%s,%s,%s,%s)\n' %
                (desc.addr, desc.fname, desc.args[0].desc, desc.args[1].desc,
                 desc.args[2].desc, desc.args[3].desc))
Beispiel #7
0
def process_thumb_notdis_label(addr, t_addr):
    # no instruction, look for possible code
    for ref in getReferencesTo(t_addr):
        idesc = get_insn_desc(ref.getFromAddress())
        if idesc is None:
            continue
        # tbb instructions create weird refs
        # also don't want anything ref'd by lrdb
        # mvn almost always constants that look like addresses
        # mov could be suspect, but also valid since ghidra tracks load + mov
        mne = idesc.get_mne()
        if mne == 'tbb' or mne == 'tbh' or mne == 'ldrb' or mne == 'mvn':
            # infomsg(0,"%s skip ref %s\n"%(addr,mne))
            return False

    if not is_likely_func_start(
            addr, require_push=False, disassemble=True, tmode=True):
        return False

    # infomsg(0,"%s dis thumb\n"%(addr))
    bad_data = getDataAt(t_addr)
    if bad_data:
        if g_options['verbose']:
            infomsg(0, '%s remove data %s\n' % (t_addr, bad_data))
        if not g_options['pretend']:
            removeData(bad_data)
    else:
        # check for data containing
        bad_data = getDataContaining(addr)
        # if it's also unaligned, assume bad
        # could check for other signs of validity, but already have valid func start
        if bad_data and (bad_data.getAddress().getOffset() & 1 == 1):
            if g_options['verbose']:
                infomsg(0,
                        '%s remove containing data %s\n' % (t_addr, bad_data))
            if not g_options['pretend']:
                removeData(bad_data)

    # if existing function without disassembled code, remove and try to recreate
    old_fn = getFunctionAt(addr)
    if old_fn:
        # infomsg(0,'%s remove func\n'%(addr))
        if not g_options['pretend']:
            removeFunction(old_fn)

    if not g_options['pretend']:
        # set thumb since this case is only used when address has thumb bit set
        set_tmode_reg_at(addr, 1)
        if not disassemble(addr):
            warn("%s dis fail" % (addr))
            return False

    if g_options['verbose']:
        infomsg(0, '%s thumb data dis func\n' % (addr))
    return do_make_func(addr)
Beispiel #8
0
    def add_block(self, blk):
        b = blk.copy()
        if b['offset'] >= self.filesize:
            warn("block %s start outside file, ignored" % (b['name']))
            b['size'] = 0

        elif self.filesize - b['offset'] < b['size']:
            warn("block %s end outside file, truncated" % (b['name']))
            b['size'] = self.filesize - b['offset']

        self.total_size += b['size']
        self.blocks.append(b)
Beispiel #9
0
def list_levent_calls():
    cd = LeventCallDescriber()

    instr = str(askString("Event","Names, numbers or *")).upper()
    event_ids = []
    do_all = False

    for s in re.split('[ ,]+',instr):
        if s == '*':
            do_all = True
        elif re.match('0x[0-9a-f]+$',s,re.I):
            event_ids.append(int(s,16))
        elif re.match('[0-9]+$',s):
            event_ids.append(int(s,10))
        else:
            event_id = cd.ld.by_name.get(s)
            if event_id is None:
                # iterate over list for case insensitive compare
                for evdef in cd.ld.list:
                    if evdef['name'].lower() == s.lower():
                        event_id = evdef['id']
                        break

            if event_id is None:
                warn('ignoring unknown event id %s'%(s))
            else:
                event_ids.append(event_id)

    if len(event_ids) == 0 and not do_all:
        warn('no valid IDs specified, exiting')
        return

    infomsg(0,"Searching for")
    msg = []
    if do_all:
        msg.append('all known')
    for event_id in event_ids:
        if event_id in cd.ld.by_id and cd.ld.by_id[event_id]['name'] !='':
            msg.append("%s (%d)"%(cd.ld.by_id[event_id]['name'],event_id))
        else:
            msg.append("%d"%(event_id))

    infomsg(0," %s\n"%(', '.join(msg)))

    for desc in cd.describe_all_calls():
        event_id = desc.args[0].val
        if (do_all and cd.ld.by_id.get(event_id)) or event_id in event_ids:
            infomsg(0,'%s %s(%s'%(desc.addr,desc.fname,desc.args[0].desc))
            if len(desc.args) == 2:
                infomsg(0,', %s'%(desc.args[1].desc))
            infomsg(0,')\n')
Beispiel #10
0
def list_prop_calls():
    filename = str(askFile("platform_camera.h or propsetN.h", "select"))
    instr = str(askString("Propcases", "Names, numbers or *")).upper()
    pd = PropsetData(filename)
    prop_ids = []
    do_all = False

    for s in re.split('[ ,]+', instr):
        if s == '*':
            do_all = True
        elif re.match('0x[0-9a-f]+$', s, re.I):
            prop_ids.append(int(s, 16))
        elif re.match('[0-9]+$', s):
            prop_ids.append(int(s, 10))
        else:
            if re.match('^PROPCASE_', s):
                prop_name = s
            else:
                prop_name = 'PROPCASE_' + s
            prop_id = pd.by_name.get(prop_name)
            if prop_id is None:
                warn('ignoring unknown propcase id %s' % (prop_name))
            else:
                prop_ids.append(prop_id)

    if len(prop_ids) == 0 and not do_all:
        warn('no valid IDs specified, exiting')
        return

    infomsg(0, "Searching for")
    msg = []
    if do_all:
        msg.append('all known')
    for prop_id in prop_ids:
        if prop_id in pd.by_id:
            msg.append("%s (%d)" % (pd.by_id[prop_id], prop_id))
        else:
            msg.append("%d" % (prop_id))

    infomsg(0, " %s from propset %d\n" % (', '.join(msg), pd.propset))

    cd = PropCallDescriber(filename)
    for desc in cd.describe_all_calls():
        prop_id = desc.args[0].val
        if (do_all and pd.by_id.get(prop_id)) or prop_id in prop_ids:
            infomsg(
                0, '%s %s(%s,%s,%s)\n' %
                (desc.addr, desc.fname, desc.args[0].desc, desc.args[1].desc,
                 desc.args[2].desc))
Beispiel #11
0
def set_tmode_reg_at(address, tmode):
    """attempt to set thumb mode register at address, true if register set"""
    # for thumb "register" value, will be None if not a thumb capable processor
    progCtx = getCurrentProgram().getProgramContext()
    tmodeReg = progCtx.getRegister("TMode")
    try:
        if tmode == 1:
            if tmodeReg:
                progCtx.setValue(tmodeReg, address, address, BigInteger("1"))
            else:
                warn("Thumb bit set without TMode register %s" % (address))
        else:
            progCtx.setValue(tmodeReg, address, address, BigInteger("0"))
        return True
    except ghidra.program.model.listing.ContextChangeException:
        warn("Set tmode failed at %s" % (address))
        return False
Beispiel #12
0
    def create_split(self, mbdef):
        addr = toAddr(mbdef['start'])
        mb_src = getMemoryBlock(addr)
        if not mb_src:
            warn("mblock %s split no source block found" % (mbdef['name']))
            return

        infomsg(
            0, "Create split mblock %s 0x%s from %s\n" %
            (mbdef['name'], addr, mb_src.getName()))
        if g_options['pretend']:
            return

        mem = getCurrentProgram().getMemory()
        mem.split(mb_src, addr)
        mb_new = getMemoryBlock(addr)
        mb_new.setName(mbdef['name'])
        self.set_attrs(mbdef, mb_new)
Beispiel #13
0
def do_make_func(addr):
    infomsg(0,'make func %s\n'%(addr));
    fc = getFunctionContaining(addr)
    f_addr = None
    if fc:
        infomsg(0,'%s already part of function %s\n'%(addr, fc.getName()))
        fb = fc.getBody()
        # check if containing function is non-contiguous (often, but not always incorrect)
        if fb.getNumAddressRanges() > 1:
            r = fb.getRangeContaining(addr)
            # if our func is start of non-contiguous func, remove it
            if r.getMinAddress() == addr:
                infomsg(0,'remove %s from %s %s\n'%(addr,fc.getName(),fc.getSymbol().address))
                if not g_options['pretend']:
                    s = fc.getSymbol()
                    if s.getSource() == SourceType.ANALYSIS or s.getSource() == SourceType.DEFAULT:
                        f_addr = fc.getSymbol().address
                        removeFunction(fc)
                    else:
                        infomsg(0,'not removing non-default source function %s\n'%(fc.getName()))
                    # removing from fc body doesn't seem reliable, works for some?
                    # fb.delete(r)
                    # fc.setBody(AddressSet(fb))
                    # analyzeChanges(currentProgram)


    if g_options['pretend']:
        return True

    f = createFunction(addr,None)
    if f_addr:
        fr = createFunction(f_addr,None)
        if fr:
            infomsg(0,'recreated %s at %s\n'%(fr.getName(),f_addr))
        else:
            infomsg(0,'failed to re-create function at %s\n'%(f_addr))

    if f:
        return True
    else:
        warn('create function failed %s'%(addr))
        return False
def process_dump(dump_name,out_dir,stubs_data):
    if not os.path.isfile(dump_name):
        warn("missing %s"%(dump_name))
        return

    dumper = BlobDumper(dump_name)
    if dumper.filesize == 0:
        warn("zero size %s"%(dump_name))
        return

    dumper.process_stubs(stubs_data)

    with open(dump_name,'rb') as fh:
        for b in dumper.blocks:
            oname = os.path.join(out_dir,b['name']+'.bin')
            fh.seek(b['offset'])
            data = fh.read(b['size'])
            infomsg(0,'Write %s 0x%08x %s\n'%(oname,b['start_adr'],b['size']))
            with open(oname,'wb') as ofh:
                ofh.write(data)
Beispiel #15
0
def load_options(secname, cfgfile, options_spec, options):
    # initialize with default values
    for ospec in options_spec:
        options[ospec['name']] = ospec['default']

    if not os.path.isfile(cfgfile):
        infomsg(0, 'Config not found %s\n' % (cfgfile))
        return True

    missing = False
    # lets caller bypass
    if options['skip_load_config']:
        infomsg(0, 'Skip load config %s\n' % (cfgfile))
    else:
        config = ConfigParser.ConfigParser()
        infomsg(0, 'Load config %s\n' % (cfgfile))
        config.read(cfgfile)
        if config.has_section(secname):
            for ospec in options_spec:
                k = ospec['name']
                if not config.has_option(secname, k):
                    missing = True
                    continue

                vt = ospec['type']
                if vt == 'bool':
                    options[k] = config.getboolean(secname, k)
                elif vt == 'int':
                    options[k] = config.getint(secname, k)
                elif vt == 'enum':
                    cv = config.get(secname, k)
                    if cv in ospec['vals']:
                        options[k] = cv
                    else:
                        warn("unexpected cfg option %s %s" % (k, cv))
                else:
                    warn("unexpected option desc %s" % (k))

        else:
            missing = True
    return missing
Beispiel #16
0
def write_options(secname, cfgfile, options_spec, options):
    # lets caller bypass
    if options['skip_create_config']:
        infomsg(0, "Skip writing config file %s\n" % (cfgfile))
        return

    infomsg(0, "Writing config file %s\n" % (cfgfile))
    try:
        fh = open(cfgfile, "w")
        fh.write('[' + secname + ']\n')
        for ospec in options_spec:
            k = ospec['name']
            fh.write('# {} {} default={}\n'.format(k, ospec['type'],
                                                   ospec['default']))
            fh.write(ospec['desc'])
            # this is g_options, to allow merging. Should always have been initialized from defaults, at least
            fh.write('{}={}\n\n'.format(k, options[k]))
        fh.close()

    except IOError:
        warn('saving default cfg failed')
Beispiel #17
0
def get_pinsn_at(address, thumb=False):
    """
    attempt to dissemble adr, return PseudoInstruction or None
    for pre-analysis without affecting program

    """
    # NOTE in modules used from interpreter window, using the currentProgram
    # variable fails on tab switches (currentProgram is set at import time)
    cp = getCurrentProgram()
    mbi = MemoryBufferImpl(cp.getMemory(), address)
    # API changed in 9.2
    if ghidra.framework.ApplicationVersion(
            getGhidraVersion()) >= ghidra.framework.ApplicationVersion('9.2'):
        pci = ProcessorContextImpl(cp.getLanguage())
    else:
        pci = ProcessorContextImpl(cp.getProgramContext().getRegisters())

    treg = pci.getRegister('TMode')

    # don't try to set thumb reg if firmware not loaded as t
    if treg:
        if thumb:
            pci.setValue(pci.getRegister('TMode'), BigInteger("1"))
        else:
            pci.setValue(pci.getRegister('TMode'), BigInteger("0"))
    elif thumb:
        warn("ignoring Thumb set on non-t processor")

    try:
        ip = cp.getLanguage().parse(mbi, pci, False)
        pi = PseudoInstruction(address, ip, mbi, pci)
        return pi
    except (ghidra.program.model.lang.UnknownInstructionException,
            ghidra.program.model.lang.InsufficientBytesException,
            ghidra.program.model.address.AddressOverflowException):
        return None
Beispiel #18
0
def process_dump(sub, dump_name, stubs_data, custom_blocks=None):
    if not os.path.isfile(dump_name):
        warn("missing %s" % (dump_name))
        return

    csums = ChecksumInfo(dump_name)
    if csums.filesize == 0:
        warn("zero size %s" % (dump_name))
        return

    if custom_blocks:
        csums.process_custom(stubs_data, custom_blocks)
    else:
        csums.process_stubs(stubs_data)

    canon_sub = (sub[0] + '.' + sub[1:]).upper()

    # most cams version starts with GM, a few early ones don't
    # assumes all firmware of a given model either do or don't
    if stubs_data.stubs_entry_misc['fw_ver_info']['verstr'][0:2] == 'GM':
        canon_sub = 'GM' + canon_sub

    # sanity check that our inferred firmware version appears in the dump at the expected place
    ver_offset = stubs_data.stubs_entry_misc['fw_ver_info'][
        'verstr_adr'] - stubs_data.stubs_entry_misc['ar_rom']['start_adr']
    if ver_offset + len(canon_sub) <= csums.filesize:
        with open(dump_name, 'rb') as fh:
            fh.seek(ver_offset)
            dump_sub = fh.read(len(canon_sub))
            if bytes(canon_sub, 'utf8') != dump_sub:
                warn("Version string %s does not match dump %s" %
                     (canon_sub, dump_sub))
                return

    else:
        warn("Version string outside dump, not verified")

    return {
        'sub': sub,
        'canon_sub': canon_sub,
        'csums': csums,
    }
Beispiel #19
0
def list_calls_main():

    funcstr = str(askString("Function", "Name or address"))
    s = getSymbol(funcstr, None)
    if s:
        if s.getSymbolType() != SymbolType.FUNCTION:
            warn('symbol %s is not a function, exiting' % (s))
            return
        addr = s.getAddress()
    else:
        addr = toAddr(funcstr)
        if not addr:
            warn('%s could not be converted to address, exiting' % (funcstr))
            return

    func = getFunctionAt(addr)
    if not func:
        warn('no function at %s, exiting' % (addr))
        return

    argstr = str(askString("Arguments 0-3", "numbers or - to ignore")).upper()

    n = 0
    matches = []
    regs = {}
    msg = []
    match_arg_count = 0
    for s in re.split('[ ,]+', argstr):
        if n > 3:
            warn('too many arguments, exiting' % (addr))
            return

        if s == '-':
            match_val = None
        elif re.match('0x[0-9a-f]+$', s, re.I):
            match_val = int(s, 16)
        elif re.match('[0-9]+$', s):
            match_val = int(s, 10)
        else:
            warn('did not understand %s, exiting' % (s))
            return

        regs['r%d' % (n)] = {'type': 'int'}
        matches.append(match_val)
        if match_val is not None:
            match_arg_count += 1
            msg.append('0x%x' % (match_val))
        else:
            msg.append('-')

        n += 1

    if len(regs) == 0:
        warn('no arguments, exiting' % (s))

    msg_str = ', '.join(msg)
    infomsg(0, "Searching for %s(%s)\n" % (func.getName(), msg_str))

    funcdesc = {func.getName(): regs}

    cd = CallDescriber(funcdesc)

    for desc in cd.describe_all_calls():
        match_count = 0
        for i, v in enumerate(matches):
            if v is None:
                continue

            if v == desc.args[i].val:
                match_count += 1

        if match_count == match_arg_count:
            infomsg(0, '%s %s(%s)\n' % (desc.addr, desc.fname, msg_str))
Beispiel #20
0
def do_likely_tail_call_list(l):
    for v in l:
        addr = toAddr(v[0])
        r = is_likely_tail_call(addr)
        if r != v[1]:
            warn('tail_call fail %s %s != %s' % (addr, r, v[1]))
Beispiel #21
0
def init_chdk_mem_map_main():
    init_options()

    stubs_data = StubsData(warnfunc=warn, infofunc=infomsg)

    # whatever askDirectory returns isn't actually string
    sub_dir = str(askDirectory("CHDK platform sub", "select"))

    filepath = os.path.join(sub_dir, 'stubs_entry.S')
    if not os.path.isfile(filepath):
        infomsg(0, 'No stubs_entry.S, trying stubs_entry.S.err\n')
        filepath = os.path.join(sub_dir, 'stubs_entry.S.err')
        if not os.path.isfile(filepath):
            warn('No stubs_entry files found')
            return

    stubs_data.load_stubs_s(filepath, process_comments=True)

    stubs_data.guess_platform_vals()

    smisc = stubs_data.stubs_entry_misc

    if not 'ar_rom' in smisc:
        warn('No ROM region identified, giving up')
        return

    if not 'main_fw_code_end' in smisc:
        warn('Main firmware code end not identified, giving up')
        return

    if len(getMemoryBlocks()) > 1:
        warn('Program already has multiple memory blocks, giving up')

    mb_rom = getMemoryBlocks()[0]

    if mb_rom.getStart() != toAddr(smisc['ar_rom']['start_adr']):
        warn('Memory block start does not match ROM, giving up')
        return

    if not mb_rom.isInitialized():
        warn('ROM block not initialized, giving up')
        return

    if mb_rom.getEnd() <= toAddr(smisc['main_fw_code_end']):
        warn(
            'Already initialized? ROM block end <= main fw code end, giving up'
        )
        return

    mbops.add_split('ROMDATA', smisc['main_fw_code_end'] + 1, w=False, x=False)

    make_romstarter_mblock(smisc)

    # if main firmware doesn't start at rom start, split
    if 'main_fw_start' in smisc and smisc['main_fw_start'] > smisc['ar_rom'][
            'start_adr']:
        mbops.add_split('ROMCODE', smisc['main_fw_start'], w=False, x=True)

    # ignored if not present
    ar_ramcode = smisc.get('ar_ramcode')
    ar_btcmcode = smisc.get('ar_btcmcode')
    ar_ramdata = smisc.get('ar_ramdata')
    ar_evec = smisc.get('ar_evec')
    ar_atcm = smisc.get('ar_atcm')

    mbops.add_stubs_ar(ar_ramdata, 'RAMDATA')
    mbops.add_stubs_ar(ar_ramcode, 'RAMCODE', x=True)
    mbops.add_stubs_ar(ar_btcmcode, 'BTCMCODE', x=True)
    mbops.add_stubs_ar(smisc.get('ar_itcm'), 'ITCM')
    mbops.add_stubs_ar(smisc.get('ar_uncached'), 'UNCACHED')
    mbops.add_stubs_ar(smisc.get('ar_dtcm'), 'DTCM')
    mbops.add_stubs_ar(smisc.get('ar_mmio'), 'MMIO', v=True)
    mbops.add_stubs_ar(smisc.get('ar_mmio_0xd'), 'MMIO', v=True)
    mbops.add_stubs_ar(smisc.get('ar_mmio_0xc1'), 'MMIO', v=True)
    mbops.add_stubs_ar(smisc.get('ar_mmio_0xc8'), 'MMIO', v=True)

    if smisc['digic'] >= 60:
        # RAM between ATCM and copied data
        mbops.add_uninit('RAM', 0x4000, 0x4000)
        # detected exception vector at address 0, add as initialized
        if ar_evec and ar_evec['start_adr'] == 0:
            mbops.add_stubs_ar(smisc.get('ar_evec'), 'EVEC')
            if ar_atcm and ar_atcm['start_adr'] == 0:
                mbops.add_uninit('ATCM',
                                 ar_evec['last_adr'] + 1,
                                 last_adr=ar_atcm['last_adr'])
            else:
                mbops.add_stubs_ar(smisc.get('ar_atcm'), 'ATCM')
        else:
            mbops.add_stubs_ar(smisc.get('ar_atcm'), 'ATCM')
    else:
        # RAM between ITCM and copied data
        mbops.add_uninit('RAM', 0x1000, 0x900)

    if ar_ramcode:
        # RAM between ram data and code (assumes code after data!)
        mbops.add_uninit('RAM',
                         ar_ramdata['last_adr'] + 1,
                         last_adr=ar_ramcode['start_adr'] - 1)
        # RAM from end of code to end of RAM
        mbops.add_uninit('RAM',
                         ar_ramcode['last_adr'] + 1,
                         last_adr=smisc['max_ram_addr'])
    else:
        # RAM from end of ram data to end of RAM
        mbops.add_uninit('RAM',
                         ar_ramdata['last_adr'] + 1,
                         last_adr=smisc['max_ram_addr'])

    if smisc['digic'] == 60:
        if ar_btcmcode and ar_btcmcode['start_adr'] == 0xbfe10800:
            # 0x800 before code
            mbops.add_uninit('BTCM', 0xbfe10000, 0x800)
            # from code end to 64k
            mbops.add_uninit('BTCM',
                             ar_btcmcode['last_adr'] + 1,
                             last_adr=0xbfe20000 - 1)
    elif smisc['digic'] == 70:
        # per https://chdk.setepontos.com/index.php?topic=11316.msg142197#msg142197
        if ar_btcmcode and ar_btcmcode['start_adr'] == 0xdffc4900:
            # 0x4900 before code. TODO this is actually initialized, could create mapped
            mbops.add_uninit('BTCM', 0xdffc0000, 0x4900)
            # from code end to 256k
            mbops.add_uninit('BTCM',
                             ar_btcmcode['last_adr'] + 1,
                             last_adr=0xdfffffff)

    if g_options['include_zico']:
        for ardef in smisc['zico_blobs']:
            mbops.add_stubs_ar(ardef, 'ZICO')

    # set whole ROM read-only before splitting
    if not g_options['pretend']:
        mb_rom.setWrite(False)

    mbops.apply_ops()
Beispiel #22
0
def do_likely_func_start_list(l):
    for v in l:
        addr = toAddr(v[0])
        r = is_likely_func_start(addr)
        if r != v[1]:
            warn('func_start fail %s %s != %s' % (addr, r, v[1]))