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

syslinux/iso2exe: check ISO md5
author Pascal Bellard <pascal.bellard@slitaz.org>
date Sat Jan 03 21:41:48 2015 +0100 (2015-01-03)
parents 6aed6fc5819d
children
line source
1 #include <stdio.h>
2 #include "libdos.h"
3 #include "iso9660.h"
4 #asm
5 use16 86
6 #endasm
8 #define ELKSSIG 0x1E6
9 #define SETUPSECTORS 0x1F1
10 #define ROFLAG 0x1F2
11 #define SYSSIZE 0x1F4
12 #define VIDEOMODE 0x1FA
13 #define BOOTFLAG 0x1FE
14 #define HEADER 0x202
15 #define VERSION 0x206
16 #define RMSWOFS 0x208
17 #define RMSWSEG 0x20A
18 #define LOADERTYPE 0x210
19 #define LOADFLAGS 0x211
20 #define SYSTEMCODE 0x214
21 #define INITRDCODE 0x218
22 #define INITRDSIZE 0x21C
23 #define HEAPPTR 0x224
24 #define CMDLINE 0x228
26 #define SYSTEM_SEGMENT 0x1000
27 #define SETUP_SEGMENT 0x9000
28 #define CMDLINE_OFFSET 0x9E00
29 #define SETUP_END 0x8200
31 #define PAGE_BITS 12
32 #define PAGE_SIZE 4096
33 #define BUFFERSZ 2048 // lower than min setup
34 static char buffer[BUFFERSZ];
35 static unsigned long initrd_addr = 0, initrd_size;
37 static int may_exit_dos = 1;
38 static void die(char *msg)
39 {
40 printf("%s.\n", msg);
41 if (may_exit_dos)
42 exit(1);
43 while (1);
44 }
46 static int iselks;
47 static int vm86(void)
48 {
49 #asm
50 mov ax, _iselks
51 dec ax
52 je fakerealmode // elks may run on a 8086
53 use16 286
54 smsw ax // 286+
55 and ax, #1 // 0:realmode 1:vm86
56 use16 86
57 fakerealmode:
58 #endasm
59 }
61 static struct {
62 unsigned long base;
63 int align;
64 } mem = { 0x100000, 0 };
66 #ifdef __MSDOS__
67 #define A20HOLDBUFFER 0x80000
68 static int a20buffer = 0;
69 #endif
71 static void movehi(void)
72 {
73 #asm
74 push si
75 push di
77 xor ax, ax
78 mov si, #_mem
79 cmp word ptr [si+2], #0x10
80 #ifdef __MSDOS__
81 jne nota20
82 mov ax, #A20HOLDBUFFER/16
83 mov _a20buffer, ax
84 mov di, [si] // mem.base & 0xFFFF
85 jmp mvbuffer
86 nota20:
87 #endif
88 jnc movehiz
89 lodsb
90 xchg ax, di
91 lodsw
92 mov cl, #4
93 shl ax, cl // 8086 support for elks
94 mvbuffer:
95 mov es, ax
96 mov si, #_buffer
97 cld
98 mov cx, #BUFFERSZ/2
99 rep
100 movw
101 jmp movedone
102 movehiz: // 30
103 use16 286 // more than 1Mb => 286+
104 mov cx, #9 // 2E..1E
105 zero1:
106 push ax
107 loop zero1
108 push word [si+2]
109 push word [si] // 1A mem.base
110 push #-1 // 18
111 push ax // 16
112 mov ax, ds
113 mov dx, ax
114 shl ax, #4
115 shr dx, #12
116 add ax, #_buffer
117 adc dx, #0
118 push dx
119 push ax
120 push #-1 // 10
121 mov cl, #8 // 0E..00
122 zero2:
123 push #0
124 loop zero2
125 mov ch, #BUFFERSZ/512
126 push ss
127 pop es
128 mov si, sp
129 mov ax, #0x8793
130 mov [si+0x15], al
131 xchg [si+0x1D], al
132 xchg [si+0x1F], al // bits 24..31
133 int 0x15
134 add sp, #0x30
135 use16 86
136 movedone:
137 pop di
138 pop si
139 #endasm
140 }
142 static unsigned vgamode, zimage = 0;
143 static unsigned getss(void)
144 {
145 #asm
146 mov ax, ss
147 #endasm
148 }
150 static unsigned extendedramsizeinkb(void)
151 {
152 #asm
153 mov ah, #0x88
154 int 0x15
155 jnc gottop
156 xor ax, ax
157 gottop:
158 #endasm
159 }
162 #include "a20.c"
164 static void load(unsigned long size)
165 {
166 if (vm86())
167 die("Need real mode");
168 switch (mem.align) {
169 case 0: // kernel
170 #ifdef __MSDOS__
171 if ((unsigned) (dosversion() - 3) > 7 - 3) {
172 printf("DOS %d not supported.\nTrying anyway...\n",
173 versiondos);
174 }
175 #endif
176 mem.align = PAGE_SIZE;
177 break;
178 case PAGE_SIZE: // first initrd : keep 16M..48M for the kernel
179 if (extendedramsizeinkb() > 0xF000U && mem.base < 0x3000000)
180 mem.base = 0x3000000;
181 initrd_addr = mem.base;
182 mem.align = 4;
183 }
184 #ifdef ALLOCMEM
185 ALLOCMEM(size);
186 #endif
187 while (size) {
188 int n, s = sizeof(buffer);
189 for (n = 0; n < s; n++) buffer[n] = 0;
190 if (s > size) s = size;
191 if ((n = isoread(buffer, s)) < 0) break;
192 movehi();
193 mem.base += n;
194 size -= n;
195 if (s != n) break; // end of file
196 }
197 initrd_size = mem.base - initrd_addr;
198 mem.base += mem.align - 1;
199 mem.base &= - mem.align;
200 }
202 static unsigned setupseg = SETUP_SEGMENT;
203 static unsigned setupofs = 0;
205 void movesetup(void)
206 {
207 #asm
208 push si
209 mov es, _setupseg
210 xchg di, _setupofs
211 mov si, #_buffer
212 cld
213 mov cx, #BUFFERSZ/2
214 rep
215 movsw
216 xchg di, _setupofs
217 pop si
218 #endasm
219 }
221 static unsigned getcs(void)
222 {
223 #asm
224 mov ax, cs
225 #endasm
226 }
228 #define WORD(x) * (unsigned short *) (x)
229 #define LONG(x) * (unsigned long *) (x)
230 static unsigned setup_version = 0;
231 static unsigned long kernel_version = 0;
232 unsigned long loadkernel(void)
233 {
234 unsigned setup;
235 #define LINUX001_SUPPORT
236 #ifdef LINUX001_SUPPORT
237 unsigned n = 512;
238 #else
239 unsigned n = BUFFERSZ;
240 #endif
241 unsigned long syssize = 0;
243 do {
244 isoread(buffer, n);
245 if (setupofs == 0) {
246 if (WORD(buffer + BOOTFLAG) != 0xAA55)
247 die("The kernel is not bootable");
248 #asm
249 int 0x12
250 jc has640k
251 dec ax
252 and al, #0xC0
253 mov cl, #6
254 shl ax, cl
255 cmp ax, _setupseg
256 jnc has640k
257 mov _setupseg, ax
258 has640k:
259 #endasm
260 syssize = LONG(buffer + SYSSIZE) << 4;
261 if (!syssize) syssize = 0x7F000;
262 setup = (1 + buffer[SETUPSECTORS]) << 9;
263 vgamode = WORD(buffer + VIDEOMODE);
264 if (setup == 512) {
265 #ifdef LINUX001_SUPPORT
266 if (WORD(buffer + 0x3F) == 0x3AE8) /* linux 0.01 */
267 goto linux001;
268 #endif
269 setup = 5 << 9;
270 }
271 #ifdef LINUX001_SUPPORT
272 n = BUFFERSZ;
273 isoread(buffer+512, BUFFERSZ-512);
274 #endif
275 #define HDRS 0x53726448
276 if (LONG(buffer + HEADER) == HDRS)
277 setup_version = WORD(buffer + VERSION);
278 #define ELKS 0x534B4C45
279 if (LONG(buffer + ELKSSIG) == ELKS)
280 iselks = 1;
281 if (setup_version < 0x204)
282 syssize &= 0x000FFFFFUL;
283 if (setup_version) {
284 #ifdef REALMODE_SWITCH
285 extern int far_realmode_switch();
286 #asm
287 jmp end_realmode_switch
288 _far_realmode_switch:
289 call REALMODE_SWITCH
290 cli
291 mov al, #0x80 // Disable NMI
292 out 0x70, al
293 retf
294 end_realmode_switch:
295 #endasm
296 WORD(buffer + RMSWOFS) = far_realmode_switch;
297 WORD(buffer + RMSWSEG) = getcs();
298 #endif
299 mem.base = LONG(buffer + SYSTEMCODE);
300 WORD(buffer + HEAPPTR) = 0x9B00;
301 // buffer[LOADFLAGS] |= 0x80;
302 WORD(buffer + LOADERTYPE) |= 0x80FF;
303 }
304 #ifdef LINUX001_SUPPORT
305 linux001:
306 #endif
307 if (!setup_version || !(buffer[LOADFLAGS] & 1)) {
308 zimage = getss() + 0x1000;
309 mem.base = zimage * 16L;
310 if (mem.base + syssize > setupseg*16L - 32) {
311 zimage = 0x9311;
312 mem.base = 0x110000L; // 1M + 64K HMA
313 }
314 }
315 }
316 movesetup();
317 setup -= n;
318 n = (setup > BUFFERSZ) ? BUFFERSZ : setup;