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

0 Members and 2 Guests are viewing this topic.

Offline tru

  • Regular Contributor
  • *
  • Posts: 107
  • Country: gb
Re: Reading firmware out of a mask ROM microcontroller
« Reply #75 on: April 23, 2021, 09:32:48 pm »
Wow, I thought that it would not work!

The special command is part of the boot loader code - not a hardware command.  Unfortunately when the boot loader starts up, it copies main part of itself into RAM and runs from there, some of the RAM is overwritten, but then the required reset for boot mode will destroy the RAM content anyway?

Have a look at the test source code included in the HEW project to get an idea of what's happening (plain text file):
ncrt0.a30

It is in assembly.  I've marked a user code section where the port P8_0 is set to high.  If you don't want to jump back into the Renesas boot loader code you can add in an infinite loop and remove all of the following code, except for the CRC code at the end.  The integrity check is simply the CRC of your code, which is automatically calculated by that code.

Since the command works, now there is possibilty we can write own code to dump out the boot loader code!
« Last Edit: April 23, 2021, 09:36:13 pm by tru »
 

Offline canadaboy25Topic starter

  • Regular Contributor
  • *
  • Posts: 152
  • Country: ca
Re: Reading firmware out of a mask ROM microcontroller
« Reply #76 on: April 23, 2021, 10:14:23 pm »
Wow, I thought that it would not work!

The special command is part of the boot loader code - not a hardware command.  Unfortunately when the boot loader starts up, it copies main part of itself into RAM and runs from there, some of the RAM is overwritten, but then the required reset for boot mode will destroy the RAM content anyway?

Have a look at the test source code included in the HEW project to get an idea of what's happening (plain text file):
ncrt0.a30

It is in assembly.  I've marked a user code section where the port P8_0 is set to high.  If you don't want to jump back into the Renesas boot loader code you can add in an infinite loop and remove all of the following code, except for the CRC code at the end.  The integrity check is simply the CRC of your code, which is automatically calculated by that code.

Since the command works, now there is possibility we can write own code to dump out the boot loader code!

It is encouraging to be able to make the LED actually do something other than blink at me!

Even though the bootloader is copied to RAM, I'm hoping it doesn't overwrite the select few bytes that are important to ending up in the lamp error mode.  Being able to examine the bootloader would allow us to see if this is the case or not.  On page 86 of the hardware manual pdf (page 53 in the document), it says that the internal RAM is not reset by pulling the reset line low.  It does say that the RAM will be undefined if the MCU is reset during a write operation though.

I'll definitely take a look at the HEW project to get up to speed with how it is working.  Do you know the process to make the hidden bootloader are accessible from software?  I can't really find anything in the hardware manual about it which is probably intentional or I'm not looking for the right terms.
« Last Edit: April 24, 2021, 07:43:26 pm by canadaboy25 »
canadaboy25

- Sometimes the light at the end of a tunnel is an on-coming train
 

Offline abyrvalg

  • Frequent Contributor
  • **
  • Posts: 824
  • Country: es
Re: Reading firmware out of a mask ROM microcontroller
« Reply #77 on: April 26, 2021, 10:22:58 am »
Just a thought: if it’s a lamp error - why dig the code further? Check the backlight circuitry instead? Or you want to know exact MCU pin to narrow down the search?
 

Offline canadaboy25Topic starter

  • Regular Contributor
  • *
  • Posts: 152
  • Country: ca
Re: Reading firmware out of a mask ROM microcontroller
« Reply #78 on: April 26, 2021, 09:26:00 pm »
Just a thought: if it’s a lamp error - why dig the code further? Check the backlight circuitry instead? Or you want to know exact MCU pin to narrow down the search?

Yes, when I first found out that it was a backlight error I figured that it would be a simple fix.  The LEDs are in parallel sets of series connected LEDs like most TVs.  I powered up each set expecting to find one that wouldn't light.  However, every string lit up and the current draw was identical between all the strings.  So obviously the physical LEDs were fine.  There is a large inverter board connected to the strings of LEDs that connects to the logic board and the power supply.  There is no voltage coming from the power supply to the inverter board but that is because the main board is not enabling the power supply.  I manually jumped the enable pin on the power supply to verify it and all voltages are correct.  So that leaves the main board or the inverter board.  I probed each of the signal lines between the main board and inverter board with the scope and there are no signals at any time, even at power up.  This seems like a problem since I don't see any way the main board could tell if there is a baclkight issue without even communicating with the inverter board.

There is an Altera CPLD on the inverter board that communicates with the main board.  This is basically a black box because I strongly doubt that the designers have left the lock bit clear in the CPLD firmware.  It would also be a much more difficult task to reverse engineer a CPLD firmware with no documentation if I could get it dumped.  I don't know if the main board first sends a signal to the CPLD on the inverter board and waits for a response, or if it happens the other way round.  It seems unlikely for a CPLD to just die, so I though it must be the main board seeing some other input that it doesn't like.  Seeing that the main board had a flash memory Renesas MCU, I figured that dumping the firmware and figuring out what specific conditions trigger the lamp error would give me a lot more direction in my troubleshooting.

Looking through the bootloader that tru posted previously, it overwrites a lot of the RAM with its own code so that will make getting a RAM dump quite hard.  I did find one interesting place in the TV firmware, though you may have already ruled this out.

In the function at E06A0 at address E0856 is the code that would print the "[EVM]Lamp error over 5 times" string.  At address E080E the code would print "[EVM]Normal Start".  There is one jump instruction that chooses between these cases based on the value of byte_D21 in RAM.  If byte_D21 == 05H, the TV starts normally, otherwise the TV goes into lamp error mode.  Further up in that function, byte_D21 is set to the value of byte_D0E.  At the top of the function, byte_D0E is set to either 05H or 04H based on the value in R0L.  If R0L == 12H, the TV will end up in lamp error mode.  R0L gets set by the function at E7494.  R0L gets set to 12H based on the values calculated from ADC pins AN0_4 and AN0_3.  There is also a function at ECE20 that seems to reference a lot of ROM addresses and then return a result based on the state of P2_4 if I have followed the function correctly.

It seems to me that either this P2_4 or the two ADC pins could be where something is going wrong unless you have already looked at this and I am missing something.

canadaboy25

- Sometimes the light at the end of a tunnel is an on-coming train
 

Offline tru

  • Regular Contributor
  • *
  • Posts: 107
  • Country: gb
Re: Reading firmware out of a mask ROM microcontroller
« Reply #79 on: April 26, 2021, 10:34:38 pm »
Do you know the process to make the hidden bootloader are accessible from software?  I can't really find anything in the hardware manual about it which is probably intentional or I'm not looking for the right terms.
On V4.04 bootloader, the download to RAM command keeps the hidden addressing mode so a downloaded code should already be able to read the hidden area if V1.00 is same.  For other commands the mode is switched to normal addressing, e.g. when reading flash.

I think now I know what controls it and they've intentionally made the setting reserved.  In the M16C/64A hardware manual see PDF reader page 694 (document page 661):
Flash Memory Control Register 0 (FMR0), bit 5

In the processor of my one, the M16C/62 hardware manual says (rather than being reserved):
Flash Memory Control Register 0 (FMR0):
bit 5:
0 = boot ROM area (addressing mapped to hidden flash area)
1 = user ROM area (addressing mapped to normal flash area)

If I have some free time, I'll try to write some code to see if I can read out the bootloader VER.4.04 using a downloaded code.


User boot mode - another thing to look at
----------------------------------------------
I've also noticed what ROM2 area is for, it is for user boot mode (for executing customer's own bootloader).  I am guessing, V1.00 bootloader doesn't just enter into serial bootloader mode, it first checks some values inside ROM2 area, and if they pass it executes from start of ROM2 instead (address 0x10000).

The checks is described on page 702 (document page 669):

So to boot into user boot mode, flash a program into flash ROM2 area so that it has:
ASCII string "UserBoot" at addresses: 0x13FF0 to 0x13FF7
0x00 at addresses: 0x13FF8 to 0x13FFB

It will never enter serial mode anymore, to revert back simply write 0xFF to those areas in ROM2, or just erase ROM2 area.

This user boot mode could mean RAM will not be overwritten, I assume it doesn't use it and execution is directly from ROM2 area.
« Last Edit: April 26, 2021, 10:45:10 pm by tru »
 

Offline canadaboy25Topic starter

  • Regular Contributor
  • *
  • Posts: 152
  • Country: ca
Re: Reading firmware out of a mask ROM microcontroller
« Reply #80 on: May 01, 2021, 02:15:51 pm »
On V4.04 bootloader, the download to RAM command keeps the hidden addressing mode so a downloaded code should already be able to read the hidden area if V1.00 is same.  For other commands the mode is switched to normal addressing, e.g. when reading flash.

I think now I know what controls it and they've intentionally made the setting reserved.  In the M16C/64A hardware manual see PDF reader page 694 (document page 661):
Flash Memory Control Register 0 (FMR0), bit 5

In the processor of my one, the M16C/62 hardware manual says (rather than being reserved):
Flash Memory Control Register 0 (FMR0):
bit 5:
0 = boot ROM area (addressing mapped to hidden flash area)
1 = user ROM area (addressing mapped to normal flash area)

If I have some free time, I'll try to write some code to see if I can read out the bootloader VER.4.04 using a downloaded code.


User boot mode - another thing to look at
----------------------------------------------
I've also noticed what ROM2 area is for, it is for user boot mode (for executing customer's own bootloader).  I am guessing, V1.00 bootloader doesn't just enter into serial bootloader mode, it first checks some values inside ROM2 area, and if they pass it executes from start of ROM2 instead (address 0x10000).

The checks is described on page 702 (document page 669):

So to boot into user boot mode, flash a program into flash ROM2 area so that it has:
ASCII string "UserBoot" at addresses: 0x13FF0 to 0x13FF7
0x00 at addresses: 0x13FF8 to 0x13FFB

It will never enter serial mode anymore, to revert back simply write 0xFF to those areas in ROM2, or just erase ROM2 area.

This user boot mode could mean RAM will not be overwritten, I assume it doesn't use it and execution is directly from ROM2 area.

Cool, so they've hid the control for the hidden memory command in plain sight.  It shouldn't be to difficult to write a simple program to read the bootloader out.

I am away for work right now but when I get back I will definitely give that a try!
canadaboy25

- Sometimes the light at the end of a tunnel is an on-coming train
 

Offline tru

  • Regular Contributor
  • *
  • Posts: 107
  • Country: gb
Re: Reading firmware out of a mask ROM microcontroller
« Reply #81 on: May 01, 2021, 03:12:39 pm »
Ouch, just a warning regarding the ROM2 user boot mode - I've just realised that if you can't get back into the standard serial bootloader mode then you can't erase!  Unless of course you code in your own erase function into your ROM2 bootloader.
 

Offline canadaboy25Topic starter

  • Regular Contributor
  • *
  • Posts: 152
  • Country: ca
Re: Reading firmware out of a mask ROM microcontroller
« Reply #82 on: September 13, 2021, 05:39:46 am »
Hi, sorry for the extended absence, I've been away for work all summer and have not had physical access to the TV.  I am back now and ready to get this thing figured out!

A few posts ago, I mentioned finding conditional jumps based off of two analog inputs.  I probed these two inputs while turning on the TV and they were both a constant 3.3V.  I traced them out and they seem to go to pullup resistors and an unpopulated 3 pin header.  So it looks like they are not even used in this model.  I am having a hard time figuring out what value the ADC would return given a 3.3V input.

Since we are able to read and write the firmware, do you think it would be possible to modify the firmware to somehow add print("Here") type instructions in critical places?  Something like flashing the power LEDs or an unused output?  Or even maybe enable a UART bus on some unused outputs?  There are just so many paths the program can take and it is very tricky to infer where exactly in the code it is getting stuck.  If the edit does not work, I can just reflash the original firmware right?  Or is there something I am overlooking about the process?
canadaboy25

- Sometimes the light at the end of a tunnel is an on-coming train
 

Offline tru

  • Regular Contributor
  • *
  • Posts: 107
  • Country: gb
Re: Reading firmware out of a mask ROM microcontroller
« Reply #83 on: September 13, 2021, 07:31:13 am »
Hi, sorry for the extended absence, I've been away for work all summer and have not had physical access to the TV.  I am back now and ready to get this thing figured out!

A few posts ago, I mentioned finding conditional jumps based off of two analog inputs.  I probed these two inputs while turning on the TV and they were both a constant 3.3V.  I traced them out and they seem to go to pullup resistors and an unpopulated 3 pin header.  So it looks like they are not even used in this model.  I am having a hard time figuring out what value the ADC would return given a 3.3V input.

Since we are able to read and write the firmware, do you think it would be possible to modify the firmware to somehow add print("Here") type instructions in critical places?  Something like flashing the power LEDs or an unused output?  Or even maybe enable a UART bus on some unused outputs?  There are just so many paths the program can take and it is very tricky to infer where exactly in the code it is getting stuck.  If the edit does not work, I can just reflash the original firmware right?  Or is there something I am overlooking about the process?
That is a very good idea to flash a LED.  There is only the software integrity check where it checks the copy of the code to RAM using the hardware CRC generator, but from memory I think it calculates that on the fly so modifying the binary code should still pass the check - I will re-look at the code when I have a bit of free time.  The only problem I see is that you cannot insert code and can only overwrite, because that would affect other code that is using relative address offsets.  The best approach is probably to modify the disassembly and recompile, but I think HEW trial version limits the compile input assembly size - you will need a full version of HEW.  Alternatively, perhaps IDA Pro allows inserting code?
« Last Edit: September 13, 2021, 07:36:17 am by tru »
 

Offline canadaboy25Topic starter

  • Regular Contributor
  • *
  • Posts: 152
  • Country: ca
Re: Reading firmware out of a mask ROM microcontroller
« Reply #84 on: September 13, 2021, 10:18:25 pm »
That is a very good idea to flash a LED.  There is only the software integrity check where it checks the copy of the code to RAM using the hardware CRC generator, but from memory I think it calculates that on the fly so modifying the binary code should still pass the check - I will re-look at the code when I have a bit of free time.  The only problem I see is that you cannot insert code and can only overwrite, because that would affect other code that is using relative address offsets.  The best approach is probably to modify the disassembly and recompile, but I think HEW trial version limits the compile input assembly size - you will need a full version of HEW.  Alternatively, perhaps IDA Pro allows inserting code?

Yes, I had thought about the problem of inserting code messing up the relative addressing.  I figured that since there are plenty of instructions that just move a constant value to a register or RAM, one of these instructions could be replaced with a subroutine call.  The subroutine could be placed in an unused portion of the firmware and then the removed instruction could be executed inside the subroutine.  Then an LED blink could be added and the subroutine would return.  This should have the desired effect without removing any existing code and without messing up the offsets.

I do not know of any way to edit the firmware from IDA but I am relatively new to using it.  It will probably be easiest for me to just compile the instructions I want to add in HEW and then splice them into the binary manually.  I shouldn't need to add that many to figure out what path the program is taking.

I will take a look at the CRC check in the bootloader you posted to see what will be required for it to accept the modified code.
« Last Edit: September 13, 2021, 10:31:53 pm by canadaboy25 »
canadaboy25

- Sometimes the light at the end of a tunnel is an on-coming train
 

Offline canadaboy25Topic starter

  • Regular Contributor
  • *
  • Posts: 152
  • Country: ca
Re: Reading firmware out of a mask ROM microcontroller
« Reply #85 on: November 02, 2021, 09:44:06 am »
 I have a bit of a problem.  I made a small modification to the TV firmware binary by changing an OR #0x10 to OR #0x0 so that timer A4 would never be activated.  This would mean that the LED would never blink and would be a good test to see if the modification was applied successfully.

I tried flashing using the M16C-flasher tool but it failed immediately after erasing.  It appears it does not like bin files as an input.  I tried reflashing the original firmware from a .mot backup file I made and it wrote the entire thing except for the vector table at the end of the firmware.  Places where there should be FF are 00 on a subsequent read.  I converted the .mot file to a .bin file to ensure it wasn't damaged and it is in fact fine.  For some reason the tool is incorrectly programming the last few bytes.

I tried using your command line tool and was able to flash block 6 (0xE0000 - 0xEFFFF) and block 5 (0xF0000 - 0xF7FFF) but the tool just errors out while trying to flash the final block (0xF8000 - 0xFFFFF).

Is there something I am doing wrong here?  I don't know why the M16C-flasher tool cannot reflash a backup that it made itself...

UPDATE:  I was able to get the original firmware loaded back on using the Renesas FlashStart tool and the original .mot backup.  So I guess I will have to figure out how to convert my modified bin file to a .mot file that the FlashStart tool likes.
« Last Edit: November 02, 2021, 10:01:48 am by canadaboy25 »
canadaboy25

- Sometimes the light at the end of a tunnel is an on-coming train
 

Offline tru

  • Regular Contributor
  • *
  • Posts: 107
  • Country: gb
Re: Reading firmware out of a mask ROM microcontroller
« Reply #86 on: November 03, 2021, 08:56:09 am »
I have a bit of a problem.  I made a small modification to the TV firmware binary by changing an OR #0x10 to OR #0x0 so that timer A4 would never be activated.  This would mean that the LED would never blink and would be a good test to see if the modification was applied successfully.

I tried flashing using the M16C-flasher tool but it failed immediately after erasing.  It appears it does not like bin files as an input.  I tried reflashing the original firmware from a .mot backup file I made and it wrote the entire thing except for the vector table at the end of the firmware.  Places where there should be FF are 00 on a subsequent read.  I converted the .mot file to a .bin file to ensure it wasn't damaged and it is in fact fine.  For some reason the tool is incorrectly programming the last few bytes.

I tried using your command line tool and was able to flash block 6 (0xE0000 - 0xEFFFF) and block 5 (0xF0000 - 0xF7FFF) but the tool just errors out while trying to flash the final block (0xF8000 - 0xFFFFF).

Is there something I am doing wrong here?  I don't know why the M16C-flasher tool cannot reflash a backup that it made itself...

UPDATE:  I was able to get the original firmware loaded back on using the Renesas FlashStart tool and the original .mot backup.  So I guess I will have to figure out how to convert my modified bin file to a .mot file that the FlashStart tool likes.
I've noticed that you mentioned the final block is 0xF8000 - 0xFFFFF.  But my program assumes that there are more blocks 4, 3, 2, 1, 0.  See the source file m16c_mem_map.h where I list each block and their address range.  Perhaps that could be the problem - when I get more time I will compare with your MCU datasheet.  The erase procedure is in blocks, and if successful all addresses will be set to 0xFF so I guess that the final block did not erase.

To convert to .mot file try the srec_cat program, I've place a copy of it on my github with an example .cmd script:
https://github.com/truhy/m16c-flasher/tree/main/Convert%20Binary%20to%20Motorola%20format

This may be useful, here's some examples from manual of srec_cat:
http://srecord.sourceforge.net/man/man1/srec_examples.html
« Last Edit: November 03, 2021, 08:58:35 am by tru »
 

Offline canadaboy25Topic starter

  • Regular Contributor
  • *
  • Posts: 152
  • Country: ca
Re: Reading firmware out of a mask ROM microcontroller
« Reply #87 on: November 04, 2021, 12:25:16 am »
I've noticed that you mentioned the final block is 0xF8000 - 0xFFFFF.  But my program assumes that there are more blocks 4, 3, 2, 1, 0.  See the source file m16c_mem_map.h where I list each block and their address range.  Perhaps that could be the problem - when I get more time I will compare with your MCU datasheet.  The erase procedure is in blocks, and if successful all addresses will be set to 0xFF so I guess that the final block did not erase.

To convert to .mot file try the srec_cat program, I've place a copy of it on my github with an example .cmd script:
https://github.com/truhy/m16c-flasher/tree/main/Convert%20Binary%20to%20Motorola%20format

This may be useful, here's some examples from manual of srec_cat:
http://srecord.sourceforge.net/man/man1/srec_examples.html

I think the erase was successful because I did a read on the chip after a failed programming attempt and all addresses were 0xFF.
I gave the srec_cat program a try previously but the FlashStart tool did not seem to like the file it generated.  It may have been some other fluke though.  I also noticed while using your tool that if I didn't do the programming in separate blocks it would just get stuck on the first block and program it over and over.  So there must be some incompatibility between the two chips

I used the backup .mot file that I reflashed to the chip as a template and wrote a quick python script to convert my bin file to the .mot file that the FlashStart tool likes.

In my edited bin file I removed the enable instruction for the timer A4 so the LED will not be blinking and I then replaced the printf subroutine in the lamp error branch of the code with a subroutine that just turns the LED on solid.  So if my code works, the LED should come on solid.  I disassembled my newly modified firmware with IDA Pro and all of the changes looked good.

Upon flashing the firmware, the LED just stays off.  So either the code is not running the branch that I think it is, or the LED output pin is configured as a timer output and needs something configured differently for it to function as a GPIO pin.  Or there is a checksum somewhere that does not like my modification.  I may re-enable the timer just so I can see if the code will still run after I have added an extra subroutine, converted it, and flashed it.
« Last Edit: November 04, 2021, 12:53:41 am by canadaboy25 »
canadaboy25

- Sometimes the light at the end of a tunnel is an on-coming train
 

Offline canadaboy25Topic starter

  • Regular Contributor
  • *
  • Posts: 152
  • Country: ca
Re: Reading firmware out of a mask ROM microcontroller
« Reply #88 on: November 04, 2021, 07:43:54 pm »
I was finally able to get my own code to run.  I removed the call to the subroutine which initializes timer A4 and also the instruction that enables timer A4.  This prevented the LED from blinking and also ensured P8_0 was free to use as a GPIO.  I then replaced the call to the printf stub in the branch which prints the backlight error message with a subroutine that I added in unused memory.  Inside my subroutine I set P8_0 to an output and set it high.  I did this by manually editing the .bin file and then converting it to a .mot file with my python script.  Flashing this code with the FlashStart tool and running it makes the LED come on and stay on solid.  So everything is working properly!

There are still so many branches that manually moving the call for my subroutine and reprogramming the chip will take ages.  I think the best thing to do is get a printf function and a UART setup.  Luckily UART0 does not seem to be used by the code at all and it is also wired up to the debug header on the board that I am connected to.  It seems likely that this was the UART originally used for debugging purposes.  I will try my best to get the UART set up correctly and then try to implement a basic printf function.  If I get that working then I can really get down to some serious debugging.
canadaboy25

- Sometimes the light at the end of a tunnel is an on-coming train
 

Offline canadaboy25Topic starter

  • Regular Contributor
  • *
  • Posts: 152
  • Country: ca
Re: Reading firmware out of a mask ROM microcontroller
« Reply #89 on: November 07, 2021, 08:32:22 am »
Success!!  Well, sort of.

I replaced the function which initializes the PWM timer for the LED with a function that initializes the UART0 interface.  I then used HEW to compile my own little subroutine which I can use to do whatever I want.  I then wrote a python script which converts the .mot file from HEW to .bin and copies the subroutine to an unused portion of the firmware.  I can then manually replace any instruction with a jump to my new subroutine and convert the file back to a .mot to be flashed to the chip.  The instruction that I replaced in the code is run from my subroutine so the program flow is not altered.

I was eventually able to implement a very basic printf and see the debug codes on a terminal!  I got "[EVM]No need to init EEPROM"  and "[EVM]Lamp error over 5 times -> ERR_STBY".  So the code was ending up where we though it was.

Looking at the graph view in IDA (attached image), there are 4 conditional branches that stand between a normal start and a backlight error.  For it to get to the backlight error, all 4 checks must fail.  I started with the first one which compares the byte 0xFE9 in RAM to 0x5 and goes to a normal start if the value is less than 5.  This really stands out as the number of attempts since the error code says 5 failed backlight attempts.

After spending hours editing the firmware and placing print statements at different locations, and even dumping the whole RAM, I traced byte_FE9 to the EEPROM integrity check function.  Before the function is called FE9 is 0 and after the function FE9 is 5.  After digging deeper into the function, byte FE9 is loaded straight into the RAM from the on-board EEPROM that I mentioned quite a few posts back.  It seems unlikely that the EEPROM happened to have that specific byte corrupted but it sure seems strange.

I decided to take a shot in the dark and "patched" the firmware to set FE9 back to 0 after the EEPROM function and flashed it to the TV.  Plugged the TV in and it powered right up!  I can play video from an HDMI source and all of the controls seem to work.  So clearly there are no major faults with the backlight circuitry.  It is really tempting to just close it up and call it a win, but I would like to repair it properly.  Obviously it is one of the other 3 conditional branches in the image I attached that is responsible for the error detection.

Looking at it again, it would make sense for it to be the last branch since as I mentioned, there is a mode to force power-up and disable error detection so that branch would have to be before the actual error detection in order to bypass it.  I suppose the next step is to start tracing the RAM value D21 and see what is controlling it.

Modifying the firmware binary by hand is a huge pain so if anyone has any ideas about how to improve the process or any thoughts about my troubleshooting logic then let me know!
canadaboy25

- Sometimes the light at the end of a tunnel is an on-coming train
 

Offline tru

  • Regular Contributor
  • *
  • Posts: 107
  • Country: gb
Re: Reading firmware out of a mask ROM microcontroller
« Reply #90 on: November 07, 2021, 08:14:16 pm »
Cool, I see I'm a bit tooo late, you've already found a nice solution with Python script.  But just to let you know, I've found out that the FlashStart tool simply doesn't like the first line that srec_cat generates.  The first line is S0 record, which is some sort of ID, replacing it with this short one should work:
S0030000FC

Impressive work, and unfortunately I can't think of any other easier way than what you're doing already.
 

Offline abyrvalg

  • Frequent Contributor
  • **
  • Posts: 824
  • Country: es
Re: Reading firmware out of a mask ROM microcontroller
« Reply #91 on: November 07, 2021, 10:53:48 pm »
> Modifying the firmware binary by hand is a huge pain
Automate it in Python at least, make a tool that takes an asm file containing the code to insert and two addresses - code insertion and jump pathching, and do all necessary steps programmatically - call HEW to assemble the asm, insert the result into the fw file at the correct offset derived from code insertion address, create a jump to your code at the patch address (a jump instruction shouldn’t be that hard to encode).
Or if you are really serious into that, try implementing the Edit->Patch program->Assemble command support in IDA plugin (take an asm line input, produce a temporary asm file containing necessary headers/footers and your line between, invoke HEW, collect resulting bytes, pass them back to IDA)
 

Offline canadaboy25Topic starter

  • Regular Contributor
  • *
  • Posts: 152
  • Country: ca
Re: Reading firmware out of a mask ROM microcontroller
« Reply #92 on: November 08, 2021, 07:43:52 am »
Cool, I see I'm a bit tooo late, you've already found a nice solution with Python script.  But just to let you know, I've found out that the FlashStart tool simply doesn't like the first line that srec_cat generates.  The first line is S0 record, which is some sort of ID, replacing it with this short one should work:
S0030000FC

Impressive work, and unfortunately I can't think of any other easier way than what you're doing already.

Oh, that is good to know.  Will probably come in handy for a future project.  I'm glad I wrote the python script as it forced me to learn how the Motorola format works which is never a bad thing.
Thanks for the kind words.

> Modifying the firmware binary by hand is a huge pain
Automate it in Python at least, make a tool that takes an asm file containing the code to insert and two addresses - code insertion and jump pathching, and do all necessary steps programmatically - call HEW to assemble the asm, insert the result into the fw file at the correct offset derived from code insertion address, create a jump to your code at the patch address (a jump instruction shouldn’t be that hard to encode).
Or if you are really serious into that, try implementing the Edit->Patch program->Assemble command support in IDA plugin (take an asm line input, produce a temporary asm file containing necessary headers/footers and your line between, invoke HEW, collect resulting bytes, pass them back to IDA)

This is exactly what I was planning on doing but dealing with different instruction lengths and types and also sometimes having to shuffle a few things around as to not upset the program flow seemed like more work than it was worth.

I hate to give up before I find the root of the problem, but I'm running out of places to look.  I traced that last jump branch back to the functions which take an analog to digital sample and compare it to a lookup table in ROM.  Adding a print statement to the ADC function prints FF continuously like I expected as I previously traced those pins to an unused connector with pullup resistors.  I pulled the pins low on the unused connector and was able to get a corresponding readout on my debug terminal.  So unless those two pins also run somewhere else on the board though an internal layer, that functionality must just not be used.  I tried probing around but could not find any other connections.  Very hard to tell for sure without a schematic.

One of the other jump branches is determined by a RAM value set by reading data from UART7.  UART7 is connected to the soft touch buttons so this must be the branch for the special start mode.  There are other clues to this throughout the firmware.

The two other branches seem to be statically set based on some values loaded in from the EEPROM upon startup.

Apparently this is a very common issue to occur on these Sharp TV's after a power outage.  This suggests that it is in fact some values getting corrupted in memory somewhere.  The "fix" online for this problem is to just disable the backlight error check in the service menu, but this only lasts as long as power is applied.  So even if I did find the corrupt value and repair it, there is a good chance that it may happen again.  At least with the firmware patch, the TV will keep working after it is unplugged.  I'll leave my little debug connector soldered to the board in case it acts up again in the future.

Big thanks to abyrvalg for finding and understanding so many relevant parts of the firmware, and a massive thanks to tru for the wealth of knowledge about these microcontrollers.  Without the help I wouldn't have known where to start.  Hopefully I'll have a chance in the future to have another go at getting the firmware out of that mask ROM chip from the other TV!
canadaboy25

- Sometimes the light at the end of a tunnel is an on-coming train
 

Offline abyrvalg

  • Frequent Contributor
  • **
  • Posts: 824
  • Country: es
Re: Reading firmware out of a mask ROM microcontroller
« Reply #93 on: November 08, 2021, 12:12:23 pm »
Maybe it's too late but I took a look into EEPROM load func (the one at 0xE5F4E - right?). LampErrorCount (that byte at 0xFE9) is loaded from EEPROM address 0x11 and this is the only possible source of non-zero value there.
There is an EEPROM map at 0xEDE3A:
struct {
  uint16 ram_addr;
  uint8 unk;
  uint8 ee_addr;
  uint8 i2c_slave_addr; //always A0
  uint8 default_value;
  uint8 unk;
} [0xB2]

LampErrorCount address is 0x11, defalut value is 0.
BTW, looks like it is possible to force defaults by holding SCL or SDA low at start. The first thing the load func does is dummy I2C access to test that SCL/SDA are not held by someone (calls at E5F51, E5F54). If there is any error it takes the E5F5E path, calling the debug printf stub to print "[SDM]EEPROM access failure", then load all RAM vars with defaults from the table.
 

Offline canadaboy25Topic starter

  • Regular Contributor
  • *
  • Posts: 152
  • Country: ca
Re: Reading firmware out of a mask ROM microcontroller
« Reply #94 on: November 08, 2021, 11:13:25 pm »
Maybe it's too late but I took a look into EEPROM load func (the one at 0xE5F4E - right?). LampErrorCount (that byte at 0xFE9) is loaded from EEPROM address 0x11 and this is the only possible source of non-zero value there.
There is an EEPROM map at 0xEDE3A:
struct {
  uint16 ram_addr;
  uint8 unk;
  uint8 ee_addr;
  uint8 i2c_slave_addr; //always A0
  uint8 default_value;
  uint8 unk;
} [0xB2]

LampErrorCount address is 0x11, defalut value is 0.
BTW, looks like it is possible to force defaults by holding SCL or SDA low at start. The first thing the load func does is dummy I2C access to test that SCL/SDA are not held by someone (calls at E5F51, E5F54). If there is any error it takes the E5F5E path, calling the debug printf stub to print "[SDM]EEPROM access failure", then load all RAM vars with defaults from the table.

Yes that is the EEPROM function I was talking about.  FE9 gets 0x5 loaded to it straight from the EEPROM.  I noticed the default settings branch too and thought perhaps the stored EEPROM value got changed.  However, if that is the only place that the FE9 byte gets modified, how does the code check for an actual backlight error if it is just supposed to load a 0 by default?  I have not been able to find any code that actually seems to check external inputs except for that ADC function which does not seem to be used.

Were you able to find any code that looks like it actually checks for backlight errors?  I'm not sure how it would work since the only place the printf("Lamp error") is called is during the startup process.  I don't see any way for it to detect an error while the TV is running.  Unless there is an interrupt service routine somewhere that is checking for errors?
canadaboy25

- Sometimes the light at the end of a tunnel is an on-coming train
 

Offline abyrvalg

  • Frequent Contributor
  • **
  • Posts: 824
  • Country: es
Re: Reading firmware out of a mask ROM microcontroller
« Reply #95 on: November 11, 2021, 12:03:47 am »
The actual lamp error condition check is in func at 0xE03BC. Pin 40 (P5.4) is checked there (by calling gpio_read(40)) to be in good (0) / bad (1) state long enough (the function looks like being called periodically, it counts good/bad state duration as number of invocations). An error 0x16 (lamp error) gets posted to some queue from there in case of error (at 000E041B, 000E0470). The EEPROM lamp error counter gets cleared (call from 000E0448) in good case.
 

Offline gashtaan

  • Contributor
  • Posts: 45
  • Country: sk
Re: Reading firmware out of a mask ROM microcontroller
« Reply #96 on: February 21, 2022, 05:52:30 am »
If the default passwords (all 0x00 or 0xFF) doesn't unlock the read command then there is actually a hack to determine the password:
https://hackaday.io/project/723-reverse-engineering-toshiba-r100-bios
I believe this is not true for v4 bootloader, ID is checked without using branches there, so code will be executed always in same amount of time. Though, I'm surprised that Renesas would make such a rookie mistake in v1 bootloader. By any chance, haven't you dumped also v1 bootloader from something?
 

Offline tru

  • Regular Contributor
  • *
  • Posts: 107
  • Country: gb
Re: Reading firmware out of a mask ROM microcontroller
« Reply #97 on: February 21, 2022, 09:25:47 am »
If the default passwords (all 0x00 or 0xFF) doesn't unlock the read command then there is actually a hack to determine the password:
https://hackaday.io/project/723-reverse-engineering-toshiba-r100-bios
I believe this is not true for v4 bootloader, ID is checked without using branches there, so code will be executed always in same amount of time. Though, I'm surprised that Renesas would make such a rookie mistake in v1 bootloader. By any chance, haven't you dumped also v1 bootloader from something?
Oh, so they've fixed the hack.  No I have not dumped v1 bootloader.  I've only encountered v4 bootloader and default password, but then again I'm not interested in hacking it. I was only trying to repair a control panel as a challenge.  This was a result after offering to pay the manufacturer to repair it, which they replied that their control panels are advanced and are not repairable, and we should purchase a new unit.
 

Offline gashtaan

  • Contributor
  • Posts: 45
  • Country: sk
Re: Reading firmware out of a mask ROM microcontroller
« Reply #98 on: February 25, 2022, 01:37:19 pm »
I'm interested in downloading firmware from some device using M3062 MCU, but this one is unfortunately locked with unknown ID. I'd like to try to test glitching on it, but it would be much helpful to have some unlocked chip to do experiments.

I was only trying to repair a control panel as a challenge.
What is that control panel you have with the chip unlocked? It's long-shot, but maybe it would be cheaper to buy some salvaged board with this chip on it.
 


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf