2 * Dump boot loader for FBA DASDs
3 * Copyright IBM Corp. 2004, 2006.
4 * Author(s): Michael Holzheu <holzheu@de.ibm.com>
6 * Uses extern functions:
15 #include "dumpcommon.S"
16 #if defined(__s390x__)
17 #define USE_64BIT_SCLP
24 #define BLOCKS_PER_WRITE 64
25 #define FBA_BLK_SIZE 0x200
26 #define STAGE2_DESC 0x218
28 ################################################################################
29 # Function entry point at 0x2000 (not used for dump) is called with C linkage
30 # %r2-%r3: load descriptor
31 # %r3 : device subchannel id
33 ################################################################################
35 #if defined(__s390x__)
36 dump_magic: .long 0x5a444642, 0x41363401 # ZDFBA64, version 1
38 dump_magic: .long 0x5a444642, 0x41333101 # ZDFBA31, version 1
41 #if defined(__s390x__)
44 /******************************** 64 BIT **************************************/
47 ################################################################################
48 # Program execution of the second stage boot loader starts at 0x2008
49 ################################################################################
56 st %r9,.Ldh_arch-.Linit_base(%r13) # init arch
57 l %r15,1f-.Linit_base(%r13) # load end of stack address
59 tm __LC_ARCH_MODE_ID(%r9),0x01 # check arch mode
60 bnz .Larch_64-.Linit_base(%r13)
62 /* 32 bit store status */
64 l %r14,.Lstore_status_32-.Linit_base(%r13)
67 st %r10,.Ldh_arch-.Linit_base(%r13)
70 la %r7,2 # first try code 2:
71 la %r6,0 # 64 bit psws are restored
72 sigp %r7,%r6,0x12 # switch to 64 bit
73 bc 8,.Lswitched_64-.Linit_base(%r13) # order accepted ?
74 la %r7,1 # code 2 failed - try code 1
75 sigp %r7,%r6,0x12 # switch to 64 bit
77 sam64 # switch to 64 bit addr mode
79 0: llgf %r15,1f-0b(%r13) # load end of stack address
81 llgf %r10,.Ldh_arch-0b(%r13)
82 cghi %r10,ARCH_S390_ID
85 /* 64 bit store status */
87 llgf %r14,.Lstore_status_64-0b(%r13)
89 lghi %r10,ARCH_S390X_ID
90 st %r10,.Ldh_arch-0b(%r13)
93 llgf %r2,IPL_SC # load ipl device subchannel id
94 llgf %r14,.Lenable_device_64-0b(%r13)
96 llgf %r14,.Ltake_dump_64-0b(%r13)
98 1: .long 0x10000-128 # end of stack
100 ################################################################################
103 ################################################################################
106 stmg %r6,%r15,48(%r15)
107 basr %r13,0 # base register
108 0: aghi %r15,-200 # create stack frame
112 bras %r14,_init_print_progress_64
114 # get start and end block
116 mvc .Ldev_start_blk-0b(4,%r13),STAGE2_DESC+4
117 mvc .Ldev_end_blk-0b(4,%r13),STAGE2_DESC+8+4
119 # setup define extend
121 l %r7,.Ldev_end_blk-0b(%r13)
122 st %r7,12+.Ldedata-0b(%r13)
124 # calculate bytes per write (blksize * blwr)
126 llgf %r11,.Ldev_blk_size-0b(%r13)
127 mh %r11,.Lblocks_per_write-0b(%r13)
128 st %r11,.Lbytes_per_write-0b(%r13)
132 stck .Ldh_time-0b(%r13) # store time
133 stidp .Ldh_cpuid-0b(%r13) # store cpu id
135 llgf %r11,.Ldev_start_blk-0b(%r13) # start block
138 lghi %r3, TMP_PAGE_START
139 mvc 0(256,%r3),.Ldh_dumpheader-0b(%r13) # move to 4k boundary
140 llgf %r4,.Lheader_size-0b(%r13)
141 srda %r4,32 # shift ==> 64 bit number
142 llgf %r6,.Ldev_blk_size-0b(%r13) # get blocksize
144 dr %r4,%r6 # nr of blocks for header =
145 # HEADER_SIZE / BLOCKSIZE = r5
147 lgr %r12,%r5 # save nr of blocks
148 bas %r14,_writeblock_64-0b(%r13) # write block to disk
149 ar %r11,%r12 # update block counter
153 lghi %r10,0 # start at address 0
156 lghi %r4,BLOCKS_PER_WRITE # write so many blocks at a time
157 lgr %r2,%r11 # restore r2
158 lgr %r3,%r10 # restore r3
159 bas %r14,_writeblock_64-0b(%r13) # write block to disk
160 llgf %r2,.Lbytes_per_write-0b(%r13)
161 agr %r10,%r2 # update data address
162 aghi %r11,BLOCKS_PER_WRITE # skip to next block
164 lgr %r2,%r10 # print progress to console
165 bras %r14,_print_progress_64
167 lg %r3,.Ldh_mem_size-0b(%r13) # get memsize
168 clgr %r10,%r3 # enough ?
169 bl .Lmloop-0b(%r13) # branch if r10 < r3
173 .lendmarker: # terminate dump file
174 stck .Ld_end_time-0b(%r13) # store end time
175 lgr %r2,%r11 # restore r2
176 lghi %r3, TMP_PAGE_START
177 mvc 0(256,%r3),.Ld_endmarker-0b(%r13) # move to 4k boundary
178 lghi %r4,1 # write one block
179 bas %r14,_writeblock_64-0b(%r13) # write block to disk
181 lmg %r6,%r15,248(%r15)
182 br %r14 # return to caller
183 .Lbytes_per_write: .long 0x00000000
184 .Lheader_size: .long HEADER_SIZE
185 .Lblocks_per_write: .word BLOCKS_PER_WRITE
187 ################################################################################
188 # This function writes a block number given in r2 to disk
189 # -r2: number of first block to write ( input by caller )
190 # We start counting with Block Nr 0 !!!
191 # -r3: address to write data from ( input by caller )
192 # -r4: number of blocks to write ( input by caller )
193 ################################################################################
196 stmg %r6,%r15,48(%r15)
197 basr %r13,0 # base register
198 0: aghi %r15,-200 # create stack frame
200 # check if blocks are within range:
203 agr %r11,%r4 # End block
204 llgf %r12,.Ldev_end_blk-0b(%r13)
205 clr %r11,%r12 # End block < dev_end_blk ?
207 la %r2,EMEM # if yes panik
208 llgf %r14,.Lpanik_64-0b(%r13)
211 1: la %r12,.Ldeccw-0b(%r13)
212 st %r12,8+.Lorb-0b(%r13) # store cpaddr to orb
213 la %r12,.Lwrccw-0b(%r13)
214 oi 1(%r12),0x04 # enable indirect data addressing
217 sth %r4,2+.Llodata-0b(%r13) # store number of blocks
218 st %r2,4+.Llodata-0b(%r13) # store first block
221 la %r12,.Lwrccw-0b(%r13)
222 la %r10,.Lida_list-0b(%r13) # pointer to ida list
223 st %r10,4+.Lwrccw-0b(%r13) # store idal data address
225 mh %r7,2+.Ldev_blk_size-0b(%r13)
226 sth %r7,2+.Lwrccw-0b(%r13) # store byte count
230 lgr %r2,%r3 # start address
231 lgr %r3,%r7 # byte count
232 lgr %r4,%r10 # address of ida list
233 bas %r14,_create_ida_list_64-0b(%r13) # create ida list
235 # CCWs are setup now, arent they?
237 llgf %r2,IPL_SC # subchannel id
238 la %r3,.Lorb-0b(%r13)
239 la %r4,.Lirb-0b(%r13)
240 la %r5,10 # initialize retries
242 bas %r14,_ssch_64-0b(%r13) # start I/O
244 lmg %r6,%r15,248(%r15)
245 br %r14 # return to caller
248 .long 0x0049504c,0x0082ff00
249 .long 0x00000000,0x00000000
251 .long 0x00000000,0x00000000
252 .long 0x00000000,0x00000000
253 .long 0x00000000,0x00000000
254 .long 0x00000000,0x00000000
255 .long 0x00000000,0x00000000
256 .long 0x00000000,0x00000000
257 .long 0x00000000,0x00000000
258 .long 0x00000000,0x00000000
260 .long 0xc0000200,0x00000000
261 .long 0x00000000,0x00001000
263 .long 0x01000000,0x00000000
265 .Lida_list: # enough for 128 blocks a 512 byte
266 .long 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0
267 .long 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0
268 .long 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0
269 .long 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0
271 ################################################################################
273 ################################################################################
277 dump_common_store_status_32
279 dump_io_subroutines_64
293 .long _enable_device_64
297 .long _store_status_32
299 .long _store_status_64
305 #else /* __s390x__ */
309 /******************************** 32 BIT **************************************/
312 ################################################################################
313 # Program execution of the second stage boot loader starts at 0x2008
314 ################################################################################
318 0: l %r15,1f-0b(%r13) # load end of stack address
320 tm __LC_ARCH_MODE_ID,0x01 # check arch mode
321 bz .Larch_31-0b(%r13)
322 la %r10,ARCH_S390X_ID
323 st %r10,.Ldh_arch-0b(%r13)
326 l %r11,IPL_SC # load ipl device subchannel id
328 l %r14,.Lenable_device_32-0b(%r13)
330 l %r14,.Ltake_dump_32-0b(%r13)
332 1: .long 0x10000-96 # end of stack
335 ################################################################################
338 ################################################################################
341 stm %r6,%r15,24(%r15)
342 basr %r13,0 # base register
343 0: s %r15,.Lc96-0b(%r13) # create stack frame
347 bras %r14,_init_print_progress_32
349 # get start and end block
351 mvc .Ldev_start_blk-0b(4,%r13),STAGE2_DESC+4
352 mvc .Ldev_end_blk-0b(4,%r13),STAGE2_DESC+8+4
354 # setup define extend
356 l %r7,.Ldev_end_blk-0b(%r13)
357 st %r7,12+.Ldedata-0b(%r13)
359 # calculate bytes per write (blksize * blwr)
361 l %r11,.Ldev_blk_size-0b(%r13)
362 mh %r11,.Lblocks_per_write-0b(%r13)
363 st %r11,.Lbytes_per_write-0b(%r13)
367 stck .Ldh_time-0b(%r13) # store time
368 stidp .Ldh_cpuid-0b(%r13) # store cpu id
370 l %r11,.Ldev_start_blk-0b(%r13) # start block
373 lhi %r3, TMP_PAGE_START
374 mvc 0(256,%r3),.Ldh_dumpheader-0b(%r13) # move to 4k boundary
376 l %r4,.Lheader_size-0b(%r13)
377 srda %r4,32 # shift ==> 64 bit number
378 l %r6,.Ldev_blk_size-0b(%r13) # get blocksize
380 dr %r4,%r6 # nr of blocks for header =
381 # HEADER_SIZE / BLOCKSIZE = r5
383 lr %r12,%r5 # save nr of blocks
384 bas %r14,_writeblock_32-0b(%r13) # write block to disk
385 ar %r11,%r12 # update block counter
389 la %r10,0 # start at address 0
392 la %r4,BLOCKS_PER_WRITE # write so many blocks at a time
393 lr %r2,%r11 # restore r2
394 lr %r3,%r10 # restore r3
395 bas %r14,_writeblock_32-0b(%r13) # write block to disk
396 l %r2,.Lbytes_per_write-0b(%r13)
397 ar %r10,%r2 # update data address
398 ah %r11,.Lblocks_per_write-0b(%r13) # skip to next block
400 lr %r2,%r10 # print progress to console
401 bras %r14,_print_progress_32
403 l %r3,.Ldh_mem_size+4-0b(%r13) # get memsize
404 clr %r10,%r3 # enough ?
405 bl .Lmloop-0b(%r13) # branch if r10 < r3
409 .lendmarker: # terminate dump file
410 la %r4,1 # write endmaker with one block
411 stck .Ld_end_time-0b(%r13) # store end time
412 lr %r2,%r11 # restore r2
413 lhi %r3, TMP_PAGE_START
414 mvc 0(256,%r3),.Ld_endmarker-0b(%r13) # move to 4k boundary
415 la %r4,1 # write 4k at a time
416 bas %r14,_writeblock_32-0b(%r13) # write block to disk
418 lm %r6,%r15,120(%r15)
419 br %r14 # return to caller
420 .Lbytes_per_write: .long 0x00000000
421 .Lheader_size: .long HEADER_SIZE
422 .Lblocks_per_write: .word BLOCKS_PER_WRITE
424 ################################################################################
425 # This function writes a block number given in r2 to disk
426 # -r2: number of first block to write ( input by caller )
427 # We start counting with Block Nr 0 !!!
428 # -r3: address to write data from ( input by caller )
429 # -r4: number of blocks to write ( input by caller )
430 ################################################################################
433 stm %r6,%r15,24(%r15)
434 basr %r13,0 # base register
435 0: s %r15,.Lc96-0b(%r13) # create stack frame
437 # check if blocks are within range:
440 ar %r11,%r4 # End block
441 l %r12,.Ldev_end_blk-0b(%r13)
442 clr %r11,%r12 # End block < dev_end_blk ?
444 la %r2,EMEM # if yes panik
445 l %r14,.Lpanik_32-0b(%r13)
448 1: la %r12,.Ldeccw-0b(%r13)
449 st %r12,8+.Lorb-0b(%r13) # store cpaddr to orb
452 sth %r4,2+.Llodata-0b(%r13) # store number of blocks
453 st %r2,4+.Llodata-0b(%r13) # store first block
456 la %r12,.Lwrccw-0b(%r13)
457 oi 1(%r12),0x04 # enable ida
458 la %r10,.Lida_list-0b(%r13) # pointer to ida list
459 st %r10,4+.Lwrccw-0b(%r13) # store data address
461 mh %r7,2+.Ldev_blk_size-0b(%r13)
462 sth %r7,2+.Lwrccw-0b(%r13) # store byte count
465 lr %r2,%r3 # start address
466 lr %r3,%r7 # byte count
467 lr %r4,%r10 # address of ida list
468 bas %r14,_create_ida_list_32-0b(%r13) # create the list
470 # CCWs are setup now, arent they?
472 l %r2,IPL_SC # subchannel id
473 la %r3,.Lorb-0b(%r13)
474 la %r4,.Lirb-0b(%r13)
475 la %r5,10 # initialize retries
477 bas %r14,_ssch_32-0b(%r13) # start I/O
479 lm %r6,%r15,120(%r15)
480 br %r14 # return to caller
485 .long 0x0049504c,0x0080ff00 # intparm is " IPL"
486 .long 0x00000000,0x00000000
488 .long 0x00000000,0x00000000
489 .long 0x00000000,0x00000000
490 .long 0x00000000,0x00000000
491 .long 0x00000000,0x00000000
492 .long 0x00000000,0x00000000
493 .long 0x00000000,0x00000000
494 .long 0x00000000,0x00000000
495 .long 0x00000000,0x00000000
497 .long 0xc0000200,0x00000000
498 .long 0x00000000,0x00001000
500 .long 0x01000000,0x00000000
502 .Lida_list: # enough for 128 blocks a 512 byte
503 .long 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0
504 .long 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0
505 .long 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0
506 .long 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0
508 ################################################################################
510 ################################################################################
515 dump_io_subroutines_32
529 .long _enable_device_32
533 #endif /* __s390x__ */
536 ################################################################################
538 ################################################################################
540 .Lc96: .long 96 # for creating stackframes
542 # device characteristics
557 # channel program for one write
560 .long 0x63400010,0x00000000+.Ldedata # define extent
562 .long 0x43400008,0x00000000+.Llodata # locate
564 .long 0x41200000,0x00000000 # write blocks
568 .long 0xffffffff,0xffffffff # can be used for memsize=xxx