Hello,
We are using the S12ZVMC128 and we need maximum protection for firmware. We are aware of the FSEC Firmware Security bits, but as we know there are a lot of hackers who can somehow reset bits etc.
We are NOT using any boot loader, so we only expect to program via the MCU programming interface which will be available on our custom board.
We do not want anyone to read the FLASh or EEPROM or SRAM, so the best we can do as per the Reference Manual is to set the Flash Security States bits to 00. Is this enough in the real world?
How secure is the S12Z series against most hacking approaches both hardware and software? Is there any documentation on the same?
Is there any unique ID coded in each chip which we can access ? At least this could help us locking the firmware to a specific physical chip.
Any help would be highly appreciated.
Manish
Hi,
the link you are mention is not a link even it looks like a link. Mea culpa, I have only copy/paste it. It is a path where the table is stored in the CodeWarrior help structure. The same you can see under my signature where I copy/past the page from the help.
The same you can find if you write, for example, "DW" into the search and it direct you to a debugger Shell Commands.
Probably answer on the second part is already answered: https://community.nxp.com/thread/455729
If you want fre tool then it is enough to install special edition version of the CodeWarrior which has some limitations for compiler.
Best regrads,
Ladislav
Hi,
The sources of information are:
- CodeWarrior for Microcontrollers V10.x > Targeting Microcontrollers > Microcontrollers V10.x Targeting Manual > CodeWarrior Command Line Debugging > Microcontrollers-Specific HIWARE Commands
(se list bellow)
The device id is size of 8 bytes from 1F_C000 to 1F_C007. Of course you can read also other "reserved" field but they store data the meaning is confidential, so I am sorry, I am not allowed to share. The same is valid for meaning of the device ID fields.
Best regards,
Ladislav
The table below lists the supported HIWARE commands followed by:
The following columns represent the status in the CodeWarrior Eclipse IDE:
Command | Status | Description |
---|---|---|
HIWARE | ||
VER | S-CW | Lists the version of all loaded commands Syntax about |
AUTOSIZE | NA | Selects window sizing mode |
OPENIO | NA | Loads an IO simulation component |
OPENPROJECT | U | Opens an existing project |
OPEN | NA | Opens a component window |
SET | U | Loads a target component |
LOAD | U | Loads an application (Code & Symbols) |
LOADCODE | U | Loads an application (Code only) |
LOADSYMBOLS | S-CW | Loads an application (Symbols only) Syntax loadsym <filename> |
FONT | U | Changes font in component windows |
BCKCOLOR | U | Changes background color of component windows |
SLAY | NA | Saves the layout and options of all components |
ACTIVATE | NA | Activates a window component (in/out focus) |
CLOSE | NA | Closes a component window |
SYSTEM | S-CW | Executes an external application Syntax system <command> |
EXIT | S-CW | Terminates this application Syntax quitIDE |
RESET | S-CW | Resets the target MCU SyntaxReset |
HELP | S-CW | Lists available commands; to get help on a specific command, use the command followed by '?' Syntax help help <command><command> ? |
HIWARE Engine | ||
LF | S-CW | Opens a log file Syntax (for command) log c <file> Syntax (for session) log s <file> |
NOLF | S-CW | Closes a log file Syntax (for command) log off c Syntax (for session) log off s |
CR | U | Records all commands to a file |
NOCR | U | Stops recording commands to a file |
LOG | S-CW | Specifies items to be logged Syntax (for command) log c <file> Syntax (for session) log s <file> |
BS | P | Sets breakpoint Syntax bp [-{hw|sw|auto}] {<func>|[<ms>:]<addr>|<file> <line> [<column>]} bp all|#<id>|<func>|<addr> enable|disable|{ignore <count>} bp #<id> cond <c-expr> |
SAVEBP | U | Saves breakpoints into a file |
STEPINTO | S-CW | Step Into Syntax step [asm|src] into |
STEPOUT | S-CW | Step out Syntax step [asm|src] out |
STEPOVER | S-CW | Step over Syntax step [asm|src] over |
RESTART | S-CW | Restart execution Syntax restart |
DDEPROTOCOL | U | DDE Protocol options |
DEFINEVALUEDLG | U | Opens a GUI to define a value for the symbol/variable given as parameter |
BC | S-CW | Clears breakpoint Syntax bp all|#<id>|<func>|<addr> off |
BD | S-CW | Lists breakpoints Syntax bp |
GO | S-CW | Starts execution (Go) Syntax go |
STOP | S-CW | Stops execution (Halt) Syntax stop |
P | S-CW | Executes an instruction (Flat step) Syntax stepi |
T | S-CW | Executes CPU instructions Syntax stepi |
Configuration Example
| ||
WB | S-CW | Writes byte(s) into target memory Syntax mem <addr-spec> [<range>] [-s|-ns] [%<conv>] =<value> |
WW | S-CW | Writes word(s) into target memory (2 bytes) Syntax mem <addr-spec> [<range>] [-s|-ns] [%<conv>] =<value> |
WL | S-CW | Writes long(s) into target memory (4 bytes) Syntax mem <addr-spec> [<range>] [-s|-ns] [%<conv>] =<value> |
MS | S-CW | Writes byte(s) into target memory (same as WB) Syntax mem <addr-spec> [<range>] [-s|-ns] [%<conv>] =<value> |
RD | S-CW | Lists registers Syntax reg all |
RS | S-CW | Sets registers Syntax reg <reg-spec>{..<reg>|#<n>} [-s|-ns] [%<conv>] =<value> |
MEM | U | Lists memory map |
DASM | S-CW | Disassembles target memory Syntax disassemble pc|[<ms>:]<addr> [<count>] |
DB | S-CW | Lists byte(s) from target memory Syntax mem <addr-spec> [<range>] [-s|-ns] [%<conv>] [-np] |
DW | S-CW | Lists words from target memory (2 bytes) Syntax mem <addr-spec> [<range>] [-s|-ns] [%<conv>] [-np] |
DL | S-CW | Lists long(s) from target memory (4 bytes ) Syntax mem <addr-spec> [<range>] [-s|-ns] [%<conv>] [-np] |
CD | S-CW | Lists or changes directory Syntax cd |
E | S-CW | Evaluates an expression and lists its result Syntax evaluate [#<format>] [-l] [<var|expr>] |
A | S-CW | Evaluates an expression and assigns its result to an existing variable Syntax var <var-spec> [-s|-ns] [%<conv>]=[evaluate [#<format>] [-l] [<var|expr>]] Example var myVar = [evaluate 1+1] - assigns value "2" to "myVar" |
PRINTF | U | Display a string on the window using printf like format |
FPRINTF | U | Write a string to a file using fprintf like format |
NB | S-CW | Changes or displays the default number base for the value of expressions Syntax evaluate [#<format>] [-l] [<var|expr>] |
LS | U | Lists also global variables and procedures of the loaded application |
SREC | P | Loads of Motorola S-records from a specified file Syntax restore -h *.lod [[<ms>:]<addr>|+<offset>] [8bit|16bit|32bit|64bit] restore -b *.lod [<ms>:]<addr> [8bit|16bit|32bit|64bit] |
SAVE | S-CW | Saves a specified block of memory to a specified file in Motorola S-record format Syntax save -h|-b [<ms>:]<addr>... <filename> [-a|-o] [8bit|16bit|32bit|64bit] |
PAUSETEXT | NA | Displays a modal message box for testing purpose |
TESTBOX | NA | Displays a modal message box with a given string |
REGFILE | U | Loads the I/O register descriptions from a 'register file' |
REGBASE | U | Sets the base address of the on-chip I/O registers |
ANDB | U | Bitwise-AND with target memory byte |
ANDW | U | Bitwise-AND with target memory word (2 bytes) |
ANDL | U | Bitwise-AND with target memory long (4 bytes) |
NANDB | U | Bitwise-NAND with target memory byte |
NANDW | U | Bitwise-NAND with target memory word (2 bytes) |
NANDL | U | Bitwise-NAND with target memory long (4 bytes) |
ORB | U | Bitwise-OR with target memory byte |
ORW | U | Bitwise-OR with target memory word (2 bytes) |
ORL | U | Bitwise-OR with target memory long (4 bytes) |
NORB | U | Bitwise-NOR with target memory byte |
NORW | U | Bitwise-NOR with target memory word (2 bytes) |
NORL | U | Bitwise-NOR with target memory long (4 bytes) |
EXORB | U | Bitwise-EXOR with target memory byte |
EXORW | U | Bitwise-EXOR with target memory word (2 bytes) |
EXORL | U | Bitwise-EXOR with target memory long (4 bytes) |
MEMCOPY | S-CW | Copies the target memory |
MEMBITCOPY | S-CW | Copies one bit from one memory address to another bit to another memory address Syntax copy [<ms>:]<addr>[..<addr>|#<bytes>] [<ms>:]<addr> |
DEFINE | S-CW | Defines a symbol and associates a value Syntax set varName ?value? <Tcl command> |
UNDEF | S-CW | Removes a symbol definition Syntax unset varName <Tcl command> |
RETURN | U | Terminates the current command processing level |
GOTO | U | Goes to the line following the label |
GOTOIF | U | Goes to the line following the label if condition is TRUE |
WHILE | S-Tcl | Executes commands as long as the condition is true |
FOR | S-Tcl | Executes commands up to a predefined number of times |
REPEAT | S-Tcl | Executes commands until a certain condition is true |
IF | S-Tcl | Executes different command sections depending on the conditions |
FOCUS | NA | Assigns a component as the destination for all subsequent commands |
WAIT | S-CW | Waits by time tenths of a second Syntax wait |
AT | U | Executes the next command at time (in ms) |
CF | S-CW | Executes commands in the specified command file |
CALL | S-CW | Executes commands in the specified command file Syntax source |
Source | ||
SPC | NA | Highlights the statement corresponding to the code address |
SMEM | NA | Highlights the statements corresponding to the code address range |
SMOD | NA | Loads the corresponding module's source text |
SPROC | NA | Highlights the statement of the procedure that is in the procedure chain |
FOLD | NA | Hides source text for clearness at program block level |
UNFOLD | NA | Exhibits the contents of folded source text blocks |
SLINE | NA | Displays the line |
FINDPROC | NA | Find the Procedure |
FIND | NA | Searches an arbitrary pattern in the currently loaded source file |
ATTRIBUTES | NA | Sets up the display |
Assembly | ||
SPC | NA | Lists the specified address |
SMEM | NA | Lists the specified address |
ATTRIBUTES | NA | Sets up the display |
Procedure | ||
ATTRIBUTES | NA | Sets up the display |
Register | ||
ATTRIBUTES | NA | Sets up the display |
Memory | ||
SPC | NA | Lists the address given as an argument |
SMEM | NA | Lists the memory range given as an argument |
SMOD | NA | Lists the first global variable of the module |
FILL | S-CW | Fills a memory range with the given value Syntax mem <addr-spec> [<range>] [-s|-ns] [%<conv>] =<value> |
UPDATERATE | NA | Sets the update rate |
ATTRIBUTES | NA | Sets up the display |
COPYMEM | S-CW | Copies a memory range to a specified location Syntax copy [<ms>:]<addr>[..<addr>|#<bytes>] [<ms>:]<addr> |
SEARCHPATTERN | NA | Search a pattern in memory |
REFRESHMEMORY | S-CW | After releasing caches, refreshes the memory Syntax refresh |
Data | ||
SPROC | NA | Displays local or global variables of the procedure given as parameter |
ADDXPR | NA | Adds a new expression in the data component |
PTRARRAY | NA | Switches on or off the pointer as array displaying |
SMOD | NA | Displays global variables of the module given as parameter |
ZOOM | NA | Exhibits the member fields of structures by 'diving' into the structure |
UPDATERATE | NA | Sets the update rate of the data component |
DUMP | P | Dumps the content of the data component to the command line Syntax display |
ATTRIBUTES | NA | Sets up the display |
REFRESHDATA | S-CW | After releasing caches, refreshes the display Syntax refresh |
Command | ||
CLR | S-CW | Clears the Command window Syntax cls |
ATTRIBUTES | NA | Sets up the display |
Hi Ladislav,
That is great info. Please note that all the Codewarrior links you provided do not work because on launching each one goes to '127.0.0.1' !!! I tried getting to the NXP site and finding them myself but gave up after lot of navigation not yielding any result. Could you please check this and post the links again?
I see that TCL/TK is used in the debugger window so scripting there will not be a problem.
I have a related question. Is there a free tool we can use for loading the ELF file without the IDE. As an example we want to have some laptops which can carry the latest software to the field and update the same using PE/Universal etc. (We don't use bootloader) but when doing so we want to run a script also which would store the date and time from the PC to the FLASH and do some other updates. Ideally it would be great if it could also debug. Any free GUI or command line tool would be fine.
Hi,
So here it is.
I am going to start that Device ID is placed on the address 0x1FC000 which is not presented in the documentation because it is internal number which reason is hidden to public.
I have created two command files you can run in the debugger window – see and test attached project.
They are AAA_Read_Device_ID_And_OTPROM.cmd and AAA_ProgramOnceField.cmd.
The project which also present reading and writing program once field is not relevant but should be created for the device we want to play with. It is not required to be code (simple code, enough to use what is generated by wizard) loaded into the MCU’s memory. However, necessary is the debugger is connected to a memory. Because of this it is enough to set:
…. And press debug
In the debug enable “Debugger Shell”:
Before continuing please modify flash clock setup in both files to value suitable for programming on the basis of the oscclk you use. In the files search for lines
Write into debugger shell command which runs the AAA_Read_Device_ID_And_OTPROM.cmd:
source "c:\D\CODING & SW\ECLIPSE\S12ZVMC-FLASH-WRITEONCEFIELD-CW106\AAA_Read_Device_ID_And_OTPROM.cmd"
(it is possible you have different path to the file…please change it)
The command will execute and shows:
Device ID
And Program field phrase 0. If you want to see another phrase you should modify AAA_Read_Device_ID_And_OTPROM.cmd line set PHRASE 1.
Change 1 to the phrase you want to see and run the command presented above “source …..” again. It is enough to press arrow up on the keyboard to see and use previous commands.
In order to program selected field use and run command “source” with the file:
AAA_ProgramOnceField.cmd
source "c:\D\CODING & SW\ECLIPSE\S12ZVMC-FLASH-WRITEONCEFIELD-CW106\AAA_ProgramOnceField.cmd"
The same note, the path you have could be different so adjust it.
The same line as in previous file should be changed to select the phrase you want to program.
As a result you will see programming algorithm and also read back of the field, example of output:
%>source "c:\D\CODING &
SW\ECLIPSE\S12ZVMC-FLASH-WRITEONC
EFIELD-CW106\AAA_ProgramOnceField
.cmd"
############################
Programming Field =
2
############################
cmdwin::mem 0x0386 %x = 0x30
cmdwin::wait 1000
cmdwin::mem 0x0382 %x = 0x05
cmdwin::mem 0x038C %x = 0x07
cmdwin::mem 0x038D %x = 0x00
cmdwin::mem 0x038E %x = 0x00
cmdwin::mem 0x038F %x = 2
cmdwin::mem 0x0390 %x = 0xA2
cmdwin::mem 0x0391 %x = 0xB2
cmdwin::mem 0x0392 %x = 0xC2
cmdwin::mem 0x0393 %x = 0xD2
cmdwin::mem 0x0394 %x = 0xE2
cmdwin::mem 0x0395 %x = 0xF2
cmdwin::mem 0x0396 %x = 0xA3
cmdwin::mem 0x0397 %x = 0xB3
cmdwin::mem 0x0386 %x = 0x80
cmdwin::wait 1000
############################
Read back Programmed Field =
2
############################
cmdwin::mem 0x0386 %x = 0x30
cmdwin::wait 1000
cmdwin::mem 0x0382 %x = 0x01
cmdwin::mem 0x038C %x = 0x04
cmdwin::mem 0x038D %x = 0x00
cmdwin::mem 0x038E %x = 0x00
cmdwin::mem 0x038F %x = 2
cmdwin::mem 0x0386 %x = 0x80
cmdwin::wait 1000
cmdwin::mem 0x0390 8
390 $a2 $b2 $c2 $d2 $e2 $f2
$a3 $b3 . . . . . . . .
….Are you able to test? Do you understand?
Best regards,
Ladislav
Hi,
I have not tried writing and reading the OTP, but I tried getting the Device ID using the command
mem 0x1FC000, this only provides a single byte. How long is the device id? I can see upto xxx09 are bytes followed by 0xFF.
Also for memory following this address, I can see a lot more data up to 1FC0BF. Is there any documentation for all of this?
Is there a PDF reference for all the scripting commands? I tried looking up PE Micro site but could not find the right document. I was looking at CPROGS12ZZ User Guide v.1.00 and PROGS12ZZ User Manual v.1.00 (.pdf)
1) The memory is program once and read anytime. You can really read it anytime you want. The programming the field is possible only once for each phrase. It is OTPROM. No mass erase or another command can return the status of the phrase back to erased status.
2) The chip ID is unique as I wrote before. However, the meaning is hidden for public.
3) Theoretically, the only thing which would be the safest for you is to safely damage BKGD pin to disable any connection to the MCU in the future when it is programmed. I have never heard about this possibility and please do not think about it as a real solution. This is only imagination.
4) If I think about security. We have to believe the security is working because if I accept fact there is some possibility to read the code via BDM then there is also possibility to analyze this code and get info about security actions….what is being read, what is being compared
5) BTW, the ID can be simply read by command flow in command window window as well as it can be added to preload file before programming the phrase
//--- Read ID ---
WB MMCCTL1 0x10 // enable ROM memory 0x40_0000
DW 0x400000'G,4 // get ID
WB MMCCTL1 0x00 // disable ROM memory 0x40_0000
Best regards,
Ladislav
Hi Ladislav
Thanks for your very helpful and useful responses.
I understand now that ReadOnce is only a command name but it can read the values written in the Write Once area any number of times. I also understand that the Write Once area can only be written to once and never erased once written even if the device is mass erased.
Please confirm that the above understanding is correct.
In point 2 you write that there is a CHIP ID, and that's great, we don't care about the meaning as long as it is unique per physical chip.
In point 5 the address you have given is that of the CHIP ID?
We are using the PEMicro Multilink Universal programmer and we can't find any 'console' or command line tool in Codewarrior to execute this script. Could you guide us on how / where this is? Also if we could insert such a script during programming (even for production) we would be able to write current date etc from the PC to the firmware? Is there any document you can point us to for this?
Hi,
ups, there is misunderstanding. I have been all the time talking about S12XEP device and having checked it back I found you use S12ZVM. I'll must go to beginning and prepare a new answer. I am solving a few similar things with different MCUs in parallel so an information mix happened in my mind.
I am really sorry. Probably I will also erase messages which could confuse someone.
Best regards,
Ladislav
I've been looking on information about this and NXP position is that:
No security feature is absolutely secure. However, NXP’s strategy is to make reading or copying the FLASH and/or EEPROM difficult for unauthorized users.
There is no special ID, however you can use write once field to create specific device.
Currently I do not have example for S12ZVM device but you can use https://community.nxp.com/message/864084 as a helping hand to continue.
There are two ways to program the field.
The first one requires special BDM code, I do not know whether such a code exists.
The second approach is to program the device with own code which writes this field (20.4.7.6 Program Once Command) after first execution and then clear the flash and write application code into it.
Before I found already existing example I created my own see attachment.
It is a little bit extended version of https://community.nxp.com/docs/DOC-334388.
Best regards,
Ladislav
Hello Ladislav,
Is this memory write once / read once during the life of the MCU or till it is fully erased by a programmer? Checking this before trying it out on our board :smileyhappy:.
Is there any suggested strategy(ies) on how to use this effectively?
This question is more like even if I write once and read once, how can I use it to ensure that my code (even if copied) detects this? because if I write any code which checks this it cannot check every time it boots but only the first time and if it set's any flag the flag will get copied when someone copies the Flash and EEPROM.
Hi,
I see the best way is to load phrase while you program the device by script of the programmer. In this way the programming of the field is not a part of application and you only test the phrase for correct value written into it.
As an example I have prepared for you a short code which contains adjusted preload.cmd file and ask for phrase you want to program in the OTPROM before application download. I have attached the project with the file. You can test.
preload.cmd file content:
DEFINEVALUEDLG "Information required to write phrase X of OTPROM" "FCLKDIV" 17 "To program it, the command script needs \nthe correct value for the FCLKDIV onchip register.\n\nDatasheet proposed values:\n\noscillator frequency\tFCLKDIV value (decimal)\n\n 16 \tMHz\t\t17\n 12 \tMHz\t\t13\n 8 \tMHz\t\t9\n 4 \tMHz\t\t5\n"
DEFINEVALUEDLG "Select phrase you want to program" "PHRASE" 0 "Phrase from 0 to 7 should be selected"
FLASH RELEASE
wb 0x03c 0x00 //disable cop
wait 20
WB 0x100 FCLKDIV // clock divider for 16MHz OSCCLK
WB 0x013 0x10 // enable ROM memory 0x40_0000
WB 0x013 0x10 // enable ROM memory 0x40_0000
WB 0x106 0x30 // clear any error flags FSTAT = 0x30
WB 0x102 0x00 // CCOBIX = 0 FCCOBIX = 0x00
WB 0x10A 0x07 // load program command FCCOBHI = 0x07
WB 0x10B 0x00 // load program command FCCOBLO = 0x00
WB 0x102 0x01 // CCOBIX = 1 FCCOBIX = 0x01
WB 0x10A 0x00 // load phrase Hi value FCCOBHI = 0x00 / phrase 0x0000
WB 0x10B PHRASE // load phrase Lo value FCCOBLO = 0xPHRASE
WB 0x102 0x02 // CCOBIX = 2
WB 0x10A 0xDE // load data
WB 0x10B 0xAD // load data
WB 0x102 0x03 // CCOBIX = 3
WB 0x10A 0xC0 // load data
WB 0x10B 0xDE // load data
WB 0x102 0x04 // CCOBIX = 4
WB 0x10A 0xBE // load data
WB 0x10B 0xEF // load data
WB 0x102 0x05 // CCOBIX = 5
WB 0x10A 0xF0 // load data
WB 0x10B 0xF0 // load data
WB 0x106 0x80 // launch command
WAIT 1
WB 0x013 0x00 // disable ROM memory 0x40_0000
undef FCLKDIV
undef PHRASE
Best regards,
Ladislav
Hello Ladislav,
1) Can you answer this part of my previous comment :
"Is this memory write once / read once during the life of the MCU or till it is fully erased by a programmer?"
2) The solution you have outlined in the previous comment is great, but it won't prevent the firmware from being copied as outlined below.
a) Even if some bytes were written, they can only be read once. So I read it on boot up and set a flag in EEPROM / Flash that the firmware is authentic. Now when someone copies the firmware illegally this flag will also be copied.
Now IF there was a CHIP ID unique to each physical device
b) We could have read this id (by programmer) and written it back in FLASH (encrypted) and check it on power up so that if someone copied it the verification would fail except on the chip it was originally programmed.
So far I cannot see how I can use this write once / read once feature to do a run time check to verify if the firmware was authentically written or illegally copied.