Home | History | Annotate | Download | only in arm-linux
      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