wok view syslinux/stuff/iso2exe/bootlinux.c @ rev 16515

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