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

syslinux: add iso2exe
author Pascal Bellard <pascal.bellard@slitaz.org>
date Thu Dec 13 14:33:27 2012 +0100 (2012-12-13)
parents
children d47403fdd900
line source
1 #include <stdio.h>
2 #include "iso9660.h"
4 static unsigned 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 BUFFERSZ 2*1024
26 static char buffer[BUFFERSZ];
27 static unsigned long initrd_addr, initrd_size;
29 static int may_exit_dos = 1;
30 static void die(char *msg)
31 {
32 printf("%s.\n", msg);
33 if (may_exit_dos)
34 exit(1);
35 while (1);
36 }
38 static int vm86(void)
39 {
40 #asm
41 smsw ax
42 and ax, #1 // 0:realmode 1:vm86
43 #endasm
44 }
46 static struct mem {
47 unsigned long base;
48 int align;
49 } kernelmem = { 0x100000, 0 };
51 #define initrdmem kernelmem
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 [_kernelmem] // 1A p->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 mov [si+0x1F], al // bits 24..31, doesn't work for me :(
85 int 0x15
86 add sp, #0x30
87 popa
88 #endasm
89 }
91 static void load(struct mem *p, unsigned long size)
92 {
93 if (vm86())
94 die("Need real mode");
95 switch (p->align) {
96 case 0: // kernel
97 p->align = 4096;
98 break;
99 case 4096: // first initrd
100 initrd_addr = p->base;
101 p->align = 4;
102 }
103 while (size) {
104 int n, s = sizeof(buffer);
105 for (n = 0; n < s; n++) buffer[n] = 0;
106 if (s > size) s = size;
107 n = isoread(buffer, s);
108 movehi();
109 if (n != -1) {
110 p->base += n;
111 size -= n;
112 }
113 if (s != n) break;
114 }
115 initrd_size = p->base - initrd_addr;
116 p->base += p->align - 1;
117 p->base &= - p->align;
118 }
120 static unsigned setupofs = 0;
122 void movesetup(void)
123 {
124 #asm
125 pusha
126 push #SETUP_SEGMENT
127 pop es
128 mov si, #_buffer
129 mov di, _setupofs
130 mov cx, #BUFFERSZ/2
131 rep
132 movsw
133 mov _setupofs, di
134 popa
135 #endasm
136 }
138 void loadkernel(void)
139 {
140 unsigned setup, n = BUFFERSZ;
141 unsigned long syssize = 0;
143 do {
144 isoread(buffer, n);
145 if (setupofs == 0) {
146 if (* (unsigned short *) (buffer + BOOTFLAG) != 0xAA55)
147 die("The kernel is not bootable");
148 setup = (1 + buffer[SETUPSECTORS]) << 9;
149 if (setup == 512) setup = 5 << 9;
150 syssize = * (unsigned long *) (buffer + SYSSIZE) << 4;
151 version = * (unsigned short *) (buffer + VERSION);
152 #define HDRS 0x53726448
153 if (* (unsigned long *) (buffer + HEADER) != HDRS)
154 version = 0;
155 if (!version || !(buffer[LOADFLAGS] & 1)) {
156 #undef ZIMAGE_SUPPORT /* Does not work... */
157 #ifdef ZIMAGE_SUPPORT
158 #asm
159 pusha
160 mov cx, #0x8000
161 mov es, cx
162 xor si, si
163 xor di, di
164 rep
165 movsw
166 push es
167 pop ds
168 push es
169 pop ss
170 popa
171 jmpi relocated, #0x8000
172 relocated:
173 #endasm
174 kernelmem.base = 0x10000;
175 if (syssize > 0x70000)
176 #endif
177 die("Not a bzImage format");
178 }
179 if (version < 0x204)
180 syssize &= 0x000FFFFFUL;
181 if (version) {
182 #ifdef REALMODE_SWITCH
183 * (unsigned short *) (buffer + RMSWOFS) =
184 realmode_switch;
185 * (unsigned short *) (buffer + RMSWSEG) =
186 getcs();
187 #endif
188 * (unsigned short *) (buffer + HEAPPTR) =
189 0x9B00;
190 // buffer[LOADFLAGS] |= 0x80;
191 * (unsigned short *) (buffer + LOADERTYPE) |=
192 0x80FF;
193 }
194 }
195 movesetup();
196 setup -= n;
197 n = (setup > BUFFERSZ) ? BUFFERSZ : setup;
198 } while (setup > 0);
200 load(&kernelmem, syssize);
201 }
203 void loadinitrd(void)
204 {
205 if (version)
206 load(&initrdmem, isofilesize);
207 }
209 void bootlinux(char *cmdline)
210 {
211 #asm
212 push #SETUP_SEGMENT
213 pop es
214 mov eax, _initrd_addr
215 or eax, eax
216 jz no_initrd
217 mov di, #0x218
218 stosd
219 mov eax, _initrd_size
220 stosd
221 no_initrd:
222 #endasm
223 if (cmdline) {
224 if (version <= 0x201) {
225 #asm
226 mov di, #0x0020
227 mov ax, #0xA33F
228 stosw
229 mov ax, #CMDLINE_OFFSET
230 stosw
231 #endasm
232 }
233 else {
234 #asm
235 mov di, #0x0228
236 mov eax, #SETUP_SEGMENT*16+CMDLINE_OFFSET
237 stosd
238 #endasm
239 }
240 #asm
241 xchg ax, di
242 mov si, .bootlinux.cmdline[bp]
243 copy:
244 lodsb
245 stosb
246 or al,al
247 jne copy
248 #endasm
249 }
250 #asm
251 push es
252 pop ds
253 push ds
254 pop ss
255 mov sp, #CMDLINE_OFFSET
256 jmpi 0, #0x9020
257 #endasm
258 }