rev |
line source |
pascal@13691
|
1 #include <stdio.h>
|
pascal@13691
|
2 #include "iso9660.h"
|
pascal@13691
|
3
|
pascal@16022
|
4 static unsigned setup_version;
|
pascal@13691
|
5 #define SETUPSECTORS 0x1F1
|
pascal@13691
|
6 #define ROFLAG 0x1F2
|
pascal@13691
|
7 #define SYSSIZE 0x1F4
|
pascal@13691
|
8 #define VIDEOMODE 0x1FA
|
pascal@13691
|
9 #define BOOTFLAG 0x1FE
|
pascal@13691
|
10 #define HEADER 0x202
|
pascal@13691
|
11 #define VERSION 0x206
|
pascal@13691
|
12 #define RMSWOFS 0x208
|
pascal@13691
|
13 #define RMSWSEG 0x20A
|
pascal@13691
|
14 #define LOADERTYPE 0x210
|
pascal@13691
|
15 #define LOADFLAGS 0x211
|
pascal@13691
|
16 #define SYSTEMCODE 0x214
|
pascal@13691
|
17 #define INITRDCODE 0x218
|
pascal@13691
|
18 #define INITRDSIZE 0x21C
|
pascal@13691
|
19 #define HEAPPTR 0x224
|
pascal@13691
|
20 #define CMDLINE 0x228
|
pascal@13691
|
21
|
pascal@16069
|
22 #define SYSTEM_SEGMENT 0x1000
|
pascal@13691
|
23 #define SETUP_SEGMENT 0x9000
|
pascal@13691
|
24 #define CMDLINE_OFFSET 0x9E00
|
pascal@16069
|
25 #define SETUP_END 0x8200
|
pascal@13691
|
26
|
pascal@13733
|
27 #define PAGE_BITS 12
|
pascal@13733
|
28 #define PAGE_SIZE 4096
|
pascal@16025
|
29 #define BUFFERSZ 2048 // lower than min setup
|
pascal@13691
|
30 static char buffer[BUFFERSZ];
|
pascal@16022
|
31 static unsigned long initrd_addr = 0, initrd_size;
|
pascal@13691
|
32
|
pascal@13691
|
33 static int may_exit_dos = 1;
|
pascal@13691
|
34 static void die(char *msg)
|
pascal@13691
|
35 {
|
pascal@13691
|
36 printf("%s.\n", msg);
|
pascal@13691
|
37 if (may_exit_dos)
|
pascal@13691
|
38 exit(1);
|
pascal@13691
|
39 while (1);
|
pascal@13691
|
40 }
|
pascal@13691
|
41
|
pascal@13691
|
42 static int vm86(void)
|
pascal@13691
|
43 {
|
pascal@13691
|
44 #asm
|
pascal@13691
|
45 smsw ax
|
pascal@13691
|
46 and ax, #1 // 0:realmode 1:vm86
|
pascal@13691
|
47 #endasm
|
pascal@13691
|
48 }
|
pascal@13691
|
49
|
pascal@16022
|
50 static struct {
|
pascal@13691
|
51 unsigned long base;
|
pascal@13691
|
52 int align;
|
pascal@16022
|
53 } mem = { 0x100000, 0 };
|
pascal@13691
|
54
|
pascal@13691
|
55 static void movehi(void)
|
pascal@13691
|
56 {
|
pascal@13691
|
57 #asm
|
pascal@13691
|
58 pusha
|
pascal@13691
|
59 xor di, di // 30
|
pascal@13691
|
60 mov cx, #9 // 2E..1E
|
pascal@13691
|
61 zero1:
|
pascal@13691
|
62 push di
|
pascal@13691
|
63 loop zero1
|
pascal@16022
|
64 push dword [_mem] // 1A mem.base
|
pascal@13691
|
65 push #-1 // 18
|
pascal@13691
|
66 push di // 16
|
pascal@13691
|
67 xor eax, eax
|
pascal@13691
|
68 cdq
|
pascal@13691
|
69 mov dx, ds
|
pascal@13691
|
70 shl edx, #4
|
pascal@13691
|
71 mov ax, #_buffer
|
pascal@13691
|
72 add edx, eax
|
pascal@13691
|
73 push edx // 12 linear_address(buffer)
|
pascal@13691
|
74 push #-1 // 10
|
pascal@13691
|
75 mov cl, #8 // 0E..00
|
pascal@13691
|
76 zero2:
|
pascal@13691
|
77 push di
|
pascal@13691
|
78 loop zero2
|
pascal@13691
|
79 mov ch, #BUFFERSZ/512
|
pascal@13691
|
80 push ss
|
pascal@13691
|
81 pop es
|
pascal@13691
|
82 mov si, sp
|
pascal@13691
|
83 mov ax, #0x8793
|
pascal@13691
|
84 mov [si+0x15], al
|
pascal@13691
|
85 xchg [si+0x1D], al
|
pascal@16008
|
86 xchg [si+0x1F], al // bits 24..31
|
pascal@13691
|
87 int 0x15
|
pascal@13691
|
88 add sp, #0x30
|
pascal@13691
|
89 popa
|
pascal@13691
|
90 #endasm
|
pascal@13691
|
91 }
|
pascal@13691
|
92
|
pascal@16022
|
93 #define ZIMAGE_SUPPORT
|
pascal@16022
|
94
|
pascal@16022
|
95 #ifdef ZIMAGE_SUPPORT
|
pascal@16041
|
96 static unsigned zimage = 0;
|
pascal@16069
|
97 #ifndef FULL_ZIMAGE
|
pascal@16022
|
98 static unsigned getss(void)
|
pascal@16022
|
99 {
|
pascal@16022
|
100 #asm
|
pascal@16022
|
101 mov ax, ss
|
pascal@16022
|
102 #endasm
|
pascal@16022
|
103 }
|
pascal@16022
|
104 #endif
|
pascal@16069
|
105 #endif
|
pascal@13733
|
106
|
pascal@13699
|
107 static int versiondos;
|
pascal@13699
|
108 static int dosversion(void)
|
pascal@13699
|
109 {
|
pascal@13699
|
110 #asm
|
pascal@13699
|
111 mov ah, #0x30
|
pascal@13699
|
112 int 0x21
|
pascal@13699
|
113 cbw
|
pascal@13699
|
114 mov _versiondos, ax
|
pascal@13699
|
115 #endasm
|
pascal@13699
|
116 }
|
pascal@13699
|
117
|
pascal@15981
|
118 static unsigned extendedramsizeinkb(void)
|
pascal@15981
|
119 {
|
pascal@15981
|
120 #asm
|
pascal@15981
|
121 mov ah, #0x88
|
pascal@15981
|
122 int 0x15
|
pascal@15981
|
123 jnc gottop
|
pascal@15981
|
124 xor ax, ax
|
pascal@15981
|
125 gottop:
|
pascal@15981
|
126 #endasm
|
pascal@15981
|
127 }
|
pascal@15981
|
128
|
pascal@16069
|
129
|
pascal@16069
|
130 #include "a20.c"
|
pascal@16069
|
131
|
pascal@16022
|
132 static void load(unsigned long size)
|
pascal@13691
|
133 {
|
pascal@13691
|
134 if (vm86())
|
pascal@13691
|
135 die("Need real mode");
|
pascal@16022
|
136 switch (mem.align) {
|
pascal@13691
|
137 case 0: // kernel
|
pascal@16069
|
138 if ((unsigned) (dosversion() - 3) > 7 - 3) {
|
pascal@13699
|
139 printf("DOS %d not supported.\nTrying anyway...\n",
|
pascal@13699
|
140 versiondos);
|
pascal@13699
|
141 }
|
pascal@16022
|
142 mem.align = PAGE_SIZE;
|
pascal@13691
|
143 break;
|
pascal@16008
|
144 case PAGE_SIZE: // first initrd : keep 16M..48M for the kernel
|
pascal@16022
|
145 if (extendedramsizeinkb() > 0xF000U && mem.base < 0x3000000)
|
pascal@16022
|
146 mem.base = 0x3000000;
|
pascal@16022
|
147 initrd_addr = mem.base;
|
pascal@16022
|
148 mem.align = 4;
|
pascal@13691
|
149 }
|
pascal@16069
|
150 #ifdef ALLOCMEM
|
pascal@16069
|
151 ALLOCMEM(size);
|
pascal@16069
|
152 #endif
|
pascal@13691
|
153 while (size) {
|
pascal@13691
|
154 int n, s = sizeof(buffer);
|
pascal@13691
|
155 for (n = 0; n < s; n++) buffer[n] = 0;
|
pascal@13691
|
156 if (s > size) s = size;
|
pascal@16022
|
157 if ((n = isoread(buffer, s)) < 0) break;
|
pascal@13691
|
158 movehi();
|
pascal@16022
|
159 mem.base += n;
|
pascal@16022
|
160 size -= n;
|
pascal@16022
|
161 if (s != n) break; // end of file
|
pascal@13691
|
162 }
|
pascal@16022
|
163 initrd_size = mem.base - initrd_addr;
|
pascal@16022
|
164 mem.base += mem.align - 1;
|
pascal@16022
|
165 mem.base &= - mem.align;
|
pascal@13691
|
166 }
|
pascal@13691
|
167
|
pascal@13691
|
168 static unsigned setupofs = 0;
|
pascal@13691
|
169
|
pascal@13691
|
170 void movesetup(void)
|
pascal@13691
|
171 {
|
pascal@13691
|
172 #asm
|
pascal@13691
|
173 pusha
|
pascal@13691
|
174 push #SETUP_SEGMENT
|
pascal@13691
|
175 pop es
|
pascal@13691
|
176 mov si, #_buffer
|
pascal@13691
|
177 mov di, _setupofs
|
pascal@13691
|
178 mov cx, #BUFFERSZ/2
|
pascal@13691
|
179 rep
|
pascal@13691
|
180 movsw
|
pascal@13691
|
181 mov _setupofs, di
|
pascal@13691
|
182 popa
|
pascal@13691
|
183 #endasm
|
pascal@13691
|
184 }
|
pascal@13691
|
185
|
pascal@14257
|
186 static unsigned getcs(void)
|
pascal@14257
|
187 {
|
pascal@14257
|
188 #asm
|
pascal@14257
|
189 mov ax, cs
|
pascal@14257
|
190 #endasm
|
pascal@14257
|
191 }
|
pascal@14257
|
192
|
pascal@14257
|
193 unsigned long loadkernel(void)
|
pascal@13691
|
194 {
|
pascal@13691
|
195 unsigned setup, n = BUFFERSZ;
|
pascal@14268
|
196 unsigned long syssize = 0, kernel_version = 0;
|
pascal@13691
|
197
|
pascal@13691
|
198 do {
|
pascal@13691
|
199 isoread(buffer, n);
|
pascal@13691
|
200 if (setupofs == 0) {
|
pascal@13691
|
201 if (* (unsigned short *) (buffer + BOOTFLAG) != 0xAA55)
|
pascal@13691
|
202 die("The kernel is not bootable");
|
pascal@13691
|
203 setup = (1 + buffer[SETUPSECTORS]) << 9;
|
pascal@13691
|
204 if (setup == 512) setup = 5 << 9;
|
pascal@13691
|
205 syssize = * (unsigned long *) (buffer + SYSSIZE) << 4;
|
pascal@16022
|
206 setup_version = * (unsigned short *) (buffer + VERSION);
|
pascal@13691
|
207 #define HDRS 0x53726448
|
pascal@13691
|
208 if (* (unsigned long *) (buffer + HEADER) != HDRS)
|
pascal@16022
|
209 setup_version = 0;
|
pascal@16022
|
210 if (setup_version < 0x204)
|
pascal@13733
|
211 syssize &= 0x000FFFFFUL;
|
pascal@16022
|
212 if (setup_version) {
|
pascal@13733
|
213 #ifdef REALMODE_SWITCH
|
pascal@13733
|
214 extern int far_realmode_switch();
|
pascal@13733
|
215 #asm
|
pascal@13733
|
216 jmp end_realmode_switch
|
pascal@13733
|
217 _far_realmode_switch:
|
pascal@14257
|
218 call REALMODE_SWITCH
|
pascal@13733
|
219 cli
|
pascal@13733
|
220 mov al, #0x80 // Disable NMI
|
pascal@13733
|
221 out 0x70, al
|
pascal@13733
|
222 retf
|
pascal@13733
|
223 end_realmode_switch:
|
pascal@13733
|
224 #endasm
|
pascal@13733
|
225 * (unsigned short *) (buffer + RMSWOFS) =
|
pascal@13733
|
226 far_realmode_switch;
|
pascal@13733
|
227 * (unsigned short *) (buffer + RMSWSEG) =
|
pascal@13733
|
228 getcs();
|
pascal@13733
|
229 #endif
|
pascal@16022
|
230 mem.base =
|
pascal@13733
|
231 * (unsigned long *) (buffer + SYSTEMCODE);
|
pascal@13733
|
232 * (unsigned short *) (buffer + HEAPPTR) =
|
pascal@13733
|
233 0x9B00;
|
pascal@13733
|
234 // buffer[LOADFLAGS] |= 0x80;
|
pascal@13733
|
235 * (unsigned short *) (buffer + LOADERTYPE) |=
|
pascal@13733
|
236 0x80FF;
|
pascal@13733
|
237 }
|
pascal@16022
|
238 if (!setup_version || !(buffer[LOADFLAGS] & 1)) {
|
pascal@13691
|
239 #ifdef ZIMAGE_SUPPORT
|
pascal@16069
|
240 #ifndef FULL_ZIMAGE
|
pascal@16041
|
241 zimage = getss() + 0x1000;
|
pascal@16041
|
242 mem.base = zimage * 16L;
|
pascal@16022
|
243 if (mem.base + syssize > SETUP_SEGMENT*16L - 32)
|
pascal@16022
|
244 die("Out of memory");
|
pascal@16022
|
245 #else
|
pascal@16069
|
246 zimage = 0x11;
|
pascal@16069
|
247 mem.base = 0x110000L; // 1M + 64K HMA
|
pascal@16069
|
248
|
pascal@16069
|
249 #endif
|
pascal@16069
|
250 #else
|
pascal@16022
|
251 die("Not a bzImage format");
|
pascal@13691
|
252 #endif
|
pascal@13691
|
253 }
|
pascal@13691
|
254 }
|
pascal@13691
|
255 movesetup();
|
pascal@13691
|
256 setup -= n;
|
pascal@13691
|
257 n = (setup > BUFFERSZ) ? BUFFERSZ : setup;
|
pascal@13691
|
258 } while (setup > 0);
|
pascal@13691
|
259
|
pascal@14257
|
260 #asm
|
pascal@14257
|
261 push ds
|
pascal@14257
|
262 push #SETUP_SEGMENT
|
pascal@14257
|
263 pop ds
|
pascal@14257
|
264 mov si, #0x200
|
pascal@14257
|
265 mov eax, #0x53726448 // HdrS
|
pascal@14257
|
266 cdq // clear edx
|
pascal@14257
|
267 cmp [si+2], eax
|
pascal@14257
|
268 jne noversion
|
pascal@14257
|
269 add si, [si+14]
|
pascal@14257
|
270 mov cx, #3
|
pascal@14257
|
271 xor ax, ax
|
pascal@14257
|
272 nextdigit:
|
pascal@14264
|
273 shl al, #4
|
pascal@14264
|
274 shl ax, #4
|
pascal@14257
|
275 next:
|
pascal@14257
|
276 lodsb
|
pascal@14257
|
277 sub al, #0x30
|
pascal@14257
|
278 cmp al, #9
|
pascal@14257
|
279 jbe nextdigit
|
pascal@14264
|
280 shl eax, #16
|
pascal@14264
|
281 shld edx, eax, #8
|
pascal@14257
|
282 loop next
|
pascal@14257
|
283 pop ds
|
pascal@14268
|
284 mov .loadkernel.kernel_version[bp], edx
|
pascal@16022
|
285 push ds
|
pascal@14257
|
286 noversion:
|
pascal@16022
|
287 pop ds
|
pascal@14257
|
288 #endasm
|
pascal@16022
|
289 load(syssize);
|
pascal@14268
|
290 return kernel_version;
|
pascal@13691
|
291 }
|
pascal@13691
|
292
|
pascal@13691
|
293 void loadinitrd(void)
|
pascal@13691
|
294 {
|
pascal@16022
|
295 if (setup_version && zimage == 0)
|
pascal@16022
|
296 load(isofilesize);
|
pascal@13691
|
297 }
|
pascal@13691
|
298
|
pascal@13691
|
299 void bootlinux(char *cmdline)
|
pascal@13691
|
300 {
|
pascal@13691
|
301 #asm
|
pascal@13691
|
302 push #SETUP_SEGMENT
|
pascal@13691
|
303 pop es
|
pascal@13691
|
304 #endasm
|
pascal@13691
|
305 if (cmdline) {
|
pascal@16022
|
306 if (setup_version <= 0x201) {
|
pascal@13691
|
307 #asm
|
pascal@13691
|
308 mov di, #0x0020
|
pascal@13691
|
309 mov ax, #0xA33F
|
pascal@13691
|
310 stosw
|
pascal@13691
|
311 mov ax, #CMDLINE_OFFSET
|
pascal@13691
|
312 stosw
|
pascal@13691
|
313 #endasm
|
pascal@13691
|
314 }
|
pascal@13691
|
315 else {
|
pascal@13691
|
316 #asm
|
pascal@13691
|
317 mov di, #0x0228
|
pascal@13691
|
318 mov eax, #SETUP_SEGMENT*16+CMDLINE_OFFSET
|
pascal@13691
|
319 stosd
|
pascal@13691
|
320 #endasm
|
pascal@13691
|
321 }
|
pascal@13691
|
322 #asm
|
pascal@13691
|
323 xchg ax, di
|
pascal@13691
|
324 mov si, .bootlinux.cmdline[bp]
|
pascal@13691
|
325 copy:
|
pascal@13691
|
326 lodsb
|
pascal@13691
|
327 stosb
|
pascal@13691
|
328 or al,al
|
pascal@13691
|
329 jne copy
|
pascal@13691
|
330 #endasm
|
pascal@13691
|
331 }
|
pascal@16025
|
332 if (setup_version >= 0x200) {
|
pascal@16025
|
333 #asm
|
pascal@16025
|
334 mov eax, _initrd_addr
|
pascal@16025
|
335 mov di, #0x218
|
pascal@16025
|
336 stosd
|
pascal@16025
|
337 mov eax, _initrd_size
|
pascal@16025
|
338 stosd
|
pascal@16025
|
339 #endasm
|
pascal@16025
|
340 }
|
pascal@16025
|
341 #asm
|
pascal@16025
|
342 push es
|
pascal@16025
|
343 pop ss
|
pascal@16025
|
344 mov sp, #CMDLINE_OFFSET
|
pascal@16025
|
345 #endasm
|
pascal@16022
|
346 #ifdef ZIMAGE_SUPPORT
|
pascal@13691
|
347 #asm
|
pascal@16041
|
348 mov bx, _zimage
|
pascal@16041
|
349 or bx, bx
|
pascal@16041
|
350 jz notzimage
|
pascal@16022
|
351 mov eax, _mem
|
pascal@16069
|
352 #ifndef FULL_ZIMAGE
|
pascal@16022
|
353 shr eax, #4 // top
|
pascal@16069
|
354 mov dx, #SYSTEM_SEGMENT
|
pascal@16069
|
355 #else
|
pascal@16069
|
356 dec eax
|
pascal@16069
|
357 shr eax, #16
|
pascal@16069
|
358 inc ax
|
pascal@16069
|
359 mov dx, #SYSTEM_SEGMENT/0x1000
|
pascal@16069
|
360 #endif
|
pascal@16022
|
361 push cs
|
pascal@16022
|
362 pop ds
|
pascal@16069
|
363 push ss
|
pascal@16069
|
364 pop es
|
pascal@16022
|
365 push es
|
pascal@16022
|
366 mov si, #sysmove
|
pascal@16069
|
367 mov di, #SETUP_END
|
pascal@16022
|
368 push di
|
pascal@16022
|
369 mov cx, #endsysmove-sysmove
|
pascal@16069
|
370 cld
|
pascal@16022
|
371 rep
|
pascal@16022
|
372 movsb
|
pascal@16022
|
373 retf
|
pascal@16022
|
374 sysmove:
|
pascal@16069
|
375 #ifndef FULL_ZIMAGE
|
pascal@16022
|
376 mov ds, bx
|
pascal@16022
|
377 mov es, dx
|
pascal@16022
|
378 xor di, di
|
pascal@16022
|
379 xor si, si
|
pascal@16022
|
380 mov cl, #8
|
pascal@16022
|
381 rep
|
pascal@16022
|
382 movsw
|
pascal@16022
|
383 inc bx
|
pascal@16022
|
384 inc dx
|
pascal@16069
|
385 cmp ax, bx
|
pascal@16022
|
386 jne sysmove
|
pascal@16069
|
387 #else
|
pascal@16069
|
388 xchg ax, cx
|
pascal@16069
|
389 mov si, di
|
pascal@16069
|
390 push es
|
pascal@16069
|
391 pop ds
|
pascal@16069
|
392 push cx
|
pascal@16069
|
393 mov cx, #0x18
|
pascal@16069
|
394 rep
|
pascal@16069
|
395 stosw
|
pascal@16069
|
396 dec cx
|
pascal@16069
|
397 mov [si+0x10], cx
|
pascal@16069
|
398 mov [si+0x18], cx
|
pascal@16069
|
399 pop cx
|
pascal@16069
|
400 mov bh, #0x93
|
pascal@16069
|
401 mov dh, #0x93
|
pascal@16069
|
402 mvdown:
|
pascal@16069
|
403 mov [si+0x12+2], bx // srce
|
pascal@16069
|
404 mov [si+0x1A+2], dx // dest
|
pascal@16069
|
405 pusha
|
pascal@16069
|
406 mov cx, #0x8000
|
pascal@16069
|
407 mov ah, #0x87
|
pascal@16069
|
408 int 0x15 // catched by himem.sys: may need dos=high,umb
|
pascal@16069
|
409 popa
|
pascal@16069
|
410 inc bx
|
pascal@16069
|
411 inc dx
|
pascal@16069
|
412 cmp cl, bl
|
pascal@16069
|
413 jne mvdown
|
pascal@16069
|
414 #endif
|
pascal@16041
|
415 notzimage:
|
pascal@16022
|
416 #endasm
|
pascal@16022
|
417 #endif
|
pascal@16022
|
418 #asm
|
pascal@16022
|
419 push ss
|
pascal@13691
|
420 pop ds
|
pascal@13691
|
421 push ds
|
pascal@16022
|
422 pop es
|
pascal@13691
|
423 jmpi 0, #0x9020
|
pascal@16022
|
424 endsysmove:
|
pascal@13691
|
425 #endasm
|
pascal@13691
|
426 }
|