Problems unsecuring S08PA4

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Problems unsecuring S08PA4

2,647 Views
omarayala
Contributor II

Hi every one,

 

I am experiencing problems while trying to unsecure an S08PA4. I need to unsecure the micro controller (mC) without erasing flash and eeprom (no mass erase option) to verify after production that the correct software version was flashed on it.

 

I am doing the following:

 

1. Define Backdoor Keys for NV_BACKKEY0, ... NV_BACKKEY7 using a pragma section.

2. Secure mC using a pragma section. I am also enabling the Backdoor mechanism by setting KEYEN to 0x2 like this

 

#pragma section {NVFSEC}

char NV_FSEC_INIT = 0xBC;

#pragma section {}

 

By the way I am using a COSMIC compiler.

 

The pragma sections are defined in Linker file and are correct (from 0xFF70 to 0xFF77 for the Backkeys and at 0xFF7F for NV_FSEC). I can see that the information is correctly generated in the *.S19 file.

 

3. Define unsecuring sequence to run from EEPROM. Since I ran out of Flash I cannot run the sequence from RAM. I did this again using a pragma section (from 0x3100 to 0x317f). The sequence looks like this:

 

  _asm("sei")                                                       /* Deactivate interrupts */

NVM_FSTAT  = Sys_D_BIT7;                       /* Launch a new Command */

  NVM_FCCOBIX = Sys_D_FCCOBIX_WORD_0;

  NVM_FCCOBHI = 0x0C;

  NVM_FCCOBIX = Sys_D_FCCOBIX_WORD_1;

  NVM_FCCOB = Sys_D_KEY_0;

  NVM_FCCOBIX = Sys_D_FCCOBIX_WORD_2;

  NVM_FCCOB = Sys_D_KEY_1;

  NVM_FCCOBIX = Sys_D_FCCOBIX_WORD_3;

  NVM_FCCOB = Sys_D_KEY_2;

  NVM_FCCOBIX = Sys_D_FCCOBIX_WORD_4;

  NVM_FCCOB = Sys_D_KEY_3;

 

After seeing that this was not working I modified the sequence a little bit. So this is how it looks like now.

 

 

 

  NVM_FSTAT  = (Sys_D_BIT5|Sys_D_BIT4);  /* Clear Flash Access Error Flag and Flash Protection Violation Flag*/
  NVM_FSTAT  = Sys_D_BIT7;              /* Launch a new Command */

  while((NVM_FSTAT & Sys_D_BIT7) == Sys_D_BIT7)

  { /* Stay here until CCIF is cleared by HW */

  }

  NVM_FCCOBIX = Sys_D_FCCOBIX_WORD_0;

  NVM_FCCOBHI = 0x0C;

  NVM_FCCOBIX = Sys_D_FCCOBIX_WORD_1;

  NVM_FCCOB = Sys_D_KEY_0;

  NVM_FCCOBIX = Sys_D_FCCOBIX_WORD_2;

  NVM_FCCOB = Sys_D_KEY_1;

  NVM_FCCOBIX = Sys_D_FCCOBIX_WORD_3;

  NVM_FCCOB = Sys_D_KEY_2;

  NVM_FCCOBIX = Sys_D_FCCOBIX_WORD_4;

  NVM_FCCOB = Sys_D_KEY_3;

  while((NVM_FSTAT & Sys_D_BIT7) == 0x00)

  { /* Stay here until command has finished */

  }

 

4. Download the *.S19 file to target system.

5. Disconnect programming tool.

5. Restart mC. -> The mC would then run its Start up routine which checks the flash and eeprom checksum before validating stimulus for activation of the backdoorkey procedure.

6. Generate stimulus (at the correct time) to activate the Backdoorkey procedure.

7. Try to make a Hot attach with an iSystem 3000 Debugger. (It fails)

8. Try to read the flash. (No information can be read)

 

Am I missing something? or is something wrong in this procedure?

 

When I make a test without securing the mC I can Hot attach the mC using the iSystem tool. So I think nothing is wrong with that tool.

 

Thank you in advanced for your help.

 

Omar

Labels (1)
17 Replies

2,108 Views
tonyp
Senior Contributor II

Are you enabling backdoor key writing (in QE128 I use it is register FCNFG bit KEYACC)?

If it helps, my code below (in assembly) works:

Unsecure        sei                       ;disable interrupts
                lda   #KEYACC_        ;enable backdoor key writing
                sta   FCNFG

                ldhx  #NVBACKKEY
Loop@@          pula                      ;in sequence, read all 8 saved bytes
                sta   ,x
                aix   #1
                cphx  #NVBACKKEY+8
                blo   Loop@@

                cli                       ;re-enable interrupts

First, I store the key in stack (RAM), and then go to this part which enables backdoor key writing, unstacks each byte and saves it to the appropriate locations.

(Also, remember that keys of zeros or $FFs are not valid.)

0 Kudos
Reply

2,108 Views
omarayala
Contributor II

Hi Tony,

for PA4 mC the procedure is different. One needs to start the 'Verify backdoor access key command'.

For other project we had, we used a QA4 and the procedure was like the one you mentioned.

Thanks anyway.

Omar

0 Kudos
Reply

2,108 Views
vicentegomez
NXP TechSupport
NXP TechSupport

Hi Omar

I do not have a sample code for cosmic, but please check the attached code this is for code warrior 10.6 using the twr-pt60, it set the back door and send them using the sw2.


Have a great day,
Vicente

-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------

0 Kudos
Reply

2,108 Views
omarayala
Contributor II

Hi Pedro,

sorry but I do not see any attached code.

Can you post it again?

Thanks

Omar

0 Kudos
Reply

2,108 Views
vicentegomez
NXP TechSupport
NXP TechSupport

Sure.

Please let me know if you have more questions

have a good day.

Regards

Vicente

0 Kudos
Reply

2,108 Views
omarayala
Contributor II

Hi Vicente,

Edward gave me some information and I think I understand better how it works. But anyway I was not able to implement its suggestions.

Now the question that I have is that according to the Datasheet of the S08PA4 it is also possible to run the backdoor key command from EEPROM (please see image taken from MC9S08PA4 Reference Manual, Rev.3, 08/2014 some messages below.

Can you confirm this? Is there any restriction when doing it from EEPROM?

Best regards,

Omar

0 Kudos
Reply

2,107 Views
vicentegomez
NXP TechSupport
NXP TechSupport

Hi Omar

yes should be possible, unfortunately I do not have sample code, but the only difference is that you need to run from EEPROM, I believe that this can be set on code-warrior on the linker, but code warrior stuff are not my area.

Regards

Vicente Gomez

0 Kudos
Reply

2,107 Views
omarayala
Contributor II

Hello Vicente,

well thanks for the information. I tried to implement some of Edward's sugestions and run the code from EEPROM. It was not sucessful. Unfortunately I cannot run it from RAM.

If I make it work I will updated this thread otherwise this topic will be still be open. It would be nice if somebody from freescale could test unsecuring the mC running the routine from EEPROM as stated in the data sheet.

Best regards,

Omar

0 Kudos
Reply

2,108 Views
omarayala
Contributor II

Hi Vicente,

well I took a look to the code you send and it is practically the same I am doing.

There are though some differences:

1. I am not running the code from RAM but from EEPROM. But it should also have the same result. Is it possible that you run the code from EEPROM and see if it works? I cannot run it from RAM since the Flash is full.

2. After giving the last key you are launching a new command. I was not doing that. Well, I am not sure what command you are launching but a tryed to do the same (NVM_FSTAT = 0x80;) before the while loop. I did not work as well. Can you tell me what is the idea of that command and whether it is necessary to have it there?

3. I am not setting the divider (NVM_FCLKDIV =0x07;). Is it really necessary? I mean I do not require to erase or programm the Flash. I just need to take a look to the flash to validate whether the correct SW is inside the mC.

Thank you for your support.

Best regards,

Omar

0 Kudos
Reply

2,108 Views
kef2
Senior Contributor V

Omar,

Valid at least for all S08/S16/Coldfire V1 MCUs:

1. It is absolutely necessary to run code from RAM  or separate EEPROM or separate flash memory bank or external memory while any flash command is being executed (including unsecure, erase verify and any other commands). Failing to do so will make code memory not readable by CPU while flash command is being executed, and as a result CPU will runaway into the weeds.

For the same reason, since most likely your interrupt vectors table is in the flash, also most likely your interrupt service handlers are also in the flash, you need to not forget to disable interrupts while any flash command is being executed.

Not whole unsecure routine has to be copied to and executed from RAM. Only the part of code which launches flash command (FSTAT = 0x80) and waits until FSTAT bit 7 is set again. Once FSTAT bit7 is set, you can return back to flash.

2. NVM_FSTAT = 0x80; launches flash command. It is correct to execute this line after all required writes to FCCOB and FCCOBIX are done. Not the opposite.

3. Yes, it's necessary. Flash controller uses its clock to sequence all flash command timings. I doubt flash unsecure command is possible with wrong flash module clock.

Hope this helps

Edward

0 Kudos
Reply

2,108 Views
kef2
Senior Contributor V

I meant independent (from flash) piece of memory, which is readable while flash command is being executed. RAM is certainly readable while flash command is in progress. Looking at S08PA datasheet I see that you also have EEPROM. That's good news. Bad news I see this caution in Chapter 4 of MC9S08PA16 Reference Manual, Rev. 1, 8/2012:

It is possible to read from flash Flash and EEPROM memory while commands are being executed on EEPROM memory. It is not possible to read from EEPROM memory while a command (erase/program) is executing on flash memory. Simultaneous EEPROM memory are implemented with error correction codes (ECC) that can resolve single bit faults and detect double bit faults.

Don't know if there's a more recent document. They mention only erase/program in (), but I think it applies to all flash commands including backdoor key unsecure. Could be checked, but {fstat=0x80; while((fstat & 0x80)==0){} } code is very small and you always should be able to find space in RAM to be able to copy and execute it from RAM.

Your code is wrong. Again,  line 3 in the body of your verify function  NVM_FSTAT  = Sys_D_BIT7;  have to be removed. You are launching flash command here while FCCOB data is not yet defined. This most likely triggers one of errors bit in FSTAT reg. Then, after you fill FCCOB and launch flash command again, your command is ignored since you have some FSTAT error bits set. Try debugging it in unsecured mode, you should see if FSTAT errors are triggered.

This part of your routine should be moved to separate function and executed from RAM

  NVM_FSTAT = 0x80;

   while((NVM_FSTAT & Sys_D_BIT7) == ZERO_U8)

  { /* Stay here until command has finished */

  }

Regards,

Edward

2,108 Views
omarayala
Contributor II

Hi Edward,

thanks again for your help. I will make those changes and try again.

Best regards,

Omar

0 Kudos
Reply

2,108 Views
omarayala
Contributor II

Hi Edward,

well I tried to implement what you suggested but I could not. As I mentioned in the first message, I do not have space in flash and to copy some code to RAM it is required to have the code in flash. I thought that the small waiting loop should not be a problem to make it fit in the 8 Bytes I had available but the copying routine also required some flash and the code does not fit in the flash and EEPROM. I also set some options for the compiler so that it optimizes as much as it can.

Maybe it would be important to have some one from Freescale confirming whether the waiting loop could be ran from EEPROM or not.

Thanks again for your help.

Best regards,

Omar Ayala

0 Kudos
Reply

2,108 Views
kef2
Senior Contributor V

Hi Omar,

Are you using C startup routine? If you didn't eliminate it, then it already has all required code to copy code to RAM. Try following my instructions in this thread

CW for S12(X). Function in RAM is easy! Works with S08 and CW6.3 for MCUs with -NoSectCompat in linker options.

I assume you tried playing with optimization settings? Picking the biggest routine in your code and optimizing it should also help.

Regards,

Edward

0 Kudos
Reply

2,107 Views
omarayala
Contributor II

Hi Edward,

thanks again for your support. Please excuse my late answer. I was on vacation.

Well I am using COSMIC compiler and the starup routine was done by hand according to our needs, so I do not have the code that copies functions from flash to RAM.

I also asked Vicente from Freescale to confirm whether it is possible to have the waiting loop in EEPROM or not. until now I have not got any answer.

Best regards,

Omar Ayala

0 Kudos
Reply

2,108 Views
omarayala
Contributor II

Hi Edward,

thanks for your message. I still have some questions.

In point 1 you wrote "... or separate EEPROM ...". What do you mean with "separate"? I am running the command from internal EEPROM (only the code that launches the backdoorkey command lies inside the EEPROM nothing else). Do you mean an external EEPROM outside the mC?

Backdoor_Datasheet.jpg

I also double checked that I deactivate the interrupts before launching the command (I do it even before I call the function that verifies the sequence). So the code looks like this now after adding some parts given from Vicente. I added here the exact definition of some defines that I use, so that every one could understand better what I am writing to some registers.

  /* NVM_FCCBIX Flash CCOB Index Register */

  #define Sys_D_FCCOBIX_WORD_0    (uint8_t) 0

  #define Sys_D_FCCOBIX_WORD_1    (uint8_t) 1

  #define Sys_D_FCCOBIX_WORD_2    (uint8_t) 2

  #define Sys_D_FCCOBIX_WORD_3    (uint8_t) 3

  #define Sys_D_FCCOBIX_WORD_4    (uint8_t) 4

  #define Sys_D_KEY_0             (uint16_t) 0x1020

  #define Sys_D_KEY_1             (uint16_t) 0x3040

  #define Sys_D_KEY_2             (uint16_t) 0x5060

  #define Sys_D_KEY_3             (uint16_t) 0x7080

 

  #define Sys_D_BIT7 (uint8_t) 0x80

#pragma section (VERIFYKEY)

STATIC void Sys_f_VerifyKey_v(void)

{

  NVM_FCLKDIV = 0x07;

  NVM_FSTAT  = (Sys_D_BIT5|Sys_D_BIT4);      /* Clear Flash Access Error Flag and Flash Protection Violation Flag*/

  NVM_FSTAT  = Sys_D_BIT7;                           /* Launch a new Command */

  NVM_FCCOBIX = Sys_D_FCCOBIX_WORD_0;

  NVM_FCCOBHI = 0x0C;

NVM_FCCOBLO = 0x00;

  NVM_FCCOBIX = Sys_D_FCCOBIX_WORD_1;

  NVM_FCCOB = Sys_D_KEY_0;

  NVM_FCCOBIX = Sys_D_FCCOBIX_WORD_2;

  NVM_FCCOB = Sys_D_KEY_1;

  NVM_FCCOBIX = Sys_D_FCCOBIX_WORD_3;

  NVM_FCCOB = Sys_D_KEY_2;

  NVM_FCCOBIX = Sys_D_FCCOBIX_WORD_4;

  NVM_FCCOB = Sys_D_KEY_3;

  /* Launch the command */

  NVM_FSTAT = 0x80;

  while((NVM_FSTAT & Sys_D_BIT7) == ZERO_U8)

  { /* Stay here until command has finished */

  }

}

#pragma section ()

NVM_FCLKCDIV = 0x07;

0 Kudos
Reply

2,108 Views
omarayala
Contributor II

I am sorry I had not finished writiing the message as I accidentally press the post button.

Well I wanted to write that I still need to check whether the value of 0x07 for NVM_FCLKDIV is correct for my configuration or not.

Best regards,

Omar

0 Kudos
Reply