2019-06-04 10:11:30 +02:00
// SPDX-License-Identifier: GPL-2.0-only
2007-07-11 12:18:54 -07:00
/* -*- linux-c -*- ------------------------------------------------------- *
*
* Copyright ( C ) 1991 , 1992 Linus Torvalds
* Copyright 2007 rPath , Inc . - All Rights Reserved
2009-04-01 18:13:46 -07:00
* Copyright 2009 Intel Corporation ; author H . Peter Anvin
2007-07-11 12:18:54 -07:00
*
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
/*
* Main module for the real - mode kernel code
*/
2019-08-11 20:49:36 +02:00
# include <linux/build_bug.h>
2007-07-11 12:18:54 -07:00
# include "boot.h"
2014-03-18 15:26:37 -04:00
# include "string.h"
2007-07-11 12:18:54 -07:00
struct boot_params boot_params __attribute__ ( ( aligned ( 16 ) ) ) ;
2022-04-06 02:29:24 +03:00
struct port_io_ops pio_ops ;
2007-07-11 12:18:54 -07:00
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 =
2022-02-27 11:59:18 -08:00
absolute_pointer ( OLD_CL_ADDRESS ) ;
2007-07-11 12:18:54 -07:00
2018-10-28 12:58:28 +00:00
BUILD_BUG_ON ( sizeof ( boot_params ) ! = 4096 ) ;
memcpy ( & boot_params . hdr , & hdr , sizeof ( hdr ) ) ;
2007-07-11 12:18:54 -07:00
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 ;
}
}
/*
2012-04-13 21:08:26 +02:00
* Query the keyboard lock status as given by the BIOS , and
* set the keyboard repeat rate to maximum . Unclear why the latter
2007-07-11 12:18:54 -07:00
* is done here ; this might be possible to kill off as stale code .
*/
2012-04-13 21:08:26 +02:00
static void keyboard_init ( void )
2007-07-11 12:18:54 -07:00
{
2012-04-13 21:08:26 +02:00
struct biosregs ireg , oreg ;
2009-04-01 18:13:46 -07:00
initregs ( & ireg ) ;
2012-04-13 21:08:26 +02:00
ireg . ah = 0x02 ; /* Get keyboard status */
intcall ( 0x16 , & ireg , & oreg ) ;
boot_params . kbd_status = oreg . al ;
ireg . ax = 0x0305 ; /* Set keyboard repeat rate */
2009-04-01 18:13:46 -07:00
intcall ( 0x16 , & ireg , NULL ) ;
2007-07-11 12:18:54 -07:00
}
/*
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
{
2009-04-01 18:13:46 -07:00
struct biosregs ireg , oreg ;
2008-08-13 13:14:22 -07:00
/* Some older BIOSes apparently crash on this call, so filter
it from machines too old to have SpeedStep at all . */
2008-08-13 10:07:05 +02:00
if ( cpu . level < 6 )
return ;
2009-04-01 18:13:46 -07:00
initregs ( & ireg ) ;
ireg . ax = 0xe980 ; /* IST Support */
ireg . edx = 0x47534943 ; /* Request value */
intcall ( 0x15 , & ireg , & oreg ) ;
boot_params . ist_info . signature = oreg . eax ;
boot_params . ist_info . command = oreg . ebx ;
boot_params . ist_info . event = oreg . ecx ;
boot_params . ist_info . perf_level = oreg . edx ;
2007-07-11 12:18:54 -07:00
}
/*
* Tell the BIOS what CPU mode we intend to run in .
*/
static void set_bios_mode ( void )
{
# ifdef CONFIG_X86_64
2009-04-01 18:13:46 -07:00
struct biosregs ireg ;
2007-07-11 12:18:54 -07:00
2009-04-01 18:13:46 -07:00
initregs ( & ireg ) ;
ireg . ax = 0xec00 ;
ireg . bx = 2 ;
intcall ( 0x15 , & ireg , NULL ) ;
2007-07-11 12:18:54 -07:00
# 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 )
{
2022-04-06 02:29:24 +03:00
init_default_io_ops ( ) ;
2008-01-30 13:33:04 +01:00
/* First, copy the boot header into the "zeropage" */
copy_boot_params ( ) ;
2010-07-11 11:06:57 +03:00
/* Initialize the early-boot console */
console_init ( ) ;
2010-08-02 16:21:22 -07:00
if ( cmdline_find_option_bool ( " debug " ) )
puts ( " early console in setup code \n " ) ;
2010-07-11 11:06:57 +03:00
2008-01-30 13:33:04 +01:00
/* 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 ( ) ;
2012-04-13 21:08:26 +02:00
/* Set keyboard repeat rate (why?) and query the lock flags */
keyboard_init ( ) ;
2007-07-11 12:18:54 -07:00
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 ( ) ;
}