2 # linux_logo in ARM assembly language
3 # based on the code from ll_asm-0.41
5 # By Vince Weaver <vince _at_ deater.net>
7 # Modified to remove non-deterministic system calls
8 # And to avoid reading from /proc
10 .include "logo.include"
12 # offsets into the results returned by the uname syscall
18 .equ U_DOMAINNAME,65*5
20 # offset into the results returned by the sysinfo syscall
37 #=========================
39 #=========================
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
45 ldr r1,out_addr @ buffer we are printing to
49 add r3,r11,#(logo-data_begin)
50 @ r3 points to logo data
52 @ r8 points to logo end
53 ldr r9,text_addr @ r9 points to text buf
56 ldrb r4,[r3],#+1 @ load a byte, increment pointer
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
62 cmp r3,r8 @ have we reached the end?
63 bge done_logo @ if so, exit
65 lsrs r5,#1 @ shift bottom bit into carry flag
66 bcs discrete_char @ if set, we jump to discrete char
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
73 orr r4,r0,r4,LSL #8 @ merge back into 16 bits
74 @ this has match_length and match_position
76 mov r7,r4 @ copy r4 to r7
77 @ no need to mask r7, as we do it
78 @ by default in output_loop
81 add r6,r0,r4,LSR #(P_BITS)
82 @ r6 = (r4 >> P_BITS) + THRESHOLD + 1
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
92 strb r4,[r1],#+1 @ store a byte, increment pointer
93 strb r4,[r9,r2] @ store a byte to text_buf[r]
96 sub r0,r0,#1 @ grrr no way to get this easier
99 subs r6,r6,#1 @ decement count
100 bne output_loop @ repeat until k>j
102 tst r5,#0xff00 @ are the top bits 0?
103 bne test_flags @ if not, re-load flags
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
112 b store_byte @ and store it
118 ldr r1,out_addr @ buffer we are printing to
120 bl write_stdout @ print the logo
122 #==========================
124 #==========================
128 add r1,r11,#(uname_info-data_begin)
129 @ os-name from uname "Linux"
131 ldr r10,out_addr @ point r10 to out_buffer
133 bl strcat @ call strcat
136 add r1,r11,#(ver_string-data_begin) @ source is " Version "
137 bl strcat @ call strcat
139 add r1,r11,#((uname_info-data_begin)+U_RELEASE)
140 @ version from uname, ie "2.6.20"
141 bl strcat @ call strcat
143 add r1,r11,#(compiled_string-data_begin)
144 @ source is ", Compiled "
145 bl strcat @ call strcat
147 add r1,r11,#((uname_info-data_begin)+U_VERSION)
149 bl strcat @ call strcat
152 strb r3,[r10],#+1 @ store a linefeed, increment pointer
153 strb r0,[r10],#+1 @ NUL terminate, increment pointer
155 bl center_and_print @ center and print
157 @===============================
159 @===============================
162 @ Load /proc/cpuinfo into buffer
165 ldr r10,out_addr @ point r10 to out_buffer
172 add r1,r11,#(one-data_begin)
173 # cheat. Who has an SMP arm?
181 @ the arm system I have does not report MHz
192 @ find 'sor\t: ' and grab up to ' '
194 add r1,r11,#(processor-data_begin)
195 @ print " Processor, "
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
211 add r1,r11,#(ram_comma-data_begin)
213 bl strcat @ call strcat
226 add r1,r11,#(bogo_total-data_begin)
227 bl strcat @ print bogomips total
229 bl center_and_print @ center and print
231 #=================================
233 #=================================
235 ldr r10,out_addr @ point r10 to out_buffer
237 add r1,r11,#((uname_info-data_begin)+U_NODENAME)
238 @ host name from uname()
239 bl strcat @ call strcat
241 bl center_and_print @ center and print
243 add r1,r11,#(default_colors-data_begin)
244 @ restore colors, print a few linefeeds
248 @================================
250 @================================
252 mov r0,#0 @ result is zero
257 @=================================
259 @=================================
260 @ r0,r1,r2 = string to find
261 @ r3 = char to end at
264 ldr r7,disk_addr @ look in cpuinfo buffer
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
274 cmp r5,#0 @ are we at EOF?
275 beq done @ if so, done
280 ldrb r5,[r7],#+1 @ load a byte, increment pointer
282 bne find_colon @ repeat till we find colon
284 add r7,r7,#1 @ skip the space
287 ldrb r5,[r7],#+1 @ load a byte, increment pointer
288 strb r5,[r10],#+1 @ store a byte, increment pointer
294 strb r0,[r10],#-1 @ replace last value with NUL
299 #================================
301 #================================
303 # output buffer in r10
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
314 #==============================
316 #==============================
317 # string to center in at output_buffer
321 stmfd SP!,{LR} @ store return address on stack
323 add r1,r11,#(escape-data_begin)
324 @ we want to output ^[[
328 ldr r2,out_addr @ point r2 to out_buffer
329 sub r2,r10,r2 @ get length by subtracting
331 rsb r2,r2,#81 @ reverse subtract! r2=81-r2
332 @ we use 81 to not count ending \n
334 bne done_center @ if result negative, don't center
336 lsrs r3,r2,#1 @ divide by 2
337 adc r3,r3,#0 @ round?
339 mov r0,#0 @ print to stdout
340 bl num_to_ascii @ print number of spaces
342 add r1,r11,#(C-data_begin)
343 @ we want to output C
347 ldr r1,out_addr @ point r1 to out_buffer
348 ldmfd SP!,{LR} @ restore return address from stack
350 #================================
352 #================================
356 mov r2,#0 @ clear count
362 bne str_loop1 @ repeat till zero
364 write_stdout_we_know_size:
365 mov r0,#STDOUT @ print to stdout
366 mov r7,#SYSCALL_WRITE
367 swi 0x0 @ run the syscall
371 @#############################
373 @#############################
374 @ r3 = value to print
375 @ r0 = 0=stdout, 1=strcat
378 stmfd SP!,{r10,LR} @ store return address on stack
379 add r10,r12,#((ascii_buffer-bss_begin))
381 @ point to end of our buffer
383 mov r4,#10 @ we'll be dividing 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
392 add r1,r10,#1 @ adjust pointer
393 ldmfd SP!,{r10,LR} @ restore return address from stack
396 bne strcat @ if 1, strcat
398 b write_stdout @ else, fallthrough to stdout
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
411 mov r7,#0 @ zero out quotient
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
420 mul r5,r7,r4 @ calculate remainder
421 sub r8,r3,r5 @ R=N-(Q*D)
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
433 #===========================================================================
435 #===========================================================================
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"
444 default_colors: .ascii "\033[0m\n\n\0"
445 escape: .ascii "\033[\0"
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"
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"
475 .ascii "Hardware : Marvell SheevaPlug Reference Board\n"
476 .ascii "Revision : 0000\n"
477 .ascii "Serial : 0000000000000000\n\0"
481 .long 0,0,0,0,512*1024*1024,0,0,0
483 .include "logo.lzss_new"
486 #============================================================================
488 #============================================================================
491 .lcomm ascii_buffer,10
492 .lcomm text_buf, (N+F-1)
493 .lcomm out_buffer,16384