rev |
line source |
pascal@19515
|
1 // This file is distributed under GPL
|
pascal@19515
|
2
|
pascal@19515
|
3 #include "crtl.h"
|
pascal@19515
|
4 #include "common.h"
|
pascal@19515
|
5
|
pascal@19515
|
6 /***************
|
pascal@19515
|
7 Memory layout assumed by kernel boot process
|
pascal@19515
|
8 --------------------------------------------
|
pascal@19515
|
9 Note: claims that kernel setup is relocatable are
|
pascal@19515
|
10 still not 100% valid:
|
pascal@19515
|
11 bzImage decompressing trashes 10000-8ffff range,
|
pascal@19515
|
12 so rm loader -> pm kernel info is lost if it was here...
|
pascal@19515
|
13 So I had to stick to 90000.
|
pascal@19515
|
14
|
pascal@19515
|
15 10000000+------------------------+ <- 256m
|
pascal@19515
|
16 | initrd | initrd is at top of mem, but
|
pascal@19515
|
17 | | not higher than 256m
|
pascal@19515
|
18 +------------------------+
|
pascal@19515
|
19 +------------------------+
|
pascal@19515
|
20 | bzImage | bzImage is at 1m
|
pascal@19515
|
21 | | VCPI/XMS/64k offset tricks used...
|
pascal@19515
|
22 00100000+------------------------+ <- 1m
|
pascal@19515
|
23 | video, BIOS etc | Do not use.
|
pascal@19515
|
24 000A0000+------------------------+
|
pascal@19515
|
25 | Reserved for BIOS | Do not use. Reserved for BIOS EBDA.
|
pascal@19515
|
26 0009A000+------------------------+ <- stack top for kernel rm code
|
pascal@19515
|
27 | Cmdline |
|
pascal@19515
|
28 00098000+------------------------+ <- heap top for kernel rm code
|
pascal@19515
|
29 | Kernel setup | The kernel real-mode code.
|
pascal@19515
|
30 00090200+------------------------+
|
pascal@19515
|
31 | Kernel boot sector | The kernel legacy boot sector.
|
pascal@19515
|
32 00090000+------------------------+
|
pascal@19515
|
33 | Zapped by ungzip | Historically zImages were loaded here
|
pascal@19515
|
34 | (zImage once was here) | bzImages use this space for ungzipping
|
pascal@19515
|
35 00010000+------------------------+
|
pascal@19515
|
36 | Boot loader | <- Boot sector entry point 0000:7C00
|
pascal@19515
|
37 00001000+------------------------+
|
pascal@19515
|
38 | Reserved for MBR/BIOS |
|
pascal@19515
|
39 00000800+------------------------+
|
pascal@19515
|
40 | Typically used by MBR |
|
pascal@19515
|
41 00000600+------------------------+
|
pascal@19515
|
42 | BIOS use only |
|
pascal@19515
|
43 00000000+------------------------+
|
pascal@19515
|
44 */
|
pascal@19515
|
45
|
pascal@19538
|
46 struct kernelparams_t {
|
pascal@20458
|
47 s8 setup_sects; // 01F1 The size of the setup in sectors
|
pascal@19515
|
48 // boot sector is NOT included here
|
pascal@19515
|
49 u16 ro_flag; // 01F2 If set, the root is mounted readonly
|
pascal@19515
|
50 u16 syssize; // 01F4 DO NOT USE - for bootsect.S use only:
|
pascal@19515
|
51 // size of pm part of kernel
|
pascal@19515
|
52 // (in 16 byte units, rounded up)
|
pascal@19515
|
53 u16 swap_dev; // 01F6 DO NOT USE - obsolete
|
pascal@19515
|
54 u16 ram_size; // 01F8 DO NOT USE - for bootsect.S use only:
|
pascal@19515
|
55 // if nonzero then kernel
|
pascal@19515
|
56 // (driver/block/ramdisk.c: rd_load())
|
pascal@19515
|
57 // will try to load the contents for the ramdisk
|
pascal@19515
|
58 // from the "root_dev" which MUST then have the
|
pascal@19515
|
59 // floppyMAJOR
|
pascal@19515
|
60 // The file-system on that floppy must be MINIX
|
pascal@19515
|
61 // If rd_load() succeeds it sets the root_dev
|
pascal@19515
|
62 // to the ramdisk for mounting it
|
pascal@19515
|
63 u16 vid_mode; // 01FA Video mode control
|
pascal@19515
|
64 u16 root_dev; // 01FC Default root device number
|
pascal@19515
|
65 u16 boot_flag; // 01FE 0xAA55 magic number
|
pascal@19515
|
66 u16 jump; // 0200 Jump instruction
|
pascal@19515
|
67 u32 header; // 0202 Magic signature "HdrS"
|
pascal@19515
|
68 u16 version; // 0206 Boot protocol version supported
|
pascal@19515
|
69 u16 realmode_switch_ofs; // 0208 Hook called just before rm->pm
|
pascal@19515
|
70 u16 realmode_switch_seg;
|
pascal@19515
|
71 u16 start_sys_seg; // 020E
|
pascal@19515
|
72 u16 kernel_version; // 020C Points to kernel version string
|
pascal@19515
|
73 u8 type_of_loader; // 0210 Boot loader identifier
|
pascal@19515
|
74 u8 loadflags; // 0211 Boot protocol option flags
|
pascal@19515
|
75 u16 setup_move_size;// 0212 Move to high memory size (used with hooks)
|
pascal@19515
|
76 u32 code32_start; // 0214 Boot loader hook (see below)
|
pascal@19515
|
77 u32 initrd_buf; // 0218 initrd load address (set by boot loader)
|
pascal@19515
|
78 u32 initrd_size; // 021C initrd size (set by boot loader)
|
pascal@19515
|
79 u32 bootsect_kludge;// 0220 DO NOT USE - for bootsect.S use only
|
pascal@19515
|
80 u16 heap_end_ptr; // 0224 Free memory after setup end
|
pascal@19515
|
81 u16 pad1; // 0226 Unused
|
pascal@19515
|
82 u32 cmd_line_ptr; // 0228 32-bit pointer to the kernel command line
|
pascal@19515
|
83 u8 pad30[0x400-0x22c]; // 022C
|
pascal@19515
|
84 // 02D0 up to 32 20-byte mem info structs from
|
pascal@19515
|
85 // int 0x15 fn 0xe820
|
pascal@19515
|
86 }; //__attribute((packed));
|
pascal@19515
|
87
|
pascal@19538
|
88 struct first1k_t {
|
pascal@19538
|
89 // these two set by rm setup:
|
pascal@19538
|
90 u16 curr_curs; // 0000 saved cursor position
|
pascal@19538
|
91 u16 ext_mem_size; // 0002 extended memory size in Kb (from int 0x15 fn 0x88)
|
pascal@19538
|
92 u8 pad00[0x20-4];
|
pascal@19538
|
93 // old-style cmdline (not used in LINLD (yet?))
|
pascal@19636
|
94 u32 cl_magic_ofs;
|
pascal@19636
|
95 //u16 cl_magic; // 0020 commandline magic number (=0xA33F)
|
pascal@19636
|
96 //u16 cl_ofs; // 0022 commandline offset
|
pascal@19538
|
97 u8 pad10[0x80-0x24];
|
pascal@19538
|
98 // these two set by rm setup:
|
pascal@19538
|
99 u8 hd0_disk_par[16]; // 0080 hd0-disk-parameter from intvector 0x41
|
pascal@19538
|
100 u8 hd1_disk_par[16]; // 0090 hd1-disk-parameter from intvector 0x46
|
pascal@19538
|
101 u8 pad20[0x01e0-0xa0];
|
pascal@19538
|
102 // this is set by rm setup:
|
pascal@19538
|
103 u32 alt_mem_size; // 01E0 extended memory size in Kb (from int 0x15 fn 0xe801)
|
pascal@19571
|
104 u8 pad28[0x01f1-0x1e4];
|
pascal@19538
|
105 struct kernelparams_t params;
|
pascal@19538
|
106 }; //__attribute((packed));
|
pascal@19538
|
107
|
pascal@19515
|
108 #if sizeof(first1k_t)!=0x400
|
pascal@19515
|
109 #error BUG: Bad first1k
|
pascal@19515
|
110 #endif
|
pascal@19515
|
111
|
pascal@19515
|
112 const u32 HdrS = 'H' + ('d'<<8) + (u32('r')<<16) + (u32('S')<<24);
|
pascal@19515
|
113
|
pascal@19515
|
114 // register value to launch the kernel real mode code
|
pascal@20751
|
115 static u32 csip;
|
pascal@19515
|
116 #ifdef NO386
|
pascal@19515
|
117 extern "C" u16 topseg();
|
pascal@19515
|
118 #else
|
pascal@19515
|
119 #define topseg() 0x9000
|
pascal@19515
|
120 #endif
|
pascal@20745
|
121 u16 rm_size;
|
pascal@20745
|
122 static u8 pm_high; // @ = @rm_size + 2, see JUMP.ASM
|
pascal@20745
|
123 static u8* rm_buf; // @ = @rm_size + 3, see JUMP.ASM
|
pascal@20745
|
124 struct image_himem imgs[2];
|
pascal@20745
|
125
|
pascal@19515
|
126 static const char kernel_file_error[] = "Can't use kernel file";
|
pascal@19515
|
127 char* load_kernel() {
|
pascal@19515
|
128
|
pascal@19636
|
129 struct image_himem *m = ±
|
pascal@20634
|
130 #define _rm_buf(m) (((u8**)(m))[-1])
|
pascal@20634
|
131 #define _pm_high (((u8*)(m))[-3])
|
pascal@20634
|
132 #define _rm_size (*(u16*)((u8*)(m)-5))
|
pascal@20745
|
133 #define _csip (*(u32*)((u8*)(m)-9))
|
pascal@19515
|
134 char *version_string;
|
pascal@19515
|
135 {
|
pascal@19538
|
136 struct kernelparams_t *kernelparams;
|
pascal@20632
|
137 kernelparams = &(((first1k_t*) (_rm_buf(m) = (u8 *)malloc_or_die(_32k)))->params);
|
pascal@19636
|
138 #define first1k ((first1k_t*)((u8 *)kernelparams-0x1F1))
|
pascal@19515
|
139
|
pascal@20751
|
140 *((u16 *)&_csip+1)=topseg()|0x20;
|
pascal@20751
|
141 // Open kernel, read first kb, check it
|
pascal@20751
|
142 m->errmsg = kernel_file_error;
|
pascal@21649
|
143 open_image(m, kernel_name);
|
pascal@20751
|
144
|
pascal@20510
|
145 do {
|
pascal@19515
|
146 // Do not use malloc below until heap_top adjustment (see <*>)
|
pascal@20751
|
147 if (readrm(m, 0x200) == 0x200) {
|
pascal@19515
|
148
|
pascal@20542
|
149 lseekcur(m->fd,-0x200);
|
pascal@19571
|
150 if(kernelparams->setup_sects == 0) {
|
pascal@19515
|
151 #if 1
|
pascal@19515
|
152 if(* (int *) &first1k->pad10[0x3F-0x24] == 0x3AE8) {
|
pascal@20632
|
153 _csip+=0xFFE00042;
|
pascal@19515
|
154 }
|
pascal@21628
|
155 else
|
pascal@19515
|
156 #endif
|
pascal@19538
|
157 kernelparams->setup_sects=4;
|
pascal@19515
|
158 }
|
pascal@19636
|
159 if((kernelparams->setup_sects)>=(_32k/512) || // 0th sector not counted
|
pascal@19636
|
160 kernelparams->boot_flag != 0xAA55)
|
pascal@20454
|
161 die("Not a kernel");
|
pascal@20632
|
162 heap_top = _rm_buf(m)+(_rm_size=0x200*(kernelparams->setup_sects+1)); // <*>
|
pascal@20632
|
163 m->size -= _rm_size;
|
pascal@20632
|
164 m->chunk_size -= _rm_size;
|
pascal@19515
|
165
|
pascal@19515
|
166 // Read remaining rm loader
|
pascal@20751
|
167 if (readrm(m, _rm_size) == _rm_size) break;
|
pascal@20510
|
168 }
|
pascal@20510
|
169 die(kernel_file_error);
|
pascal@20510
|
170 } while (0);
|
pascal@19515
|
171
|
pascal@19515
|
172 // Tell rm loader some info
|
pascal@19515
|
173
|
pascal@20528
|
174 if((int)vid_mode) kernelparams->vid_mode = vid_mode;
|
pascal@20528
|
175 if((int)root_dev) kernelparams->root_dev = root_dev;
|
pascal@20485
|
176 version_string = "";
|
pascal@19515
|
177
|
pascal@19538
|
178 if(kernelparams->header == HdrS) { // starting linux 1.3.73
|
pascal@19538
|
179 if(kernelparams->loadflags & 1) {
|
pascal@21332
|
180 extern void far last_ditch();
|
pascal@21332
|
181 kernelparams->realmode_switch_ofs = (u16) last_ditch;
|
pascal@21332
|
182 kernelparams->realmode_switch_seg = _CS;
|
pascal@19515
|
183 pm_high++;
|
pascal@19515
|
184
|
pascal@19515
|
185 // Hook on int15 to work around fn 88 DOS breakage
|
pascal@19515
|
186 hook_int15_88();
|
pascal@19515
|
187 }
|
pascal@21623
|
188 if (kernelparams->kernel_version)
|
pascal@21623
|
189 version_string = (char *) first1k+kernelparams->kernel_version+0x200;
|
pascal@19538
|
190 kernelparams->type_of_loader = 0xff; // kernel do not know us (yet :-)
|
pascal@19538
|
191 if(kernelparams->version >= 0x201) {
|
pascal@19515
|
192 // * offset limit of the setup heap
|
pascal@19515
|
193 // heap_end_ptr appears to be relative to the start of setup (ofs 0x0200)
|
pascal@19538
|
194 kernelparams->heap_end_ptr = _32k-0x0200;
|
pascal@19538
|
195 kernelparams->loadflags |= 0x80; // says to rm loader it's ok to use heap
|
pascal@19515
|
196 }
|
pascal@19515
|
197 // * if we will ever stop moving ourself to 0x90000
|
pascal@19515
|
198 // we must say setup.S how much to move
|
pascal@19538
|
199 //kernelparams->setup_move_size = _32k;
|
pascal@19538
|
200 if(kernelparams->version >= 0x202) { // starting linux 2.4.0-test3-pre3
|
pascal@19538
|
201 kernelparams->cmd_line_ptr = (((u32)(topseg()+0x0800))<<4);
|
pascal@19515
|
202 goto cmd_line_ok;
|
pascal@19515
|
203 }
|
pascal@19515
|
204 }
|
pascal@19636
|
205 first1k->cl_magic_ofs = 0x8000A33F;
|
pascal@19515
|
206 }
|
pascal@19515
|
207
|
pascal@19515
|
208 cmd_line_ok:
|
pascal@19515
|
209 // Check and enable A20 if needed
|
pascal@19515
|
210 enable_a20_or_die();
|
pascal@19515
|
211
|
pascal@19515
|
212 // Read remaining kernel (pm part)
|
pascal@19515
|
213 // Try to load kernel high, maybe even blindly storing it
|
pascal@19515
|
214 // in unallocated memory as a last resort
|
pascal@19515
|
215
|
pascal@19571
|
216 {
|
pascal@19571
|
217 struct image_himem *m = ±
|
pascal@21628
|
218 if((u16)(((m->fallback=(u32(u16(_CS)+0x1000)<<4))+m->size)>>16) >=
|
pascal@21628
|
219 (u16)(topseg()>>12) || _pm_high) {
|
pascal@20634
|
220 m->fallback = base_himem;
|
pascal@19515
|
221 }
|
pascal@19515
|
222
|
pascal@19571
|
223 load_image(m);
|
pascal@19571
|
224 }
|
pascal@19515
|
225 return version_string;
|
pascal@19515
|
226 }
|
pascal@19515
|
227
|
pascal@20634
|
228 struct initrdparams_t {
|
pascal@20634
|
229 u32 header; // 0202 Magic signature "HdrS"
|
pascal@20634
|
230 u16 version; // 0206 Boot protocol version supported
|
pascal@20634
|
231 u16 realmode_switch_ofs; // 0208 Hook called just before rm->pm
|
pascal@20634
|
232 u16 realmode_switch_seg;
|
pascal@21576
|
233 u16 start_sys_seg; // 020C
|
pascal@21576
|
234 u16 kernel_version; // 020E Points to kernel version string
|
pascal@20634
|
235 u8 type_of_loader; // 0210 Boot loader identifier
|
pascal@20634
|
236 u8 loadflags; // 0211 Boot protocol option flags
|
pascal@20634
|
237 u16 setup_move_size;// 0212 Move to high memory size (used with hooks)
|
pascal@20634
|
238 u32 code32_start; // 0214 Boot loader hook (see below)
|
pascal@20634
|
239 u32 initrd_buf; // 0218 initrd load address (set by boot loader)
|
pascal@20634
|
240 u32 initrd_size; // 021C initrd size (set by boot loader)
|
pascal@20634
|
241 };
|
pascal@20634
|
242
|
pascal@19515
|
243 // Read initrd if needed
|
pascal@19515
|
244 void load_initrd() {
|
pascal@19515
|
245 struct image_himem *m = &initrd;
|
pascal@21623
|
246 if (((int)initrd_name | m->fd) == 0) return; // !initrd_name && !m->fd
|
pascal@20538
|
247 #if defined(__BORLANDC__) && defined(NO386)
|
pascal@20538
|
248 #pragma option -3
|
pascal@20538
|
249 asm{
|
pascal@20538
|
250 .386p
|
pascal@20538
|
251 }
|
pascal@20538
|
252 #endif
|
pascal@19636
|
253 m->errmsg = "Can't use initrd file";
|
pascal@19636
|
254
|
pascal@21649
|
255 open_image(m, initrd_name);
|
pascal@19636
|
256
|
pascal@20542
|
257 if ((m->fallback=(memtop()-m->size)&(~PAGE_MASK))-m[-1].fallback < m[-1].size) {
|
pascal@19636
|
258 close(m->fd);
|
pascal@19538
|
259 puts(m->errmsg);
|
pascal@19515
|
260 return;
|
pascal@19515
|
261 }
|
pascal@19515
|
262
|
pascal@19515
|
263 load_image(m);
|
pascal@20634
|
264
|
pascal@20634
|
265 struct initrdparams_t *initrdparams = ((struct initrdparams_t *)&(((first1k_t*) _rm_buf(m-1))->params.header));
|
pascal@20634
|
266 if(initrdparams->header == HdrS) {
|
pascal@20634
|
267 initrdparams->initrd_buf = m->fallback;
|
pascal@20634
|
268 initrdparams->initrd_size = m->size;
|
pascal@19515
|
269 }
|
pascal@19515
|
270 }
|