[go: up one dir, main page]

File: common.S

package info (click to toggle)
s390-tools 1.6.2-1
  • links: PTS
  • area: main
  • in suites: lenny
  • size: 2,160 kB
  • ctags: 3,968
  • sloc: ansic: 26,413; asm: 5,072; sh: 4,042; cpp: 1,518; perl: 1,299; makefile: 587
file content (290 lines) | stat: -rw-r--r-- 9,977 bytes parent folder | download
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
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
#
#  Common code for the different second stage boot loaders
#    Copyright IBM Corp. 2001, 2006.
#    Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com),
#		Heiko Carstens (heiko.carstens@de.ibm.com)
#

# some definitions from kernel land
__LC_IPLDEV  = 0xC6C
__LC_PANIC_MAGIC= 0xE00

# Error codes shown as address in disabled wait psw

EENABLE_DEV  = 0x00000100 # enable device failed
EDISABLE_DEV = 0x00000101 # disable device failed
ESSCH        = 0x00000102 # start subchannel failed
EWRONGTYPE   = 0x00000200 # wrong ipl type supplied
	.macro stage2_start
#
# Function entry point at 0x2000 is called with C linkage
#   %r2-%r3: load descriptor
#   %r3    : device subchannel id
#   %r4    : load address
#
        basr   %r1,0
        b      _load_blocklist-.(%r1)
	.align 8

#
# Program execution of the second stage boot loader starts at 0x2008
#
        .globl _start
_start: stm    %r0,%r15,0x180           # store all registers 
        basr   %r13,0
0:      l      %r15,3f-0b(%r13)         # load end of stack address

	bas    %r14,_menu-0b(%r13)	# show menu
	sll    %r2,3			# get offset from config number
	lr     %r6,%r2

        l      %r11,0xb8                # load ipl device subchannel id
	lr     %r2,%r11
	bas    %r14,_enable_device-0b(%r13)
        la     %r10,0
        st     %r10,__LC_PANIC_MAGIC    # clear panic flag
	lm     %r2,%r3,STAGE2_DESC      # get block with configurations
	lr     %r4,%r11
	l      %r5,4f-0b(%r13)
	la     %r12,0(%r5)              # FIXME: provide the correct offset
        bas    %r14,_load_direct-0b(%r13)
	ar     %r6,%r12
        lm     %r2,%r3,8(%r6)           # get block with load descriptors
        lr     %r4,%r11
        lr     %r5,%r12                 # set load address
        bas    %r14,_load_direct-0b(%r13)
	la     %r12,32(%r12)		# skip header entry
1:      lm     %r2,%r3,0(%r12)		# load blocklist container of descriptor
	l      %r4,20(%r12)		# load type
	lhi    %r5,0xf
	nr     %r4,%r5			# only the last four bits are the type
	l      %r5,28(%r12)		# load address
	l      %r6,24(%r12)		# load psw mask
	sll    %r4,2
	l      %r1,5f-0b(%r4,%r13)	# function pointer according to type
	lr     %r4,%r11			# pass subchannel id
        bas    %r14,0(%r1)
2:	la     %r12,32(%r12)		# next load descriptor
        b      1b-0b(%r13)
3:      .long  0x10000-96
4:	.long  0x8000
5:	.long  _bug			# type 0: not allowed
	.long  _execute			# type 1: jump to target
	.long  _load_binary		# type 2: binary file

_bug:
	basr   %r1,0
0:	l      %r2,1f-0b(%r1)
	bas    %r4,_panik-0b(%r1)	# won't return
        br     %r14
1:	.long  EWRONGTYPE


_load_binary:
        stm    %r6,%r15,24(%r15)
        basr   %r13,0                   # base register
0:      s      %r15,1f-0b(%r13)         # create stack frame
        lr     %r12,%r4
	bas    %r14,_load_blocklist-0b(%r13)
        lm     %r6,%r15,120(%r15)
        br     %r14
1:	.long  96
	
_execute:
	basr   %r1,0
0:	st     %r6,0(%r0)		# write supplied psw to address 0
	st     %r5,4(%r0)
	lr     %r2,%r11
	bas    %r14,_disable_device-0b(%r1)
	lpsw   0			# execute what we have loaded

#include "menu.S"

	.endm

#
# The load descriptor is 32 bytes in length and contains 3 entries:
#   offset 0  : a blocklist descriptor (fba/eckd, 64 bit)
#   offset 23 : a type (8 bit)
#   offset 24 : an address (64 bit)
# The meaning of the address and the validity of the blocklst
# depends on the type.
#   type = 1 : load binary, blocklist valid, address = load address
#   type = 2 : load psw, blocklist invalid, address = PSW
#
	.macro blocklist_traverser
# parameter
#   %r2+%r3: blocklist head descriptor
#   %r4    : device subchannel id
#   %r5    : load address
_load_blocklist:
        stm    %r6,%r15,24(%r15)
        basr   %r13,0                   # base register
0:      s      %r15,7f-0b(%r13)         # create stack frame
1:	lr     %r12,%r4                 # save device subchannel id
	lr     %r11,%r5                 # save load address
	lr     %r8,%r2                  # save descriptor
	lr     %r9,%r3
	bas    %r14,_extract_length-0b(%r13)   # get length from descriptor
	lr     %r10,%r2                 # save returned length
	lr     %r2,%r8                  # reload descriptor to %r2/%r3
	lr     %r3,%r9
	lr     %r4,%r12                 # reload device id to %r4
	l      %r5,9f-0b(%r13)          # get memory area for indirect block
        bas    %r14,_load_direct-0b(%r13) # load indirect block
	lr     %r9,%r10                 # (length / 8 - 1) = # direct descr.
	srl    %r9,3
	bctr   %r9,0
	l      %r8,9f-0b(%r13)
2:	clc    0(8,%r8),8f-0b(%r13)     # test block descriptor
	be     6f-0b(%r13)              # descriptor == 0 -> done
	lm     %r2,%r3,0(%r8)           # pass block descriptor
	bas    %r14,_is_zero_block-0b(%r13)    # test for special 0 descriptor
	ltr    %r2,%r2                  # is it a hole to fill with 0?
	bne    4f-0b(%r13)              # no, normal block descriptor
	lm     %r2,%r3,0(%r8)           # pass block descriptor
	bas    %r14,_extract_length-0b(%r13)   # get length from descriptor
	lr     %r3,%r2                  # move length to an odd register
	lr     %r2,%r11                 # move address to an even register
	alr    %r11,%r3                 # add length to load address
	slr    %r5,%r5                  # set length of source to zero
3:	mvcle  %r2,%r4,0                # clear storage
	bo     3b-0b(%r13)	
	b      5f-0b(%r13)
4:	lm     %r2,%r3,0(%r8)           # pass block descriptor
	lr     %r4,%r12                 # pass device subchannel id
        lr     %r5,%r11                 # pass load address
        bas    %r14,_load_direct-0b(%r13) # load indirect block
	lr     %r11,%r2                 # move updated load address
5:	la     %r8,8(%r8)               # next descriptor
	bct    %r9,2b-0b(%r13)
	lm     %r2,%r3,0(%r8)           # load continuation descriptor
	lr     %r4,%r12                 # move device id for next round
	lr     %r5,%r11			# move load address for next round
	clc    0(8,%r8),8f-0b(%r13)     # test continuation descriptor
	bne    1b-0b(%r13)              # != 0 -> load next indirect block
6:      lr     %r2,%r11                 # return updated load address
	lm     %r6,%r15,120(%r15)
        br     %r14
7:      .long  96
8:      .long  0,0
9:      .long  0x8200                   # memory address for indirect blocks

        .endm

	.macro device_fn
#
# Enable I/O on the ipl device. 
#   %r2 : device subchannel id
#
_enable_device:
        stm    %r6,%r15,24(%r15)
        basr   %r13,0                   # base register
0:      s      %r15,1f-0b(%r13)
	lr     %r1,%r2
	l      %r2,4f-0b(%r13)          # set panik code early
        stsch  2f-0b(%r13)
        oi     2f-0b+5(%r13),0x84       # enable ssch and multipath mode
        msch   2f-0b(%r13)
	bnz    _panik-0b(%r13)          # subchannel busy or in error ?
	lctl   %c6,%c6,3f-0b(%r13)      # enable all interrupt classes
        lm     %r6,%r15,120(%r15)
        br     %r14
1:	.long  96
	.align 8
2:	.fill  64,1,0
3:	.long  0xff000000               # CR6 initial value
4:      .long  EENABLE_DEV

#
# Disable I/O on the ipl device.
#   %r2 : device subchannel id
#
_disable_device:
        stm    %r6,%r15,24(%r15)
        basr   %r13,0                   # base register
0:      s      %r15,1f-0b(%r13)
	lr     %r1,%r2
	l      %r2,3f-0b(%r13)          # set panik code early
	lctl   %c6,%c6,2f-0b(%r13)      # disable all interrupt classes
        stsch  2f-0b(%r13)
        ni     2f-0b+5(%r13),0x7B       # disable ssch and multipath mode
        msch   2f-0b(%r13)
	bnz    _panik-0b(%r13)          # subchannel busy or in error ?
        lm     %r6,%r15,120(%r15)
        br     %r14
1:	.long  96
        .align 8
2:	.long  0x00000000               # CR6 (all interrupts classes disabled)
3:      .long  EDISABLE_DEV
	.endm	

	.macro io_subroutines
#
# Start I/O
#   %r2 : device subchannel id
#   %r3 : address of orb
#   %r4 : address of irb
#   %r5 : retry count
#
_ssch:
        stm    %r6,%r15,24(%r15)
        basr   %r13,0                   # base register
0:      s      %r15,6f-0b(%r13)         # create stack frame
	lr     %r12,%r2                 # save subchannel id
	lr     %r11,%r3                 # save orb
	lr     %r10,%r4                 # save irb
	lr     %r9,%r5                  # save retry count
1:	lr     %r1,%r12
	ssch   0(%r11)                  # go
        bnz    4f-0b(%r13)              # houston, we have a problem
2:	lr     %r2,%r12                 # call _wait4de with subchannel id
	lr     %r3,%r10                 # and irb address as parameters
	bas    %r14,_wait4de-0b(%r13)   # wait until DE or error
	tm     9(%r10),0xff             # test channel status
	bnz    4f-0b(%r13)
	tm     8(%r10),0xf3             # test device status
	bz     5f-0b(%r13)
	bct    %r9,1b-0b(%r13)          # something went wrong, retry.
4:	l      %r2,7f-0b(%r13)
	bas    %r4,_panik-0b(%r13)      # won't return
5:	lm     %r6,%r15,120(%r15)
        br     %r14
6:	.long  96
7:      .long  ESSCH

#
# Wait for interrupt subroutine
#   %r2 : device subchannel id
#   %r3 : address of irb
#
_wait4de:
	lr     %r1,%r2
	basr   %r4,0
0:      mvc    0x78(8),5f-0b(%r4)       # set i/o new psw
1:	lpsw   4f-0b(%r4)
2:      c      %r1,0xb8                 # compare subchannel id
        bne    1b-0b(%r4)               # unequal -> continue waiting
	tsch   0(%r3)
	tm     9(%r3),0xff              # test channel status
	bnz    3f-0b(%r4)
	tm     8(%r3),0xf3              # got something unusual ?
	bnz    3f-0b(%r4)
        tm     8(%r3),0x04              # got device end ?
        bz     1b-0b(%r4)               # still busy -> continue waiting
3:      br     %r14
        .align 8
4:	.long  0x020a0000,0x80000000+1b
5:	.long  0x00080000,0x80000000+2b # io new psw

#
# Panik routine. Loads a disabled wait psw
#   %r2 : panik code
#
_panik:
	basr   %r1,0
0:	st     %r2,1f-0b+4(%r1)         # store code in address part of psw
	lpsw   1f-0b(%r1)
	.align 8
1:	.long  0x000a0000,0x00000000
        .endm