/*
 * CDDL HEADER START
 *
 * The contents of this file are subject to the terms of the
 * Common Development and Distribution License (the "License").
 * You may not use this file except in compliance with the License.
 *
 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
 * or http://www.opensolaris.org/os/licensing.
 * See the License for the specific language governing permissions
 * and limitations under the License.
 *
 * When distributing Covered Code, include this CDDL HEADER in each
 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
 * If applicable, add the following below this CDDL HEADER, with the
 * fields enclosed by brackets "[]" replaced with your own identifying
 * information: Portions Copyright [yyyy] [name of copyright owner]
 *
 * CDDL HEADER END
 */

/*
 * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
 * Use is subject to license terms.
 */

	.file	"_rtboot.s"

/ bootstrap routine for run-time linker
/ we get control from exec which has loaded our text and
/ data into the process' address space and created the process 
/ stack
/
/ on entry, the process stack looks like this:
/
/			# <- %esp
/_______________________#  high addresses
/	strings		#  
/_______________________#
/	0 word		#
/_______________________#
/	Auxiliary	#
/	entries		#
/	...		#
/	(size varies)	#
/_______________________#
/	0 word		#
/_______________________#
/	Environment	#
/	pointers	#
/	...		#
/	(one word each)	#
/_______________________#
/	0 word		#
/_______________________#
/	Argument	# low addresses
/	pointers	#
/	Argc words	#
/_______________________#
/	argc		# 
/_______________________# <- %ebp

#include <SYS.h>

	.set	EB_NULL,0
	.set	EB_DYNAMIC,1
	.set	EB_LDSO_BASE,2
	.set	EB_ARGV,3
	.set	EB_ENVP,4
	.set	EB_AUXV,5
	.set	EB_DEVZERO,6
	.set	EB_PAGESIZE,7
	.set	EB_MAX,8
	.set	EB_MAX_SIZE32,64

	.text
	.globl	__rtboot
	.globl	__rtld
	.type	__rtboot,@function
	.align	4
__rtboot:
	movl	%esp,%ebp
	subl	$EB_MAX_SIZE32,%esp	/ make room for a max sized boot vector
	movl	%esp,%esi		/ use esi as a pointer to &eb[0]
	movl	$EB_ARGV,0(%esi)	/ set up tag for argv
	leal	4(%ebp),%eax		/ get address of argv
	movl	%eax,4(%esi)		/ put after tag
	movl	$EB_ENVP,8(%esi)	/ set up tag for envp
	movl	(%ebp),%eax		/ get # of args
	addl	$2,%eax			/ one for the zero & one for argc
	leal	(%ebp,%eax,4),%edi	/ now points past args & @ envp
	movl	%edi,12(%esi)		/ set envp
	addl	$-4,%edi		/ start loop at &env[-1]
.L00:	addl	$4,%edi			/ next
	cmpl	$0,(%edi)		/ search for 0 at end of env
	jne	.L00
	addl	$4,%edi			/ advance past 0
	movl	$EB_AUXV,16(%esi)	/ set up tag for auxv
	movl	%edi,20(%esi)		/ point to auxv
	movl	$EB_NULL,24(%esi)	/ set up NULL tag
	call	.L01		/ only way to get IP into a register
.L01:	popl	%ebx		/ pop the IP we just "pushed"
	leal	s.EMPTY - .L01(%ebx),%eax
	pushl	%eax
	leal	s.ZERO - .L01(%ebx),%eax
	pushl	%eax
	leal	s.LDSO - .L01(%ebx),%eax
	pushl	%eax
	movl	%esp,%edi	/ save pointer to strings
	leal	f.MUNMAP - .L01(%ebx),%eax
	pushl	%eax
	leal	f.CLOSE - .L01(%ebx),%eax
	pushl	%eax
	leal	f.SYSCONFIG - .L01(%ebx),%eax
	pushl	%eax
	leal	f.FSTATAT - .L01(%ebx),%eax
	pushl	%eax
	leal	f.MMAP - .L01(%ebx),%eax
	pushl	%eax
	leal	f.OPENAT - .L01(%ebx),%eax
	pushl	%eax
	leal	f.PANIC - .L01(%ebx),%eax
	pushl	%eax
	movl	%esp,%ecx	/ save pointer to functions

	pushl	%ecx		/ address of functions
	pushl	%edi		/ address of strings
	pushl	%esi		/ &eb[0]
	call	__rtld		/ __rtld(&eb[0], strings, funcs)
	movl	%esi,%esp	/ restore the stack (but leaving boot vector)
	jmp	*%eax 		/ transfer control to ld.so.1
	.size	__rtboot,.-__rtboot

	.align	4
s.LDSO:		.string	"/usr/lib/ld.so.1"
s.ZERO:		.string	"/dev/zero"
s.EMPTY:	.string	"(null)"
s.ERROR:	.string	": no (or bad) /usr/lib/ld.so.1\n"
l.ERROR:

	.align	4
f.PANIC:
	movl	%esp,%ebp
/ Add using of argument string
	pushl	$l.ERROR - s.ERROR
	call	.L02
.L02:	popl	%ebx
	leal	s.ERROR - .L02(%ebx),%eax
	pushl	%eax
	pushl	$2
	call	f.WRITE
	jmp	f.EXIT
/ Not reached
	
f.OPENAT:
	movl	$SYS_openat,%eax
	jmp	__syscall
f.MMAP:
	movl	$SYS_mmap,%eax
	jmp	__syscall
f.MUNMAP:
	movl	$SYS_munmap,%eax
	jmp	__syscall
f.READ:
	movl	$SYS_read,%eax
	jmp	__syscall
f.WRITE:
	movl	$SYS_write,%eax
	jmp	__syscall
f.LSEEK:
	movl	$SYS_lseek,%eax
	jmp	__syscall
f.CLOSE:
	movl	$SYS_close,%eax
	jmp	__syscall
f.FSTATAT:
	movl	$SYS_fstatat,%eax
	jmp	__syscall
f.SYSCONFIG:
	movl	$SYS_sysconfig,%eax
	jmp	__syscall
f.EXIT:
	movl	$SYS_exit,%eax
/	jmp	__syscall
__syscall:
	int	$T_SYSCALLINT
	jc	__err_exit
	ret
__err_exit:
	movl	$-1,%eax
	ret