- skip SMM init if already done at first boot time (fixes reboot failure)
[bochs-mirror.git] / load32bitOShack.cc
blobc03d11f8a7cba0dacee749f98d6b16f17b3cada2
1 /////////////////////////////////////////////////////////////////////////
2 // $Id: load32bitOShack.cc,v 1.24 2007/11/24 14:22:32 sshwarts Exp $
3 /////////////////////////////////////////////////////////////////////////
4 //
5 // Copyright (C) 2001 MandrakeSoft S.A.
6 //
7 // MandrakeSoft S.A.
8 // 43, rue d'Aboukir
9 // 75002 Paris - France
10 // http://www.linux-mandrake.com/
11 // http://www.mandrakesoft.com/
13 // This library is free software; you can redistribute it and/or
14 // modify it under the terms of the GNU Lesser General Public
15 // License as published by the Free Software Foundation; either
16 // version 2 of the License, or (at your option) any later version.
18 // This library is distributed in the hope that it will be useful,
19 // but WITHOUT ANY WARRANTY; without even the implied warranty of
20 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21 // Lesser General Public License for more details.
23 // You should have received a copy of the GNU Lesser General Public
24 // License along with this library; if not, write to the Free Software
25 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
28 #include "bochs.h"
29 #include "cpu/cpu.h"
30 #include "iodev/iodev.h"
31 #define LOG_THIS genlog->
34 static void bx_load_linux_hack(void);
35 static void bx_load_null_kernel_hack(void);
36 static Bit32u bx_load_kernel_image(char *path, Bit32u paddr);
38 void bx_load32bitOSimagehack(void)
40 if (SIM->get_param_string(BXPN_LOAD32BITOS_IOLOG) &&
41 (SIM->get_param_string(BXPN_LOAD32BITOS_IOLOG)->getptr()[0] != '\0'))
44 // Replay IO from log to initialize IO devices to
45 // a reasonable state needed for the OS. This is done
46 // in lieu of running the 16-bit BIOS to init things,
47 // since we want to test straight 32bit stuff for
48 // freemware.
50 FILE *fp = fopen(SIM->get_param_string(BXPN_LOAD32BITOS_IOLOG)->getptr(), "r");
51 if (fp == NULL) {
52 BX_PANIC(("could not open IO init file."));
55 while (1) {
56 unsigned len, op, port, val;
57 int ret;
58 ret = fscanf(fp, "%u %u %x %x\n", &len, &op, &port, &val);
59 if (ret != 4) {
60 BX_PANIC(("could not open IO init file."));
62 if (op == 0) {
63 // read
64 bx_devices.inp(port, len);
66 else if (op == 1) {
67 // write
68 bx_devices.outp(port, val, len);
70 else {
71 BX_PANIC(("bad IO op in init filen"));
73 if (feof(fp)) break;
75 } //if iolog file to load
77 // Invoke proper hack depending on which OS image we're loading
78 switch (SIM->get_param_enum(BXPN_LOAD32BITOS_WHICH)->get()) {
79 case Load32bitOSLinux:
80 bx_load_linux_hack();
81 break;
82 case Load32bitOSNullKernel:
83 bx_load_null_kernel_hack();
84 break;
85 default:
86 BX_PANIC(("load32bitOSImage: OS not recognized"));
90 struct gdt_entry
92 Bit32u low;
93 Bit32u high;
96 struct linux_setup_params
98 /* 0x000 */ Bit8u orig_x;
99 /* 0x001 */ Bit8u orig_y;
100 /* 0x002 */ Bit16u memory_size_std;
101 /* 0x004 */ Bit16u orig_video_page;
102 /* 0x006 */ Bit8u orig_video_mode;
103 /* 0x007 */ Bit8u orig_video_cols;
104 /* 0x008 */ Bit16u unused1;
105 /* 0x00a */ Bit16u orig_video_ega_bx;
106 /* 0x00c */ Bit16u unused2;
107 /* 0x00e */ Bit8u orig_video_lines;
108 /* 0x00f */ Bit8u orig_video_isVGA;
109 /* 0x010 */ Bit16u orig_video_points;
110 /* 0x012 */ Bit8u pad1[0x40 - 0x12];
111 /* 0x040 */ Bit8u apm_info[0x80 - 0x40];
112 /* 0x080 */ Bit8u hd0_info[16];
113 /* 0x090 */ Bit8u hd1_info[16];
114 /* 0x0a0 */ Bit8u pad2[0x1e0 - 0xa0];
115 /* 0x1e0 */ Bit32u memory_size_ext;
116 /* 0x1e4 */ Bit8u pad3[0x1f1 - 0x1e4];
117 /* 0x1f1 */ Bit8u setup_sects;
118 /* 0x1f2 */ Bit16u mount_root_rdonly;
119 /* 0x1f4 */ Bit16u sys_size;
120 /* 0x1f6 */ Bit16u swap_dev;
121 /* 0x1f8 */ Bit16u ramdisk_flags;
122 /* 0x1fa */ Bit16u vga_mode;
123 /* 0x1fc */ Bit16u orig_root_dev;
124 /* 0x1fe */ Bit16u bootsect_magic;
125 /* 0x200 */ Bit8u pad4[0x210 - 0x200];
126 /* 0x210 */ Bit32u loader_type;
127 /* 0x214 */ Bit32u kernel_start;
128 /* 0x218 */ Bit32u initrd_start;
129 /* 0x21c */ Bit32u initrd_size;
130 /* 0x220 */ Bit8u pad5[0x400 - 0x220];
131 /* 0x400 */ struct gdt_entry gdt[128];
132 /* 0x800 */ Bit8u commandline[2048];
135 static void bx_load_linux_setup_params(Bit32u initrd_start, Bit32u initrd_size)
137 BX_MEM_C *mem = BX_MEM(0);
138 struct linux_setup_params *params =
139 (struct linux_setup_params *) &mem->vector[0x00090000];
141 memset( params, '\0', sizeof(*params) );
143 /* Video settings (standard VGA) */
144 params->orig_x = 0;
145 params->orig_y = 0;
146 params->orig_video_page = 0;
147 params->orig_video_mode = 3;
148 params->orig_video_cols = 80;
149 params->orig_video_lines = 25;
150 params->orig_video_points = 16;
151 params->orig_video_isVGA = 1;
152 params->orig_video_ega_bx = 3;
154 /* Memory size (total mem - 1MB, in KB) */
155 params->memory_size_ext = (mem->megabytes - 1) * 1024;
157 /* Boot parameters */
158 params->loader_type = 1;
159 params->bootsect_magic = 0xaa55;
160 params->mount_root_rdonly = 0;
161 params->orig_root_dev = 0x0100;
162 params->initrd_start = initrd_start;
163 params->initrd_size = initrd_size;
165 /* Initial GDT */
166 params->gdt[2].high = 0x00cf9a00;
167 params->gdt[2].low = 0x0000ffff;
168 params->gdt[3].high = 0x00cf9200;
169 params->gdt[3].low = 0x0000ffff;
172 void bx_load_linux_hack(void)
174 Bit32u initrd_start = 0, initrd_size = 0;
176 // The RESET function will have been called first.
177 // Set CPU and memory features which are assumed at this point.
179 // Load Linux kernel image
180 bx_load_kernel_image(SIM->get_param_string(BXPN_LOAD32BITOS_PATH)->getptr(), 0x100000);
182 // Load initial ramdisk image if requested
183 char * tmpPtr = SIM->get_param_string(BXPN_LOAD32BITOS_INITRD)->getptr();
184 if ( tmpPtr && tmpPtr[0] ) /* The initial value is "" and not NULL */
186 initrd_start = 0x00800000; /* FIXME: load at top of memory */
187 initrd_size = bx_load_kernel_image( tmpPtr, initrd_start );
190 // Setup Linux startup parameters buffer
191 bx_load_linux_setup_params( initrd_start, initrd_size );
193 // Enable A20 line
194 BX_SET_ENABLE_A20( 1 );
196 // Setup PICs the way Linux likes it
197 BX_OUTP( 0x20, 0x11, 1 );
198 BX_OUTP( 0xA0, 0x11, 1 );
199 BX_OUTP( 0x21, 0x20, 1 );
200 BX_OUTP( 0xA1, 0x28, 1 );
201 BX_OUTP( 0x21, 0x04, 1 );
202 BX_OUTP( 0xA1, 0x02, 1 );
203 BX_OUTP( 0x21, 0x01, 1 );
204 BX_OUTP( 0xA1, 0x01, 1 );
205 BX_OUTP( 0x21, 0xFF, 1 );
206 BX_OUTP( 0xA1, 0xFB, 1 );
208 // Disable interrupts and NMIs
209 BX_CPU(0)->clear_IF ();
210 BX_OUTP( 0x70, 0x80, 1 );
212 // Enter protected mode
213 // Fixed by george (kyriazis at nvidia.com)
214 // BX_CPU(0)->cr0.pe = 1;
215 // BX_CPU(0)->cr0.val32 |= 0x01;
217 BX_CPU(0)->SetCR0(BX_CPU(0)->cr0.val32 | 0x01);
219 // load esi with real_mode
220 BX_CPU(0)->gen_reg[BX_32BIT_REG_ESI].dword.erx = 0x90000;
222 // Set up initial GDT
223 BX_CPU(0)->gdtr.limit = 0x400;
224 BX_CPU(0)->gdtr.base = 0x00090400;
226 // Jump to protected mode entry point
227 BX_CPU(0)->jump_protected( NULL, 0x10, 0x00100000 );
230 void bx_load_null_kernel_hack(void)
232 // The RESET function will have been called first.
233 // Set CPU and memory features which are assumed at this point.
235 bx_load_kernel_image(SIM->get_param_string(BXPN_LOAD32BITOS_PATH)->getptr(), 0x100000);
237 // EIP deltas
238 BX_CPU(0)->prev_rip = BX_CPU(0)->eip_reg.dword.eip = 0x00100000;
240 // CS deltas
241 BX_CPU(0)->sregs[BX_SEG_REG_CS].cache.u.segment.base = 0x00000000;
242 BX_CPU(0)->sregs[BX_SEG_REG_CS].cache.u.segment.limit = 0xFFFFF;
243 BX_CPU(0)->sregs[BX_SEG_REG_CS].cache.u.segment.limit_scaled = 0xFFFFFFFF;
244 BX_CPU(0)->sregs[BX_SEG_REG_CS].cache.u.segment.g = 1; // page gran
245 BX_CPU(0)->sregs[BX_SEG_REG_CS].cache.u.segment.d_b = 1; // 32bit
247 #if BX_SUPPORT_ICACHE
248 BX_CPU(0)->updateFetchModeMask();
249 #endif
251 // DS deltas
252 BX_CPU(0)->sregs[BX_SEG_REG_DS].cache.u.segment.base = 0x00000000;
253 BX_CPU(0)->sregs[BX_SEG_REG_DS].cache.u.segment.limit = 0xFFFFF;
254 BX_CPU(0)->sregs[BX_SEG_REG_DS].cache.u.segment.limit_scaled = 0xFFFFFFFF;
255 BX_CPU(0)->sregs[BX_SEG_REG_DS].cache.u.segment.g = 1; // page gran
256 BX_CPU(0)->sregs[BX_SEG_REG_DS].cache.u.segment.d_b = 1; // 32bit
258 // CR0 deltas
259 BX_CPU(0)->cr0.set_PE(1); // protected mode
262 Bit32u
263 bx_load_kernel_image(char *path, Bit32u paddr)
265 struct stat stat_buf;
266 int fd, ret;
267 unsigned long size, offset;
268 Bit32u page_size;
270 // read in ROM BIOS image file
271 fd = open(path, O_RDONLY
272 #ifdef O_BINARY
273 | O_BINARY
274 #endif
276 if (fd < 0) {
277 BX_INFO(( "load_kernel_image: couldn't open image file '%s'.", path ));
278 BX_EXIT(1);
280 ret = fstat(fd, &stat_buf);
281 if (ret) {
282 BX_INFO(( "load_kernel_image: couldn't stat image file '%s'.", path ));
283 BX_EXIT(1);
286 size = (unsigned long)stat_buf.st_size;
287 page_size = ((Bit32u)size + 0xfff) & ~0xfff;
289 BX_MEM_C *mem = BX_MEM(0);
290 if ( (paddr + size) > mem->len ) {
291 BX_INFO(( "load_kernel_image: address range > physical memsize!" ));
292 BX_EXIT(1);
295 offset = 0;
296 while (size > 0) {
297 ret = read(fd, (bx_ptr_t) &mem->vector[paddr + offset], size);
298 if (ret <= 0) {
299 BX_INFO(( "load_kernel_image: read failed on image" ));
300 BX_EXIT(1);
302 size -= ret;
303 offset += ret;
305 close(fd);
306 BX_INFO(("load_kernel_image: '%s', size=%u read into memory at %08x",
307 path, (unsigned) stat_buf.st_size, (unsigned) paddr));
309 return page_size;