Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /* -*- linux-c -*- ------------------------------------------------------- *
0003  *
0004  *   Copyright (C) 1991, 1992 Linus Torvalds
0005  *   Copyright 2007 rPath, Inc. - All Rights Reserved
0006  *   Copyright 2009 Intel Corporation; author H. Peter Anvin
0007  *
0008  * ----------------------------------------------------------------------- */
0009 
0010 /*
0011  * Main module for the real-mode kernel code
0012  */
0013 #include <linux/build_bug.h>
0014 
0015 #include "boot.h"
0016 #include "string.h"
0017 
0018 struct boot_params boot_params __attribute__((aligned(16)));
0019 
0020 struct port_io_ops pio_ops;
0021 
0022 char *HEAP = _end;
0023 char *heap_end = _end;      /* Default end of heap = no heap */
0024 
0025 /*
0026  * Copy the header into the boot parameter block.  Since this
0027  * screws up the old-style command line protocol, adjust by
0028  * filling in the new-style command line pointer instead.
0029  */
0030 
0031 static void copy_boot_params(void)
0032 {
0033     struct old_cmdline {
0034         u16 cl_magic;
0035         u16 cl_offset;
0036     };
0037     const struct old_cmdline * const oldcmd =
0038         absolute_pointer(OLD_CL_ADDRESS);
0039 
0040     BUILD_BUG_ON(sizeof(boot_params) != 4096);
0041     memcpy(&boot_params.hdr, &hdr, sizeof(hdr));
0042 
0043     if (!boot_params.hdr.cmd_line_ptr &&
0044         oldcmd->cl_magic == OLD_CL_MAGIC) {
0045         /* Old-style command line protocol. */
0046         u16 cmdline_seg;
0047 
0048         /* Figure out if the command line falls in the region
0049            of memory that an old kernel would have copied up
0050            to 0x90000... */
0051         if (oldcmd->cl_offset < boot_params.hdr.setup_move_size)
0052             cmdline_seg = ds();
0053         else
0054             cmdline_seg = 0x9000;
0055 
0056         boot_params.hdr.cmd_line_ptr =
0057             (cmdline_seg << 4) + oldcmd->cl_offset;
0058     }
0059 }
0060 
0061 /*
0062  * Query the keyboard lock status as given by the BIOS, and
0063  * set the keyboard repeat rate to maximum.  Unclear why the latter
0064  * is done here; this might be possible to kill off as stale code.
0065  */
0066 static void keyboard_init(void)
0067 {
0068     struct biosregs ireg, oreg;
0069     initregs(&ireg);
0070 
0071     ireg.ah = 0x02;     /* Get keyboard status */
0072     intcall(0x16, &ireg, &oreg);
0073     boot_params.kbd_status = oreg.al;
0074 
0075     ireg.ax = 0x0305;   /* Set keyboard repeat rate */
0076     intcall(0x16, &ireg, NULL);
0077 }
0078 
0079 /*
0080  * Get Intel SpeedStep (IST) information.
0081  */
0082 static void query_ist(void)
0083 {
0084     struct biosregs ireg, oreg;
0085 
0086     /* Some older BIOSes apparently crash on this call, so filter
0087        it from machines too old to have SpeedStep at all. */
0088     if (cpu.level < 6)
0089         return;
0090 
0091     initregs(&ireg);
0092     ireg.ax  = 0xe980;   /* IST Support */
0093     ireg.edx = 0x47534943;   /* Request value */
0094     intcall(0x15, &ireg, &oreg);
0095 
0096     boot_params.ist_info.signature  = oreg.eax;
0097     boot_params.ist_info.command    = oreg.ebx;
0098     boot_params.ist_info.event      = oreg.ecx;
0099     boot_params.ist_info.perf_level = oreg.edx;
0100 }
0101 
0102 /*
0103  * Tell the BIOS what CPU mode we intend to run in.
0104  */
0105 static void set_bios_mode(void)
0106 {
0107 #ifdef CONFIG_X86_64
0108     struct biosregs ireg;
0109 
0110     initregs(&ireg);
0111     ireg.ax = 0xec00;
0112     ireg.bx = 2;
0113     intcall(0x15, &ireg, NULL);
0114 #endif
0115 }
0116 
0117 static void init_heap(void)
0118 {
0119     char *stack_end;
0120 
0121     if (boot_params.hdr.loadflags & CAN_USE_HEAP) {
0122         asm("leal %P1(%%esp),%0"
0123             : "=r" (stack_end) : "i" (-STACK_SIZE));
0124 
0125         heap_end = (char *)
0126             ((size_t)boot_params.hdr.heap_end_ptr + 0x200);
0127         if (heap_end > stack_end)
0128             heap_end = stack_end;
0129     } else {
0130         /* Boot protocol 2.00 only, no heap available */
0131         puts("WARNING: Ancient bootloader, some functionality "
0132              "may be limited!\n");
0133     }
0134 }
0135 
0136 void main(void)
0137 {
0138     init_default_io_ops();
0139 
0140     /* First, copy the boot header into the "zeropage" */
0141     copy_boot_params();
0142 
0143     /* Initialize the early-boot console */
0144     console_init();
0145     if (cmdline_find_option_bool("debug"))
0146         puts("early console in setup code\n");
0147 
0148     /* End of heap check */
0149     init_heap();
0150 
0151     /* Make sure we have all the proper CPU support */
0152     if (validate_cpu()) {
0153         puts("Unable to boot - please use a kernel appropriate "
0154              "for your CPU.\n");
0155         die();
0156     }
0157 
0158     /* Tell the BIOS what CPU mode we intend to run in. */
0159     set_bios_mode();
0160 
0161     /* Detect memory layout */
0162     detect_memory();
0163 
0164     /* Set keyboard repeat rate (why?) and query the lock flags */
0165     keyboard_init();
0166 
0167     /* Query Intel SpeedStep (IST) information */
0168     query_ist();
0169 
0170     /* Query APM information */
0171 #if defined(CONFIG_APM) || defined(CONFIG_APM_MODULE)
0172     query_apm_bios();
0173 #endif
0174 
0175     /* Query EDD information */
0176 #if defined(CONFIG_EDD) || defined(CONFIG_EDD_MODULE)
0177     query_edd();
0178 #endif
0179 
0180     /* Set the video mode */
0181     set_video();
0182 
0183     /* Do the last things and invoke protected mode */
0184     go_to_protected_mode();
0185 }