1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160
|
/* $Id: bare.S,v 1.4 1996/04/23 01:53:40 davem Exp $
* base.S: Ugly low-level boot program entry code. The job of this
* module is to parse the boot flags, try to mount the remote
* root filesystem and load the kernel into virtual memory.
*
* Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
*/
#include "bare.h"
#include <asm/ptrace.h>
.data
.globl C_LABEL(romvec)
.globl C_LABEL(idp_ptr)
C_LABEL(romvec):
.word 0
C_LABEL(idp_ptr):
.word 0
.text
.align 8
.globl C_LABEL(first_adr_in_text)
C_LABEL(first_adr_in_text):
/* Grrr, boot block, scratching my head... */
.globl C_LABEL(b_block) /* Start of actual boot block */
.globl C_LABEL(b_block_size) /* In bytes */
.globl C_LABEL(b_block_cksum) /* Checksum of boot block bytes */
b start_of_execution /* XXX Hack */
nop
.align 8
C_LABEL(b_block):
.skip (BOOTBLOCK_NENTRIES * BOOTBLOCK_ENTSIZE)
C_LABEL(b_block_size):
.word 0
C_LABEL(b_block_cksum):
.word 0
/* Ok, the prom has left in %o0 the PROM pointer. We leave it here
* for when we jump into the kernel. So save out of this window before
* you dick with %o0. As far as I know we could be loaded *anywhere*, so
* we relocate ourselves to the "linked" location. Self modifying code rules.
*/
start_of_execution:
sethi %hi(C_LABEL(first_adr_in_text)), %o1 ! This is our top
or %o1, %lo(C_LABEL(first_adr_in_text)), %o1 ! of stack too.
sub %o1, REGWIN_SZ, %o1
add %o1, 0x7, %o1
andn %o1, 0x7, %o1
save %o1, 0x0, %sp ! save is an add
here:
call there
sethi %hi(here), %o4
there:
sub %o7, here-C_LABEL(first_adr_in_text), %o5
or %o4, %lo(here), %o4
cmp %o4, %o7
be loaded_ok
nop
/* Gotta relocate, compute our size sans bss segment. */
set C_LABEL(edata)+4, %o3
set C_LABEL(first_adr_in_text), %o2
sub %o3, %o2, %o3
rel_loop:
ld [%o5], %o4
add %o5, 0x4, %o5
st %o4, [%o2]
subcc %o3, 0x4, %o3
bg rel_loop
add %o2, 0x4, %o2
/* Pray that we are now in a sane place in memory */
sethi %hi(loaded_ok), %o2
or %o2, %lo(loaded_ok), %o2
jmp %o2
nop
loaded_ok:
/* Save the PROM pointer */
sethi %hi(C_LABEL(romvec)), %o1
or %o1, %lo(C_LABEL(romvec)), %o1
st %i0, [%o1]
/* Build a PSR we can live with */
rd %psr, %o1
#if 0
andn %o1, PSR_PIL, %o1
sethi %hi(SANE_PSR), %g4
or %g4, %lo(SANE_PSR), %g4
or %o1, %g4, %o1
#endif
/* V8 book says this works to calculate num_windows */
sethi %hi(0xffffffff), %g2
rd %wim, %g3
or %g2, %lo(0xffffffff), %g2
wr %g2, 0x0, %wim
WRITE_PAUSE
rd %wim, %g4
WRITE_PAUSE
wr %g3, 0x0, %wim
WRITE_PAUSE
/* Restore old %psr */
wr %o1, 0x0, %psr
WRITE_PAUSE
or %g0, 0x0, %g3
1:
srl %g4, 0x1, %g4
subcc %g4, 0x0, %g0
bne 1b
add %g3, 0x1, %g3
/* %g3 now contains nwindows */
sethi %hi(C_LABEL(nwindows)), %o4
st %g3, [%o4 + %lo(C_LABEL(nwindows))]
/* Now zero out our bss segment, lord knows the nasty prom monster
* didn't do it for us.
*/
sethi %hi(C_LABEL(end)), %g1
or %g1, %lo(C_LABEL(end)), %g1
add %g1, 0x4, %g1
sethi %hi(C_LABEL(edata)), %g2
or %g2, %lo(C_LABEL(edata)), %g2
/* Slow, inefficient, who cares, this is messy boot code */
bzero_bss_loop:
st %g0, [%g2]
add %g2, 0x4, %g2
cmp %g2, %g1
bl bzero_bss_loop
nop
call C_LABEL(init_me) ! Fun with empirical constants and prom
nop
/* Dump back into the prom */
get_me_out_of_here:
set C_LABEL(romvec), %g2
ld [%g2], %g2
ld [%g2 + 0x74], %g2
restore
call %g2
nop
|