--- /dev/null
+#
+# linux_logo in ARM assembly language
+# based on the code from ll_asm-0.41
+#
+# By Vince Weaver <vince _at_ deater.net>
+#
+# Modified to remove non-deterministic system calls
+# And to avoid reading from /proc
+
+.include "../logo.include"
+
+# offsets into the results returned by the uname syscall
+.equ U_SYSNAME,0
+.equ U_NODENAME,65
+.equ U_RELEASE,65*2
+.equ U_VERSION,(65*3)
+.equ U_MACHINE,(65*4)
+.equ U_DOMAINNAME,65*5
+
+# offset into the results returned by the sysinfo syscall
+.equ S_TOTALRAM,16
+
+# Sycscalls
+.equ SYSCALL_EXIT, 1
+.equ SYSCALL_WRITE, 4
+
+#
+.equ STDIN,0
+.equ STDOUT,1
+.equ STDERR,2
+
+ .globl _start
+_start:
+ ldr r11,data_addr
+ ldr r12,bss_addr
+
+ #=========================
+ # PRINT LOGO
+ #=========================
+
+# LZSS decompression algorithm implementation
+# by Stephan Walter 2002, based on LZSS.C by Haruhiko Okumura 1989
+# optimized some more by Vince Weaver
+
+ ldr r1,out_addr @ buffer we are printing to
+
+ mov r2,#(N-F) @ R
+
+ add r3,r11,#(logo-data_begin)
+ @ r3 points to logo data
+ ldr r8,logo_end_addr
+ @ r8 points to logo end
+ ldr r9,text_addr @ r9 points to text buf
+
+decompression_loop:
+ ldrb r4,[r3],#+1 @ load a byte, increment pointer
+
+ mov r5,#0xff @ load top as a hackish 8-bit counter
+ orr r5,r4,r5,LSL #8 @ shift 0xff left by 8 and or in the byte we loaded
+
+test_flags:
+ cmp r3,r8 @ have we reached the end?
+ bge done_logo @ if so, exit
+
+ lsrs r5,#1 @ shift bottom bit into carry flag
+ bcs discrete_char @ if set, we jump to discrete char
+
+offset_length:
+ ldrb r0,[r3],#+1 @ load a byte, increment pointer
+ ldrb r4,[r3],#+1 @ load a byte, increment pointer
+ @ we can't load halfword as no unaligned loads on arm
+
+ orr r4,r0,r4,LSL #8 @ merge back into 16 bits
+ @ this has match_length and match_position
+
+ mov r7,r4 @ copy r4 to r7
+ @ no need to mask r7, as we do it
+ @ by default in output_loop
+
+ mov r0,#(THRESHOLD+1)
+ add r6,r0,r4,LSR #(P_BITS)
+ @ r6 = (r4 >> P_BITS) + THRESHOLD + 1
+ @ (=match_length)
+
+output_loop:
+ ldr r0,pos_mask @ urgh, can't handle simple constants
+ and r7,r7,r0 @ mask it
+ ldrb r4,[r9,r7] @ load byte from text_buf[]
+ add r7,r7,#1 @ advance pointer in text_buf
+
+store_byte:
+ strb r4,[r1],#+1 @ store a byte, increment pointer
+ strb r4,[r9,r2] @ store a byte to text_buf[r]
+ add r2,r2,#1 @ r++
+ mov r0,#(N)
+ sub r0,r0,#1 @ grrr no way to get this easier
+ and r2,r2,r0 @ mask r
+
+ subs r6,r6,#1 @ decement count
+ bne output_loop @ repeat until k>j
+
+ tst r5,#0xff00 @ are the top bits 0?
+ bne test_flags @ if not, re-load flags
+
+ b decompression_loop
+
+discrete_char:
+ ldrb r4,[r3],#+1 @ load a byte, increment pointer
+ mov r6,#1 @ we set r6 to one so byte
+ @ will be output once
+
+ b store_byte @ and store it
+
+
+# end of LZSS code
+
+done_logo:
+ ldr r1,out_addr @ buffer we are printing to
+
+ bl write_stdout @ print the logo
+
+ #==========================
+ # PRINT VERSION
+ #==========================
+first_line:
+
+ mov r0,#0
+ add r1,r11,#(uname_info-data_begin)
+ @ os-name from uname "Linux"
+
+ ldr r10,out_addr @ point r10 to out_buffer
+
+ bl strcat @ call strcat
+
+
+ add r1,r11,#(ver_string-data_begin) @ source is " Version "
+ bl strcat @ call strcat
+
+ add r1,r11,#((uname_info-data_begin)+U_RELEASE)
+ @ version from uname, ie "2.6.20"
+ bl strcat @ call strcat
+
+ add r1,r11,#(compiled_string-data_begin)
+ @ source is ", Compiled "
+ bl strcat @ call strcat
+
+ add r1,r11,#((uname_info-data_begin)+U_VERSION)
+ @ compiled date
+ bl strcat @ call strcat
+
+ mov r3,#0xa
+ strb r3,[r10],#+1 @ store a linefeed, increment pointer
+ strb r0,[r10],#+1 @ NUL terminate, increment pointer
+
+ bl center_and_print @ center and print
+
+ @===============================
+ @ Middle-Line
+ @===============================
+middle_line:
+ @=========
+ @ Load /proc/cpuinfo into buffer
+ @=========
+
+ ldr r10,out_addr @ point r10 to out_buffer
+
+ @=============
+ @ Number of CPUs
+ @=============
+number_of_cpus:
+
+ add r1,r11,#(one-data_begin)
+ # cheat. Who has an SMP arm?
+ bl strcat
+
+ @=========
+ @ MHz
+ @=========
+print_mhz:
+
+ @ the arm system I have does not report MHz
+
+ @=========
+ @ Chip Name
+ @=========
+chip_name:
+ mov r0,#'s'
+ mov r1,#'o'
+ mov r2,#'r'
+ mov r3,#' '
+ bl find_string
+ @ find 'sor\t: ' and grab up to ' '
+
+ add r1,r11,#(processor-data_begin)
+ @ print " Processor, "
+ bl strcat
+
+ @========
+ @ RAM
+ @========
+
+
+ ldr r3,[r11,#((sysinfo_buff-data_begin)+S_TOTALRAM)]
+ @ size in bytes of RAM
+ movs r3,r3,lsr #20 @ divide by 1024*1024 to get M
+ adc r3,r3,#0 @ round
+
+ mov r0,#1
+ bl num_to_ascii
+
+ add r1,r11,#(ram_comma-data_begin)
+ @ print 'M RAM, '
+ bl strcat @ call strcat
+
+
+ @========
+ @ Bogomips
+ @========
+
+ mov r0,#'I'
+ mov r1,#'P'
+ mov r2,#'S'
+ mov r3,#'\n'
+ bl find_string
+
+ add r1,r11,#(bogo_total-data_begin)
+ bl strcat @ print bogomips total
+
+ bl center_and_print @ center and print
+
+ #=================================
+ # Print Host Name
+ #=================================
+last_line:
+ ldr r10,out_addr @ point r10 to out_buffer
+
+ add r1,r11,#((uname_info-data_begin)+U_NODENAME)
+ @ host name from uname()
+ bl strcat @ call strcat
+
+ bl center_and_print @ center and print
+
+ add r1,r11,#(default_colors-data_begin)
+ @ restore colors, print a few linefeeds
+ bl write_stdout
+
+
+ @================================
+ @ Exit
+ @================================
+exit:
+ mov r0,#0 @ result is zero
+ mov r7,#SYSCALL_EXIT
+ swi 0x0 @ and exit
+
+
+ @=================================
+ @ FIND_STRING
+ @=================================
+ @ r0,r1,r2 = string to find
+ @ r3 = char to end at
+ @ r5 trashed
+find_string:
+ ldr r7,disk_addr @ look in cpuinfo buffer
+find_loop:
+ ldrb r5,[r7],#+1 @ load a byte, increment pointer
+ cmp r5,r0 @ compare against first byte
+ ldrb r5,[r7] @ load next byte
+ cmpeq r5,r1 @ if first byte matched, comp this one
+ ldrb r5,[r7,#+1] @ load next byte
+ cmpeq r5,r2 @ if first two matched, comp this one
+ beq find_colon @ if all 3 matched, we are found
+
+ cmp r5,#0 @ are we at EOF?
+ beq done @ if so, done
+
+ b find_loop
+
+find_colon:
+ ldrb r5,[r7],#+1 @ load a byte, increment pointer
+ cmp r5,#':'
+ bne find_colon @ repeat till we find colon
+
+ add r7,r7,#1 @ skip the space
+
+store_loop:
+ ldrb r5,[r7],#+1 @ load a byte, increment pointer
+ strb r5,[r10],#+1 @ store a byte, increment pointer
+ cmp r5,r3
+ bne store_loop
+
+almost_done:
+ mov r0,#0
+ strb r0,[r10],#-1 @ replace last value with NUL
+
+done:
+ bx r14 @ return
+
+ #================================
+ # strcat
+ #================================
+ # value to cat in r1
+ # output buffer in r10
+ # r3 trashed
+strcat:
+ ldrb r3,[r1],#+1 @ load a byte, increment pointer
+ strb r3,[r10],#+1 @ store a byte, increment pointer
+ cmp r3,#0 @ is it zero?
+ bne strcat @ if not loop
+ sub r10,r10,#1 @ point to one less than null
+ bx r14 @ return
+
+
+ #==============================
+ # center_and_print
+ #==============================
+ # string to center in at output_buffer
+
+center_and_print:
+
+ stmfd SP!,{LR} @ store return address on stack
+
+ add r1,r11,#(escape-data_begin)
+ @ we want to output ^[[
+ bl write_stdout
+
+str_loop2:
+ ldr r2,out_addr @ point r2 to out_buffer
+ sub r2,r10,r2 @ get length by subtracting
+
+ rsb r2,r2,#81 @ reverse subtract! r2=81-r2
+ @ we use 81 to not count ending \n
+
+ bne done_center @ if result negative, don't center
+
+ lsrs r3,r2,#1 @ divide by 2
+ adc r3,r3,#0 @ round?
+
+ mov r0,#0 @ print to stdout
+ bl num_to_ascii @ print number of spaces
+
+ add r1,r11,#(C-data_begin)
+ @ we want to output C
+ bl write_stdout
+
+done_center:
+ ldr r1,out_addr @ point r1 to out_buffer
+ ldmfd SP!,{LR} @ restore return address from stack
+
+ #================================
+ # WRITE_STDOUT
+ #================================
+ # r1 has string
+ # r0,r2,r3 trashed
+write_stdout:
+ mov r2,#0 @ clear count
+
+str_loop1:
+ add r2,r2,#1
+ ldrb r3,[r1,r2]
+ cmp r3,#0
+ bne str_loop1 @ repeat till zero
+
+write_stdout_we_know_size:
+ mov r0,#STDOUT @ print to stdout
+ mov r7,#SYSCALL_WRITE
+ swi 0x0 @ run the syscall
+ bx r14 @ return
+
+
+ @#############################
+ @ num_to_ascii
+ @#############################
+ @ r3 = value to print
+ @ r0 = 0=stdout, 1=strcat
+
+num_to_ascii:
+ stmfd SP!,{r10,LR} @ store return address on stack
+ add r10,r12,#((ascii_buffer-bss_begin))
+ add r10,r10,#10
+ @ point to end of our buffer
+
+ mov r4,#10 @ we'll be dividing by 10
+div_by_10:
+ bl divide @ Q=r7,$0, R=r8,$1
+ add r8,r8,#0x30 @ convert to ascii
+ strb r8,[r10],#-1 @ store a byte, decrement pointer
+ adds r3,r7,#0 @ move Q in for next divide, update flags
+ bne div_by_10 @ if Q not zero, loop
+
+write_out:
+ add r1,r10,#1 @ adjust pointer
+ ldmfd SP!,{r10,LR} @ restore return address from stack
+
+ cmp r0,#0
+ bne strcat @ if 1, strcat
+
+ b write_stdout @ else, fallthrough to stdout
+
+
+ @===================================================
+ @ Divide - because ARM has no hardware int divide
+ @ yes this is an awful algorithm, but simple
+ @ and uses few registers
+ @==================================================
+ @ r3=numerator r4=denominator
+ @ r7=quotient r8=remainder
+ @ r5=trashed
+divide:
+
+ mov r7,#0 @ zero out quotient
+divide_loop:
+ mul r5,r7,r4 @ multiply Q by denominator
+ add r7,r7,#1 @ increment quotient
+ cmp r5,r3 @ is it greater than numerator?
+ ble divide_loop @ if not, loop
+ sub r7,r7,#2 @ otherwise went too far, decrement
+ @ and done
+
+ mul r5,r7,r4 @ calculate remainder
+ sub r8,r3,r5 @ R=N-(Q*D)
+ bx r14 @ return
+
+
+bss_addr: .word bss_begin
+data_addr: .word data_begin
+out_addr: .word out_buffer
+disk_addr: .word disk_buffer
+logo_end_addr: .word logo_end
+pos_mask: .word ((POSITION_MASK<<8)+0xff)
+text_addr: .word text_buf
+
+#===========================================================================
+# section .data
+#===========================================================================
+.data
+data_begin:
+ver_string: .ascii " Version \0"
+compiled_string: .ascii ", Compiled \0"
+processor: .ascii " Processor, \0"
+ram_comma: .ascii "M RAM, \0"
+bogo_total: .ascii " Bogomips Total\n\0"
+
+default_colors: .ascii "\033[0m\n\n\0"
+escape: .ascii "\033[\0"
+C: .ascii "C\0"
+
+one: .ascii "One \0"
+
+uname_info:
+.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"
+.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"
+.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"
+.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"
+.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"
+.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"
+.ascii "#1 Wed May 13 15:51:54 UTC 2009\0"
+.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"
+.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"
+.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"
+.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"
+.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"
+
+
+disk_buffer:
+.ascii "Processor : Feroceon 88FR131 rev 1 (v5l)\n"
+.ascii "BogoMIPS : 1192.75\n"
+.ascii "Features : swp half thumb fastmult edsp \n"
+.ascii "CPU implementer : 0x56\n"
+.ascii "CPU architecture: 5TE\n"
+.ascii "CPU variant : 0x2\n"
+.ascii "CPU part : 0x131\n"
+.ascii "CPU revision : 1\n"
+.ascii "\n"
+.ascii "Hardware : Marvell SheevaPlug Reference Board\n"
+.ascii "Revision : 0000\n"
+.ascii "Serial : 0000000000000000\n\0"
+
+
+sysinfo_buff:
+.long 0,0,0,0,512*1024*1024,0,0,0
+
+.include "../logo.lzss_new"
+
+
+#============================================================================
+# section .bss
+#============================================================================
+.bss
+bss_begin:
+.lcomm ascii_buffer,10
+.lcomm text_buf, (N+F-1)
+.lcomm out_buffer,16384