rev |
line source |
pascal@13691
|
1 #include <stdio.h>
|
pascal@13691
|
2 #include "iso9660.h"
|
pascal@13691
|
3
|
pascal@13691
|
4 static unsigned version;
|
pascal@13691
|
5 #define SETUPSECTORS 0x1F1
|
pascal@13691
|
6 #define ROFLAG 0x1F2
|
pascal@13691
|
7 #define SYSSIZE 0x1F4
|
pascal@13691
|
8 #define VIDEOMODE 0x1FA
|
pascal@13691
|
9 #define BOOTFLAG 0x1FE
|
pascal@13691
|
10 #define HEADER 0x202
|
pascal@13691
|
11 #define VERSION 0x206
|
pascal@13691
|
12 #define RMSWOFS 0x208
|
pascal@13691
|
13 #define RMSWSEG 0x20A
|
pascal@13691
|
14 #define LOADERTYPE 0x210
|
pascal@13691
|
15 #define LOADFLAGS 0x211
|
pascal@13691
|
16 #define SYSTEMCODE 0x214
|
pascal@13691
|
17 #define INITRDCODE 0x218
|
pascal@13691
|
18 #define INITRDSIZE 0x21C
|
pascal@13691
|
19 #define HEAPPTR 0x224
|
pascal@13691
|
20 #define CMDLINE 0x228
|
pascal@13691
|
21
|
pascal@13691
|
22 #define SETUP_SEGMENT 0x9000
|
pascal@13691
|
23 #define CMDLINE_OFFSET 0x9E00
|
pascal@13691
|
24
|
pascal@13733
|
25 #define PAGE_BITS 12
|
pascal@13733
|
26 #define PAGE_SIZE 4096
|
pascal@13733
|
27 #define BUFFERSZ PAGE_SIZE
|
pascal@13691
|
28 static char buffer[BUFFERSZ];
|
pascal@13691
|
29 static unsigned long initrd_addr, initrd_size;
|
pascal@13691
|
30
|
pascal@13691
|
31 static int may_exit_dos = 1;
|
pascal@13691
|
32 static void die(char *msg)
|
pascal@13691
|
33 {
|
pascal@13691
|
34 printf("%s.\n", msg);
|
pascal@13691
|
35 if (may_exit_dos)
|
pascal@13691
|
36 exit(1);
|
pascal@13691
|
37 while (1);
|
pascal@13691
|
38 }
|
pascal@13691
|
39
|
pascal@13691
|
40 static int vm86(void)
|
pascal@13691
|
41 {
|
pascal@13691
|
42 #asm
|
pascal@13691
|
43 smsw ax
|
pascal@13691
|
44 and ax, #1 // 0:realmode 1:vm86
|
pascal@13691
|
45 #endasm
|
pascal@13691
|
46 }
|
pascal@13691
|
47
|
pascal@13691
|
48 static struct mem {
|
pascal@13691
|
49 unsigned long base;
|
pascal@13691
|
50 int align;
|
pascal@13691
|
51 } kernelmem = { 0x100000, 0 };
|
pascal@13691
|
52
|
pascal@13691
|
53 #define initrdmem kernelmem
|
pascal@13691
|
54
|
pascal@13691
|
55 static void movehi(void)
|
pascal@13691
|
56 {
|
pascal@13691
|
57 #asm
|
pascal@13691
|
58 pusha
|
pascal@13691
|
59 xor di, di // 30
|
pascal@13691
|
60 mov cx, #9 // 2E..1E
|
pascal@13691
|
61 zero1:
|
pascal@13691
|
62 push di
|
pascal@13691
|
63 loop zero1
|
pascal@13691
|
64 push dword [_kernelmem] // 1A p->base
|
pascal@13691
|
65 push #-1 // 18
|
pascal@13691
|
66 push di // 16
|
pascal@13691
|
67 xor eax, eax
|
pascal@13691
|
68 cdq
|
pascal@13691
|
69 mov dx, ds
|
pascal@13691
|
70 shl edx, #4
|
pascal@13691
|
71 mov ax, #_buffer
|
pascal@13691
|
72 add edx, eax
|
pascal@13691
|
73 push edx // 12 linear_address(buffer)
|
pascal@13691
|
74 push #-1 // 10
|
pascal@13691
|
75 mov cl, #8 // 0E..00
|
pascal@13691
|
76 zero2:
|
pascal@13691
|
77 push di
|
pascal@13691
|
78 loop zero2
|
pascal@13691
|
79 mov ch, #BUFFERSZ/512
|
pascal@13691
|
80 push ss
|
pascal@13691
|
81 pop es
|
pascal@13691
|
82 mov si, sp
|
pascal@13691
|
83 mov ax, #0x8793
|
pascal@13691
|
84 mov [si+0x15], al
|
pascal@13691
|
85 xchg [si+0x1D], al
|
pascal@13691
|
86 mov [si+0x1F], al // bits 24..31, doesn't work for me :(
|
pascal@13691
|
87 int 0x15
|
pascal@13691
|
88 add sp, #0x30
|
pascal@13691
|
89 popa
|
pascal@13691
|
90 #endasm
|
pascal@13691
|
91 }
|
pascal@13691
|
92
|
pascal@13733
|
93 #undef ZIMAGE_SUPPORT /* Does not work... */
|
pascal@13733
|
94
|
pascal@13699
|
95 static int versiondos;
|
pascal@13699
|
96 static int dosversion(void)
|
pascal@13699
|
97 {
|
pascal@13699
|
98 #asm
|
pascal@13699
|
99 mov ah, #0x30
|
pascal@13699
|
100 int 0x21
|
pascal@13699
|
101 cbw
|
pascal@13699
|
102 mov _versiondos, ax
|
pascal@13699
|
103 #endasm
|
pascal@13699
|
104 }
|
pascal@13699
|
105
|
pascal@13691
|
106 static void load(struct mem *p, unsigned long size)
|
pascal@13691
|
107 {
|
pascal@13691
|
108 if (vm86())
|
pascal@13691
|
109 die("Need real mode");
|
pascal@13691
|
110 switch (p->align) {
|
pascal@13691
|
111 case 0: // kernel
|
pascal@13699
|
112 switch (dosversion()) {
|
pascal@13699
|
113 case 3: case 4: case 6: break;
|
pascal@13699
|
114 default:
|
pascal@13699
|
115 printf("DOS %d not supported.\nTrying anyway...\n",
|
pascal@13699
|
116 versiondos);
|
pascal@13699
|
117 }
|
pascal@13733
|
118 p->align = PAGE_SIZE;
|
pascal@13691
|
119 break;
|
pascal@13691
|
120 case 4096: // first initrd
|
pascal@13691
|
121 initrd_addr = p->base;
|
pascal@13691
|
122 p->align = 4;
|
pascal@13691
|
123 }
|
pascal@13691
|
124 while (size) {
|
pascal@13691
|
125 int n, s = sizeof(buffer);
|
pascal@13691
|
126 for (n = 0; n < s; n++) buffer[n] = 0;
|
pascal@13691
|
127 if (s > size) s = size;
|
pascal@13691
|
128 n = isoread(buffer, s);
|
pascal@13691
|
129 movehi();
|
pascal@13691
|
130 if (n != -1) {
|
pascal@13691
|
131 p->base += n;
|
pascal@13691
|
132 size -= n;
|
pascal@13691
|
133 }
|
pascal@13691
|
134 if (s != n) break;
|
pascal@13691
|
135 }
|
pascal@13691
|
136 initrd_size = p->base - initrd_addr;
|
pascal@13691
|
137 p->base += p->align - 1;
|
pascal@13691
|
138 p->base &= - p->align;
|
pascal@13691
|
139 }
|
pascal@13691
|
140
|
pascal@13691
|
141 static unsigned setupofs = 0;
|
pascal@13691
|
142
|
pascal@13691
|
143 void movesetup(void)
|
pascal@13691
|
144 {
|
pascal@13691
|
145 #asm
|
pascal@13691
|
146 pusha
|
pascal@13691
|
147 push #SETUP_SEGMENT
|
pascal@13691
|
148 pop es
|
pascal@13691
|
149 mov si, #_buffer
|
pascal@13691
|
150 mov di, _setupofs
|
pascal@13691
|
151 mov cx, #BUFFERSZ/2
|
pascal@13691
|
152 rep
|
pascal@13691
|
153 movsw
|
pascal@13691
|
154 mov _setupofs, di
|
pascal@13691
|
155 popa
|
pascal@13691
|
156 #endasm
|
pascal@13691
|
157 }
|
pascal@13691
|
158
|
pascal@13691
|
159 void loadkernel(void)
|
pascal@13691
|
160 {
|
pascal@13691
|
161 unsigned setup, n = BUFFERSZ;
|
pascal@13691
|
162 unsigned long syssize = 0;
|
pascal@13691
|
163
|
pascal@13691
|
164 do {
|
pascal@13691
|
165 isoread(buffer, n);
|
pascal@13691
|
166 if (setupofs == 0) {
|
pascal@13691
|
167 if (* (unsigned short *) (buffer + BOOTFLAG) != 0xAA55)
|
pascal@13691
|
168 die("The kernel is not bootable");
|
pascal@13691
|
169 setup = (1 + buffer[SETUPSECTORS]) << 9;
|
pascal@13691
|
170 if (setup == 512) setup = 5 << 9;
|
pascal@13691
|
171 syssize = * (unsigned long *) (buffer + SYSSIZE) << 4;
|
pascal@13691
|
172 version = * (unsigned short *) (buffer + VERSION);
|
pascal@13691
|
173 #define HDRS 0x53726448
|
pascal@13691
|
174 if (* (unsigned long *) (buffer + HEADER) != HDRS)
|
pascal@13691
|
175 version = 0;
|
pascal@13733
|
176 if (version < 0x204)
|
pascal@13733
|
177 syssize &= 0x000FFFFFUL;
|
pascal@13733
|
178 if (version) {
|
pascal@13733
|
179 #ifdef REALMODE_SWITCH
|
pascal@13733
|
180 extern int far_realmode_switch();
|
pascal@13733
|
181 #asm
|
pascal@13733
|
182 jmp end_realmode_switch
|
pascal@13733
|
183 _far_realmode_switch:
|
pascal@13733
|
184 call _realmode_switch
|
pascal@13733
|
185 cli
|
pascal@13733
|
186 mov al, #0x80 // Disable NMI
|
pascal@13733
|
187 out 0x70, al
|
pascal@13733
|
188 retf
|
pascal@13733
|
189 end_realmode_switch:
|
pascal@13733
|
190 #endasm
|
pascal@13733
|
191 * (unsigned short *) (buffer + RMSWOFS) =
|
pascal@13733
|
192 far_realmode_switch;
|
pascal@13733
|
193 * (unsigned short *) (buffer + RMSWSEG) =
|
pascal@13733
|
194 getcs();
|
pascal@13733
|
195 #endif
|
pascal@13733
|
196 kernelmem.base =
|
pascal@13733
|
197 * (unsigned long *) (buffer + SYSTEMCODE);
|
pascal@13733
|
198 * (unsigned short *) (buffer + HEAPPTR) =
|
pascal@13733
|
199 0x9B00;
|
pascal@13733
|
200 // buffer[LOADFLAGS] |= 0x80;
|
pascal@13733
|
201 * (unsigned short *) (buffer + LOADERTYPE) |=
|
pascal@13733
|
202 0x80FF;
|
pascal@13733
|
203 }
|
pascal@13691
|
204 if (!version || !(buffer[LOADFLAGS] & 1)) {
|
pascal@13691
|
205 #ifdef ZIMAGE_SUPPORT
|
pascal@13691
|
206 #asm
|
pascal@13691
|
207 pusha
|
pascal@13691
|
208 mov cx, #0x8000
|
pascal@13691
|
209 mov es, cx
|
pascal@13691
|
210 xor si, si
|
pascal@13691
|
211 xor di, di
|
pascal@13691
|
212 rep
|
pascal@13697
|
213 movsw // move 64K data
|
pascal@13691
|
214 push es
|
pascal@13691
|
215 pop ds
|
pascal@13691
|
216 push es
|
pascal@13691
|
217 pop ss
|
pascal@13697
|
218 mov ch, #0x70
|
pascal@13697
|
219 mov es, cx
|
pascal@13697
|
220 mov ch, #0x80
|
pascal@13697
|
221 rep
|
pascal@13697
|
222 seg cs
|
pascal@13697
|
223 movsw // move 64K code
|
pascal@13691
|
224 popa
|
pascal@13697
|
225 jmpi relocated, #0x7000
|
pascal@13691
|
226 relocated:
|
pascal@13691
|
227 #endasm
|
pascal@13691
|
228 kernelmem.base = 0x10000;
|
pascal@13697
|
229 if (syssize > 0x60000) /* 384K max */
|
pascal@13691
|
230 #endif
|
pascal@13691
|
231 die("Not a bzImage format");
|
pascal@13691
|
232 }
|
pascal@13691
|
233 }
|
pascal@13691
|
234 movesetup();
|
pascal@13691
|
235 setup -= n;
|
pascal@13691
|
236 n = (setup > BUFFERSZ) ? BUFFERSZ : setup;
|
pascal@13691
|
237 } while (setup > 0);
|
pascal@13691
|
238
|
pascal@13691
|
239 load(&kernelmem, syssize);
|
pascal@13691
|
240 }
|
pascal@13691
|
241
|
pascal@13691
|
242 void loadinitrd(void)
|
pascal@13691
|
243 {
|
pascal@13691
|
244 if (version)
|
pascal@13691
|
245 load(&initrdmem, isofilesize);
|
pascal@13691
|
246 }
|
pascal@13691
|
247
|
pascal@13691
|
248 void bootlinux(char *cmdline)
|
pascal@13691
|
249 {
|
pascal@13691
|
250 #asm
|
pascal@13691
|
251 push #SETUP_SEGMENT
|
pascal@13691
|
252 pop es
|
pascal@13691
|
253 mov eax, _initrd_addr
|
pascal@13691
|
254 or eax, eax
|
pascal@13691
|
255 jz no_initrd
|
pascal@13691
|
256 mov di, #0x218
|
pascal@13691
|
257 stosd
|
pascal@13691
|
258 mov eax, _initrd_size
|
pascal@13691
|
259 stosd
|
pascal@13691
|
260 no_initrd:
|
pascal@13691
|
261 #endasm
|
pascal@13691
|
262 if (cmdline) {
|
pascal@13691
|
263 if (version <= 0x201) {
|
pascal@13691
|
264 #asm
|
pascal@13691
|
265 mov di, #0x0020
|
pascal@13691
|
266 mov ax, #0xA33F
|
pascal@13691
|
267 stosw
|
pascal@13691
|
268 mov ax, #CMDLINE_OFFSET
|
pascal@13691
|
269 stosw
|
pascal@13691
|
270 #endasm
|
pascal@13691
|
271 }
|
pascal@13691
|
272 else {
|
pascal@13691
|
273 #asm
|
pascal@13691
|
274 mov di, #0x0228
|
pascal@13691
|
275 mov eax, #SETUP_SEGMENT*16+CMDLINE_OFFSET
|
pascal@13691
|
276 stosd
|
pascal@13691
|
277 #endasm
|
pascal@13691
|
278 }
|
pascal@13691
|
279 #asm
|
pascal@13691
|
280 xchg ax, di
|
pascal@13691
|
281 mov si, .bootlinux.cmdline[bp]
|
pascal@13691
|
282 copy:
|
pascal@13691
|
283 lodsb
|
pascal@13691
|
284 stosb
|
pascal@13691
|
285 or al,al
|
pascal@13691
|
286 jne copy
|
pascal@13691
|
287 #endasm
|
pascal@13691
|
288 }
|
pascal@13691
|
289 #asm
|
pascal@13691
|
290 push es
|
pascal@13691
|
291 pop ds
|
pascal@13691
|
292 push ds
|
pascal@13691
|
293 pop ss
|
pascal@13691
|
294 mov sp, #CMDLINE_OFFSET
|
pascal@13691
|
295 jmpi 0, #0x9020
|
pascal@13691
|
296 #endasm
|
pascal@13691
|
297 }
|