# Disassembling the firmware of the Siemens (Infeneon) C167CS-LM microcontroller

**URL:** <https://community.hex-rays.com/t/disassembling-the-firmware-of-the-siemens-infeneon-c167cs-lm-microcontroller/701>\
**Category:** IDA General\
**Created:** [April 3, 2026, 8:35am UTC](https://community.hex-rays.com/t/disassembling-the-firmware-of-the-siemens-infeneon-c167cs-lm-microcontroller/701 "2026-04-03T08:35:13Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![nixlinch](https://avatars.discourse-cdn.com/v4/letter/n/eada6e/32.png) [@nixlinch](https://community.hex-rays.com/u/nixlinch)\
**Post date:** [April 3, 2026, 8:35am UTC](https://community.hex-rays.com/t/disassembling-the-firmware-of-the-siemens-infeneon-c167cs-lm-microcontroller/701/1 "2026-04-03T08:35:13Z")

</div>

Hello everyone!

Recently, I needed to disassemble the firmware on a very old Infineon C167CS-LM microcontroller (don’t ask why).  
I remembered I had an IDA Pro. I launched IDA Pro and opened the firmware binary file. I selected the C166 family, and in the models from this family, I selected the C167CS. IDA disassembled only a very small portion of the code, namely:  
basic hardware traps:  
RESET\_HANDLER,  
BTRAP\_HANDLER, etc.

But there weren’t enough interrupts disassembled, there should have been 56, as stated in the documentation for this microcontroller, but only 10 interrupt declarations were disassembled. But since this file only stored ROM data, and not the full 16 MB dump, I deleted all segments except the ROM. I extended the ROM itself to the end of the file (to address 0x7FFFFF, the file is 512 KB in size), and nothing changed. Then I tried manually marking the bytes that should be interrupt declarations as code using the C key. This definitely helped, but the jmps instructions that appeared in place of the previously unknown bytes were invalid, since they referenced the address of the 9th segment, which physically doesn’t exist (I remind you that the file is 512 KB in size).  
I also noticed one peculiarity: the declarations, initially correctly interpreted by the ida, only jumped to segment 0, while the invalid ones only jumped to segment 9.

Example valid declaration:  
ROM:00000028 BTRAP:  
jmps 0, BTRAP\_HANDLER  
Example invalid declaration:  
ROM:00000040: CC0INT:  
jmps 9, 250h; 90250h

I didn’t install any ida plugins. If anyone knows how to fix this problem, please write here.

I am new to this business, so please don’t judge me too harshly in this matter.

[firmware file](https://wdfiles.ru/1uR1s)

I would be grateful for any information that will help me with this difficult task.

Thanks in advance!

---

<div class="post-metadata">

**Author:** ![igor](https://sea2.discourse-cdn.com/flex002/user_avatar/community.hex-rays.com/igor/32/35_2.png) [@igor](https://community.hex-rays.com/u/igor)\
**Post date:** [April 3, 2026, 11:07am UTC](https://community.hex-rays.com/t/disassembling-the-firmware-of-the-siemens-infeneon-c167cs-lm-microcontroller/701/2 "2026-04-03T11:07:25Z")

</div>

In general, IDA only proactively disassembles code using known entrypoints (e.g. interrupt vectors) and following code flow which uses standard conventions.

There are several reasons not all code is disassembled.

**Missing code**

It seems most interrupt handlers are in code segment 9 which is not present in the loaded portion, so only the handlers in the segment 0 were disassembled.

**Non-standard calling convention**

It seems some of the functions used by the startup code (`sub_698`, `sub_71E`) use r3 as the return register instead of the usual call/ret pattern. So you need to convert the values loaded into r3 to offset and continue disassembly at that location manually. It may be easier to perform this task in text listing mode (press space to switch between it and graph mode). The end result looks like this:

```auto
ROM:00000590 mov r3, #loc_598
ROM:00000594 jmpa cc_UC, sub_698
ROM:00000598 ; ---------------------------------------------------------------------------
ROM:00000598
ROM:00000598 loc_598: ; DATA XREF: ROM:00000590↑o
ROM:00000598 mov r0, #0E000h
ROM:0000059C mov r1, #0E790h
ROM:000005A0 mov r2, #4
ROM:000005A2 mov r3, #loc_5AA
ROM:000005A6 jmpa cc_UC, sub_698
ROM:000005AA ; ---------------------------------------------------------------------------
ROM:000005AA
ROM:000005AA loc_5AA: ; DATA XREF: ROM:000005A2↑o
ROM:000005AA mov r0, #0C000h
ROM:000005AE mov r1, #0D7FEh
ROM:000005B2 mov r2, #4
ROM:000005B4 mov r3, #loc_5BA
ROM:000005B8 jmpr cc_UC, sub_698
ROM:000005BA ; ---------------------------------------------------------------------------
ROM:000005BA
ROM:000005BA loc_5BA: ; DATA XREF: ROM:000005B4↑o
ROM:000005BA mov ADDRSEL2, #883h
ROM:000005BE mov r0, #0
ROM:000005C2 mov r1, #3FFEh
ROM:000005C6 mov r2, #8
ROM:000005C8 mov r3, #loc_5CE
ROM:000005CC jmpr cc_UC, sub_698
ROM:000005CE ; ---------------------------------------------------------------------------
ROM:000005CE
ROM:000005CE loc_5CE: ; DATA XREF: ROM:000005C8↑o
ROM:000005CE mov ADDRSEL2, #2000h
ROM:000005D2 mov WDTCON, #9201h
ROM:000005D6 srvwdt
ROM:000005DA mov r0, #0EF00h
ROM:000005DE mov r1, #0EFFFh
ROM:000005E2 mov r2, #10h
ROM:000005E6 mov r3, #loc_5EE
ROM:000005EA jmpa cc_UC, sub_71E
ROM:000005EE ; ---------------------------------------------------------------------------
ROM:000005EE
ROM:000005EE loc_5EE: ; DATA XREF: ROM:000005E6↑o

```

**Unhandled/non-recognized code patterns**

The code at 0000389C seems to perform an indexed table jump (i.e. a switch statement)

```auto
ROM:00003892 movbz r0, byte_C11A
ROM:00003896 shl r0, #1
ROM:00003898 extp #0, #1
ROM:0000389C mov r0, [r0+#3CAh]
ROM:000038A0 jmpi cc_UC, [r0]

```

and 3CA contains a table of offsets:

```auto
ROM:000003CA dw loc_38A2, unk_38EC, unk_3992, unk_39BA, unk_39EE, unk_3A1E
ROM:000003D6 dw unk_3A60, unk_3AA6, unk_3ACC, unk_3AEC, unk_3B22, unk_3B64
ROM:000003E2 dw unk_3B9A, unk_3BD4, unk_3C10, unk_3C3A

```

it can be marked up manually using the [manual switch idiom](https://hex-rays.com/blog/igors-tip-of-the-week-53-manual-switch-idioms).

 ![image](https://us1.discourse-cdn.com/flex002/uploads/rays_hex/original/1X/ff4833c00be3b46883bf6ace38e1329be5ec219a.png)

**Indirectly referenced code**

sub\_35F6 seems to use a table of functions invoked using indirect call instruction:

```auto
ROM:0000361E mov r8, #34Ah
ROM:00003622 mov r9, #0
ROM:00003626 jmpr cc_UC, loc_367E
<skipped>
ROM:0000366E mov r4, [r8+#6]
ROM:00003672 nop
ROM:00003674 calli cc_UC, [r4]
ROM:00003678 ; ---------------------------------------------------------------------------
ROM:00003678
ROM:00003678 loc_3678: ; CODE XREF: sub_35F6+3A↑j
ROM:00003678 add r7, #1
ROM:0000367A add r8, #8
ROM:0000367E
ROM:0000367E loc_367E: ; CODE XREF: sub_35F6+30↑j
ROM:0000367E cmp r7, #10h
ROM:00003682 jmpr cc_C, loc_3628

```

After creating a struct and applying it to the location 34A, we can uncover more code:

```auto
ROM:0000034A functab: ftab_entry <10h, 1Fh, 1Fh, 1Fh, 0, sub_2754>
ROM:0000034A ; DATA XREF: sub_35F6+28↓o
ROM:00000352 ftab_entry <11h, 0, 14h, 0, 0, unk_2D52> ; jumptable 000038A0 case 2
ROM:0000035A ftab_entry <1Ah, 1Fh, 1Fh, 0, 0, unk_2C16>
ROM:00000362 ftab_entry <20h, 1Fh, 1Fh, 1Fh, 0, sub_2480>
ROM:0000036A ftab_entry <23h, 18h, 18h, 0, 0, unk_2B4E>
ROM:00000372 ftab_entry <27h, 1Fh, 1Fh, 1, 0, sub_2504>
ROM:0000037A ftab_entry <31h, 1Fh, 1Fh, 0, 0, unk_2F10>
ROM:00000382 ftab_entry <34h, 0, 14h, 0, 0, sub_28D2>
ROM:0000038A ftab_entry <36h, 0, 14h, 0, 0, sub_29B2>
ROM:00000392 ftab_entry <37h, 0, 14h, 0, 0, unk_2A1E>
ROM:0000039A ftab_entry <3Bh, 0, 14h, 0, 0, unk_32C8>
ROM:000003A2 ftab_entry <3Dh, 18h, 18h, 0, 0, unk_2A6C>
ROM:000003AA ftab_entry <3Eh, 1Fh, 1Fh, 1Fh, 0, loc_24EC>
ROM:000003B2 ftab_entry <81h, 1Fh, 0, 0, 0, loc_2124>
ROM:000003BA ftab_entry <82h, 1Fh, 0, 0, 0, loc_215C>
ROM:000003C2 ftab_entry <83h, 1Fh, 1Fh, 1Fh, 0, loc_218E>

```

Even then there is still unexplored code between the functions but that will be an exercise for the reader 🙂 .

---

<div class="post-metadata">

**Author:** ![nixlinch](https://avatars.discourse-cdn.com/v4/letter/n/eada6e/32.png) [@nixlinch](https://community.hex-rays.com/u/nixlinch)\
**Post date:** [April 3, 2026, 12:00pm UTC](https://community.hex-rays.com/t/disassembling-the-firmware-of-the-siemens-infeneon-c167cs-lm-microcontroller/701/3 "2026-04-03T12:00:45Z")

</div>

So ida wasn’t mistaken about the presence of the 9th segment?

---

<div class="post-metadata">

**Author:** ![igor](https://sea2.discourse-cdn.com/flex002/user_avatar/community.hex-rays.com/igor/32/35_2.png) [@igor](https://community.hex-rays.com/u/igor)\
**Post date:** [April 3, 2026, 12:40pm UTC](https://community.hex-rays.com/t/disassembling-the-firmware-of-the-siemens-infeneon-c167cs-lm-microcontroller/701/4 "2026-04-03T12:40:23Z")

</div>

From the C166V2 manual:

> Segments are contiguous blocks of 64 KBytes each. They are referenced via the Code  
> Segment Pointer (CSP) for code fetches and via an explicit segment number for data  
> accesses overriding the standard DPP scheme.  
> During code fetching, segments are not changed automatically, but rather must be  
> switched explicitly. The instructions JMPS, CALLS, and RETS will do this. Larger  
> sequential programs make sure that the highest used code location of a segment  
> contains an unconditional branch instruction to the respective following segment, to  
> prevent the prefetcher from trying to leave the current segment.

your file is only 512KB long (0x80000), so seems to contain only segments 0 to 7. Possibly the dump does not use the usual 64KB chunk per segment but another layout. It’s hard to say without knowing the exact hardware and dumping process.

---

<div class="post-metadata">

**Author:** ![veskohard](https://avatars.discourse-cdn.com/v4/letter/v/9fc348/32.png) [@veskohard](https://community.hex-rays.com/u/veskohard)\
**Post date:** [April 3, 2026, 7:29pm UTC](https://community.hex-rays.com/t/disassembling-the-firmware-of-the-siemens-infeneon-c167cs-lm-microcontroller/701/5 "2026-04-03T19:29:25Z")

</div>

In SIEMENS D42 flash is 512kb and must be loaded at 0x80000

`ROM:00080000 FA 00 44 04 jmps 0, loc_80444`

---

<div class="post-metadata">

**Author:** ![veskohard](https://avatars.discourse-cdn.com/v4/letter/v/9fc348/32.png) [@veskohard](https://community.hex-rays.com/u/veskohard)\
**Post date:** [April 5, 2026, 7:44pm UTC](https://community.hex-rays.com/t/disassembling-the-firmware-of-the-siemens-infeneon-c167cs-lm-microcontroller/701/6 "2026-04-05T19:44:38Z")

</div>

Also add mapping (Options\>General\>Analysis\>Memory mapping\>Add mapping)  
0x00000

0x80000

0x04000

---

<div class="post-metadata">

**Author:** ![nixlinch](https://avatars.discourse-cdn.com/v4/letter/n/eada6e/32.png) [@nixlinch](https://community.hex-rays.com/u/nixlinch)\
**Post date:** [April 26, 2026, 8:37am UTC](https://community.hex-rays.com/t/disassembling-the-firmware-of-the-siemens-infeneon-c167cs-lm-microcontroller/701/7 "2026-04-26T08:37:15Z")

</div>

Tell me more about how you labeled the function table in 34A and how you determined its size.
