main.c (4390B)
1// SPDX-License-Identifier: GPL-2.0-only 2/* -*- linux-c -*- ------------------------------------------------------- * 3 * 4 * Copyright (C) 1991, 1992 Linus Torvalds 5 * Copyright 2007 rPath, Inc. - All Rights Reserved 6 * Copyright 2009 Intel Corporation; author H. Peter Anvin 7 * 8 * ----------------------------------------------------------------------- */ 9 10/* 11 * Main module for the real-mode kernel code 12 */ 13#include <linux/build_bug.h> 14 15#include "boot.h" 16#include "string.h" 17 18struct boot_params boot_params __attribute__((aligned(16))); 19 20struct port_io_ops pio_ops; 21 22char *HEAP = _end; 23char *heap_end = _end; /* Default end of heap = no heap */ 24 25/* 26 * Copy the header into the boot parameter block. Since this 27 * screws up the old-style command line protocol, adjust by 28 * filling in the new-style command line pointer instead. 29 */ 30 31static void copy_boot_params(void) 32{ 33 struct old_cmdline { 34 u16 cl_magic; 35 u16 cl_offset; 36 }; 37 const struct old_cmdline * const oldcmd = 38 absolute_pointer(OLD_CL_ADDRESS); 39 40 BUILD_BUG_ON(sizeof(boot_params) != 4096); 41 memcpy(&boot_params.hdr, &hdr, sizeof(hdr)); 42 43 if (!boot_params.hdr.cmd_line_ptr && 44 oldcmd->cl_magic == OLD_CL_MAGIC) { 45 /* Old-style command line protocol. */ 46 u16 cmdline_seg; 47 48 /* Figure out if the command line falls in the region 49 of memory that an old kernel would have copied up 50 to 0x90000... */ 51 if (oldcmd->cl_offset < boot_params.hdr.setup_move_size) 52 cmdline_seg = ds(); 53 else 54 cmdline_seg = 0x9000; 55 56 boot_params.hdr.cmd_line_ptr = 57 (cmdline_seg << 4) + oldcmd->cl_offset; 58 } 59} 60 61/* 62 * Query the keyboard lock status as given by the BIOS, and 63 * set the keyboard repeat rate to maximum. Unclear why the latter 64 * is done here; this might be possible to kill off as stale code. 65 */ 66static void keyboard_init(void) 67{ 68 struct biosregs ireg, oreg; 69 initregs(&ireg); 70 71 ireg.ah = 0x02; /* Get keyboard status */ 72 intcall(0x16, &ireg, &oreg); 73 boot_params.kbd_status = oreg.al; 74 75 ireg.ax = 0x0305; /* Set keyboard repeat rate */ 76 intcall(0x16, &ireg, NULL); 77} 78 79/* 80 * Get Intel SpeedStep (IST) information. 81 */ 82static void query_ist(void) 83{ 84 struct biosregs ireg, oreg; 85 86 /* Some older BIOSes apparently crash on this call, so filter 87 it from machines too old to have SpeedStep at all. */ 88 if (cpu.level < 6) 89 return; 90 91 initregs(&ireg); 92 ireg.ax = 0xe980; /* IST Support */ 93 ireg.edx = 0x47534943; /* Request value */ 94 intcall(0x15, &ireg, &oreg); 95 96 boot_params.ist_info.signature = oreg.eax; 97 boot_params.ist_info.command = oreg.ebx; 98 boot_params.ist_info.event = oreg.ecx; 99 boot_params.ist_info.perf_level = oreg.edx; 100} 101 102/* 103 * Tell the BIOS what CPU mode we intend to run in. 104 */ 105static void set_bios_mode(void) 106{ 107#ifdef CONFIG_X86_64 108 struct biosregs ireg; 109 110 initregs(&ireg); 111 ireg.ax = 0xec00; 112 ireg.bx = 2; 113 intcall(0x15, &ireg, NULL); 114#endif 115} 116 117static void init_heap(void) 118{ 119 char *stack_end; 120 121 if (boot_params.hdr.loadflags & CAN_USE_HEAP) { 122 asm("leal %P1(%%esp),%0" 123 : "=r" (stack_end) : "i" (-STACK_SIZE)); 124 125 heap_end = (char *) 126 ((size_t)boot_params.hdr.heap_end_ptr + 0x200); 127 if (heap_end > stack_end) 128 heap_end = stack_end; 129 } else { 130 /* Boot protocol 2.00 only, no heap available */ 131 puts("WARNING: Ancient bootloader, some functionality " 132 "may be limited!\n"); 133 } 134} 135 136void main(void) 137{ 138 init_default_io_ops(); 139 140 /* First, copy the boot header into the "zeropage" */ 141 copy_boot_params(); 142 143 /* Initialize the early-boot console */ 144 console_init(); 145 if (cmdline_find_option_bool("debug")) 146 puts("early console in setup code\n"); 147 148 /* End of heap check */ 149 init_heap(); 150 151 /* Make sure we have all the proper CPU support */ 152 if (validate_cpu()) { 153 puts("Unable to boot - please use a kernel appropriate " 154 "for your CPU.\n"); 155 die(); 156 } 157 158 /* Tell the BIOS what CPU mode we intend to run in. */ 159 set_bios_mode(); 160 161 /* Detect memory layout */ 162 detect_memory(); 163 164 /* Set keyboard repeat rate (why?) and query the lock flags */ 165 keyboard_init(); 166 167 /* Query Intel SpeedStep (IST) information */ 168 query_ist(); 169 170 /* Query APM information */ 171#if defined(CONFIG_APM) || defined(CONFIG_APM_MODULE) 172 query_apm_bios(); 173#endif 174 175 /* Query EDD information */ 176#if defined(CONFIG_EDD) || defined(CONFIG_EDD_MODULE) 177 query_edd(); 178#endif 179 180 /* Set the video mode */ 181 set_video(); 182 183 /* Do the last things and invoke protected mode */ 184 go_to_protected_mode(); 185}