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

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