root/arch/sparc/boot/boot.S

/* [previous][next][first][last][top][bottom][index][help] */
   1 /* boot.S: The initial boot code for the Sparc port of Linux.
   2 
   3    Copyright (C) 1994 David S. Miller (davem@caip.rutgers.edu)
   4 
   5            This file has to serve three purposes.
   6 
   7            1) determine the prom-version and cpu/architecture
   8            2) print enough useful info before we start to execute
   9               c-code that I can possibly begin to debug things
  10            3) Hold the vector of trap entry points
  11 
  12    The Sparc offers many challenges to kernel design. Here I will
  13    document those I have come across thus far. Upon bootup the boot
  14    prom loads your a.out image into memory. This memory the prom has
  15    already mapped for you, however as far as I can tell the virtual
  16    adress cache is not turned on although the MMU is translating 
  17    things. You get loaded at 0xf8004000 exactly. So, when you link
  18    a boot-loadable object you want to do something like:
  19 
  20         ld -e start -T f8004000 -o mykernel myobj1.o myobj2.o ....
  21 
  22    to produce a proper image.
  23 
  24    At boot time you are given (as far as I can tell at this time)
  25    one key to figure out what machine you are one and what devices
  26    are available. The prom when it loads you leaves a pointer to
  27    the 'rom vector' in register %o0 right before it jumps to your
  28    starting address. This is a pointer to a struct that is full of
  29    pointer to functions (ie. printf, halt, reboot), pointers to
  30    linked lists (ie. memory mappings), and pointer to imperical
  31    constants (ie. stdin and stdout magic cookies + rom version).
  32    Starting with this piece of information you can figure out 
  33    just about anything you want about the machine you are on.
  34 */
  35 
  36 #include "boot.h"
  37 #include "version.h"
  38 
  39         .data
  40 
  41 /* First thing to go in the data segment is the interrupt stack. */
  42 
  43         .globl  _intstack
  44         .globl  _eintstack
  45 _intstack:
  46         .skip   4 * NBPG                ! 16k = 128 128-byte stack frames
  47 _eintstack:
  48 
  49 
  50 
  51 /* 
  52    The following are used with the prom_vector node-ops to figure out
  53    the cpu-type 
  54 */
  55 
  56         .globl  _cputyp
  57 
  58 _cputyp:
  59         .word   1
  60 
  61 _cputypval:
  62         .asciz "sun4c"
  63         .ascii "     "
  64 
  65 _cputypvar:
  66         .asciz "compatability"
  67 
  68 _cputypvallen = _cputypvar - _cputypval
  69 
  70 /* This hold the prom-interface-version number for either v0 or v2. */
  71 
  72         .align 4
  73         .globl  _prom_iface_vers
  74 
  75 _prom_iface_vers:       .skip 4
  76 
  77 /* WARNING: evil messages follow */
  78 
  79         .align 4
  80 
  81 sun4_notsup:
  82         .asciz  "Sparc-Linux: sun4 support not implemented yet\n\n"
  83         .align 4
  84 
  85 sun4m_notsup:
  86         .asciz  "Sparc-Linux: sun4m support does not exist\n\n"
  87         .align 4
  88 
  89 sun4d_notsup:
  90         .asciz  "Sparc-Linux: sun4d support does not exist\n\n"
  91         .align 4
  92 
  93 you_lose:
  94         .asciz  "You lose..... Thanks for playing...\n"
  95         .align 4
  96 
  97 /*
  98    Fill up the prom vector, note in particular the kind first element,
  99    no joke.
 100 */
 101 
 102                         .globl _prom_vector_p
 103 
 104 _prom_vector_p:         .skip 4
 105 prom_magic:             .skip 4                 ! magic mushroom, beware...
 106 prom_rom_vers:          .skip 4                 ! interface version (v0 or v2)
 107 prom_pluginvers:        .skip 4                 ! XXX help help help ???
 108 prom_revision:          .skip 4                 ! PROM revision (ie. 1.4)
 109 prom_bootstr:           .skip 4                 ! what we are invoked with
 110 prom_putchar:           .skip 4                 ! void putchar(int ch)  BLOCKING.
 111 prom_getchar:           .skip 4                 ! int getchar(void)     BLOCKING.
 112 prom_nputchar:          .skip 4                 ! int purchar(int ch)   non-block
 113 prom_ngetchar:          .skip 4                 ! int getchar(void)     non-block
 114 prom_halt:              .skip 4                 ! void halt(void)  solaris friend
 115 prom_eval:              .skip 4                 ! void eval(int len, char* string)
 116 prom_v0mem_desc:        .skip 4                 ! V0 memory descriptor list ptr.
 117 prom_nodefuncs:         .skip 4                 ! Magical Node functions
 118 prom_v0devfuncs:        .skip 4                 ! V0 device operations
 119 prom_putstring:         .skip 4                 ! prom putstring()
 120 prom_bootme:            .skip 4                 ! reset()
 121 prom_printf:            .skip 4                 ! minimal printf()
 122 
 123 /* The prom_abort pointer MUST be mapped in all contexts, because if you
 124    don't then if a user process is running when you press the abort key
 125    sequence, all sorts of bad things can happen
 126 */
 127 
 128 prom_abort:             .skip 4                 ! "L1-A" magic cookie
 129                                                 ! must be mapped in ALL contexts
 130 prom_ticks:             .skip 4                 ! number of ticks since reset
 131 
 132 /* prom_sync is a place where the kernel should place a pointer to a kernel
 133    function that when called will sync all pending information to the drives
 134    and then promptly return. If the kernel gets aborted with 'L1-A' one can
 135    give the 'sync' command to the boot prompt and this magic cookie gets
 136    executed. Nice feature eh?
 137 */
 138 
 139 prom_sync:              .skip 4                 ! hook in prom for "sync" func
 140 prom_v0bootarg:         .skip 4                 ! v0 prom boot arguements
 141 prom_v2bootarg:         .skip 4                 ! same as above for v2 proms
 142 prom_ethaddr_func:      .skip 4                 ! extract ethernet device address
 143 prom_v2devfunc:         .skip 4                 ! ptr to v2 style device ops.
 144 prom_xtra_array:        .skip 4                 ! who knows :-( help help
 145 prom_setcontext:        .skip 4                 ! set context on sun4c
 146 prom_stdin:             .skip 4                 ! prom stdin magic cookie
 147 prom_stdout:            .skip 4                 ! prom stdout magic cookie
 148 
 149 
 150         .align 4
 151 
 152         .globl boot_msg
 153 
 154 /* memory descriptor property strings, v2 = yuk yuk yuk  */
 155 /* XXX how to figure out vm mapped by prom? May have to scan magic addresses */
 156 
 157 mem_prop_physavail:     .asciz "available"
 158 mem_prop_phystot:       .asciz "reg"
 159 
 160 /* v2_memory descriptor struct kludged here for assembly, if it ain't broke */
 161 
 162                 .align 4
 163 v2_mem_struct:  .skip 0xff
 164 
 165                         .align 4
 166 v2_printf_physavail:    .asciz "Physical Memory Available: 0x%x bytes"
 167 v2_printf_phystot:      .asciz "Physical Memory: 0x%x bytes"
 168 
 169 /* A place to store property strings returned from the prom 'node' funcs */
 170 
 171                         .align 4
 172 prop_string_buf:        .skip 32
 173 
 174 prop_name:      .asciz "name"
 175                 .align 4
 176 
 177 current_node:   .skip 4
 178                 .align 4
 179 
 180 
 181 /* nice little boot message */
 182 
 183 boot_msg:       
 184         .ascii "Booting Sparc-Linux V0.00PRE-ALPHA "
 185         .ascii WHO_COMPILED_ME 
 186         .asciz " \n"
 187         .align 4
 188 
 189         .globl boot_msg2
 190 
 191 boot_msg2:
 192         .asciz "Booting Sparclinux V0.00 PRE-ALPHA on a (SUN4C)\n\n"
 193 
 194         .align 4
 195 
 196 pstring1:
 197         .asciz "Prom Magic Cookie: 0x%x  "
 198         .align 4
 199 
 200 pstring2:
 201         .asciz "Interface Version: v%d\n"
 202         .align 4
 203 
 204 pstring3:
 205         .asciz "Prom Revision: V%d\n\n"
 206         .align 4
 207 
 208 pstring4:
 209         .ascii "Total Physical Memory: %d bytes\nVM mapped by Prom: %d bytes\n"
 210         .asciz "Available Physical Memory: %d bytes\n"
 211         .align 4
 212 
 213 
 214 newline:
 215         .asciz "\n"
 216         .align 4
 217 
 218         .text
 219 
 220         .globl  _msgbuf
 221 msgbufsize = NBPG                       ! 1 page for msg buffer
 222 _msgbuf = KERNBASE + NBPG
 223 
 224 
 225 IE_reg_addr = _msgbuf + msgbufsize      ! this page not used; points to IEreg
 226 
 227 /*
 228    ignore the following variable settings, I used them when I had
 229    no stinkin idea what the linker was doing with the symbols to
 230    get them in the right place for load time
 231 */
 232 
 233 whereis_kernbase      = KERNBASE
 234 whereis_prom_vector_p = _prom_vector_p-KERNBASE
 235         
 236 /* Ok, things start to get interesting. We get linked such that 'start'
 237    is the entry symbol. However, it is real low in kernel address space
 238    and as such a nifty place to place the trap table. We achieve this goal
 239    by just jumping to 'dostart' for the first trap's entry as the sparc
 240    never receives the zero trap as it is real special.
 241 
 242    Each trap entry point is the size of 4 sparc instructions (or 4 bytes
 243    * 4 insns = 16 bytes). There are 128 hardware traps (some undefined
 244    or unimplemented) and 128 software traps (ditto).
 245 
 246    One of the instructions must be a branch. More often than not this
 247    will be to a trap handler entry point becuase it is completely
 248    impossible to handle any trap in 4 insns. I welcome anyone to 
 249    challenge this theory. :-)
 250 
 251    On entry into this table the hardware has loaded the program counter
 252    at which the trap occurred into register %l1 and the next program
 253    counter into %l2, this way we can return from the trap with a simple
 254 
 255            jmp %l1; rett %l2
 256 
 257    after properly servicing the trap. It wouldn't be a bad idea to load
 258    some more information into the local regs since we have technically
 259    2 or 3 instructions to play with besides the jmp to the 'real' trap
 260    handler (one can even go in the delay slot). For now I am going to put
 261    the %psr (processor status register) and the trap-type value in %l0
 262    and %l3 respectively.
 263 
 264    TODO: Write cheesy macros to make this table more manageable.
 265          Ugh, this shit is long...
 266 
 267 */
 268 
 269         .globl  start
 270         .globl  _trapbase
 271 start:
 272 _trapbase:
 273         b dostart; nop; nop; nop        ! we never get trap #0 it is special
 274                                         ! TRAP code should go here, TODO :>
 275 
 276 _msgbufmapped:
 277         .word   1
 278 
 279 
 280 /* The following two things point to window management tables. The first
 281    one is used to quickly look up how many user windows there are from
 282    trap-land. The second is used in a trap handler to determine if a rett
 283    instruction will land us smack inside the invalid window that possibly
 284    the trap was called to fix-up.
 285 */
 286 
 287           .data
 288           .skip   32                      ! alignment byte & negative indicies
 289 lnx_uw:       .skip   32                      ! u_char uwtab[-31..31];
 290 lnx_winmask:  .skip   32                      ! u_char wmask[0..31];
 291 
 292         .text
 293         
 294         
 295 /* Cool, here we go. Pick up the romvec pointer in %o0 and stash it in
 296    %g7 and at _prom_vector_p. And also quickly check whether we are on
 297    a v0 or v2 prom.
 298 */
 299 
 300 dostart:        mov     %o0, %g7
 301                 st      %o0, [_prom_vector_p]   ! we will need it later
 302                 ld      [%g7 + 0x4], %o2
 303                 cmp     %o2, 2                  ! a v2 prom?
 304                 be      found_v2
 305                 nop
 306 
 307 /* Old sun4's pass our load address into %o0 instead of the prom
 308    pointer. On sun4's you have to hard code the romvec pointer into
 309    your code. Sun probably still does that because they don't even
 310    trust their own "OpenBoot" specifications.
 311 */
 312 
 313                 set     0x4000, %g6
 314                 cmp     %o0, %g6                ! an old sun4?
 315                 beq     no_sun4_here
 316                 nop
 317 
 318                 st      %g0, [_prom_iface_vers] ! useless, disappear soon
 319                 b       not_v2
 320                 nop
 321 
 322 found_v2:
 323                 set     0x2, %o5
 324                 st      %o5, [_prom_iface_vers]
 325 
 326 not_v2:
 327 
 328 /* Get the machine type via the mysterious romvec node operations.
 329    Here we can find out whether we are on a sun4 sun4c, sun4m, or
 330    a sun4m. The "nodes" are set up as a bunch of n-ary trees which
 331    you can traverse to get information about devices and such. The
 332    information acquisition happens via the node-ops which are defined
 333    in the linux_openprom.h header file. Of particular interest is the
 334    'nextnode(int node)' function as it does the smart thing when
 335    presented with a value of '0', it gives you the first node in the
 336    tree. These node integers probably offset into some internal prom
 337    pointer table the openboot has. It's completely undocumented, so
 338    I'm not about to go sifting through the prom address space, but may
 339    do so if I get suspicious enough. :-)
 340 */
 341 
 342                 mov     0, %o0                  ! next_node(0) = first_node
 343                 ld      [%g7 + 0x1c], %o4
 344                 ld      [%o4], %o4
 345                 call    %o4
 346                 nop
 347 
 348                 set     _cputypvar, %o1         ! first node has cpu-arch
 349                 set     _cputypval, %o2         ! information, the string
 350                 ld      [%g7 + 0x1c], %o4       ! 'compatability' tells
 351                 ld      [%o4 + 0x0c], %o4       ! that we want 'sun4x' where
 352                 call    %o4                     ! x is one of '', 'c', 'm',
 353                 nop                             ! 'd' or 'e'. %o2 holds pointer
 354                                                 ! to a buf where above string
 355                                                 ! will get stored by the prom.
 356                 set     _cputypval, %o2
 357                 ldub    [%o2 + 4], %o0
 358                 cmp     %o0, 'c'                ! we already know we are not
 359                 beq     is_sun4c                ! on a plain sun4 because of
 360                 nop                             ! the check for 0x4000 in %o0
 361                 cmp     %o0, 'm'                ! at start:
 362                 beq     is_sun4m
 363                 nop
 364                 b       no_sun4d_here           ! god bless the person who
 365                 nop                             ! tried to run this on sun4d
 366 
 367 is_sun4m:
 368 is_sun4c:                                       ! OK, this is a sun4c, yippie
 369                 mov     %g7, %g6                ! load up the promvec offsets
 370                 st      %g6, [prom_magic]       ! magic mushroom :>
 371                 add     %g7, 0x4, %g6
 372                 st      %g6, [prom_rom_vers]
 373                 add     %g7, 0x8, %g6
 374                 st      %g6, [prom_pluginvers]
 375                 add     %g7, 0xc, %g6
 376                 st      %g6, [prom_revision]
 377                 add     %g7, 0x10, %g6
 378                 st      %g6, [prom_v0mem_desc]
 379                 add     %g7, 0x1c, %g6
 380                 st      %g6, [prom_nodefuncs]
 381                 add     %g7, 0x20, %g6
 382                 st      %g6, [prom_bootstr]
 383                 add     %g7, 0x24, %g6
 384                 st      %g6, [prom_v0devfuncs]
 385                 add     %g7, 0x48, %g6
 386                 st      %g6, [prom_stdin]
 387                 add     %g7, 0x4c, %g6
 388                 st      %g6, [prom_stdout]
 389                 add     %g7, 0x54, %g6
 390                 st      %g6, [prom_putchar]
 391                 add     %g7, 0x50, %g6
 392                 st      %g6, [prom_getchar]
 393                 add     %g7, 0x5c, %g6
 394                 st      %g6, [prom_nputchar]
 395                 add     %g7, 0x58, %g6
 396                 st      %g6, [prom_ngetchar]
 397                 add     %g7, 0x60, %g6
 398                 st      %g6, [prom_putstring]
 399                 add     %g7, 0x64, %g6
 400                 st      %g6, [prom_bootme]
 401                 add     %g7, 0x68, %g6
 402                 st      %g6, [prom_printf]
 403                 add     %g7, 0x6c, %g6
 404                 st      %g6, [prom_abort]
 405                 add     %g7, 0x70, %g6
 406                 st      %g6, [prom_ticks]
 407                 add     %g7, 0x74, %g6
 408                 st      %g6, [prom_halt]
 409                 add     %g7, 0x78, %g6
 410                 st      %g6, [prom_sync]
 411                 add     %g7, 0x7c, %g6
 412                 st      %g6, [prom_eval]
 413                 add     %g7, 0x80, %g6
 414                 st      %g6, [prom_v0bootarg]
 415                 add     %g7, 0x84, %g6
 416                 st      %g6, [prom_ethaddr_func]
 417                 add     %g7, 0x88, %g6
 418                 st      %g6, [prom_v2bootarg]
 419                 add     %g7, 0x98, %g6
 420                 st      %g6, [prom_v2devfunc]
 421                 add     %g7, 0xc8, %g6
 422                 st      %g6, [prom_xtra_array]
 423                 add     %g7, 0x104, %g6
 424                 st      %g6, [prom_setcontext]
 425 
 426 /* That was easy, now lets try to print some message on the screen.
 427    We have to be careful because the prom addressed things weird and
 428    we aren't really mapped into memory as far as the rom routines are
 429    concerned. So all addresses we have ourselves and would like the
 430    prom to actually use must be calculated as (addr - KERNBASE) in order
 431    for anything to work at all. We will map ourselves later before we
 432    call any c-code to avoid this hassle.
 433 */
 434 
 435                 set     boot_msg-KERNBASE, %o0  
 436                 ld      [prom_printf-KERNBASE], %o2
 437                 ld      [%o2], %o1
 438                 call    %o1                     ! print boot message #1
 439                 nop
 440 
 441 _newline:       set     newline-KERNBASE, %o0
 442                 ld      [prom_printf-KERNBASE], %o2
 443                 ld      [%o2], %o1
 444                 call    %o1
 445                 nop
 446 
 447                 b       0f
 448                 nop                             ! damn delay slots...
 449 
 450 0:              nop                             ! duh   
 451                 set     pstring1-KERNBASE, %o0
 452                 ld      [prom_printf-KERNBASE], %o3
 453                 ld      [%o3], %o2
 454                 ld      [prom_magic-KERNBASE], %o3
 455                 ld      [%o3], %o1
 456                 call    %o2
 457                 nop; nop; nop
 458 
 459                 set     pstring2-KERNBASE, %o0
 460                 ld      [prom_printf-KERNBASE], %o3
 461                 ld      [%o3], %o2
 462                 ld      [_prom_iface_vers], %o3
 463                 ld      [%o3], %o1
 464                 call    %o2
 465                 nop; nop; nop
 466 
 467 /* Print out various bits of memory information. At this point
 468    I just cycle through the documented v0_prom memory lists for
 469    the values. They are linked lists and allow for description of
 470    non-contiguous physical memory configurations, thus the 'memloop'
 471    things to traverse the linked lists.
 472 */
 473 
 474 /* Things are different for v0 and v2. v2 requires traversing the node trees
 475    and that really sucks.
 476 */
 477 
 478 /* Another Note:
 479         The prom printf() function can take up to 5 arguements in registers
 480         %o1 -- %o5 , the format string goes in %o0. It is your usual libc
 481         printf() believe it or not.
 482 */
 483 
 484                 cmp     %o0, 0x2
 485                 be      v2_mem_probe
 486                 nop
 487 
 488                 set     pstring4-KERNBASE, %o0
 489                 ld      [prom_printf-KERNBASE], %o5
 490                 ld      [%o5], %o4
 491                 ld      [_prom_vector_p], %l1
 492                 ld      [%l1+16], %l2
 493                 ld      [%l2], %l3
 494                 ld      [%l3 + 8], %o1          ! 'nbytes' memory accumulator
 495 
 496                 ld      [_prom_vector_p], %l1
 497                 ld      [%l1 + 16], %l2
 498                 ld      [%l2], %l3
 499                 ld      [%l3], %l4
 500 
 501 memloop:
 502                 cmp     %l4, 0
 503                 be      mv_to_vmprom            ! is there more?
 504                 nop
 505 
 506                 ld      [%l4 + 0x8], %l6        ! aparently so...
 507                 add     %o1, %l6, %o1
 508                 b       memloop
 509                 ld      [%l4], %l4
 510 
 511 mv_to_vmprom:
 512 
 513                 ld      [_prom_vector_p], %l0
 514                 ld      [%l0 + 20], %l1
 515                 ld      [%l1], %l2
 516                 ld      [%l2 + 8], %o2          ! memory accumulator
 517 
 518                 ld      [_prom_vector_p], %l0
 519                 ld      [%l0 + 20], %l1
 520                 ld      [%l1], %l2
 521                 ld      [%l2], %l4
 522 
 523 memloop2:
 524                 cmp     %l4, 0
 525                 be      mv_to_vmprom2           ! is there more?
 526                 nop
 527                 ld      [%l4 + 0x8], %l6        ! aparently so...
 528                 add     %o2, %l6, %o2
 529                 b       memloop2
 530                 ld      [%l4], %l4
 531 
 532 mv_to_vmprom2:
 533 
 534                 ld      [_prom_vector_p], %l0
 535                 ld      [%l0 + 24], %l1
 536                 ld      [%l1], %l2
 537                 ld      [%l2 + 8], %o3          ! memory accumulator
 538 
 539                 ld      [_prom_vector_p], %l0
 540                 ld      [%l0 + 24], %l1
 541                 ld      [%l1], %l2
 542                 ld      [%l2], %l4
 543 
 544 memloop3:
 545                 cmp     %l4, 0
 546                 be      mv_to_vmprom3           ! is there more?
 547                 nop
 548                 ld      [%l4 + 0x8], %l6        ! aparently so...
 549                 add     %o3, %l6, %o3
 550                 b       memloop3
 551                 ld      [%l4], %l4
 552 
 553 mv_to_vmprom3:
 554 
 555                 call    %o4
 556                 nop; nop; nop
 557 
 558 
 559                 set     newline-KERNBASE, %o0
 560                 ld      [prom_printf-KERNBASE], %o2
 561                 ld      [%o2], %o1
 562                 call    %o1
 563                 nop
 564 
 565                 b       halt_me
 566                 nop
 567 
 568 no_sun4_here:
 569                 ld      [%g7 + 0x68], %o1
 570                 set     sun4_notsup, %o0
 571                 call    %o1
 572                 nop
 573                 b       rest_of_boot                    ! next stage...
 574                 nop
 575 
 576 v2_mem_probe:
 577                 set     you_lose-KERNBASE, %o0          ! I just print this
 578                 ld      [prom_printf-KERNBASE], %o1     ! crap to debug my node
 579                 ld      [%o1], %o2                      ! routines :-)
 580                 call    %o2
 581                 nop
 582 
 583                 st      %g0, [current_node]
 584                 set     prop_string_buf, %o2
 585                 or      %g0, %g0, %o0
 586                 ld      [prop_name], %o1
 587                 or      %g0, 31, %o3            
 588 
 589 node_find_loop:
 590                 ld      [prom_nodefuncs], %o4
 591                 ld      [%o4 + 0xc], %o4
 592                 call    %o4
 593                 nop
 594                 ld      [prop_string_buf], %l3
 595                 cmp     %l3, 'm'
 596                 bne     node_find_loop2
 597                 ld      [prop_string_buf + 1], %l3
 598                 cmp     %l3, 'e'
 599                 bne     node_find_loop2
 600                 ld      [prop_string_buf + 2], %l3
 601                 cmp     %l3, 'm'
 602                 bne     node_find_loop2
 603                 nop
 604                 b       found_mem_node
 605                 nop
 606 
 607 node_find_loop2:
 608                 ld      [current_node], %o0             ! get next node
 609                 ld      [prom_nodefuncs], %o1
 610                 ld      [%o1], %o1
 611                 call    %o1
 612                 nop
 613                 st      %o0, [current_node]
 614                 set     prop_string_buf, %o2
 615                 set     prop_name, %o1
 616                 b       node_find_loop
 617                 or      %g0, 31, %o3            
 618                                                 
 619 found_mem_node:
 620                 set     v2_mem_struct-KERNBASE, %o2
 621                 set     0xff, %o3
 622                 set     mem_prop_physavail-KERNBASE, %o1
 623                 ld      [current_node], %o0
 624                 ld      [prom_nodefuncs], %o4
 625                 ld      [%o4 + 0xc], %o4
 626                 call    %o4
 627                 nop
 628 
 629                 set     v2_printf_physavail-KERNBASE, %o0
 630                 ld      [v2_mem_struct + 0x8], %o1
 631                 ld      [prom_printf], %o4
 632                 ld      [%o4], %o4              
 633                 call    %o4
 634                 
 635                 set     v2_mem_struct-KERNBASE, %o2
 636                 set     0xff, %o3
 637                 set     mem_prop_phystot-KERNBASE, %o1
 638                 ld      [current_node], %o0
 639                 ld      [prom_nodefuncs], %o4
 640                 ld      [%o4 + 0xc], %o4
 641                 call    %o4
 642                 nop
 643 
 644                 set     v2_printf_physavail-KERNBASE, %o0
 645                 ld      [v2_mem_struct + 0x8], %o1
 646                 ld      [prom_printf], %o4
 647                 ld      [%o4], %o4              
 648                 call    %o4
 649                 nop
 650 
 651                 b       rest_of_boot
 652                 nop
 653 
 654 rest_of_boot:
 655                 call    halt_me
 656                 nop                             ! who cares at this point
 657 
 658 /* There, happy now adrian? */
 659 
 660 no_sun4d_here:
 661                 ld      [%g7 + 0x68], %o1
 662                 set     sun4d_notsup, %o0
 663                 call    %o1
 664                 nop
 665                 b       halt_me
 666                 nop
 667 
 668 halt_me:
 669                 ld      [%g7 + 0x74], %o0
 670                 call    %o0                     ! get us out of here...
 671                 nop                             ! aparently solaris is better
 672 
 673 _strlen:
 674                 mov     %o0, %l1
 675                 mov     %g0, %l3
 676                 ldub    [%l1], %l2
 677                 sll     %l2, 24, %l2
 678                 sra     %l2, 24, %l2
 679 len_loop:
 680                 cmp     %l2, 0
 681                 be      len_loop_end
 682                 nop
 683                 add     %l3, 0x1, %l3
 684                 add     %l1, 0x1, %l1
 685                 ldub    [%l1], %l2
 686                 sll     %l2, 24, %l2
 687                 sra     %l2, 24, %l2
 688                 b       len_loop
 689                 nop
 690 
 691 len_loop_end:
 692                 mov     %l3, %o0
 693                 ret
 694                 nop
 695                 
 696 
 697 
 698 
 699 

/* [previous][next][first][last][top][bottom][index][help] */