1 # 2 # linux_logo in ARM assembly language 3 # based on the code from ll_asm-0.41 4 # 5 # By Vince Weaver <vince _at_ deater.net> 6 # 7 # Modified to remove non-deterministic system calls 8 # And to avoid reading from /proc 9 10 .include "../logo.include" 11 12 # offsets into the results returned by the uname syscall 13 .equ U_SYSNAME,0 14 .equ U_NODENAME,65 15 .equ U_RELEASE,65*2 16 .equ U_VERSION,(65*3) 17 .equ U_MACHINE,(65*4) 18 .equ U_DOMAINNAME,65*5 19 20 # offset into the results returned by the sysinfo syscall 21 .equ S_TOTALRAM,16 22 23 # Sycscalls 24 .equ SYSCALL_EXIT, 1 25 .equ SYSCALL_WRITE, 4 26 27 # 28 .equ STDIN,0 29 .equ STDOUT,1 30 .equ STDERR,2 31 32 .globl _start 33 _start: 34 ldr r11,data_addr 35 ldr r12,bss_addr 36 37 #========================= 38 # PRINT LOGO 39 #========================= 40 41 # LZSS decompression algorithm implementation 42 # by Stephan Walter 2002, based on LZSS.C by Haruhiko Okumura 1989 43 # optimized some more by Vince Weaver 44 45 ldr r1,out_addr @ buffer we are printing to 46 47 mov r2,#(N-F) @ R 48 49 add r3,r11,#(logo-data_begin) 50 @ r3 points to logo data 51 ldr r8,logo_end_addr 52 @ r8 points to logo end 53 ldr r9,text_addr @ r9 points to text buf 54 55 decompression_loop: 56 ldrb r4,[r3],#+1 @ load a byte, increment pointer 57 58 mov r5,#0xff @ load top as a hackish 8-bit counter 59 orr r5,r4,r5,LSL #8 @ shift 0xff left by 8 and or in the byte we loaded 60 61 test_flags: 62 cmp r3,r8 @ have we reached the end? 63 bge done_logo @ if so, exit 64 65 lsrs r5,#1 @ shift bottom bit into carry flag 66 bcs discrete_char @ if set, we jump to discrete char 67 68 offset_length: 69 ldrb r0,[r3],#+1 @ load a byte, increment pointer 70 ldrb r4,[r3],#+1 @ load a byte, increment pointer 71 @ we can't load halfword as no unaligned loads on arm 72 73 orr r4,r0,r4,LSL #8 @ merge back into 16 bits 74 @ this has match_length and match_position 75 76 mov r7,r4 @ copy r4 to r7 77 @ no need to mask r7, as we do it 78 @ by default in output_loop 79 80 mov r0,#(THRESHOLD+1) 81 add r6,r0,r4,LSR #(P_BITS) 82 @ r6 = (r4 >> P_BITS) + THRESHOLD + 1 83 @ (=match_length) 84 85 output_loop: 86 ldr r0,pos_mask @ urgh, can't handle simple constants 87 and r7,r7,r0 @ mask it 88 ldrb r4,[r9,r7] @ load byte from text_buf[] 89 add r7,r7,#1 @ advance pointer in text_buf 90 91 store_byte: 92 strb r4,[r1],#+1 @ store a byte, increment pointer 93 strb r4,[r9,r2] @ store a byte to text_buf[r] 94 add r2,r2,#1 @ r++ 95 mov r0,#(N) 96 sub r0,r0,#1 @ grrr no way to get this easier 97 and r2,r2,r0 @ mask r 98 99 subs r6,r6,#1 @ decement count 100 bne output_loop @ repeat until k>j 101 102 tst r5,#0xff00 @ are the top bits 0? 103 bne test_flags @ if not, re-load flags 104 105 b decompression_loop 106 107 discrete_char: 108 ldrb r4,[r3],#+1 @ load a byte, increment pointer 109 mov r6,#1 @ we set r6 to one so byte 110 @ will be output once 111 112 b store_byte @ and store it 113 114 115 # end of LZSS code 116 117 done_logo: 118 ldr r1,out_addr @ buffer we are printing to 119 120 bl write_stdout @ print the logo 121 122 #========================== 123 # PRINT VERSION 124 #========================== 125 first_line: 126 127 mov r0,#0 128 add r1,r11,#(uname_info-data_begin) 129 @ os-name from uname "Linux" 130 131 ldr r10,out_addr @ point r10 to out_buffer 132 133 bl strcat @ call strcat 134 135 136 add r1,r11,#(ver_string-data_begin) @ source is " Version " 137 bl strcat @ call strcat 138 139 add r1,r11,#((uname_info-data_begin)+U_RELEASE) 140 @ version from uname, ie "2.6.20" 141 bl strcat @ call strcat 142 143 add r1,r11,#(compiled_string-data_begin) 144 @ source is ", Compiled " 145 bl strcat @ call strcat 146 147 add r1,r11,#((uname_info-data_begin)+U_VERSION) 148 @ compiled date 149 bl strcat @ call strcat 150 151 mov r3,#0xa 152 strb r3,[r10],#+1 @ store a linefeed, increment pointer 153 strb r0,[r10],#+1 @ NUL terminate, increment pointer 154 155 bl center_and_print @ center and print 156 157 @=============================== 158 @ Middle-Line 159 @=============================== 160 middle_line: 161 @========= 162 @ Load /proc/cpuinfo into buffer 163 @========= 164 165 ldr r10,out_addr @ point r10 to out_buffer 166 167 @============= 168 @ Number of CPUs 169 @============= 170 number_of_cpus: 171 172 add r1,r11,#(one-data_begin) 173 # cheat. Who has an SMP arm? 174 bl strcat 175 176 @========= 177 @ MHz 178 @========= 179 print_mhz: 180 181 @ the arm system I have does not report MHz 182 183 @========= 184 @ Chip Name 185 @========= 186 chip_name: 187 mov r0,#'s' 188 mov r1,#'o' 189 mov r2,#'r' 190 mov r3,#' ' 191 bl find_string 192 @ find 'sor\t: ' and grab up to ' ' 193 194 add r1,r11,#(processor-data_begin) 195 @ print " Processor, " 196 bl strcat 197 198 @======== 199 @ RAM 200 @======== 201 202 203 ldr r3,[r11,#((sysinfo_buff-data_begin)+S_TOTALRAM)] 204 @ size in bytes of RAM 205 movs r3,r3,lsr #20 @ divide by 1024*1024 to get M 206 adc r3,r3,#0 @ round 207 208 mov r0,#1 209 bl num_to_ascii 210 211 add r1,r11,#(ram_comma-data_begin) 212 @ print 'M RAM, ' 213 bl strcat @ call strcat 214 215 216 @======== 217 @ Bogomips 218 @======== 219 220 mov r0,#'I' 221 mov r1,#'P' 222 mov r2,#'S' 223 mov r3,#'\n' 224 bl find_string 225 226 add r1,r11,#(bogo_total-data_begin) 227 bl strcat @ print bogomips total 228 229 bl center_and_print @ center and print 230 231 #================================= 232 # Print Host Name 233 #================================= 234 last_line: 235 ldr r10,out_addr @ point r10 to out_buffer 236 237 add r1,r11,#((uname_info-data_begin)+U_NODENAME) 238 @ host name from uname() 239 bl strcat @ call strcat 240 241 bl center_and_print @ center and print 242 243 add r1,r11,#(default_colors-data_begin) 244 @ restore colors, print a few linefeeds 245 bl write_stdout 246 247 248 @================================ 249 @ Exit 250 @================================ 251 exit: 252 mov r0,#0 @ result is zero 253 mov r7,#SYSCALL_EXIT 254 swi 0x0 @ and exit 255 256 257 @================================= 258 @ FIND_STRING 259 @================================= 260 @ r0,r1,r2 = string to find 261 @ r3 = char to end at 262 @ r5 trashed 263 find_string: 264 ldr r7,disk_addr @ look in cpuinfo buffer 265 find_loop: 266 ldrb r5,[r7],#+1 @ load a byte, increment pointer 267 cmp r5,r0 @ compare against first byte 268 ldrb r5,[r7] @ load next byte 269 cmpeq r5,r1 @ if first byte matched, comp this one 270 ldrb r5,[r7,#+1] @ load next byte 271 cmpeq r5,r2 @ if first two matched, comp this one 272 beq find_colon @ if all 3 matched, we are found 273 274 cmp r5,#0 @ are we at EOF? 275 beq done @ if so, done 276 277 b find_loop 278 279 find_colon: 280 ldrb r5,[r7],#+1 @ load a byte, increment pointer 281 cmp r5,#':' 282 bne find_colon @ repeat till we find colon 283 284 add r7,r7,#1 @ skip the space 285 286 store_loop: 287 ldrb r5,[r7],#+1 @ load a byte, increment pointer 288 strb r5,[r10],#+1 @ store a byte, increment pointer 289 cmp r5,r3 290 bne store_loop 291 292 almost_done: 293 mov r0,#0 294 strb r0,[r10],#-1 @ replace last value with NUL 295 296 done: 297 bx r14 @ return 298 299 #================================ 300 # strcat 301 #================================ 302 # value to cat in r1 303 # output buffer in r10 304 # r3 trashed 305 strcat: 306 ldrb r3,[r1],#+1 @ load a byte, increment pointer 307 strb r3,[r10],#+1 @ store a byte, increment pointer 308 cmp r3,#0 @ is it zero? 309 bne strcat @ if not loop 310 sub r10,r10,#1 @ point to one less than null 311 bx r14 @ return 312 313 314 #============================== 315 # center_and_print 316 #============================== 317 # string to center in at output_buffer 318 319 center_and_print: 320 321 stmfd SP!,{LR} @ store return address on stack 322 323 add r1,r11,#(escape-data_begin) 324 @ we want to output ^[[ 325 bl write_stdout 326 327 str_loop2: 328 ldr r2,out_addr @ point r2 to out_buffer 329 sub r2,r10,r2 @ get length by subtracting 330 331 rsb r2,r2,#81 @ reverse subtract! r2=81-r2 332 @ we use 81 to not count ending \n 333 334 bne done_center @ if result negative, don't center 335 336 lsrs r3,r2,#1 @ divide by 2 337 adc r3,r3,#0 @ round? 338 339 mov r0,#0 @ print to stdout 340 bl num_to_ascii @ print number of spaces 341 342 add r1,r11,#(C-data_begin) 343 @ we want to output C 344 bl write_stdout 345 346 done_center: 347 ldr r1,out_addr @ point r1 to out_buffer 348 ldmfd SP!,{LR} @ restore return address from stack 349 350 #================================ 351 # WRITE_STDOUT 352 #================================ 353 # r1 has string 354 # r0,r2,r3 trashed 355 write_stdout: 356 mov r2,#0 @ clear count 357 358 str_loop1: 359 add r2,r2,#1 360 ldrb r3,[r1,r2] 361 cmp r3,#0 362 bne str_loop1 @ repeat till zero 363 364 write_stdout_we_know_size: 365 mov r0,#STDOUT @ print to stdout 366 mov r7,#SYSCALL_WRITE 367 swi 0x0 @ run the syscall 368 bx r14 @ return 369 370 371 @############################# 372 @ num_to_ascii 373 @############################# 374 @ r3 = value to print 375 @ r0 = 0=stdout, 1=strcat 376 377 num_to_ascii: 378 stmfd SP!,{r10,LR} @ store return address on stack 379 add r10,r12,#((ascii_buffer-bss_begin)) 380 add r10,r10,#10 381 @ point to end of our buffer 382 383 mov r4,#10 @ we'll be dividing by 10 384 div_by_10: 385 bl divide @ Q=r7,$0, R=r8,$1 386 add r8,r8,#0x30 @ convert to ascii 387 strb r8,[r10],#-1 @ store a byte, decrement pointer 388 adds r3,r7,#0 @ move Q in for next divide, update flags 389 bne div_by_10 @ if Q not zero, loop 390 391 write_out: 392 add r1,r10,#1 @ adjust pointer 393 ldmfd SP!,{r10,LR} @ restore return address from stack 394 395 cmp r0,#0 396 bne strcat @ if 1, strcat 397 398 b write_stdout @ else, fallthrough to stdout 399 400 401 @=================================================== 402 @ Divide - because ARM has no hardware int divide 403 @ yes this is an awful algorithm, but simple 404 @ and uses few registers 405 @================================================== 406 @ r3=numerator r4=denominator 407 @ r7=quotient r8=remainder 408 @ r5=trashed 409 divide: 410 411 mov r7,#0 @ zero out quotient 412 divide_loop: 413 mul r5,r7,r4 @ multiply Q by denominator 414 add r7,r7,#1 @ increment quotient 415 cmp r5,r3 @ is it greater than numerator? 416 ble divide_loop @ if not, loop 417 sub r7,r7,#2 @ otherwise went too far, decrement 418 @ and done 419 420 mul r5,r7,r4 @ calculate remainder 421 sub r8,r3,r5 @ R=N-(Q*D) 422 bx r14 @ return 423 424 425 bss_addr: .word bss_begin 426 data_addr: .word data_begin 427 out_addr: .word out_buffer 428 disk_addr: .word disk_buffer 429 logo_end_addr: .word logo_end 430 pos_mask: .word ((POSITION_MASK<<8)+0xff) 431 text_addr: .word text_buf 432 433 #=========================================================================== 434 # section .data 435 #=========================================================================== 436 .data 437 data_begin: 438 ver_string: .ascii " Version \0" 439 compiled_string: .ascii ", Compiled \0" 440 processor: .ascii " Processor, \0" 441 ram_comma: .ascii "M RAM, \0" 442 bogo_total: .ascii " Bogomips Total\n\0" 443 444 default_colors: .ascii "\033[0m\n\n\0" 445 escape: .ascii "\033[\0" 446 C: .ascii "C\0" 447 448 one: .ascii "One \0" 449 450 uname_info: 451 .ascii "Linux\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" 452 .ascii "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" 453 .ascii "lindt\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" 454 .ascii "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" 455 .ascii "2.6.32\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" 456 .ascii "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" 457 .ascii "#1 Wed May 13 15:51:54 UTC 2009\0" 458 .ascii "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" 459 .ascii "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" 460 .ascii "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" 461 .ascii "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" 462 .ascii "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" 463 464 465 disk_buffer: 466 .ascii "Processor : Feroceon 88FR131 rev 1 (v5l)\n" 467 .ascii "BogoMIPS : 1192.75\n" 468 .ascii "Features : swp half thumb fastmult edsp \n" 469 .ascii "CPU implementer : 0x56\n" 470 .ascii "CPU architecture: 5TE\n" 471 .ascii "CPU variant : 0x2\n" 472 .ascii "CPU part : 0x131\n" 473 .ascii "CPU revision : 1\n" 474 .ascii "\n" 475 .ascii "Hardware : Marvell SheevaPlug Reference Board\n" 476 .ascii "Revision : 0000\n" 477 .ascii "Serial : 0000000000000000\n\0" 478 479 480 sysinfo_buff: 481 .long 0,0,0,0,512*1024*1024,0,0,0 482 483 .include "../logo.lzss_new" 484 485 486 #============================================================================ 487 # section .bss 488 #============================================================================ 489 .bss 490 bss_begin: 491 .lcomm ascii_buffer,10 492 .lcomm text_buf, (N+F-1) 493 .lcomm out_buffer,16384 494