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