1 /////////////////////////////////////////////////////////////////////////
2 // $Id: load32bitOShack.cc,v 1.30 2008/05/01 20:08:36 sshwarts Exp $
3 /////////////////////////////////////////////////////////////////////////
5 // Copyright (C) 2001 MandrakeSoft S.A.
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
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
50 FILE *fp
= fopen(SIM
->get_param_string(BXPN_LOAD32BITOS_IOLOG
)->getptr(), "r");
52 BX_PANIC(("could not open IO init file."));
56 unsigned len
, op
, port
, val
;
58 ret
= fscanf(fp
, "%u %u %x %x\n", &len
, &op
, &port
, &val
);
60 BX_PANIC(("could not open IO init file."));
64 bx_devices
.inp(port
, len
);
68 bx_devices
.outp(port
, val
, len
);
71 BX_PANIC(("bad IO op in init filen"));
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
:
82 case Load32bitOSNullKernel
:
83 bx_load_null_kernel_hack();
86 BX_PANIC(("load32bitOSImage: OS not recognized"));
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 struct linux_setup_params
*params
=
138 (struct linux_setup_params
*) BX_MEM(0)->get_vector(0x00090000);
140 memset(params
, '\0', sizeof(*params
));
142 /* Video settings (standard VGA) */
145 params
->orig_video_page
= 0;
146 params
->orig_video_mode
= 3;
147 params
->orig_video_cols
= 80;
148 params
->orig_video_lines
= 25;
149 params
->orig_video_points
= 16;
150 params
->orig_video_isVGA
= 1;
151 params
->orig_video_ega_bx
= 3;
153 /* Memory size (total mem - 1MB, in KB) */
154 params
->memory_size_ext
= (BX_MEM(0)->get_memory_len()/(1024*1024) - 1) * 1024;
156 /* Boot parameters */
157 params
->loader_type
= 1;
158 params
->bootsect_magic
= 0xaa55;
159 params
->mount_root_rdonly
= 0;
160 params
->orig_root_dev
= 0x0100;
161 params
->initrd_start
= initrd_start
;
162 params
->initrd_size
= initrd_size
;
165 params
->gdt
[2].high
= 0x00cf9a00;
166 params
->gdt
[2].low
= 0x0000ffff;
167 params
->gdt
[3].high
= 0x00cf9200;
168 params
->gdt
[3].low
= 0x0000ffff;
171 void bx_load_linux_hack(void)
173 Bit32u initrd_start
= 0, initrd_size
= 0;
175 // The RESET function will have been called first.
176 // Set CPU and memory features which are assumed at this point.
178 // Load Linux kernel image
179 bx_load_kernel_image(SIM
->get_param_string(BXPN_LOAD32BITOS_PATH
)->getptr(), 0x100000);
181 // Load initial ramdisk image if requested
182 char *tmpPtr
= SIM
->get_param_string(BXPN_LOAD32BITOS_INITRD
)->getptr();
183 if (tmpPtr
&& tmpPtr
[0]) /* The initial value is "" and not NULL */
185 initrd_start
= 0x00800000; /* FIXME: load at top of memory */
186 initrd_size
= bx_load_kernel_image(tmpPtr
, initrd_start
);
189 // Setup Linux startup parameters buffer
190 bx_load_linux_setup_params(initrd_start
, initrd_size
);
193 BX_SET_ENABLE_A20(1);
195 // Setup PICs the way Linux likes it
196 BX_OUTP(0x20, 0x11, 1);
197 BX_OUTP(0xA0, 0x11, 1);
198 BX_OUTP(0x21, 0x20, 1);
199 BX_OUTP(0xA1, 0x28, 1);
200 BX_OUTP(0x21, 0x04, 1);
201 BX_OUTP(0xA1, 0x02, 1);
202 BX_OUTP(0x21, 0x01, 1);
203 BX_OUTP(0xA1, 0x01, 1);
204 BX_OUTP(0x21, 0xFF, 1);
205 BX_OUTP(0xA1, 0xFB, 1);
207 // Disable interrupts and NMIs
208 BX_CPU(0)->clear_IF();
209 BX_OUTP(0x70, 0x80, 1);
211 // Enter protected mode
212 // Fixed by george (kyriazis at nvidia.com)
213 // BX_CPU(0)->cr0.pe = 1;
214 // BX_CPU(0)->cr0.val32 |= 0x01;
216 BX_CPU(0)->SetCR0(BX_CPU(0)->cr0
.val32
| 0x01);
218 // load esi with real_mode
219 BX_CPU(0)->gen_reg
[BX_32BIT_REG_ESI
].dword
.erx
= 0x90000;
221 // Set up initial GDT
222 BX_CPU(0)->gdtr
.limit
= 0x400;
223 BX_CPU(0)->gdtr
.base
= 0x00090400;
225 // Jump to protected mode entry point
226 BX_CPU(0)->jump_protected(NULL
, 0x10, 0x100000);
229 void bx_load_null_kernel_hack(void)
231 // The RESET function will have been called first.
232 // Set CPU and memory features which are assumed at this point.
234 bx_load_kernel_image(SIM
->get_param_string(BXPN_LOAD32BITOS_PATH
)->getptr(), 0x100000);
237 BX_CPU(0)->prev_rip
= BX_CPU(0)->gen_reg
[BX_32BIT_REG_EIP
].dword
.erx
= 0x100000;
240 BX_CPU(0)->sregs
[BX_SEG_REG_CS
].cache
.u
.segment
.base
= 0x00000000;
241 BX_CPU(0)->sregs
[BX_SEG_REG_CS
].cache
.u
.segment
.limit
= 0xFFFFF;
242 BX_CPU(0)->sregs
[BX_SEG_REG_CS
].cache
.u
.segment
.limit_scaled
= 0xFFFFFFFF;
243 BX_CPU(0)->sregs
[BX_SEG_REG_CS
].cache
.u
.segment
.g
= 1; // page gran
244 BX_CPU(0)->sregs
[BX_SEG_REG_CS
].cache
.u
.segment
.d_b
= 1; // 32bit
246 #if BX_SUPPORT_ICACHE
247 BX_CPU(0)->updateFetchModeMask();
251 BX_CPU(0)->sregs
[BX_SEG_REG_DS
].cache
.u
.segment
.base
= 0x00000000;
252 BX_CPU(0)->sregs
[BX_SEG_REG_DS
].cache
.u
.segment
.limit
= 0xFFFFF;
253 BX_CPU(0)->sregs
[BX_SEG_REG_DS
].cache
.u
.segment
.limit_scaled
= 0xFFFFFFFF;
254 BX_CPU(0)->sregs
[BX_SEG_REG_DS
].cache
.u
.segment
.g
= 1; // page gran
255 BX_CPU(0)->sregs
[BX_SEG_REG_DS
].cache
.u
.segment
.d_b
= 1; // 32bit
258 BX_CPU(0)->cr0
.set_PE(1); // protected mode
262 bx_load_kernel_image(char *path
, Bit32u paddr
)
264 struct stat stat_buf
;
266 unsigned long size
, offset
;
269 // read in ROM BIOS image file
270 fd
= open(path
, O_RDONLY
276 BX_INFO(("load_kernel_image: couldn't open image file '%s'.", path
));
279 ret
= fstat(fd
, &stat_buf
);
281 BX_INFO(("load_kernel_image: couldn't stat image file '%s'.", path
));
285 size
= (unsigned long) stat_buf
.st_size
;
286 page_size
= ((Bit32u
)size
+ 0xfff) & ~0xfff;
288 if ((paddr
+ size
) > BX_MEM(0)->get_memory_len()) {
289 BX_INFO(("load_kernel_image: address range > physical memsize!"));
295 ret
= read(fd
, (bx_ptr_t
) BX_MEM(0)->get_vector(paddr
+ offset
), size
);
297 BX_INFO(("load_kernel_image: read failed on image"));
304 BX_INFO(("load_kernel_image: '%s', size=%u read into memory at %08x",
305 path
, (unsigned) stat_buf
.st_size
, (unsigned) paddr
));