Author Topic: Reading firmware out of a mask ROM microcontroller  (Read 44641 times)

ealex and 20 Guests are viewing this topic.

Online tru

  • Regular Contributor
  • *
  • Posts: 152
  • Country: gb
Re: Reading firmware out of a mask ROM microcontroller
« Reply #100 on: July 17, 2025, 11:19:10 pm »
Interesting.  That MCU belongs to the M16C/26 series.  The memory map is different from my M16C/62P series, but addresses do sort of align.

I think I may have found your problem... looking in the "M16C/Tiny Rewriting the User ROM Area in EW0 Mode" PDF, which you can get from here: https://www.renesas.com/en/document/apn/m16ctiny-rewriting-user-rom-area-ew0-mode?r=1053151
It says block A and B (the virtual EEPROM areas) are not readable until you set the PM10 bit to a 1, which is part of the PM1 register.
Quote
Furthermore, before data can be read from the data area (block A or B), the data area access enable bit (PM10) in Processor Mode Register 1 (PM1) must be set to 1.

In the datasheet, the PM1 register is located at address 0x0005, but I don't know which bit is the PM10.  Perhaps someone can let us know which document lists the various bits of the registers (SFRs)?  The list of available docs are here:
https://www.renesas.com/en/products/m16c-26?srsltid=AfmBOoqpkL-_8H0XfHaC-XK56cBqUKKcrKtGtKTqWtBzXN04iRctHLI7#documents

I assume PM10 by default is set to 0, meaning to read out blocks A and B you will need to first write a program that is able to run in RAM and then jump back into the bootloader after setting the bit.  Your program will need to be downloaded into RAM using the download switch of my m16c flasher.  I think I have a sample LED blink (GPIO) program that I wrote a while back that jumps back to the bootloader.  I will see if I can find it.
 

Offline limbast

  • Contributor
  • Posts: 12
  • Country: lv
Re: Reading firmware out of a mask ROM microcontroller
« Reply #101 on: July 18, 2025, 07:47:44 am »
Hello.
The description of the PM1 register bits is in the M16C/26 Hardware Manual on page 31.
https://www.farnell.com/datasheets/17451.pdf
I compared the M16C/26 and M16C/62P Hardware Manuals. The PM1 registers are at the same address, but the bits have completely different purposes.
After reset, access to block A and B is prohibited, for access, the PM10 (B0) bit must be set.
« Last Edit: July 18, 2025, 07:55:26 am by limbast »
 

Online tru

  • Regular Contributor
  • *
  • Posts: 152
  • Country: gb
Re: Reading firmware out of a mask ROM microcontroller
« Reply #102 on: July 24, 2025, 10:44:38 pm »
Ok, I had some spare time and coded it for you.  I think this will only work on bootloader V4.04, not sure what your version is, but you can find that out by running my m16cflasher.

The binary file and bat script to upload and run it: https://drive.google.com/file/d/1irQrziR5RjSqoqwbHgP8jesq2tBIZ4yw/view?usp=drive_link
The source code (Renesas HEW IDE): https://drive.google.com/file/d/1IQOE0Jk7IvsWC5HmFdv14cnuWKkOvJvq/view?usp=drive_link

The assembly file is named ncrt0.a30, which you can view in notepad if you just want to look at the source.

Renesas HEW IDE can be downloaded here (requires free registration then login): https://www.renesas.com/en/software-tool/cc-compiler-package-r8c-and-m16c-families#downloads
It is commercial but the eval version can compile short sources, so you may want to download [Evaluation Software] C/C++ Compiler Package for M16C Series and R8C Family M3T-NC30WA V.6.00 Release 00
« Last Edit: August 11, 2025, 06:36:17 pm by tru »
 

Offline limbast

  • Contributor
  • Posts: 12
  • Country: lv
Re: Reading firmware out of a mask ROM microcontroller
« Reply #103 on: July 25, 2025, 06:44:00 pm »
Thank you!
I used your program m16cflasher to read the dump, but the bat files you wrote don't work for some reason, I think it's related to the location of m16cflasher. I used your program simply with parameters.
The program responded "VER.0.10" to the command "m16cflasher path=\\.\com4 ver", that is, the bootloader version is not the one you specified, but I'll try anyway.
 

Offline limbast

  • Contributor
  • Posts: 12
  • Country: lv
Re: Reading firmware out of a mask ROM microcontroller
« Reply #104 on: August 11, 2025, 02:09:15 pm »
Tru, I used your program. But it didn't work to read areas A and B.
You made a bat file to load the program into the MCU. Its contents are as follows:
m16cflasher /download /com=4 /id_addr=0x0FFFDF /id=00000000000000 /file=enable_blockab.mot.bin
I downloaded your m16cflasher flasher from github
https://github.com/truhy/m16c-flasher.
The version from github does not understand the parameters as you specified them in your bat file. The flasher does not understand the slash before the parameters, and the COM port is specified by the path parameter and backslashes. Below is a screenshot of the program running.
2636721-0
When I specify the parameters as the flasher understands (the last line on the screenshot), it crashes.
2636727-1
Maybe I have the wrong version of the m16cflasher flasher? The size of my version from github is 453210 bytes.
« Last Edit: August 11, 2025, 02:11:53 pm by limbast »
 

Online tru

  • Regular Contributor
  • *
  • Posts: 152
  • Country: gb
Re: Reading firmware out of a mask ROM microcontroller
« Reply #105 on: August 11, 2025, 05:03:25 pm »
Sorry, I had modified a bat file taken from an older version (before adding linux support).  In the newer version to align with linux, slash was removed and we supply physical serial com path instead.  I've updated the zip in the previous post.   Or edit your bat file with this instead:
m16cflasher download path=\\.\COM4 id_addr=0x0FFFDF id=00000000000000 file=enable_blockab.mot.bin
*Don't forget to change the COM4 to your detected serial device.

The download (upload to ram) command may not be supported by your bootloader version, but let's see.

Ouch, just noticed you've tried latest version and added it crashes.  I'll test in a few days on my side.
« Last Edit: August 11, 2025, 06:07:08 pm by tru »
 

Offline limbast

  • Contributor
  • Posts: 12
  • Country: lv
Re: Reading firmware out of a mask ROM microcontroller
« Reply #106 on: August 11, 2025, 06:06:01 pm »
That's exactly what I did, you can see it on the screenshot (last line), I didn't use a bat file, I wrote commands in the command line. But the flasher crashes when I press ENTER.
It seems that the flasher doesn't work correctly with the bootloader of my MCU VER.0.10 and that's why it crashes?
 

Online tru

  • Regular Contributor
  • *
  • Posts: 152
  • Country: gb
Re: Reading firmware out of a mask ROM microcontroller
« Reply #107 on: August 11, 2025, 06:49:50 pm »
Just tried a quick test, and noticed the binary file that was converted from .mot (compiled file) was zero padded from the beginning of the file, and doesn't work.  I've removed these zeroes and is fine now.  It loads and run on the MCU (M30624FGPGP) but then again it's got V4.04 bootloader.

Again, I've updated the link in the previous post with the updated enable_blockab.mot.bin download file.
I'm not sure yet why it crashes on yours, if I may ask what version of Windows you are on (I am on Windows 10)? - noted from your screenshot you are using Windows 10 also.

We need to sort out the crashing first before ruling out the V0.10 bootloader support for the download command.

Failing all this, there is one last trick to readout blocks A+B, which is to backup the entire flash (except A & B of course), then write and flash (say only block 0) with your own program to enable A+B areas, read those areas and finally send them out the serial port yourself.  After that you would restore the original flash area.  I must warn you to be careful with the m16cflasher not to do an erase all blocks command.
« Last Edit: August 12, 2025, 07:46:43 am by tru »
 

Offline limbast

  • Contributor
  • Posts: 12
  • Country: lv
Re: Reading firmware out of a mask ROM microcontroller
« Reply #108 on: August 12, 2025, 06:14:54 pm »
After you corrected the enable_blockab.mot.bin file, your program loaded successfully without a crash.
After that, I tried to read the VirtualEEPROM area (0xF000-0xFFFF), but it still doesn't contain data.
2637527-0
After loading your program, do I need to activate it somehow or does it start itself immediately after loading?
 

Online tru

  • Regular Contributor
  • *
  • Posts: 152
  • Country: gb
Re: Reading firmware out of a mask ROM microcontroller
« Reply #109 on: August 12, 2025, 08:01:24 pm »
The program starts running immediately after loading, areas A+B should then be enabled.  After that, the program rereads the bootloader back into RAM and jumps to the start of it (i.e. re-run it) so that we can get back control of bootloader commands, this is because the bootloader overwrote parts of itself with our program in RAM.

Hmm, I've just realised there may be a problem, if the bootloader at the start of it has initialization that sets the PM1 register (i.e. locks A+B) then that will revert the bits we set.  Perhaps we may need to jump back to bootloader but somewhere after the initialisation code.  We can find this out by looking at a dump of your V0.10 bootloader code.
« Last Edit: August 12, 2025, 11:44:38 pm by tru »
 

Offline limbast

  • Contributor
  • Posts: 12
  • Country: lv
Re: Reading firmware out of a mask ROM microcontroller
« Reply #110 on: August 13, 2025, 12:53:31 pm »
I looked through the M16C/26 Hardware Manual and did not find the addresses where the bootloader is located.
How can I dump the bootloader?
With your flasher I can read a full MCU dump, will this be useful?
« Last Edit: August 13, 2025, 12:56:12 pm by limbast »
 

Online tru

  • Regular Contributor
  • *
  • Posts: 152
  • Country: gb
Re: Reading firmware out of a mask ROM microcontroller
« Reply #111 on: August 13, 2025, 08:02:17 pm »
The bootloader (boot ROM area) is held in a separate bank that must be switched into in order to read it out.  The address range is from 0xfe000 to 0xfffff, and is the same as part of block 1 flash.
The memory map is shown here in this document:
https://www.renesas.com/en/document/apn/programming-flash-memory-flash-over-usb?srsltid=AfmBOop0OiDD0oNLTGNvVHFkL_z02Kr0FOoV5Yq64EiaXznL3FOR_cUZ

There is a dedicated command for dumping the bootloader out but I'm not sure if it is supported by your version:
m16cflasher ba_output path=\\.\COM4 id_addr=0x0FFFDF id=00000000000000 from_addr=0x0FF000 to_addr=0x0FFFFF file=bootarea.bin
« Last Edit: August 13, 2025, 08:05:12 pm by tru »
 

Offline limbast

  • Contributor
  • Posts: 12
  • Country: lv
Re: Reading firmware out of a mask ROM microcontroller
« Reply #112 on: August 14, 2025, 05:34:07 am »
Indeed, the location of the Boot ROM area is specified in the Hardware Manual. My mistake is that I searched for the word "bootloader" and studied the section 3.Memory, but it does not show the Boot ROM area. The memory block addresses are specified in section 17.2.Memory Map, I did not look at this section.
 

Online tru

  • Regular Contributor
  • *
  • Posts: 152
  • Country: gb
Re: Reading firmware out of a mask ROM microcontroller
« Reply #113 on: August 14, 2025, 08:13:29 am »
A small correction, just noticed that your boot ROM area starts from a slightly lower address than mine so the command to use is:
m16cflasher ba_output path=\\.\COM4 id_addr=0x0FFFDF id=00000000000000 from_addr=0x0FE000 to_addr=0x0FFFFF file=bootarea.bin
 

Offline limbast

  • Contributor
  • Posts: 12
  • Country: lv
Re: Reading firmware out of a mask ROM microcontroller
« Reply #114 on: August 14, 2025, 03:12:39 pm »
The dump of the VER.0.10 bootloader is in the attachment
 

Online tru

  • Regular Contributor
  • *
  • Posts: 152
  • Country: gb
Re: Reading firmware out of a mask ROM microcontroller
« Reply #115 on: August 15, 2025, 08:31:24 am »
That is cool - it seems all of the commands work on older bootloader!  I've converted the binary into .mot (motorola hex format) using srec_cat tool.  Also generated the disassembly file.
The disassembly made using trial version of Renesas development IDE (HEW) with the included M16C/R8 software debugger, and selecting the .mot file as a download module.  Also of note, I had to replace the S-record footer in the .mot file for it to be seen as a valid file in HEW.

When I get some time will look at it in more detail - other members are welcome to help here.  For reference we need these two manuals:
I find it strange that the hardware manual is not actually listed on the Renesas list of documents page!

Anyway, as starter, we are interested in the PM1 SFR register and bit0, and as described in the hardware manual it is at address 0x0005.  Opening the .asm file in notepad++ and searching for 0005H we find two matches, and I can see they don't modify bit0 so the virtual EEPROM areas are not disabled by it.
« Last Edit: August 15, 2025, 08:35:21 am by tru »
 

Offline limbast

  • Contributor
  • Posts: 12
  • Country: lv
Re: Reading firmware out of a mask ROM microcontroller
« Reply #116 on: August 15, 2025, 10:37:17 am »
Tru, I found that I initially gave a link to the wrong Hardware Manual
https://www.farnell.com/datasheets/17451.pdf
This is for the M16C26A MCU. It describes the M30260 and M30263 MCUs.
Here is a link to the Hardware Manual for the M16C26 which describes my M30262.
https://www.alldatasheet.com/datasheet-pdf/pdf/249845/RENESAS/M16C26.html
The documents are different, including the PM1 byte, although the PM10 bit is in the same place.
In addition, I noticed that my MCU, in which I loaded your program and tried to read Virtual EEPROM, no longer responds to the main board's messages, although the status LED is still blinking.
Before all the experiments, I read several versions of dumps with both the M16C-Flasher program (mot) and your flasher (bin).
First, I flashed the MCU with the M16C-Flasher program (Addresses from FA000 to FFFFF). The MCU did not establish communication, there is no response via UART.
Then I tried to flash it with your flasher. I read the dump from address F8000 to FFFFF. The flasher gets looping when loading Block 3 from address FA000-FC000. That is, it reaches FBFFF, again reports that it will flash Block 3 and starts flashing from FA000 and so on in a circle.
 

Offline abyrvalg

  • Frequent Contributor
  • **
  • Posts: 898
  • Country: es
Re: Reading firmware out of a mask ROM microcontroller
« Reply #117 on: August 16, 2025, 01:37:28 pm »
I can confirm that the upper 4K code of bootarea.bin (the one you've converted to mot) doesn't touch PM1 bits other that bit 7.
But what is in low 4K of the same dump? It should belong to 0xFE000-0xFF000 addresses, but looking at the disassembly shows that it treats itself as being mapped to 0xFF000-0xFFFFF indeed. It initializes some SFRs (writing 0x8C to PM1 among them), copies another piece of code from 0xFF1E0 to 0x400 RAM and jumps there. The RAM code part seems to be doing flash programming. There are another two PM1 writes in other parts of that code, one writes 0x08 to entire reg, another one clear bit3. This code also manipulates several undocumented SFRs located near FMRx ones: 0x1B1, 0x1B6, 0x1BF.
 

Online tru

  • Regular Contributor
  • *
  • Posts: 152
  • Country: gb
Re: Reading firmware out of a mask ROM microcontroller
« Reply #118 on: August 16, 2025, 05:23:37 pm »
@abyrvalg, thanks.  Interesting you're right.

Just some extra info... on these MCUs, the reset entry address is user configured, execution starts from the 20bit address (almost 3 bytes) stored in the reset vector address in the vector table.  The reset vector address is located inside the dump at 0xFFFFC to 0xFFFFF:
0xFFFFC: 00
0xFFFFD: F0
0xFFFFE: 0F
0xFFFFF: FF
Only the first 3 bytes is used and since the first byte is LSB we need to reverse the order, which gives the reset entry address as: 0x0FF000
So the code from 0xFF000 to 0xFFFFF is what I thought was the only code, but we should also look at 0xFE000-0xFEFFF, which abyrvalg did for us already.  I have attached the disassembly of the full range.

@limbast

I should have warned you earlier, that my code was made mostly by copying and pasting from my other projects.  It was a 1 hour rush job so no validations and very little testing, etc.

I think I know why my program hangs - it is because with some serial drivers (depends on your serial adapter) they do not respect the timeout setting - they simply hang when the MCU does not respond (not sending anything back).  I did implement Windows Asynchronous mode - which will always timeout even if the driver does not respect the timeout serial setting, but it is off by default because I didn't have time to test it.

Another thing, flashing requires the correct block addresses to be set inside the m16c_mem_map.h source file and I didn't want to go through all documents + models to put them in, only added for my MCU.  I don't recommend you do any flashing yet, until we can dump out the virtual EEPROM area using the download to RAM command we are using.
« Last Edit: August 16, 2025, 05:46:49 pm by tru »
 

Offline abyrvalg

  • Frequent Contributor
  • **
  • Posts: 898
  • Country: es
Re: Reading firmware out of a mask ROM microcontroller
« Reply #119 on: August 17, 2025, 01:40:57 pm »
@tru, looks like I've found why your enable_blockab payload doesn't work on limbast's MCU: you don't need that complex "jump back to bootloader" code on this MCU/boot version, just do this instead:
Code: [Select]
BSET 0, 0005H  ; set PM10
JMP.A 0FF088H ; jump back to serial bootloader entry point

limbast's VER.0.10 BootROM doesn't copy itself to 0x600 RAM buffer, it runs from 0xFFxxx addresses directly, copying to RAM only small funcs like "read SR", "program 1 page" etc when it receives corresponding commands. Also the DOWNLOAD command (0xFA) RAM address is different, it is 0x546 (version header) / 0x54E (actual code entry point).
 

Online tru

  • Regular Contributor
  • *
  • Posts: 152
  • Country: gb
Re: Reading firmware out of a mask ROM microcontroller
« Reply #120 on: August 18, 2025, 07:21:15 pm »
Wow, abyrvalg very nice, I've just tried that with my VER.4.04 bootloader, simply jumping to 0xFF020 does indeed get me back into the bootloader!
In the assembly I have assembly .org directive set to 0x600 which is correct for my version, but for limbast, perhaps we need to set to 0x546.

Also, I've noticed that some SFRs are write protected by default, controlled with the Protect Register (address 0x000A).  The correct download code for limbast could be this:
Code: [Select]
.section rom,code
.org 0546h       ; Download starting RAM address

.byte 'VER.1.00' ; Version header
BSET 1,000AH     ; Enable write to PM1 register
BSET 0,0005H     ; Set PM10 (bit 0) to 1 in PM1 register (0005H) - enable A+B access
BCLR 1,000AH     ; Disable write to PM1 register
JMP 0FF088H      ; jump back to serial bootloader entry point
Attached is updated payload binary, and source with corrected srec_cat.bat so it doesn't fill in zeroes.  I cannot test it - we will have to wait for limbast.

« Last Edit: August 18, 2025, 07:22:52 pm by tru »
 

Online tru

  • Regular Contributor
  • *
  • Posts: 152
  • Country: gb
Re: Reading firmware out of a mask ROM microcontroller
« Reply #121 on: August 18, 2025, 07:43:34 pm »
My mistake shows I am a noob at assembly.  I've just realised that the .org directive will only affect relative addressing instructions, and I could have just used your mentioned code JMP.A instead, which is jump to absolute address.
 

Offline limbast

  • Contributor
  • Posts: 12
  • Country: lv
Re: Reading firmware out of a mask ROM microcontroller
« Reply #122 on: August 22, 2025, 04:16:02 pm »
tru, I loaded your program into the MCU using the command:
Code: [Select]
m16cflasher download path=\\.\COM4 id_addr=0x0FFFDF id=00000000000000 file=enable_blockab.mot-v2.binThen I read the "eeprom" using the command:
Code: [Select]
m16cflasher path=\\.\com4 read id_addr=0x0fffdf id=0000000000 from_addr=0x00f000 to_addr=0x00ffff file=eeprom.binThe dump was empty, all bytes are FF.
To make sure that access to block A and B works, I wrote data (I just used your BIN) to this area using the command:
Code: [Select]
m16cflasher path=\\.\com4 program id_addr=0x0fffdf id=0000000000 from_addr=0x00f000 to_addr=0x00f017 file=enable_blockab.mot-v2.binYour flasher flashed the entire 4kb area, and not the 24 byte range I specified.
2643587-0
I don't know if the data in this area would have been erased if it had been there. Maybe I can't specify the address range to the flasher, since it only works with memory in blocks.
Then I read this area and the data was read as it was written. Your program works!

Thanks!

But there's something else.
« Last Edit: August 22, 2025, 04:19:37 pm by limbast »
 

Offline limbast

  • Contributor
  • Posts: 12
  • Country: lv
Re: Reading firmware out of a mask ROM microcontroller
« Reply #123 on: August 22, 2025, 04:50:58 pm »
As I wrote above, after loading the first version of your program (size 140 bytes) and reading the "eeprom" area, my board stopped responding to requests from the main board.
I have a second board, it responds to the request, but gives a temperature error. The problem is not in the board, but in the MCU: the MCU ADC pins on both boards have the same voltage. Moreover, I swapped the microcontrollers, and the temperature measurement problem moved from one board to another. Maybe this is a hardware problem with the microcontroller, maybe its internal ADC is broken, or maybe it is software. I managed to order a new MCU, I received it a few days ago, installed it and flashed it with M16C-Flasher, and the board worked fine. I was confused. Since the new MCU is completely empty, including the "eeprom" area, and it worked, I assume that nothing is written to the "eeprom" area, and the data from this area is not used. Am I right? However, I do not exclude that the MCU determines that the "eeprom" area is clean and initializes it with some data. Now, with the help of your program, I have verified that in the MCU that does not communicate with the main board, the EEPROM area is clean, as in the new MCU (and it communicates with the main board), it is not initialized with any data.

So, a new question arose: what could have changed in the MCU after loading your first version of the program, which memory areas could have been changed and how to flash a full copy of one MCU to another? Before loading your latest version of the program into the "working" MCU, I can read the dumps of both MCUs, will this be informative for you, tru?
PS you need to add to github what you did, thanks for your work!
 

Online tru

  • Regular Contributor
  • *
  • Posts: 152
  • Country: gb
Re: Reading firmware out of a mask ROM microcontroller
« Reply #124 on: August 22, 2025, 07:36:59 pm »
Thanks for the insight - very helpful.  You are correct, the erase can only do entire blocks, i.e partial block erase is not possible.

Programming (flashing) will not work correct for your MCU due to the wrong erase block list, which is defined only for my MCU (M16C/62P).  Most likely, it is erasing the wrong block or trying to erase a partial block but failing, because that is not allowed.  When I have a bit more time, I will modify the block list to support your M16C/26 series, as well as a new commandline option to select the MCU series.

Regarding github, yes, I've recently merged in pull request with changes made by someone else.  I think he fixed the retry and loop issue that you mentioned in an earlier post.
 


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf