1#
2#  linux_logo in ppc assembly language
3#    based on the code from ll_asm-0.36
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
11# offsets into the results returned by the uname syscall
12.equ U_SYSNAME,0
13.equ U_NODENAME,65
14.equ U_RELEASE,65*2
15.equ U_VERSION,(65*3)
16.equ U_MACHINE,(65*4)
17.equ U_DOMAINNAME,65*5
18
19# offset into the SYSCALL_SYSINFO buffer
20.equ S_TOTALRAM,16
21
22# Sycscalls
23.equ SYSCALL_EXIT,     1
24#.equ SYSCALL_READ,     3
25.equ SYSCALL_WRITE,    4
26#.equ SYSCALL_OPEN,     5
27#.equ SYSCALL_CLOSE,    6
28#.equ SYSCALL_SYSINFO,116
29#.equ SYSCALL_UNAME,  122
30
31#
32.equ STDIN, 0
33.equ STDOUT,1
34.equ STDERR,2
35
36.equ BSS_BEGIN,25
37.equ DATA_BEGIN,26
38
39.include "logo.include"
40
41	.globl _start
42_start:
43
44        #========================
45	# Initialization
46	#========================
47
48
49#	eieio				# coolest opcode of all time ;)
50					# not needed, but I had to put it here
51  	# the hack loading BSS_BEGIN and DATA_BEGIN
52	# saves one instruction on any future load from memory
53	# as we can just do an addi rather than an lis;addi
54
55	lis	25,bss_begin@ha
56	addi	25,25,bss_begin@l
57
58	lis	26,data_begin@ha
59	addi	26,26,data_begin@l
60
61	addi	14,BSS_BEGIN,(out_buffer-bss_begin)
62					# the output buffer
63
64	addi	21,BSS_BEGIN,(text_buf-bss_begin)
65
66
67	mr	17,14		    	# store out-buffer for later
68
69        #=========================
70	# PRINT LOGO
71	#=========================
72
73# LZSS decompression algorithm implementation
74# by Stephan Walter 2002, based on LZSS.C by Haruhiko Okumura 1989
75# optimized some more by Vince Weaver
76
77
78	li	8,(N-F)			# grab "R"
79
80	addi	9,DATA_BEGIN,(logo-data_begin)-1
81					# logo_pointer
82
83	addi	12,DATA_BEGIN,(logo_end-data_begin)-1
84					# end of the logo
85
86
87	mr      16,17
88
89decompression_loop:
90	lbzu 	10,1(9)			# load in a byte
91					# auto-update
92	mr	11,10			# copy to 11
93	ori	11,11,0xff00		# re-load top as a hackish
94					# 8-bit counter
95
96test_flags:
97	cmpw	0,12,9			# have we reached the end?
98	ble	done_logo		# ! if so exit
99
100	andi.	13,11,0x1
101	srawi   11,11,1
102
103	bne	0,discrete_char
104
105offset_length:
106	lbzu  	10,1(9)
107	lbzu	24,1(9)
108	slwi	24,24,8
109	or	24,24,10
110
111	mr	10,24
112
113	srawi  15,10,P_BITS
114	addi   15,15,THRESHOLD+1 # cl = ax >> (P_BITS)+THRESH+1
115	       			 # = match length
116
117output_loop:
118	andi.  24,24,(POSITION_MASK<<8+0xff)	# mask it
119	lbzx   10,21,24
120	addi   24,24,1
121
122store_byte:
123	stbu   10,1(16)
124
125	stbx    10,21,8
126	addi	8,8,1
127	andi.	8,8,(N-1)
128
129	addic.	15,15,-1
130	bne	0,output_loop
131
132	andi.	13,11,0xff00
133	bne	test_flags
134
135	b	decompression_loop
136
137discrete_char:
138
139	lbzu    10,1(9)
140	li	15,1
141
142	b       store_byte
143
144done_logo:
145
146	addi	4,17,1		# restore (plus one because r17 is decremented)
147	bl	write_stdout	# and print the logo
148
149
150        #==========================
151	# First Line
152	#==========================
153
154
155	#==========================
156	# PRINT VERSION
157	#==========================
158
159#	li	0,SYSCALL_UNAME		# uname syscall
160#	addi	3,BSS_BEGIN,(uname_info-bss_begin)
161					# uname struct
162#	sc				# do syscall
163
164
165	addi	16,DATA_BEGIN,(uname_info-data_begin)+U_SYSNAME@l-1
166					# os-name from uname "Linux"
167	bl	strcat
168
169	addi	16,DATA_BEGIN,(ver_string-data_begin)-1
170					# source is " Version "
171	bl 	strcat
172
173	addi	16,DATA_BEGIN,(uname_info-data_begin)+U_RELEASE@l-1
174					# version from uname "2.4.1"
175	bl 	strcat
176
177	addi	16,DATA_BEGIN,(compiled_string-data_begin)-1
178					# source is ", Compiled "
179	bl 	strcat
180
181	addi	16,DATA_BEGIN,(uname_info-data_begin)+U_VERSION-1
182      					# compiled date
183	bl 	strcat
184
185	bl	center_and_print	# write it to screen
186
187
188	#===============================
189	# Middle-Line
190	#===============================
191
192	#=========
193	# Load /proc/cpuinfo into buffer
194	#=========
195
196#	li	0,SYSCALL_OPEN		# open()
197#	addi	3,DATA_BEGIN,(cpuinfo-data_begin)
198					# '/proc/cpuinfo'
199#	li	4,0			# O_RDONLY <bits/fcntl.h>
200#	sc				# syscall.  fd in r0.
201					# we should check that r0>=0
202
203#	mr	13,3			# save fd in r13
204
205#	li	0,SYSCALL_READ		# read
206#	addi	4,BSS_BEGIN,(disk_buffer-bss_begin)
207#	li	5,4096		 	# 4096 is maximum size of proc file ;)
208#	sc
209
210#	mr	3,13			# restore fd
211#	li	0,6			# close
212#	sc
213
214	#=============
215	# Number of CPUs
216	#=============
217
218	mr	14,17 			# point output to out_buf
219
220	# Assume 1 CPU for now
221	# my iBook's /proc/cpuinfo does not have a "processor" line ???
222
223	addi	16,DATA_BEGIN,(one-data_begin)-1
224	bl	strcat
225
226	#=========
227	# MHz
228	#=========
229
230    	lis	20,('l'<<8)+'o'		# find 'lock ' and grab up to M
231	addi	20,20,('c'<<8)+'k'
232	li	23,'M'
233   	bl	find_string
234
235	addi	16,DATA_BEGIN,(megahertz-data_begin)-1
236					# print 'MHz '
237	bl	strcat
238
239
240	#=========
241	# Chip Name
242	#=========
243
244   	lis     20,('c'<<8)+'p'     	# find 'cpu\t: ' and grab up to \n
245	addi	20,20,('u'<<8)+'\t'
246	li	23,'\n'
247	bl	find_string
248
249	addi	16,DATA_BEGIN,(comma-data_begin)-1
250					# print ', '
251	bl	strcat
252
253	#========
254	# RAM
255	#========
256
257#	li	0,SYSCALL_SYSINFO	# sysinfo() syscall
258#	addi	3,BSS_BEGIN,(sysinfo_buff-bss_begin)
259					# sysinfo_buffer
260
261#	sc
262
263	lwz	4,(sysinfo_buff+S_TOTALRAM-data_begin)(DATA_BEGIN)
264					# load bytes of RAM into r4
265
266	srawi	4,4,20		# divide by 2^20 to get MB
267	li	5,0
268
269	bl	num_to_ascii
270
271	addi	16,DATA_BEGIN,(ram_comma-data_begin)-1
272					# print 'M RAM, '
273
274	bl	strcat
275
276	#========
277	# Bogomips
278	#========
279
280	lis	20,('m'<<8)+'i'		# find 'mips' and grab up to \n
281	addi	20,20,('p'<<8)+'s'
282	li	23,'\n'
283	bl	find_string
284
285	addi	16,DATA_BEGIN,(bogo_total-data_begin)-1
286					# print "Bogomips Total"
287	bl	strcat
288
289	bl	center_and_print	# center it
290
291
292	#=================================
293	# Print Host Name
294	#=================================
295
296	mr	14,17			# restore out buffer
297
298	addi	16,DATA_BEGIN,((uname_info-data_begin)+U_NODENAME)-1
299					# hostname
300
301	bl	strcat
302
303	bl	center_and_print
304
305	#================================
306	# Exit
307	#================================
308exit:
309        li      3,0		# 0 exit value
310	li      0,SYSCALL_EXIT  # put the exit syscall number in eax
311	sc	             	# and exit
312
313
314
315
316	#=================================
317	# FIND_STRING
318	#=================================
319	#   r23 is char to end at
320	#   r20 is the 4-char ascii string to look for
321	#   r14 points at output buffer
322	#   r16,r21
323
324find_string:
325
326	addi	16,DATA_BEGIN,(disk_buffer-data_begin)-1
327					# look in cpuinfo buffer
328					# -1 so we can use lbzu
329
330find_loop:
331	lwzu	13,1(16)		# load in 32 bits, incrementing 8bits
332	cmpwi	13,0			# ! if null, we are done
333	beq	done
334	cmpw	13,20			# compare with out 4 char string
335	bne	find_loop		# ! if no match, keep looping
336
337
338					# ! if we get this far, we matched
339
340	li	21,':'
341find_colon:
342	lbzu	13,1(16)		# repeat till we find colon
343	cmpwi	13,0
344	beq	done
345	cmpw	13,21
346	bne	find_colon
347
348	addi	16,16,1			# skip a char [should be space]
349
350store_loop:
351	 lbzu	13,1(16)
352	 cmpwi	13,0
353	 beq	done
354    	 cmpw	13,23			# is it end string?
355	 beq 	almost_done		# ! if so, finish
356	 stbu	13,1(14)		# ! if not store and continue
357	 b	store_loop
358
359almost_done:
360	li	13,0			# replace last value with null
361	stb	13,1(14)
362
363done:
364	blr
365
366	#================================
367	# strcat
368	#================================
369	# r13 = "temp"
370	# r16 = "source"
371       	# r14 = "destination"
372strcat:
373	lbzu	13,1(16)		# load a byte from [r16]
374	stbu	13,1(14)		# store a byte to [r14]
375	cmpwi	13,0			# is it zero?
376	bne	strcat			# ! if not loop
377	subi	14,14,1			# point to one less than null
378	blr				# return
379
380	#==============================
381	# center_and_print
382	#==============================
383	# r14 is end of buffer
384	# r17 is start of buffer
385	# r29 = saved link register
386	# r4-r10, r19-r22, r30 trashed
387
388center_and_print:
389
390	mflr 	29			# back up return address
391
392	subf	5,17,14			# see how long the output
393					# buffer is
394
395	cmpwi	5,80			# see if we are >80
396        bgt	done_center		# ! if so, bail
397
398	li	4,80			# 80 column screen
399	subf	4,5,4			# subtract strlen
400	srawi	23,4,1			# divide by two
401
402	lis	4,escape@ha
403	addi	4,4,escape@l
404	bl	write_stdout
405
406	mr	4,23
407	li	5,1			# print to stdout
408	bl	num_to_ascii		# print number
409
410	lis	4,c@ha
411	addi	4,4,c@l
412	bl	write_stdout
413
414
415done_center:
416
417	addi	4,17,1			# move string to output+1
418	bl	write_stdout		# call write stdout
419
420	lis	4,linefeed@ha
421	addi	4,4,linefeed@l
422
423	mtlr	29	      		# restore link register
424					# and let write_stdout
425					# return for us
426
427
428
429	#================================
430	# WRITE_STDOUT
431	#================================
432	# r4 has string
433	# r0,r3,r4,r5,r6 trashed
434
435write_stdout:
436	li	0,SYSCALL_WRITE		# write syscall
437	li	3,STDOUT		# stdout
438
439	li	5,0			# string length counter
440strlen_loop:
441	lbzx 	6,4,5			# get byte from (r4+r5)
442       	addi	5,5,1			# increment counter
443	cmpi	0,6,0			# is it zero?
444	bne	strlen_loop		# ! if not keep counting
445	addi	5,5,-1
446	sc				# syscall
447
448	blr				# return
449
450
451	##############################
452	# Num to Ascii
453	##############################
454	# num is in r4
455	# r5 =0 then strcat, otherwise stdout
456	# r5-r10,r19,r20,r21,r22,r30 trashed
457
458num_to_ascii:
459
460	mflr    30			# save the link register
461
462	addi	16,BSS_BEGIN,(num_to_ascii_end-bss_begin)
463					# the end of a backwards growing
464					# 10 byte long buffer.
465
466	li	20,10			# we will divide by 10
467	mr	19,4			# load in the value passed
468
469div_by_10:
470	divw	21,19,20		# divide r19 by r20 put into r21
471
472	mullw	22,21,20		# find remainder.  1st q*dividend
473	subf	22,22,19		# then subtract from original = R
474	addi	22,22,0x30		# convert remainder to ascii
475
476	stbu	22,-1(16)		# Store to backwards buffer
477
478	mr	19,21			# move Quotient as new dividend
479	cmpwi	19,0			# was quotient zero?
480	bne    	div_by_10		# ! if not keep dividing
481
482write_out:
483	cmpwi	5,0			# ! if r5 is 0 then skip ahead
484	bne 	stdout_num
485
486	addi	16,16,-1		# point to the beginning
487	bl	strcat			# and strcat it
488
489	mtlr	30			# restore link register
490
491	blr				# return
492
493stdout_num:
494        mr	4,16			# point to our buffer
495	mtlr	30			# restore link register
496	b	write_stdout		# stdout will return for us
497
498
499#===========================================================================
500.data
501#===========================================================================
502
503
504data_begin:
505
506.include "logo.lzss_new"
507
508ver_string:	.ascii	" Version \0"
509compiled_string:	.ascii	", Compiled \0"
510megahertz:	.ascii	"MHz PPC \0"
511.equ space, ram_comma+6
512.equ comma, ram_comma+5
513linefeed:   	.ascii  "\n\0"
514escape:		.ascii	"\033[\0"
515c:		.ascii  "C\0"
516ram_comma:	.ascii	"M RAM, \0"
517
518bogo_total:	.ascii	" Bogomips Total\0"
519
520default_colors:	.ascii	"\033[0m\n\n\0"
521
522cpuinfo:	.ascii	"/proc/cpuinfo\0"
523
524one:	.ascii	"One \0"
525
526disk_buffer:
527.ascii "processor	: 0\n"
528.ascii "cpu		: 745/755\n"
529.ascii "temperature 	: 22-24 C (uncalibrated)\n"
530.ascii "clock		: 600.000000MHz\n"
531.ascii "revision	: 51.17 (pvr 0008 3311)\n"
532.ascii "bogomips	: 49.79\n"
533.ascii "timebase	: 24960000\n"
534.ascii "platform	: PowerMac\n"
535.ascii "model		: PowerBook4,1\n"
536.ascii "machine		: PowerBook4,1\n"
537.ascii "motherboard	: PowerBook4,1 MacRISC2 MacRISC Power Macintosh\n"
538.ascii "detected as	: 257 (iBook 2)\n"
539.ascii "pmac flags	: 0000001b\n"
540.ascii "L2 cache	: 256K unified\n"
541.ascii "pmac-generation	: NewWorld\n\0"
542
543uname_info:
544.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"
545.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"
546.ascii "henparma\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
547.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"
548.ascii "2.6.29\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
549.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"
550.ascii "#1 Wed May 13 15:51:54 UTC 2009\0"
551.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"
552.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"
553.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"
554.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"
555.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"
556
557
558sysinfo_buff:
559.long 0,0,0,0,512*1024*1024,0,0,0
560
561#============================================================================
562#.bss
563#============================================================================
564
565.lcomm bss_begin,0
566.lcomm	num_to_ascii_buff,10
567.lcomm num_to_ascii_end,1
568.lcomm  text_buf, (N+F-1)	# These buffers must follow each other
569.lcomm	out_buffer,16384
570
571
572
573
574
575
576
577
578
579
580