2005-04-17 02:20:36 +04:00
/ *
* linux/ b o o t / h e a d . S
*
* Copyright ( C ) 1 9 9 1 , 1 9 9 2 , 1 9 9 3 L i n u s T o r v a l d s
* /
/ *
* head. S c o n t a i n s t h e 3 2 - b i t s t a r t u p c o d e .
*
* NOTE! ! ! S t a r t u p h a p p e n s a t a b s o l u t e a d d r e s s 0 x00 0 0 1 0 0 0 , w h i c h i s a l s o w h e r e
* the p a g e d i r e c t o r y w i l l e x i s t . T h e s t a r t u p c o d e w i l l b e o v e r w r i t t e n b y
* the p a g e d i r e c t o r y . [ A c c o r d i n g t o c o m m e n t s e t c e l s e w h e r e o n a c o m p r e s s e d
* kernel i t w i l l e n d u p a t 0 x10 0 0 + 1 M b I h o p e s o a s I a s s u m e t h i s . - A C ]
*
* Page 0 i s d e l i b e r a t e l y k e p t s a f e , s i n c e S y s t e m M a n a g e m e n t M o d e c o d e i n
* laptops m a y n e e d t o a c c e s s t h e B I O S d a t a s t o r e d t h e r e . T h i s i s a l s o
* useful f o r f u t u r e d e v i c e d r i v e r s t h a t e i t h e r a c c e s s t h e B I O S v i a V M 8 6
* mode.
* /
/ *
* High l o a d e d s t u f f b y H a n s L e r m e n & W e r n e r A l m e s b e r g e r , F e b . 1 9 9 6
* /
.text
# include < l i n u x / l i n k a g e . h >
# include < a s m / s e g m e n t . h >
2006-12-07 04:14:04 +03:00
# include < a s m / p a g e . h >
2006-12-07 04:14:04 +03:00
# include < a s m / b o o t . h >
2007-10-22 03:41:35 +04:00
# include < a s m / a s m - o f f s e t s . h >
2005-04-17 02:20:36 +04:00
2007-01-02 09:11:47 +03:00
.section " .text .head " , " ax" ,@progbits
2005-04-17 02:20:36 +04:00
.globl startup_32
2006-12-07 04:14:04 +03:00
2005-04-17 02:20:36 +04:00
startup_32 :
2007-10-26 21:29:04 +04:00
cld
2007-10-22 03:41:35 +04:00
/ * test K E E P _ S E G M E N T S f l a g t o s e e i f t h e b o o t l o a d e r i s a s k i n g
* us t o n o t r e l o a d s e g m e n t s * /
testb $ ( 1 < < 6 ) , B P _ l o a d f l a g s ( % e s i )
2007-10-26 21:29:04 +04:00
jnz 1 f
2007-10-22 03:41:35 +04:00
2007-10-26 21:29:04 +04:00
cli
2005-04-17 02:20:36 +04:00
movl $ ( _ _ B O O T _ D S ) ,% e a x
movl % e a x ,% d s
movl % e a x ,% e s
movl % e a x ,% f s
movl % e a x ,% g s
2006-12-07 04:14:04 +03:00
movl % e a x ,% s s
2007-10-26 21:29:04 +04:00
1 :
2007-10-22 03:41:35 +04:00
2006-12-07 04:14:04 +03:00
/ * Calculate t h e d e l t a b e t w e e n w h e r e w e w e r e c o m p i l e d t o r u n
* at a n d w h e r e w e w e r e a c t u a l l y l o a d e d a t . T h i s c a n o n l y b e d o n e
* with a s h o r t l o c a l c a l l o n x86 . N o t h i n g e l s e w i l l t e l l u s w h a t
* address w e a r e r u n n i n g a t . T h e r e s e r v e d c h u n k o f t h e r e a l - m o d e
2007-07-11 23:18:33 +04:00
* data a t 0 x1 e 4 ( d e f i n e d a s a s c r a t c h f i e l d ) a r e u s e d a s t h e s t a c k
* for t h i s c a l c u l a t i o n . O n l y 4 b y t e s a r e n e e d e d .
2006-12-07 04:14:04 +03:00
* /
2007-07-11 23:18:33 +04:00
leal ( 0 x1 e 4 + 4 ) ( % e s i ) , % e s p
2006-12-07 04:14:04 +03:00
call 1 f
1 : popl % e b p
subl $ 1 b , % e b p
2006-12-07 04:14:04 +03:00
/ * % ebp c o n t a i n s t h e a d d r e s s w e a r e l o a d e d a t b y t h e b o o t l o a d e r a n d % e b x
* contains t h e a d d r e s s w h e r e w e s h o u l d m o v e t h e k e r n e l i m a g e t e m p o r a r i l y
* for s a f e i n - p l a c e d e c o m p r e s s i o n .
2006-12-07 04:14:04 +03:00
* /
2006-12-07 04:14:04 +03:00
2006-12-07 04:14:04 +03:00
# ifdef C O N F I G _ R E L O C A T A B L E
2006-12-07 04:14:04 +03:00
movl % e b p , % e b x
addl $ ( C O N F I G _ P H Y S I C A L _ A L I G N - 1 ) , % e b x
andl $ ( ~ ( C O N F I G _ P H Y S I C A L _ A L I G N - 1 ) ) , % e b x
2006-12-07 04:14:04 +03:00
# else
2006-12-07 04:14:04 +03:00
movl $ L O A D _ P H Y S I C A L _ A D D R , % e b x
2006-12-07 04:14:04 +03:00
# endif
/* Replace the compressed data size with the uncompressed size */
subl i n p u t _ l e n ( % e b p ) , % e b x
movl o u t p u t _ l e n ( % e b p ) , % e a x
addl % e a x , % e b x
/* Add 8 bytes for every 32K input block */
shrl $ 1 2 , % e a x
addl % e a x , % e b x
/* Add 32K + 18 bytes of extra slack */
addl $ ( 3 2 7 6 8 + 1 8 ) , % e b x
/* Align on a 4K boundary */
addl $ 4 0 9 5 , % e b x
andl $ ~ 4 0 9 5 , % e b x
/ * Copy t h e c o m p r e s s e d k e r n e l t o t h e e n d o f o u r b u f f e r
* where d e c o m p r e s s i o n i n p l a c e b e c o m e s s a f e .
* /
pushl % e s i
leal _ e n d ( % e b p ) , % e s i
leal _ e n d ( % e b x ) , % e d i
movl $ ( _ e n d - s t a r t u p _ 3 2 ) , % e c x
std
rep
movsb
cld
popl % e s i
/ * Compute t h e k e r n e l s t a r t a d d r e s s .
* /
# ifdef C O N F I G _ R E L O C A T A B L E
2006-12-07 04:14:04 +03:00
addl $ ( C O N F I G _ P H Y S I C A L _ A L I G N - 1 ) , % e b p
andl $ ( ~ ( C O N F I G _ P H Y S I C A L _ A L I G N - 1 ) ) , % e b p
2006-12-07 04:14:04 +03:00
# else
2006-12-07 04:14:04 +03:00
movl $ L O A D _ P H Y S I C A L _ A D D R , % e b p
2006-12-07 04:14:04 +03:00
# endif
2005-04-17 02:20:36 +04:00
/ *
2006-12-07 04:14:04 +03:00
* Jump t o t h e r e l o c a t e d a d d r e s s .
2005-04-17 02:20:36 +04:00
* /
2006-12-07 04:14:04 +03:00
leal r e l o c a t e d ( % e b x ) , % e a x
jmp * % e a x
.section " .text "
relocated :
2005-04-17 02:20:36 +04:00
/ *
* Clear B S S
* /
xorl % e a x ,% e a x
2006-12-07 04:14:04 +03:00
leal _ e d a t a ( % e b x ) ,% e d i
leal _ e n d ( % e b x ) , % e c x
2005-04-17 02:20:36 +04:00
subl % e d i ,% e c x
cld
rep
stosb
2006-12-07 04:14:04 +03:00
/ *
* Setup t h e s t a c k f o r t h e d e c o m p r e s s o r
* /
2008-04-08 14:54:30 +04:00
leal b o o t _ s t a c k _ e n d ( % e b x ) , % e s p
2006-12-07 04:14:04 +03:00
2005-04-17 02:20:36 +04:00
/ *
* Do t h e d e c o m p r e s s i o n , a n d j u m p t o t h e n e w k e r n e l . .
* /
2006-12-07 04:14:04 +03:00
movl o u t p u t _ l e n ( % e b x ) , % e a x
pushl % e a x
2008-08-06 17:25:26 +04:00
# push a r g u m e n t s f o r d e c o m p r e s s _ k e r n e l :
2006-12-07 04:14:04 +03:00
pushl % e b p # o u t p u t a d d r e s s
movl i n p u t _ l e n ( % e b x ) , % e a x
pushl % e a x # i n p u t _ l e n
leal i n p u t _ d a t a ( % e b x ) , % e a x
pushl % e a x # i n p u t _ d a t a
2008-04-08 14:54:30 +04:00
leal b o o t _ h e a p ( % e b x ) , % e a x
2008-08-06 17:25:26 +04:00
pushl % e a x # h e a p a r e a
pushl % e s i # r e a l m o d e p o i n t e r
2005-04-17 02:20:36 +04:00
call d e c o m p r e s s _ k e r n e l
2006-12-07 04:14:04 +03:00
addl $ 2 0 , % e s p
popl % e c x
# if C O N F I G _ R E L O C A T A B L E
/ * Find t h e a d d r e s s o f t h e r e l o c a t i o n s .
* /
movl % e b p , % e d i
addl % e c x , % e d i
/ * Calculate t h e d e l t a b e t w e e n w h e r e v m l i n u x w a s c o m p i l e d t o r u n
* and w h e r e i t w a s a c t u a l l y l o a d e d .
* /
movl % e b p , % e b x
2006-12-07 04:14:04 +03:00
subl $ L O A D _ P H Y S I C A L _ A D D R , % e b x
jz 2 f / * N o t h i n g t o b e d o n e i f l o a d e d a t c o m p i l e d a d d r . * /
2005-04-17 02:20:36 +04:00
/ *
2006-12-07 04:14:04 +03:00
* Process r e l o c a t i o n s .
2005-04-17 02:20:36 +04:00
* /
2006-12-07 04:14:04 +03:00
1 : subl $ 4 , % e d i
movl 0 ( % e d i ) , % e c x
testl % e c x , % e c x
jz 2 f
addl % e b x , - _ _ P A G E _ O F F S E T ( % e b x , % e c x )
jmp 1 b
2 :
# endif
2005-04-17 02:20:36 +04:00
/ *
2006-12-07 04:14:04 +03:00
* Jump t o t h e d e c o m p r e s s e d k e r n e l .
2005-04-17 02:20:36 +04:00
* /
xorl % e b x ,% e b x
2006-12-07 04:14:04 +03:00
jmp * % e b p
.bss
2008-04-08 14:54:30 +04:00
/* Stack and heap for uncompression */
2006-12-07 04:14:04 +03:00
.balign 4
2008-04-08 14:54:30 +04:00
boot_heap :
.fill BOOT_ H E A P _ S I Z E , 1 , 0
boot_stack :
.fill BOOT_ S T A C K _ S I Z E , 1 , 0
boot_stack_end :