#
#  Third stage boot loader
#    Copyright (C) 2003 IBM Deutschland Entwicklung GmbH, IBM Corporation
#    Author(s):	Heiko Carstens (heiko.carstens@de.ibm.com)
#              	Peter Oberparleiter (peter.oberparleiter@de.ibm.com)
#

# some definitions from kernel land
__LC_IPLDEV		= 0xC6C
IPL_DEVICE		= 0x10404
INITRD_START		= 0x10408
INITRD_SIZE		= 0x10410
COMMAND_LINE		= 0x10480
COMMAND_LINE_SIZE	= 896		# max command line length
COMMAND_LINE_EXTRA	= 0xA000-0x400	# address of extra command line

_parm_addr:				#
	.quad  0			# address of parmline
_initrd_addr:				#
	.quad  0			# address of initrd
_initrd_len:				#
	.quad  0			# length of initrd
_load_psw:				#
	.quad  0			# load psw of kernel
_extra_parm:				#
	.quad  0			# use extra parm line mechanism?

#
# Program execution of the third stage boot loader starts at 0xA028
#
        .globl _start
_start: basr   %r13,0                   # base register
0:	l      %r2,0xb8			# subchannel id of ipl device
	st     %r2,__LC_IPLDEV          # old ipl device storage location
	l      %r3,1f-0b(%r13)          # load address of IPL_DEVICE
	st     %r2,0(%r3)               # new ipl device storage location

	l      %r1,2f-0b(%r13)		# load address of parmfile parameter
	l      %r1,4(%r1)		# load address of parmfile
	l      %r2,3f-0b(%r13)          # load address of kernel command line
	mvc    0x0(256,%r2),0(%r1)      # move command line to 0x10480
	mvc    0x100(256,%r2),0x100(%r1)
	mvc    0x200(256,%r2),0x200(%r1)
	mvc    0x300(127,%r2),0x300(%r1)
	xc     0x37f(1,%r2),0x37f(%r2)

	l      %r1,11f-0b(%r13)		# check for extra parm flag
	l      %r1,4(%r1)
	ltr    %r1,%r1
	jz     .Lnoextra		# skip if zero

	l      %r1,9f-0b(%r13)		# check for extra command line
	sr     %r0,%r0
	ic     %r0,0(%r1)
	ltr    %r0,%r0
	jz     .Lnoextra		# skip if no extra command line present

	la     %r3,10f-0b(%r13)		# convert to ascii
	tr     0x0(256,%r1),0(%r3)
	tr     0x100(256,%r1),0(%r3)
	tr     0x200(256,%r1),0(%r3)
	tr     0x300(127,%r1),0(%r3)

	lhi    %r4,COMMAND_LINE_SIZE
.Lfindend:
	ic     %r0,0(%r2)		# find end of current parameter string
	ltr    %r0,%r0
	jz     .Lappend			# got it
	ahi    %r2,1
	brct   %r4,.Lfindend
	j      .Lnoextra		# none found

.Lappend:
	ic     %r0,0(%r1)		# append extra parameters
	stc    %r0,0(%r2)
	ahi    %r1,1
	ahi    %r2,1
	ltr    %r0,%r0			# at end of string?
	jz     .Lnoextra		# yes, continue with ipl
	brct   %r4,.Lappend		# no, loop

	xc     0x37f(1,%r2),0x37f(%r2)	# nil-terminate string

.Lnoextra:
	l      %r1,4f-0b(%r13)		# load address of initrd parameter
	l      %r2,5f-0b(%r13)		# load address of INITRD_START
	mvc    0(8,%r2),0(%r1)		# copy INITRD_START address

	l      %r1,6f-0b(%r13)		# load address of initrd length parmeter
	l      %r2,7f-0b(%r13)		# load address of INITRD_SIZE
	mvc    0(8,%r2),0(%r1)		# copy INITRD_SIZE length

	l      %r1,8f-0b(%r13)
	mvc    0(8,%r0),0(%r1)		# copy load psw to 0

	lm     %r0,%r15,0x180		# load saved registers
	lpsw   0			# start kernel
	
1:	.long  IPL_DEVICE
2:	.long  _parm_addr
3:	.long  COMMAND_LINE
4:	.long  _initrd_addr
5:	.long  INITRD_START
6:	.long  _initrd_len
7:	.long  INITRD_SIZE
8:	.long  _load_psw
9:	.long  COMMAND_LINE_EXTRA
11:	.long  _extra_parm
10:	.byte 0x00, 0x01, 0x02, 0x03, 0x07, 0x09, 0x07, 0x7F
	.byte 0x07, 0x07, 0x07, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F
	.byte 0x10, 0x11, 0x12, 0x13, 0x07, 0x0A, 0x08, 0x07
	.byte 0x18, 0x19, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07
	.byte 0x07, 0x07, 0x1C, 0x07, 0x07, 0x0A, 0x17, 0x1B
	.byte 0x07, 0x07, 0x07, 0x07, 0x07, 0x05, 0x06, 0x07
	.byte 0x07, 0x07, 0x16, 0x07, 0x07, 0x07, 0x07, 0x04
	.byte 0x07, 0x07, 0x07, 0x07, 0x14, 0x15, 0x07, 0x1A
	.byte 0x20, 0xFF, 0x83, 0x84, 0x85, 0xA0, 0x07, 0x86
	.byte 0x87, 0xA4, 0x9B, 0x2E, 0x3C, 0x28, 0x2B, 0x7C
	.byte 0x26, 0x82, 0x88, 0x89, 0x8A, 0xA1, 0x8C, 0x07
	.byte 0x8D, 0xE1, 0x21, 0x24, 0x2A, 0x29, 0x3B, 0xAA
	.byte 0x2D, 0x2F, 0x07, 0x8E, 0x07, 0x07, 0x07, 0x8F
	.byte 0x80, 0xA5, 0x07, 0x2C, 0x25, 0x5F, 0x3E, 0x3F
	.byte 0x07, 0x90, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07
	.byte 0x70, 0x60, 0x3A, 0x23, 0x40, 0x27, 0x3D, 0x22
	.byte 0x07, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67
	.byte 0x68, 0x69, 0xAE, 0xAF, 0x07, 0x07, 0x07, 0xF1
	.byte 0xF8, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70
	.byte 0x71, 0x72, 0xA6, 0xA7, 0x91, 0x07, 0x92, 0x07
	.byte 0xE6, 0x7E, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78
	.byte 0x79, 0x7A, 0xAD, 0xAB, 0x07, 0x07, 0x07, 0x07
	.byte 0x5E, 0x9C, 0x9D, 0xFA, 0x07, 0x07, 0x07, 0xAC
	.byte 0xAB, 0x07, 0x5B, 0x5D, 0x07, 0x07, 0x07, 0x07
	.byte 0x7B, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47
	.byte 0x48, 0x49, 0x07, 0x93, 0x94, 0x95, 0xA2, 0x07
	.byte 0x7D, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50
	.byte 0x51, 0x52, 0x07, 0x96, 0x81, 0x97, 0xA3, 0x98
	.byte 0x5C, 0xF6, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58
	.byte 0x59, 0x5A, 0xFD, 0x07, 0x99, 0x07, 0x07, 0x07
	.byte 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37
	.byte 0x38, 0x39, 0x07, 0x07, 0x9A, 0x07, 0x07, 0x07
