summaryrefslogtreecommitdiff
path: root/src/arch/i386/init/crt0.S.lb
blob: 67ef91059b64b6ed169b8cb56922e750670a80c2 (plain)
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
/* -*- asm -*-
 * $ $
 *
 */

/* 
 * Copyright (C) 1996-2002 Markus Franz Xaver Johannes Oberhumer
 *
 * This file is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License as
 * published by the Free Software Foundation; either version 2 of
 * the License, or (at your option) any later version.
 *
 * Originally this code was part of ucl the data compression library
 * for upx the ``Ultimate Packer of eXecutables''.
 *
 * - Converted to gas assembly, and refitted to work with etherboot.
 *   Eric Biederman 20 Aug 2002
 * - Merged the nrv2b decompressor into crt0.base of LinuxBIOS
 *   Eric Biederman 26 Sept 2002
 */


#include <arch/asm.h>
#include <arch/intel.h>
#include <console/loglevel.h>	

/*
 * This is the entry code the code in .reset section
 * jumps to this address.
 *
 */
.section ".rom.data", "a", @progbits
.section ".rom.text", "ax", @progbits

	intel_chip_post_macro(0x01)             /* delay for chipsets */

#include "crt0_includes.h"

#if USE_DCACHE_RAM == 0
#ifndef CONSOLE_DEBUG_TX_STRING
	/* uses:	 esp, ebx, ax, dx */
# define __CRT_CONSOLE_TX_STRING(string) \
	mov	string, %ebx	; \
	CALLSP(crt_console_tx_string)

# if defined(TTYS0_BASE) && (ASM_CONSOLE_LOGLEVEL > BIOS_DEBUG)
#  define CONSOLE_DEBUG_TX_STRING(string)        __CRT_CONSOLE_TX_STRING(string)
# else
#  define CONSOLE_DEBUG_TX_STRING(string)
# endif
#endif

	/* clear boot_complete flag */
	xorl	%ebp, %ebp
__main:
	CONSOLE_DEBUG_TX_STRING($str_copying_to_ram)

	/*
	 *	Copy data into RAM and clear the BSS. Since these segments
	 *	isn\'t really that big we just copy/clear using bytes, not
	 *	double words.
	 */
	intel_chip_post_macro(0x11)		/* post 11 */

	cld				/* clear direction flag */
	
	/* copy linuxBIOS from it's initial load location to 
	 * the location it is compiled to run at.
	 * Normally this is copying from FLASH ROM to RAM.
	 */
#if !CONFIG_COMPRESS
	movl	$_liseg, %esi
	movl	$_iseg,  %edi
	movl	$_eiseg, %ecx
	subl	%edi, %ecx
	rep	movsb
#else
	leal	4+_liseg, %esi
	leal	_iseg, %edi
	movl	%ebp, %esp	/* preserve %ebp */
	movl	$-1, %ebp	/* last_m_off = -1 */
	jmp	dcl1_n2b

/* ------------- DECOMPRESSION -------------

 Input:
   %esi - source
   %edi - dest
   %ebp - -1
   cld

 Output:
   %eax - 0
   %ecx - 0
*/

.macro getbit bits
.if	\bits == 1
	addl	%ebx, %ebx
	jnz	1f
.endif
	movl	(%esi), %ebx
	subl	$-4, %esi	/* sets carry flag */
	adcl	%ebx, %ebx
1:
.endm

decompr_literals_n2b:
	movsb

decompr_loop_n2b:
	addl	%ebx, %ebx
	jnz	dcl2_n2b
dcl1_n2b:
	getbit	32
dcl2_n2b:
	jc	decompr_literals_n2b
	xorl	%eax, %eax
	incl	%eax		/* m_off = 1 */
loop1_n2b:
	getbit	1
	adcl	%eax, %eax	/* m_off = m_off*2 + getbit() */
	getbit	1
	jnc	loop1_n2b	/* while(!getbit()) */
	xorl	%ecx, %ecx
	subl	$3, %eax
	jb	decompr_ebpeax_n2b	/* if (m_off == 2) goto decompr_ebpeax_n2b ? */
	shll	$8, %eax	
	movb	(%esi), %al	/* m_off = (m_off - 3)*256 + src[ilen++] */
	incl	%esi
	xorl	$-1, %eax	
	jz	decompr_end_n2b	/* if (m_off == 0xffffffff) goto decomp_end_n2b */
	movl	%eax, %ebp	/* last_m_off = m_off ?*/
decompr_ebpeax_n2b:
	getbit	1		
	adcl	%ecx, %ecx	/* m_len = getbit() */
	getbit	1
	adcl	%ecx, %ecx	/* m_len = m_len*2 + getbit()) */
	jnz	decompr_got_mlen_n2b	/* if (m_len == 0) goto decompr_got_mlen_n2b */
	incl	%ecx		/* m_len++ */
loop2_n2b:
	getbit	1	
	adcl	%ecx, %ecx	/* m_len = m_len*2 + getbit() */
	getbit	1
	jnc	loop2_n2b	/* while(!getbit()) */
	incl	%ecx
	incl	%ecx		/* m_len += 2 */
decompr_got_mlen_n2b:
	cmpl	$-0xd00, %ebp
	adcl	$1, %ecx	/* m_len = m_len + 1 + (last_m_off > 0xd00) */
	movl	%esi, %edx
	leal	(%edi,%ebp), %esi	/* m_pos = dst + olen + -m_off  */
	rep
	movsb			/* dst[olen++] = *m_pos++ while(m_len > 0) */
	movl	%edx, %esi
	jmp	decompr_loop_n2b
decompr_end_n2b:
	intel_chip_post_macro(0x12)		/* post 12 */

	movl	%esp, %ebp
#endif

	CONSOLE_DEBUG_TX_STRING($str_pre_main)
	leal	_iseg, %edi
	jmp	%edi

.Lhlt:	
	intel_chip_post_macro(0xee)	/* post fe */
	hlt
	jmp	.Lhlt

#ifdef __CRT_CONSOLE_TX_STRING
	/* Uses esp, ebx, ax, dx  */
crt_console_tx_string:
	mov	(%ebx), %al
	inc	%ebx
	cmp	$0, %al
	jne	9f
	RETSP
9:
/* Base Address */
#ifndef TTYS0_BASE
#define TTYS0_BASE	0x3f8
#endif
/* Data */
#define TTYS0_RBR (TTYS0_BASE+0x00)

/* Control */
#define TTYS0_TBR TTYS0_RBR
#define TTYS0_IER (TTYS0_BASE+0x01)
#define TTYS0_IIR (TTYS0_BASE+0x02)
#define TTYS0_FCR TTYS0_IIR
#define TTYS0_LCR (TTYS0_BASE+0x03)
#define TTYS0_MCR (TTYS0_BASE+0x04)
#define TTYS0_DLL TTYS0_RBR
#define TTYS0_DLM TTYS0_IER

/* Status */
#define TTYS0_LSR (TTYS0_BASE+0x05)
#define TTYS0_MSR (TTYS0_BASE+0x06)
#define TTYS0_SCR (TTYS0_BASE+0x07)
	
	mov	%al, %ah
10:	mov	$TTYS0_LSR, %dx
	inb	%dx, %al
	test	$0x20, %al
	je	10b
	mov	$TTYS0_TBR, %dx
	mov	%ah, %al
	outb	%al, %dx

	jmp crt_console_tx_string
#endif /* __CRT_CONSOLE_TX_STRING */

#if defined(CONSOLE_DEBUG_TX_STRING) && (ASM_CONSOLE_LOGLEVEL > BIOS_DEBUG)
.section ".rom.data"
str_copying_to_ram:  .string "Copying LinuxBIOS to ram.\r\n"
str_pre_main:        .string "Jumping to LinuxBIOS.\r\n"
.previous

#endif /* ASM_CONSOLE_LOGLEVEL > BIOS_DEBUG */

#endif /* USE_DCACHE_RAM */