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

syslinux/iso2exe: fix cmdline
author Pascal Bellard <pascal.bellard@slitaz.org>
date Fri Mar 07 10:50:10 2014 +0000 (2014-03-07)
parents 592369f78d12
children 8cf93f4aedd1
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 SETUP_SEGMENT 0x9000
23 #define CMDLINE_OFFSET 0x9E00
25 #define PAGE_BITS 12
26 #define PAGE_SIZE 4096
27 #define BUFFERSZ 2048 // lower than min setup
28 static char buffer[BUFFERSZ];
29 static unsigned long initrd_addr = 0, initrd_size;
31 static int may_exit_dos = 1;
32 static void die(char *msg)
33 {
34 printf("%s.\n", msg);
35 if (may_exit_dos)
36 exit(1);
37 while (1);
38 }
40 static int vm86(void)
41 {
42 #asm
43 smsw ax
44 and ax, #1 // 0:realmode 1:vm86
45 #endasm
46 }
48 static struct {
49 unsigned long base;
50 int align;
51 } mem = { 0x100000, 0 };
53 static void movehi(void)
54 {
55 #asm
56 pusha
57 xor di, di // 30
58 mov cx, #9 // 2E..1E
59 zero1:
60 push di
61 loop zero1
62 push dword [_mem] // 1A mem.base
63 push #-1 // 18
64 push di // 16
65 xor eax, eax
66 cdq
67 mov dx, ds
68 shl edx, #4
69 mov ax, #_buffer
70 add edx, eax
71 push edx // 12 linear_address(buffer)
72 push #-1 // 10
73 mov cl, #8 // 0E..00
74 zero2:
75 push di
76 loop zero2
77 mov ch, #BUFFERSZ/512
78 push ss
79 pop es
80 mov si, sp
81 mov ax, #0x8793
82 mov [si+0x15], al
83 xchg [si+0x1D], al
84 xchg [si+0x1F], al // bits 24..31
85 int 0x15
86 add sp, #0x30
87 popa
88 #endasm
89 }
91 #define ZIMAGE_SUPPORT
93 #ifdef ZIMAGE_SUPPORT
94 static int zimage = 0;
95 static unsigned zimage_base;
96 static unsigned getss(void)
97 {
98 #asm
99 mov ax, ss
100 #endasm
101 }
102 #endif
104 static int versiondos;
105 static int dosversion(void)
106 {
107 #asm
108 mov ah, #0x30
109 int 0x21
110 cbw
111 mov _versiondos, ax
112 #endasm
113 }
115 static unsigned extendedramsizeinkb(void)
116 {
117 #asm
118 mov ah, #0x88
119 int 0x15
120 jnc gottop
121 xor ax, ax
122 gottop:
123 #endasm
124 }
126 static void load(unsigned long size)
127 {
128 if (vm86())
129 die("Need real mode");
130 switch (mem.align) {
131 case 0: // kernel
132 switch (dosversion()) {
133 case 3: case 4: case 6: case 7: break;
134 default:
135 printf("DOS %d not supported.\nTrying anyway...\n",
136 versiondos);
137 }
138 mem.align = PAGE_SIZE;
139 break;
140 case PAGE_SIZE: // first initrd : keep 16M..48M for the kernel
141 if (extendedramsizeinkb() > 0xF000U && mem.base < 0x3000000)
142 mem.base = 0x3000000;
143 initrd_addr = mem.base;
144 mem.align = 4;
145 }
146 while (size) {
147 int n, s = sizeof(buffer);
148 for (n = 0; n < s; n++) buffer[n] = 0;
149 if (s > size) s = size;
150 if ((n = isoread(buffer, s)) < 0) break;
151 movehi();
152 mem.base += n;
153 size -= n;
154 if (s != n) break; // end of file
155 }
156 initrd_size = mem.base - initrd_addr;
157 mem.base += mem.align - 1;
158 mem.base &= - mem.align;
159 }
161 static unsigned setupofs = 0;
163 void movesetup(void)
164 {
165 #asm
166 pusha
167 push #SETUP_SEGMENT
168 pop es
169 mov si, #_buffer
170 mov di, _setupofs
171 mov cx, #BUFFERSZ/2
172 rep
173 movsw
174 mov _setupofs, di
175 popa
176 #endasm
177 }
179 static unsigned getcs(void)
180 {
181 #asm
182 mov ax, cs
183 #endasm
184 }
186 unsigned long loadkernel(void)
187 {
188 unsigned setup, n = BUFFERSZ;
189 unsigned long syssize = 0, kernel_version = 0;
191 do {
192 isoread(buffer, n);
193 if (setupofs == 0) {
194 if (* (unsigned short *) (buffer + BOOTFLAG) != 0xAA55)
195 die("The kernel is not bootable");
196 setup = (1 + buffer[SETUPSECTORS]) << 9;
197 if (setup == 512) setup = 5 << 9;
198 syssize = * (unsigned long *) (buffer + SYSSIZE) << 4;
199 setup_version = * (unsigned short *) (buffer + VERSION);
200 #define HDRS 0x53726448
201 if (* (unsigned long *) (buffer + HEADER) != HDRS)
202 setup_version = 0;
203 if (setup_version < 0x204)
204 syssize &= 0x000FFFFFUL;
205 if (setup_version) {
206 #ifdef REALMODE_SWITCH
207 extern int far_realmode_switch();
208 #asm
209 jmp end_realmode_switch
210 _far_realmode_switch:
211 call REALMODE_SWITCH
212 cli
213 mov al, #0x80 // Disable NMI
214 out 0x70, al
215 retf
216 end_realmode_switch:
217 #endasm
218 * (unsigned short *) (buffer + RMSWOFS) =
219 far_realmode_switch;
220 * (unsigned short *) (buffer + RMSWSEG) =
221 getcs();
222 #endif
223 mem.base =
224 * (unsigned long *) (buffer + SYSTEMCODE);
225 * (unsigned short *) (buffer + HEAPPTR) =
226 0x9B00;
227 // buffer[LOADFLAGS] |= 0x80;
228 * (unsigned short *) (buffer + LOADERTYPE) |=
229 0x80FF;
230 }
231 if (!setup_version || !(buffer[LOADFLAGS] & 1)) {
232 #ifdef ZIMAGE_SUPPORT
233 zimage = 1;
234 zimage_base = getss() + 0x1000L;
235 mem.base = zimage_base * 16L;
236 if (mem.base + syssize > SETUP_SEGMENT*16L - 32)
237 die("Out of memory");
238 #else
239 die("Not a bzImage format");
240 #endif
241 }
242 }
243 movesetup();
244 setup -= n;
245 n = (setup > BUFFERSZ) ? BUFFERSZ : setup;
246 } while (setup > 0);
248 #asm
249 push ds
250 push #SETUP_SEGMENT
251 pop ds
252 mov si, #0x200
253 mov eax, #0x53726448 // HdrS
254 cdq // clear edx
255 cmp [si+2], eax
256 jne noversion
257 add si, [si+14]
258 mov cx, #3
259 xor ax, ax
260 nextdigit:
261 shl al, #4
262 shl ax, #4
263 next:
264 lodsb
265 sub al, #0x30
266 cmp al, #9
267 jbe nextdigit
268 shl eax, #16
269 shld edx, eax, #8
270 loop next
271 pop ds
272 mov .loadkernel.kernel_version[bp], edx
273 push ds
274 noversion:
275 pop ds
276 #endasm
277 load(syssize);
278 return kernel_version;
279 }
281 void loadinitrd(void)
282 {
283 if (setup_version && zimage == 0)
284 load(isofilesize);
285 }
287 void bootlinux(char *cmdline)
288 {
289 #asm
290 push #SETUP_SEGMENT
291 pop es
292 #endasm
293 if (cmdline) {
294 if (setup_version <= 0x201) {
295 #asm
296 mov di, #0x0020
297 mov ax, #0xA33F
298 stosw
299 mov ax, #CMDLINE_OFFSET
300 stosw
301 #endasm
302 }
303 else {
304 #asm
305 mov di, #0x0228
306 mov eax, #SETUP_SEGMENT*16+CMDLINE_OFFSET
307 stosd
308 #endasm
309 }
310 #asm
311 xchg ax, di
312 mov si, .bootlinux.cmdline[bp]
313 copy:
314 lodsb
315 stosb
316 or al,al
317 jne copy
318 #endasm
319 }
320 if (setup_version >= 0x200) {
321 #asm
322 mov eax, _initrd_addr
323 mov di, #0x218
324 stosd
325 mov eax, _initrd_size
326 stosd
327 #endasm
328 }
329 #asm
330 push es
331 pop ss
332 mov sp, #CMDLINE_OFFSET
333 #endasm
334 #ifdef ZIMAGE_SUPPORT
335 if (zimage) {
336 #asm
337 mov eax, _mem
338 shr eax, #4 // top
339 mov bx, _zimage_base
340 mov dx, #0x1000
341 push cs
342 pop ds
343 mov es, ax
344 push es
345 mov si, #sysmove
346 xor di, di
347 push di
348 mov cx, #endsysmove-sysmove
349 rep
350 movsb
351 retf
352 sysmove:
353 mov ds, bx
354 mov es, dx
355 xor di, di
356 xor si, si
357 mov cl, #8
358 rep
359 movsw
360 inc bx
361 inc dx
362 cmp ax,bx
363 jne sysmove
364 #endasm
365 }
366 #endif
367 #asm
368 push ss
369 pop ds
370 push ds
371 pop es
372 jmpi 0, #0x9020
373 endsysmove:
374 #endasm
375 }