While reverse engineering very early hardware initialization code of an old S3C6410 based tablet, I came across an instruction that changes a bit that the user manual (relevant info on pg. 3-50) states should not be changed. This is stage bl1 code that executes out of the 4 kilobyte "steppingstone" SRAM area.

Note that the following code can't be directly assembled, it's just the output of Ida pro copied into a text editor, so that I can manipulate it more easily.

0C000914 init_clocks                     
0C000914 LDR     R0, dword_C000A80       ;r0 <- 0x7E00F000
0C000918 LDR     R1, [R0,#0x900]         ;r1 <- [0x7E00F900], OTHERS register of system controller
0C00091C MOV     R2, #0x40               ;r2 <- 0x40
0C000920 ORR     R1, R1, R2              ;set bit 6 of r1 
0C000924 STR     R1, [R0,#0x900]         ;APLL selected as SYS CLOCK
0C000928 NOP                             ;nop block, probably necessary to wait after changing SYS CLOCK
0C00092C NOP                             ;No Operation
0C000930 NOP                             ;No Operation
0C000934 NOP                             ;No Operation
0C000938 NOP                             ;No Operation
0C00093C MOV     R2, #0x80               ;r2 <- 0x80
0C000940 ORR     R1, R1, R2              ;set bit 7 of r1
0C000944 STR     R1, [R0,#0x900]         ;SYNCMODE bit set to synchronous mode
0C000948 syncack_delay                     
0C000948 LDR     R1, [R0,#0x900]         ;r1 <- contents of OTHERS register
0C00094C MOV     R2, #0xF00              ;r2 <- 0xf00, SYNCACK mask
0C000950 AND     R1, R1, R2              ;clear all but SYNCACK bits 11:8
0C000954 CMP     R1, #0xF00              ;are all SYNCACK bits set
0C000958 BNE     syncack_delay           ;if not, loop back
0C00095C MOV     R1, #0xFF00             ;r1 <- 0xff00
0C000960 ORR     R1, R1, #0xFF           ;r1 <- 0xffff
0C000964 STR     R1, [R0]                ;[0x7E00F000] <- r1, APLL_LOCK register
                                         ;pll_locktime of APLL_LOCK: 0xffff

0C000968 STR     R1, [R0,#4]             ;pll_locktime of MPLL_LOCK: 0xffff
0C00096C STR     R1, [R0,#8]             ;pll_locktime of EPLL_LOCK: 0xffff
0C000970 LDR     R1, [R0,#0x28]          ;r1 <- [0x7e00f028], CLK_DIV2 register
0C000974 BIC     R1, R1, #0x70000        ;clear bits 18:16
0C000978 ORR     R1, R1, #0x30000        ;set bits 17:16
0C00097C STR     R1, [R0,#0x28]          ;uart clock divider ratio: 3
0C000980 LDR     R1, [R0,#0x20]          ;r1 <- [0x7e00f020], CLK_DIV0 register
0C000984 BIC     R1, R1, #0x30000        ;clear bits 17:16
0C000988 BIC     R1, R1, #0xFF00         ;clear bits 15:8
0C00098C BIC     R1, R1, #0xFF           ;clear bits 7:0
0C000990 LDR     R2, dword_C000A84       ;r2 <- 0x3310
0C000994 ORR     R1, R1, R2              ;set bits 13:12, 8:9, and 4
0C000998 STR     R1, [R0,#0x20]          ;PCLK ratio: 3, HCLKX2 ratio: 1, HCLK ratio: 1, MPLL ratio: 1, ARM ratio: 0
0C00099C LDR     R1, dword_C000A88       ;r1 <- 0x810A0301
0C0009A0 STR     R1, [R0,#0xC]           ;[0x7e00f00c] <- r1, APLL_CON register 
                                         ;APLL S divide: 1, APLL P divide: 3, APLL M divide: 266, 0x10a, APLL control enabled

0C0009A4 LDR     R1, dword_C000A88       ;r1 <- 0x810A0301
0C0009A8 STR     R1, [R0,#0x10]          ;[0x7e00f010] <- r1, MPLL_CON register 
                                         ;MPLL S divide: 1, MPLL P divide: 3, MPLL M divide: 266, 0x10a, MPLL control enabled

0C0009AC LDR     R1, dword_C000A8C       ;r1 <- 0x80200203
0C0009B0 STR     R1, [R0,#0x14]          ;[0x7e00f014] <- r1, EPLL_CON0 register
                                         ;EPLL S divide: 3, EPLL P divide: 1, EPLL M divide: 32, 0x20, EPLL control enabled

0C0009B4 MOV     R1, #0                  ;r1 <- 0
0C0009B8 STR     R1, [R0,#0x18]          ;[0x7e00f018] <- r1, EPLL_CON1 register, EPLL K divide: 0 
0C0009BC LDR     R1, [R0,#0x1C]          ;r1 <- [0x7e00f018], CLK_SRC register
0C0009C0 LDR     R2, dword_C000A90       ;r2 <- 0x2007
0C0009C4 ORR     R1, R1, R2              ;set bits 13, 2:0
0C0009C8 STR     R1, [R0,#0x1C]          ;uart clock source is MPLL, EPLL_SEL: 1, MPLL_SEL: 1, APLL_SEL: 1
0C0009CC MOV     R1, #0x10000            ;r1 <- 65536, loop counter
0C0009D0 dec_64k                     
0C0009D0 SUBS    R1, R1, #1              ;decrement r1, set flags
0C0009D4 BNE     dec_64k                 ;loop back until r1 = 0 
0C0009D8 LDR     R1, [R0,#0x900]         ;r1 <- OTHERS register
0C0009DC ORR     R1, R1, #0x20           ;set bit 5
0C0009E0 STR     R1, [R0,#0x900]         ;set bit 5 of OTHERS register, marked as "DO NOT CHANGE" ???
0C0009E4 MOV     PC, LR                  ;return to init_hardware subroutine

0C0009E8 unrelated_routine                 
0C0009E8 LDR     R0, dword_C000A54       
0C0009EC LDR     R1, dword_C000A94       
0C0009F0 STR     R1, [R0]                
0C0009F4 LDR     R0, dword_C000A70       
0C0009F8 MOV     R1, #0                  
0C0009FC STR     R1, [R0,#8]             
0C000A00 STR     R1, [R0,#0xC]           
0C000A04 MOV     R1, #3                  
0C000A08 STR     R1, [R0]                
0C000A0C LDR     R1, dword_C000A98       
0C000A10 STR     R1, [R0,#4]             
0C000A14 MOV     R1, #0x22               
0C000A18 STR     R1, [R0,#0x28]          
0C000A1C LDR     R1, dword_C000A9C       
0C000A20 STR     R1, [R0,#0x2C]          
0C000A24 LDR     R1, dword_C000AA0       
0C000A28 STR     R1, [R0,#0x20]          
0C000A2C MOV     PC, LR                  
0C000A30 LDR     R0, dword_C000AA4       
0C000A34 LDR     R1, [R0]                
0C000A38 ORR     R1, R1, #0x70           
0C000A3C ORR     R1, R1, #0x7700         
0C000A40 STR     R1, [R0]                
0C000A44 LDR     R1, [R0,#4]             
0C000A48 ORR     R1, R1, #3              
0C000A4C STR     R1, [R0,#4]             
0C000A50 MOV     PC, LR                  

0C000A54 dword_C000A54 DCD 0x7F008000    
0C000A58 dword_C000A58 DCD 0x55540000    
0C000A5C dword_C000A5C DCD 0x55555555    
0C000A60 dword_C000A60 DCD 0x7F008924    
0C000A64 dword_C000A64 DCD 0x71200000    
0C000A68 dword_C000A68 DCD 0x71300000    
0C000A6C dword_C000A6C DCD 0x7E00F904    
0C000A70 dword_C000A70 DCD 0x7F005000    
0C000A74 dword_C000A74 DCD 0x4B4B4B4B    
0C000A78 dword_C000A78 DCD 0x7E00F908    
0C000A7C dword_C000A7C DCD 0x7E00FA00    
0C000A80 dword_C000A80 DCD 0x7E00F000    
0C000A84 dword_C000A84 DCD 0x3310        
0C000A88 dword_C000A88 DCD 0x810A0301    
0C000A8C dword_C000A8C DCD 0x80200203    
0C000A90 dword_C000A90 DCD 0x2007        
0C000A94 dword_C000A94 DCD 0x220022      
0C000A98 dword_C000A98 DCD 0xE45         
0C000A9C dword_C000A9C DCD 0x1FFF        
0C000AA0 dword_C000AA0 DCD 0x4F4F4F4F    
0C000AA4 dword_C000AA4 DCD 0x70200000    

The OTHERS register of the system controller is loaded into r1, logically OR'd with 0x20, setting bit 5, then written back into OTHERS register. Changing a bit that apparently shouldn't be changed.

The bootloader is never verified, so it can be overwritten in flash at will. This is a rooted android tablet, so I used the DD command to swap the STR R1, [R0,#0x900] instruction at SRAM location 0x0C0009E0 out with a NOP. The tablet still boots. So am I interpretting the instruction incorrectly? (just started learning arm assembly) Is this just a harmless bug? Or could these "DO NOT CHANGE" bits have some hidden functionality?

  • 1
    do you have source code for it (U-Boot is GPL so it should be made available)? Are there any comments? – Igor Skochinsky Oct 7 '19 at 13:54
  • 1
    As a comment, in the past I saw firmware executing instructions that write to read only registers. So it could be a mistake, miscompilation, or simply a different way to write nop. That case was not ARM though. – mrexodia Oct 15 '19 at 15:02
  • The name of the tablet's motherboard is smdk6410, and apparently that is also the name of a development board. I think this tablet is just a slight redesign of the reference board. Anyway after googling "smdk6410 u-boot 1.1.6" i found a comment mentioning that it had something to do with the synchronisation of the VIC port on line 253 of this source file: github.com/beebingoo/u-boot-1.1.6-mini6410/blob/master/board/… – My life is a bug. Oct 18 '19 at 22:34

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.