LPC824 ROM-bootloader disassembly analysis

Publisher:数据迷航者Latest update time:2018-12-11 Source: eefocusKeywords:LPC824  ROM-bootloader Reading articles on mobile phones Scan QR code
Read articles on your mobile phone anytime, anywhere

1 ROM-bootloader disassembly analysis


In Keil (IAR cannot implement this yet, and other IDEs have not been tried. This section focuses on code analysis, and there is no need to consider the tool software too much). Cancel the "Run to main" option on the Debug tab of Option, and select Stop after reset in Setting. This way, after entering the debugging interface, the program stops at the beginning of the bootloader, and the assembly code flow of the bootloader in the ROM can be analyzed.


wps2075.tmp[10]

wps2095.tmp[6]

Figure 35 ROM-Bootloader debugging settings for LPC824


The ROM is located between 0x1FFF0000 and 0x1FFF3000, with a total of 12KB of ROM, including the bootloader, ROM-API, etc.


wps20A6.tmp[6]

Figure 35 LPC824 ROM and RAM location map


Enter the debugging interface or press the RST button during debugging, it will stay at the first code of booloader. At the same time, modify the addresses 0x0 and 0x1FFF0000 in the Memory window, and the content remains unchanged. It can be seen that the ROM at the position of 0x1FFF0000 after reset is also mapped to the address 0x0 (after comparison, it is temporarily speculated that only the first 512Bytes of content are mapped to the addresses 0x0-0x1FF, and the content from 0x200 is still the user's Flash code).


wps20A8.tmp[6]


Note that the byte order of ARM is little-endian, and the last bit of PC must be 1 (indicating thumb mode). According to the startup logic of ARM, SP and PC are initialized to the two 32-bit (4-byte) contents at addresses 0x0 and 0x04, which are 0x10000FFC and 0x1FFF0008, respectively, because the logic of ARM is that the contents at addresses 0x08 and 0x0C are the addresses of the two interrupt service mileages, NMI and HardFault.


__Vectors       DCD     __initial_sp              ; Top of Stack


                DCD     Reset_Handler             ; Reset Handler


                DCD     NMI_Handler               ; NMI Handler


                DCD     HardFault_Handler         ; Hard Fault Handler


It can be seen that at this time SP=0x10000FFC is the top of SRAM0, and PC=0x1FFF0008 is the first instruction address.


wps20B9.tmp[6]

Figure 35 LPC824 ROM-Bootloader startup debugging interface


From the above figure, we can see that NMI is not used, because the NMI interrupt of LPC824 uses the NMISRC register in the SYSCON module to select a peripheral interrupt as the source of the ARM Cortex-M0+ core NMI interrupt, which is not used in the bootloader. Therefore, NMI_Handler is not needed and directly jumps to the content of @0x1FFF000C, that is, the address 0x1FFF0011.


0x1FFF0008 4A00      LDR      r2,[pc,#0]  ; @0x1FFF000C


0x1FFF000A 4710      BX       r2


The content at 0x1FFF000C is exactly the execution address of HardFault_Handler, and the content is also 0x1FFF0011. Therefore, the actual code execution result is at 0x1FFF0011. Therefore, HardFault_Handler also executes the code at 0x1FFF0011. (In fact, it should be ROM to ensure that the code is flawless and HardFault_Handler is not used).


The next step is to read the contents at 0x1FFF0064 and 0x1FFF0068 and store them in the r2 and r3 registers. The content of r3 is 0x1FFF0078, which is an address in the ROM. The content stored in this address is 0x000002FC, which is the address of the user code CRP. By reading the content of this address, the CRP value of the user code can be read and the CRP1/2/3 level can be verified.


0x1FFF0010 4A14      LDR      r2,[pc,#80] ; @0x1FFF0064


0x1FFF0012 4B15      LDR      r3,[pc,#84] ; @0x1FFF0068


0x1FFF0014 681B      LDR      r3,[r3,#0x00]


0x1FFF0016 4D16      LDR      r5,[pc,#88] ; @0x1FFF0070


0x1FFF0018 682D      LDR      r5,[r5,#0x00]


0x1FFF001A 4E16      LDR      r6,[pc,#88] ; @0x1FFF0074


0x1FFF001C 6836      LDR      r6,[r6,#0x00]


0x1FFF001E 681C      LDR      r4,[r3,#0x00]


0x1FFF0020 42AC CMP      r4,r5


0x1FFF0022 D001 BEQ 0x1FFF0028


0x1FFF0024 42B4 CMP      r4,r6


0x1FFF0026 D101      BNE      0x1FFF002C


0x1FFF0028 4C10      LDR      r4,[pc,#64] ; @0x1FFF006C


0x1FFF002A 6824      LDR      r4,[r4,#0x00]


0x1FFF002C 6014 STR      r4,[r2,#0x00]


Obviously, to compare CRP with CRP1/2/3, first read the CRP value of the current user code and the value of constant CRP1/3. Then compare the CRP value with CRP3 and CRP1. If one of them is the same, jump to 0x1FFF0028, otherwise jump to 0x1FFF002C. The effect after the above execution is as follows:


wps20BA.tmp[6]

Figure 35 LPC824 ROM-Bootloader CRP1/3 comparison and conditional execution


The consequence of the comparison success or failure is whether the code of 0x1FFF0028 is executed. If they are the same, the code is executed. The value of the address saved at 0x1FFF006C (the address is 0x1FFF007C) (the value is 0x87654321) is loaded into r4. Otherwise, r4 remains as it is, that is, the CRP value of the user code, and then r4 is saved to the location where the r2 register value is used as the address. The content of r2 is 0x400483F0, which is the register address space of SYSCON, before the DEVICE_ID register. However, the function of this address register is not explained in the data sheet. According to the bootloader flowchart, it is speculated that it is to enable debugging.


wps20CA.tmp[6]

wps20CB.tmp[6]

Figure 35 LPC824 ROM-Bootloader saves CRP value to 0x400483F0


The following code is:


0x1FFF002E 4B08      LDR      r3,[pc,#32] ; @0x1FFF0050


0x1FFF0030 681A      LDR      r2,[r3,#0x00]


0x1FFF0032 4C08      LDR      r4,[pc,#32] ; @0x1FFF0054


0x1FFF0034 8824      LDRH     r4,[r4,#0x00]


0x1FFF0036 4D08      LDR      r5,[pc,#32] ; @0x1FFF0058


0x1FFF0038 882D      LDRH     r5,[r5,#0x00]


0x1FFF003A 42AC CMP      r4,r5


0x1FFF003C D001 BEQ 0x1FFF0042


0x1FFF003E 4A07      LDR      r2,[pc,#28] ; @0x1FFF005C


0x1FFF0040 6812      LDR      r2,[r2,#0x00]


0x1FFF0042 4695 MOV sp,r2


By reading the contents of 0x1FFF0054 and 0x1FFF0058 as addresses (0x0C00013C and 0x1FFF008C respectively), the contents of these two addresses are read into r4 and r5, and then r4 and r5 are compared. If they are the same, 0x1FFF003E is skipped and jumps directly to 0x1FFF0042. Therefore, the meaning of this code is to decide whether to execute the two lines of code 0x1FFF003E by comparing the values ​​at 0x0C00013C (Reserved area) and 0x1FFF008C (constant in ROM). The result of this routine is that the values ​​of the two addresses are 0x0000C0FA, so the code is skipped.


The difference between executing this line of code and not is whether the content of r2 is the value of the address at 0x1FFF0050 (the address is 0x0C000118) or the value of the address at 0x1FFF005C (the address is 0x1FFF0088). After modifying the Z flag of PSR to change the result of CMP instruction, we can see that the value of r2 changes to 0x100003FF or 0x10001FFF, and then save r2 to the sp register, which shows that its function is to modify the stack address executed by ROM-Bootloader. It is speculated that the value at the address 0x0C00013C may be some information about the ROM version or chip die version?


Finally, jump to the content saved in 0x1FFF0060 as the new PC execution address (the new PC execution address is 0x1FFF0269, note that the last bit of PC must be 1 to indicate thumb mode).


0x1FFF0044 4A06      LDR      r2,[pc,#24] ; @0x1FFF0060


0x1FFF0046 4710 BX       r2


After jumping to 0x1FFF0268, the code is as follows:


0x1FFF0268 B510      PUSH     {r4,lr}


0x1FFF026A 4A5B      LDR      r2,[pc,#364] ; @0x1FFF03D8


0x1FFF026C 495B      LDR      r1,[pc,#364] ; @0x1FFF03DC


0x1FFF026E 8810      LDRH     r0,[r2,#0x00]


0x1FFF0270 4288 CMP      r0,r1


0x1FFF0272 D000 BEQ 0x1FFF0276


0x1FFF0274 E7FE      B        0x1FFF0274


0x1FFF0276 485B      LDR      r0,[pc,#364] ; @0x1FFF03E4


Save r4 and lr to the stack, then read the content at 0x1FFF03D8 as the value of the address (the address is 0x0C00013C, the Reserved area), save it to r0, and compare it with the content at 0x1FFF03DC (the constant in ROM) saved to r1. If they are not equal, it will stay on the following statement forever.


0x1FFF0274 E7FE      B        0x1FFF0274


After this routine test, the contents of r0 and r1 are both 0x0000C0FA, which is the same as the previous judgment. Is it suspected that another version comparison is being performed? The execution effect is as follows:


wps20DC.tmp[6]

Figure 35 ROM-Bootloader comparison version information of LPC824?


Next is multiple reads and writes, reading from the address space near 0x0C000100, and writing to the address space approximately 0x40048000--0x400483FFSYSCON address space. The 0x0C000100 area is Reserved, and it is speculated that TRIM data is modulated, etc., which will be analyzed in detail later, TODO.


0x1FFF0276 485B      LDR      r0,[pc,#364] ; @0x1FFF03E4        ; r0 = [0x1FFF03E4] = 0x400483C0


0x1FFF0278 4959      LDR      r1,[pc,#356] ; @0x1FFF03E0        ; r1 = [0x1FFF03E0] = 0x12345678


0x1FFF027A 6101 STR r1,[r0,#0x10] ; [0x400483D0] <= 0x123456678, register not specified in SYSCON.


0x1FFF027C 495A      LDR      r1,[pc,#360] ; @0x1FFF03E8        ; r1 = [0x1FFF03E8] = 0x0C000130


0x1FFF027E 680B      LDR      r3,[r1,#0x00] ; r3 = [0x0C000130] = 0


0x1FFF0280 4946      LDR      r1,[pc,#280] ; @0x1FFF039C        ; r1 = [0x1FFF039C] = 0x40048200


0x1FFF0282 39C0      SUBS     r1,r1,#0xC0 ; r1 = r1 - 0xC0 = 0x40048140


0x1FFF0284 620B STR r3,[r1,#0x20] ; [r1 + 0x20] = [0x40048160] = 0 Register not specified in SYSCON.


0x1FFF0286 4B59      LDR      r3,[pc,#356] ; @0x1FFF03EC        ;


0x1FFF0288 681B      LDR      r3,[r3,#0x00] ;


0x1FFF028A 624B STR      r3,[r1,#0x24] ;


; [r1 + 0x24] = [0x40048164] = r3 = [[0x0C000134] + 0x00] = 0 ; Undefined register in SYSCON.


0x1FFF028C 2100 MOVS     r1,#0x00 ; r1 = 0


0x1FFF028E 6101 STR r1,[r0,#0x10] ; [r0 + 0x10] = [0x400483D0] = 0 Register not defined in SYSCON.


; [r0 + 0x3C] = [0x400483D0] = r1 = 0 ; Undefined register in SYSCON.


0x1FFF0290 4957      LDR      r1,[pc,#348] ; @0x1FFF03F0        ;


0x1FFF0292 6809      LDR      r1,[r1,#0x00] ;


0x1FFF0294 6381 STR      r1,[r0,#0x38] ;


; [r0 + 0x38] = [0x400483F8] = r1 = [[0x1FFF03F0] + 0x00] = [0x0C00010C] = 0x00008241   ; SYSCON.DEVICE_ID


0x1FFF0296 4957      LDR      r1,[pc,#348] ; @0x1FFF03F4        ;


0x1FFF0298 6809      LDR      r1,[r1,#0x00] ;


0x1FFF029A 63C1 STR      r1,[r0,#0x3C] ;


; [r0 + 0x3C] = [0x400483FC] = r1 = [[0x1FFF03F4] + 0x00] = [0x0C000110] = 0x202000FB ; Undefined register in SYSCON.


0x1FFF029C 4956      LDR      r1,[pc,#344] ; @0x1FFF03F8        ;


0x1FFF029E 6809      LDR      r1,[r1,#0x00] ;


0x1FFF02A0 6001 STR      r1,[r0,#0x00]


; [r0 + 0x00] = [0x400483C0] = r1 = [[0x1FFF03F8] + 0x00] = [0x0C000124] = 0x0000001F ; Undefined register in SYSCON.


0x1FFF02A2 4956      LDR      r1,[pc,#344] ; @0x1FFF03FC        ;


0x1FFF02A4 6809      LDR      r1,[r1,#0x00] ;


0x1FFF02A6 6041 STR      r1,[r0,#0x04] ;


; [r0 + 0x04] = [0x400483C4] = r1 = [[0x1FFF03FC] + 0x00] = [0x0C000128] = 0x00000007 ; Undefined register in SYSCON.


0x1FFF02A8 4955      LDR      r1,[pc,#340] ; @0x1FFF0400        ;


0x1FFF02AA 6809      LDR      r1,[r1,#0x00] ;


0x1FFF02AC 6081 STR      r1,[r0,#0x08] ;


; [r0 + 0x08] = [0x400483C8] = r1 = [[0x1FFF0400] + 0x00] = [0x0C00012C] = 0x000000FB ; Undefined register in SYSCON.


0x1FFF02AE 4855      LDR      r0,[pc,#340] ; @0x1FFF0404        ;


0x1FFF02B0 493B      LDR      r1,[pc,#236] ; @0x1FFF03A0        ;


0x1FFF02B2 6800      LDR      r0,[r0,#0x00] ;


0x1FFF02B4 3140      ADDS     r1,r1,#0x40 ;


0x1FFF02B6 6008 STR      r0,[r1,#0x00] ;


; [r1 + 0x00] = [[0x1FFF03A0] + 0x40 + 0x00] = [0x40048080] = r0 = [[0x1FFF0404] + 0x00] = [0x0C00011C] = 0x000000DF ; Undefined register in SYSCON.


0x1FFF02B8 4853      LDR      r0,[pc,#332] ; @0x1FFF0408        ;


0x1FFF02BA 4C39 LDR r4,[pc,#228] ; @0x1FFF03A0 ;


0x1FFF02BC 6800      LDR      r0,[r0,#0x00] ;


0x1FFF02BE 3C40      SUBS     r4,r4,#0x40 ;


0x1FFF02C0 62A0 STR      r0,[r4,#0x28] ;


; [r4 + 0x28] = [[0x1FFF03A0] - 0x40 + 0x28] = [0x40048018] = r0 = [[0x1FFF0408] + 0x00] = [0x0C000120] = 0x000000DA ; Undefined register in SYSCON.


Finally, make a judgment and jump to 0x1FFF02D0.


0x1FFF02C2 78D0      LDRB     r0,[r2,#0x03] ;r0 = [r2 + 0x03].B = [0x0C00013F].B = 0


0x1FFF02C4 285A      CMP      r0,#0x5A


0x1FFF02C6 D103 BNE 0x1FFF02D0 ;If r0 is not equal to 0x5A, jump to 0x1FFF02D0, otherwise the next execution


0x1FFF02C8 2001      MOVS     r0,#0x01


0x1FFF02CA 0300      LSLS     r0,r0,#12


0x1FFF02CC F7FFFEBC BL.W 0x1FFF0048 ; if r0 = 0x5A, then r0 = 0x1 << 12; and jump to 0x1FFF0048


0x1FFF02D0 484E      LDR      r0,[pc,#312] ; @0x1FFF040C


0x1FFF02D2 F000FEE5 BL.W 0x1FFF10A0 ;r0 = [0x1FFF040C] = 0x40040000; and jump to 0x1FFF10A0


Next, the value 0x00020005 is read from the ROM address 0x1FFF130C and written to 0x40040000 (the Flash controller address space, the register definition is not clear). And the 19th bit of the 0x40040000 register is set to 1. It is speculated that it may be setting some parameters of the Flash.


0x1FFF10A0 499A      LDR      r1,[pc,#616] ; @0x1FFF130C


0x1FFF10A2 6001 STR      r1,[r0,#0x00] ; [r0 + 0x00] = [0x40040000] = r1 = [0x1FFF130C] = 0x00020005


0x1FFF10A4 6801      LDR      r1,[r0,#0x00]


0x1FFF10A6 2201 MOVS     r2,#0x01


0x1FFF10A8 04D2      LSLS     r2,r2,#19


0x1FFF10AA 4311      ORRS     r1,r1,r2


0x1FFF10AC 6001 STR      r1,[r0,#0x00] ; [r0] = [0x40040000] = r1 = [r0] | (0x1 << 19) = 0x000A0005


0x1FFF10AE 4770 BX       lr


Finally, return. Then make r0 = [[0x1FFF0410]] = [0x0C000138] = 0x00000040.


0x1FFF02D6 484E      LDR      r0,[pc,#312] ; @0x1FFF0410


0x1FFF02D8 6800 LDR r0,[r0,#0x00] ; Return value r0 = [[0x1FFF0410]] = [0x0C000138] = 0x00000040


0x1FFF02DA F001FEB5  BL.W     0x1FFF2048


And jump to 0x1FFF2048.


0x1FFF2048 4948      LDR      r1,[pc,#288] ; @0x1FFF216C


0x1FFF204A B280      UXTH     r0,r0


0x1FFF204C 4308      ORRS     r0,r0,r1


; r0 = r0 | r1 = r0 | [0x1FFF216C] = 0x00000040| 0xC0DE0000 = 0xC0DE0040


0x1FFF204E 4948      LDR      r1,[pc,#288] ; @0x1FFF2170


0x1FFF2050 6248 STR      r0,[r1,#0x24]


;[r1 + 0x24]  = [[0x1FFF2170] + 0x24] = [0x40048224] = r0 = 0xC0DE0040


0x1FFF2052 4770 BX       lr


Return to read 0xA0000000C, which is the status of P0_12, the ISP pin. If it is not low level 0x00, jump to 0x1FFF030E, which is the user code. Otherwise, execute the following code to enter the ISP boot mode.


0x1FFF02DE 6B20      LDR      r0,[r4,#0x30] ;r0 = [0x40048000 + 0x30] = 0x00000013


0x1FFF02E0 0740      LSLS     r0,r0,#29 ; r0 = r0 << 29 = 0x60000000


0x1FFF02E2 D414      BMI      0x1FFF030E


0x1FFF02E4 484B      LDR      r0,[pc,#300] ; @0x1FFF0414


0x1FFF02E6 2105 MOVS     r1,#0x05 ;


0x1FFF02E8 6800      LDR      r0,[r0,#0x00] ; r0 = [[0x1FFF0414]] = [0x0C000144] = 0x0000000C


0x1FFF02EA 0749      LSLS     r1,r1,#29 ; r1 = 5 << 29 = 0xA0000000


0x1FFF02EC 1840      ADDS     r0,r0,r1 ; r0 = r0 + r1 = 0xA000000C


0x1FFF02EE 7800      LDRB     r0,[r0,#0x00] ; r0 = [r0 + 0x00] = [0xA000000C] = 0x00000001


0x1FFF02F0 2800 CMP      r0,#0x00


0x1FFF02F2 D10C      BNE      0x1FFF030E


0x1FFF02F4 4848      LDR      r0,[pc,#288] ; @0x1FFF0418


0x1FFF02F6 4949      LDR      r1,[pc,#292] ; @0x1FFF041C


0x1FFF02F8 6800      LDR      r0,[r0,#0x00]


0x1FFF02FA 6809      LDR      r1,[r1,#0x00]


0x1FFF02FC 6800      LDR      r0,[r0,#0x00]


0x1FFF02FE 4288 CMP      r0,r1


0x1FFF0300 D005 BEQ 0x1FFF030E


0x1FFF0302 4947      LDR      r1,[pc,#284] ; @0x1FFF0420


0x1FFF0304 4288 CMP      r0,r1


0x1FFF0306 D002 BEQ 0x1FFF030E


0x1FFF0308 F7FFFF7A  BL.W     0x1FFF0200


0x1FFF030C BD10      POP      {r4,pc}


0x1FFF030E F7FFFFA5  BL.W     0x1FFF025C


The returned code 0x1FFF025C is very simple, and it returns 0x1FFF022E after restoring the previous r4 and lr.


0x1FFF025C B510      PUSH     {r4,lr}


0x1FFF025E F7FFFFE6  BL.W     0x1FFF022E


The following code sets the register at 0x40048000 to 0x2, i.e. SYSCON.SYSMEMREMAP = 0x02, which means that the user Flash is mapped to address 0x0.


0x1FFF022E B570      PUSH     {r4-r6,lr}


0x1FFF0230 4C5B      LDR      r4,[pc,#364] ; @0x1FFF03A0


0x1FFF0232 2000 MOVS     r0,#0x00


0x1FFF0234 2102 MOVS     r1,#0x02


0x1FFF0236 3C40      SUBS     r4,r4,#0x40


0x1FFF0238 6021 STR r1,[r4,#0x00]


; [r4 + 0x00] = [[0x1FFF03A0] - 0x40] = [0x40048040 - 0x40] = [0x40048000] = r1 = 0x02


Then read 8 4-byte checksums from 0 to 0x1F, and if it is equal to 0, it means the user code is valid, then jump to the user code.


0x1FFF023A 4603 MOV r3,r0


0x1FFF023C 4602 MOV      r2,r0


0x1FFF023E 4601 MOV      r1,r0


0x1FFF0240 008D      LSLS     r5,r1,#2


0x1FFF0242 595D      LDR      r5,[r3,r5]


0x1FFF0244 1C49      ADDS     r1,r1,#1


0x1FFF0246 18AA      ADDS     r2,r5,r2


0x1FFF0248 2908 CMP r1,#0x08 ;r1 accumulates from 0 to 7, r5 gets 4 bytes of data from 0x00 to 0x1F and accumulates to r2


0x1FFF024A DBF9      BLT      0x1FFF0240


0x1FFF024C 2A00 CMP r2,#0x00 ; Compare r2 equal to 0, indicating that the user code is valid, jump


0x1FFF024E D002 BEQ 0x1FFF0256


0x1FFF024C 2A00 CMP      r2,#0x00


0x1FFF024E D002 BEQ 0x1FFF0256


0x1FFF0250 2000 MOVS     r0,#0x00


0x1FFF0252 6020 STR r0,[r4,#0x00]


0x1FFF0254 BD70      POP      {r4-r6,pc}


0x1FFF0256 F7FFFEF7  BL.W     0x1FFF0048


Finally, the stack is set to sp = __initial_sp and jumps to the Reset_Handler represented by the user code address 0x4.


0x1FFF0048 6801      LDR      r1,[r0,#0x00]


0x1FFF004A 468D MOV sp,r1 ;sp = [0x00] = __initial_sp


0x1FFF004C 6841      LDR      r1,[r0,#0x04] ;r1 = [0x04] = Reset_Handler


0x1FFF004E 4708 BX       r1


From here enter the user code lpc824_startup.s.


Keywords:LPC824  ROM-bootloader Reference address:LPC824 ROM-bootloader disassembly analysis

Previous article:LPC824 IAP implementation method
Next article:Summary of problems when downloading programs in ISP mode using FlashMagic tool on LPC54618

Latest Microcontroller Articles
Change More Related Popular Components

EEWorld
subscription
account

EEWorld
service
account

Automotive
development
circle

About Us Customer Service Contact Information Datasheet Sitemap LatestNews


Room 1530, 15th Floor, Building B, No.18 Zhongguancun Street, Haidian District, Beijing, Postal Code: 100190 China Telephone: 008610 8235 0740

Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved 京ICP证060456号 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号