2007-07-11 12:18:54 -07:00
/* -*- linux-c -*- ------------------------------------------------------- *
*
* Copyright ( C ) 1991 , 1992 Linus Torvalds
* Copyright 2007 rPath , Inc . - All Rights Reserved
*
* This file is part of the Linux kernel , and is made available under
* the terms of the GNU General Public License version 2.
*
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
/*
* Main module for the real - mode kernel code
*/
# include "boot.h"
struct boot_params boot_params __attribute__ ( ( aligned ( 16 ) ) ) ;
char * HEAP = _end ;
char * heap_end = _end ; /* Default end of heap = no heap */
/*
* Copy the header into the boot parameter block . Since this
* screws up the old - style command line protocol , adjust by
* filling in the new - style command line pointer instead .
*/
static void copy_boot_params ( void )
{
struct old_cmdline {
u16 cl_magic ;
u16 cl_offset ;
} ;
const struct old_cmdline * const oldcmd =
( const struct old_cmdline * ) OLD_CL_ADDRESS ;
BUILD_BUG_ON ( sizeof boot_params ! = 4096 ) ;
memcpy ( & boot_params . hdr , & hdr , sizeof hdr ) ;
if ( ! boot_params . hdr . cmd_line_ptr & &
oldcmd - > cl_magic = = OLD_CL_MAGIC ) {
/* Old-style command line protocol. */
u16 cmdline_seg ;
/* Figure out if the command line falls in the region
of memory that an old kernel would have copied up
to 0x90000 . . . */
if ( oldcmd - > cl_offset < boot_params . hdr . setup_move_size )
cmdline_seg = ds ( ) ;
else
cmdline_seg = 0x9000 ;
boot_params . hdr . cmd_line_ptr =
( cmdline_seg < < 4 ) + oldcmd - > cl_offset ;
}
}
/*
* Set the keyboard repeat rate to maximum . Unclear why this
* is done here ; this might be possible to kill off as stale code .
*/
static void keyboard_set_repeat ( void )
{
u16 ax = 0x0305 ;
u16 bx = 0 ;
asm volatile ( " int $0x16 "
: " +a " ( ax ) , " +b " ( bx )
: : " ecx " , " edx " , " esi " , " edi " ) ;
}
/*
2007-07-18 17:19:30 -07:00
* Get Intel SpeedStep ( IST ) information .
2007-07-11 12:18:54 -07:00
*/
2007-07-18 17:19:30 -07:00
static void query_ist ( void )
2007-07-11 12:18:54 -07:00
{
asm ( " int $0x15 "
2007-07-18 17:19:30 -07:00
: " =a " ( boot_params . ist_info . signature ) ,
" =b " ( boot_params . ist_info . command ) ,
" =c " ( boot_params . ist_info . event ) ,
" =d " ( boot_params . ist_info . perf_level )
2007-07-11 12:18:54 -07:00
: " a " ( 0x0000e980 ) , /* IST Support */
" d " ( 0x47534943 ) ) ; /* Request value */
}
/*
* Tell the BIOS what CPU mode we intend to run in .
*/
static void set_bios_mode ( void )
{
# ifdef CONFIG_X86_64
u32 eax , ebx ;
eax = 0xec00 ;
ebx = 2 ;
asm volatile ( " int $0x15 "
: " +a " ( eax ) , " +b " ( ebx )
: : " ecx " , " edx " , " esi " , " edi " ) ;
# endif
}
2008-01-30 13:33:04 +01:00
static void init_heap ( void )
2007-07-11 12:18:54 -07:00
{
2008-01-30 13:33:04 +01:00
char * stack_end ;
2007-07-11 12:18:54 -07:00
if ( boot_params . hdr . loadflags & CAN_USE_HEAP ) {
2008-01-30 13:33:04 +01:00
asm ( " leal %P1(%%esp),%0 "
: " =r " ( stack_end ) : " i " ( - STACK_SIZE ) ) ;
heap_end = ( char * )
( ( size_t ) boot_params . hdr . heap_end_ptr + 0x200 ) ;
if ( heap_end > stack_end )
heap_end = stack_end ;
2007-07-11 12:18:54 -07:00
} else {
/* Boot protocol 2.00 only, no heap available */
puts ( " WARNING: Ancient bootloader, some functionality "
" may be limited! \n " ) ;
}
2008-01-30 13:33:04 +01:00
}
void main ( void )
{
/* First, copy the boot header into the "zeropage" */
copy_boot_params ( ) ;
/* End of heap check */
init_heap ( ) ;
2007-07-11 12:18:54 -07:00
/* Make sure we have all the proper CPU support */
if ( validate_cpu ( ) ) {
puts ( " Unable to boot - please use a kernel appropriate "
" for your CPU. \n " ) ;
die ( ) ;
}
/* Tell the BIOS what CPU mode we intend to run in. */
set_bios_mode ( ) ;
/* Detect memory layout */
detect_memory ( ) ;
/* Set keyboard repeat rate (why?) */
keyboard_set_repeat ( ) ;
/* Query MCA information */
query_mca ( ) ;
/* Voyager */
# ifdef CONFIG_X86_VOYAGER
query_voyager ( ) ;
# endif
2007-07-18 17:19:30 -07:00
/* Query Intel SpeedStep (IST) information */
query_ist ( ) ;
2007-07-11 12:18:54 -07:00
/* Query APM information */
# if defined(CONFIG_APM) || defined(CONFIG_APM_MODULE)
query_apm_bios ( ) ;
# endif
/* Query EDD information */
# if defined(CONFIG_EDD) || defined(CONFIG_EDD_MODULE)
query_edd ( ) ;
# endif
2008-01-30 13:33:03 +01:00
/* Set the video mode */
set_video ( ) ;
2007-07-11 12:18:54 -07:00
/* Do the last things and invoke protected mode */
go_to_protected_mode ( ) ;
}