Code Patching for OTP microcontroller
5 years ago, one of my colleagues developed a project upon 8051 platform. Unfortunately, there was a fatal bug in the firmware which would lead to a business fiasco and damage company's goodwill. Our boss asked us if there was any means to save the business and escape from the crisis. I knew that the microcontroller' intermal memory was actually using OTP (One Time Programming) EPROM technology, so I promised to study the code and try to hack it.
After a short survey, I found we can save the chips even these parts had already been programmed .
So I told boss that the code could be patched. The distributors called back the microcontrollers and reprogrammed with the patched code. Everybody was grateful. However, nobody even mentioned me or expressed their appreciation. It seems that code was self-healing. But after that, many project managers who have bug issues will ask my help. Unfortunately not all the microcontrollers can saved if
- The microcontrollers are really masked in silicon production process, or
- The microcontrollers are fully fixed, because the unused area are programmed to 0x00.
OTP is an EPROM derivated process, the EPROM can be erased by UV light. This method is popular in early microcontroller products. As ceramic package is very expensive, the plastic package of EPROM is more and more popular. It can be erased (I will told you how to erase it in another Blog.) by a special method. It is a de facto One-Time-Programming memory, since it can not be erased because of package. Anyway, remember a fact that every byte in EPROM can be programmed from 0xFF to 0x00, but not in the other way.
Hack 8051 and Patch it

Here is my detail implementation of code patching. I use 8051 and assembly language as example, but the principle still applies to any other platforms such as PIC, Z8 OTP microcontroller.
Let us study the firmware. Normally we can call the code leads to a software bug as "buggy code", the code prior to buggy code as "prior code", the code followed the buggy code as "trailing code", and the patches as "patch code". These terminologies are just for your reference. In general, buggy code is just a few bytes, we can easily reprogrammed these bytes, whatever it represented, into 0x00. In 8051 assembly lanuage, 0x00 stands for no operation ("NOP"). IF THE UNUSED AREA WERE PROGRAMMED AS 0XFF, we can put our "patch code" in the unused area. It is better to put the code at a memory section start address, such as 0x8000, 0x9000, 0xA000, because these addresses can be easily programmed in the trailing code area. The most important issue is how to jump to patch code and jump back. Remember only jump is suitable in certain microcontroller platform, because of stack limitation. It is very tricky to find trailing code to jump the patch code. Rule is try to find a code can be reprogrammed as "LJMP #patch_code", "AJMP #patch_code", "SJMP #patch_code". You must interprete the assembly pseudo code into hex code and match with trailing code one by one. One major limitation is relative jump. If there is a relative jump. You have to recalculate the relative jumping distance and make a new assembly code. If you can find one in trailing code, then re-programmed all code from buggy code to the location to 0x00, which means NOP. Followed a JMP to patch code. In the patch code, write a software patch and copy all involved trailing code here, then a JMP back to the following address of your JMP code. If it is not available in trailing area, then try prior code instead. You will feel lucky as soon as you find one.
For example, there is a buggy code at address 0x7122, we plan to put patch code at address 0x8000. LJMP 0x8000 in 8051 assembly code is 0x028000. AJMP 0x8000 in 8051 assembly code is 0x81,0x00. I would like to find LJMP first. In the trailing code, I found one assembly code MOV R7, A on address 0x7208, which means 0xFF. I am really lucky to find a 0xFF. But many other assembly codes are all right as well. For instance, MOV A,@Ri, MOV @Ri,A are also all right, since all the code can be reprogrammed as 0x02. But still we have to check the following code can be reprogrammed into 0x80 or not. The next byte is 0x83, which means MOV direct, direct. I reprogrammed these three sytes into 0x028000, because codes range from buggy code and current address are reprogrammed into 0x00 as NO OPERATION in 8051, these code fragment has to be copied to patched code as well with LJMP back to address followed the current address (PC+1). In this sample, it should be PC+3 at address of 0x720C, since MOV direct, direct need extra two bytes. So update your 8051 assembly code and reprogrammed the device. It should work now. NOP will introduce some small delay, but in general it is all right in non-time-critical task. So enjoy hacking...
There are some limitations for memory patching:
- Unused space should keep its unprogrammed state as 0xFF;
- Enough unused space available for patching;
- Non-ISR bug patch;
- AJMP, SJMP leads to a relative address jump, which means the trailing bytes are changing in final hex code;
- Security bit status. The microcontrollers can not be reprogrammed if its security bit is programmed;
- Detail know-how of target microcontroller platform, especially assembly code;
- Absolute location for assemblers and compilers. (Today more and more projects are programmed in C, the final hex code changes a lot depends on host OS, complier version, compling model, memory usage, variables modifier...).
Today more and more microcontrollers are using flash memory, but OTP microcontrollers are relatively cheap, because most of the silicon processes are very old.
- allankliu's blog
- Add new comment
- 1376 reads




