wok-next view syslinux/stuff/iso2exe/bootlinux.c @ rev 16055

syslinux/iso2exe: fix 'a la tazusb' install
author Pascal Bellard <pascal.bellard@slitaz.org>
date Tue Mar 11 15:44:47 2014 +0000 (2014-03-11)
parents d814ca840c3c
children 3865e09ec026
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 unsigned zimage = 0;
95 static unsigned getss(void)
96 {
97 #asm
98 mov ax, ss
99 #endasm
100 }
101 #endif
103 static int versiondos;
104 static int dosversion(void)
105 {
106 #asm
107 mov ah, #0x30
108 int 0x21
109 cbw
110 mov _versiondos, ax
111 #endasm
112 }
114 static unsigned extendedramsizeinkb(void)
115 {
116 #asm
117 mov ah, #0x88
118 int 0x15
119 jnc gottop
120 xor ax, ax
121 gottop:
122 #endasm
123 }
125 static void load(unsigned long size)
126 {
127 if (vm86())
128 die("Need real mode");
129 switch (mem.align) {
130 case 0: // kernel
131 switch (dosversion()) {
132 case 3: case 4: case 6: case 7: break;
133 default:
134 printf("DOS %d not supported.\nTrying anyway...\n",
135 versiondos);
136 }
137 mem.align = PAGE_SIZE;
138 break;
139 case PAGE_SIZE: // first initrd : keep 16M..48M for the kernel
140 if (extendedramsizeinkb() > 0xF000U && mem.base < 0x3000000)
141 mem.base = 0x3000000;
142 initrd_addr = mem.base;
143 mem.align = 4;
144 }
145 while (size) {
146 int n, s = sizeof(buffer);
147 for (n = 0; n < s; n++) buffer[n] = 0;
148 if (s > size) s = size;
149 if ((n = isoread(buffer, s)) < 0) break;
150 movehi();
151 mem.base += n;
152 size -= n;
153 if (s != n) break; // end of file
154 }
155 initrd_size = mem.base - initrd_addr;
156 mem.base += mem.align - 1;
157 mem.base &= - mem.align;
158 }
160 static unsigned setupofs = 0;
162 void movesetup(void)
163 {
164 #asm
165 pusha
166 push #SETUP_SEGMENT
167 pop es
168 mov si, #_buffer
169 mov di, _setupofs
170 mov cx, #BUFFERSZ/2
171 rep
172 movsw
173 mov _setupofs, di
174 popa
175 #endasm
176 }
178 static unsigned getcs(void)
179 {
180 #asm
181 mov ax, cs
182 #endasm
183 }
185 unsigned long loadkernel(void)
186 {
187 unsigned setup, n = BUFFERSZ;
188 unsigned long syssize = 0, kernel_version = 0;
190 do {
191 isoread(buffer, n);
192 if (setupofs == 0) {
193 if (* (unsigned short *) (buffer + BOOTFLAG) != 0xAA55)
194 die("The kernel is not bootable");
195 setup = (1 + buffer[SETUPSECTORS]) << 9;
196 if (setup == 512) setup = 5 << 9;
197 syssize = * (unsigned long *) (buffer + SYSSIZE) << 4;
198 setup_version = * (unsigned short *) (buffer + VERSION);
199 #define HDRS 0x53726448
200 if (* (unsigned long *) (buffer + HEADER) != HDRS)
201 setup_version = 0;
202 if (setup_version < 0x204)
203 syssize &= 0x000FFFFFUL;
204 if (setup_version) {
205 #ifdef REALMODE_SWITCH
206 extern int far_realmode_switch();
207 #asm
208 jmp end_realmode_switch
209 _far_realmode_switch:
210 call REALMODE_SWITCH
211 cli
212 mov al, #0x80 // Disable NMI
213 out 0x70, al
214 retf
215 end_realmode_switch:
216 #endasm
217 * (unsigned short *) (buffer + RMSWOFS) =
218 far_realmode_switch;
219 * (unsigned short *) (buffer + RMSWSEG) =
220 getcs();
221 #endif
222 mem.base =
223 * (unsigned long *) (buffer + SYSTEMCODE);
224 * (unsigned short *) (buffer + HEAPPTR) =
225 0x9B00;
226 // buffer[LOADFLAGS] |= 0x80;
227 * (unsigned short *) (buffer + LOADERTYPE) |=
228 0x80FF;
229 }
230 if (!setup_version || !(buffer[LOADFLAGS] & 1)) {
231 #ifdef ZIMAGE_SUPPORT
232 zimage = getss() + 0x1000;
233 mem.base = zimage * 16L;
234 if (mem.base + syssize > SETUP_SEGMENT*16L - 32)
235 die("Out of memory");
236 #else
237 die("Not a bzImage format");
238 #endif
239 }
240 }
241 movesetup();
242 setup -= n;
243 n = (setup > BUFFERSZ) ? BUFFERSZ : setup;
244 } while (setup > 0);
246 #asm
247 push ds
248 push #SETUP_SEGMENT
249 pop ds
250 mov si, #0x200
251 mov eax, #0x53726448 // HdrS
252 cdq // clear edx
253 cmp [si+2], eax
254 jne noversion
255 add si, [si+14]
256 mov cx, #3
257 xor ax, ax
258 nextdigit:
259 shl al, #4
260 shl ax, #4
261 next:
262 lodsb
263 sub al, #0x30
264 cmp al, #9
265 jbe nextdigit
266 shl eax, #16
267 shld edx, eax, #8
268 loop next
269 pop ds
270 mov .loadkernel.kernel_version[bp], edx
271 push ds
272 noversion:
273 pop ds
274 #endasm
275 load(syssize);
276 return kernel_version;
277 }
279 void loadinitrd(void)
280 {
281 if (setup_version && zimage == 0)
282 load(isofilesize);
283 }
285 void bootlinux(char *cmdline)
286 {
287 #asm
288 push #SETUP_SEGMENT
289 pop es
290 #endasm
291 if (cmdline) {
292 if (setup_version <= 0x201) {
293 #asm
294 mov di, #0x0020
295 mov ax, #0xA33F
296 stosw
297 mov ax, #CMDLINE_OFFSET
298 stosw
299 #endasm
300 }
301 else {
302 #asm
303 mov di, #0x0228
304 mov eax, #SETUP_SEGMENT*16+CMDLINE_OFFSET
305 stosd
306 #endasm
307 }
308 #asm
309 xchg ax, di
310 mov si, .bootlinux.cmdline[bp]
311 copy:
312 lodsb
313 stosb
314 or al,al
315 jne copy
316 #endasm
317 }
318 if (setup_version >= 0x200) {
319 #asm
320 mov eax, _initrd_addr
321 mov di, #0x218
322 stosd
323 mov eax, _initrd_size
324 stosd
325 #endasm
326 }
327 #asm
328 push es
329 pop ss
330 mov sp, #CMDLINE_OFFSET
331 #endasm
332 #ifdef ZIMAGE_SUPPORT
333 #asm
334 mov bx, _zimage
335 or bx, bx
336 jz notzimage
337 mov eax, _mem
338 shr eax, #4 // top
339 mov dx, #0x1000
340 push cs
341 pop ds
342 mov es, ax
343 push es
344 mov si, #sysmove
345 xor di, di
346 push di
347 mov cx, #endsysmove-sysmove
348 rep
349 movsb
350 retf
351 sysmove:
352 mov ds, bx
353 mov es, dx
354 xor di, di
355 xor si, si
356 mov cl, #8
357 rep
358 movsw
359 inc bx
360 inc dx
361 cmp ax,bx
362 jne sysmove
363 notzimage:
364 #endasm
365 #endif
366 #asm
367 push ss
368 pop ds
369 push ds
370 pop es
371 jmpi 0, #0x9020
372 endsysmove:
373 #endasm
374 }