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

syslinux/iso2exe: menu can create usbkey/floppy
author Pascal Bellard <pascal.bellard@slitaz.org>
date Fri Dec 14 15:43:12 2012 +0100 (2012-12-14)
parents 7d300004a3b8
children 58b695f73790
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 // move 64K data
166 push es
167 pop ds
168 push es
169 pop ss
170 mov ch, #0x70
171 mov es, cx
172 mov ch, #0x80
173 rep
174 seg cs
175 movsw // move 64K code
176 popa
177 jmpi relocated, #0x7000
178 relocated:
179 #endasm
180 kernelmem.base = 0x10000;
181 if (syssize > 0x60000) /* 384K max */
182 #endif
183 die("Not a bzImage format");
184 }
185 if (version < 0x204)
186 syssize &= 0x000FFFFFUL;
187 if (version) {
188 #ifdef REALMODE_SWITCH
189 * (unsigned short *) (buffer + RMSWOFS) =
190 realmode_switch;
191 * (unsigned short *) (buffer + RMSWSEG) =
192 getcs();
193 #endif
194 * (unsigned short *) (buffer + HEAPPTR) =
195 0x9B00;
196 // buffer[LOADFLAGS] |= 0x80;
197 * (unsigned short *) (buffer + LOADERTYPE) |=
198 0x80FF;
199 }
200 }
201 movesetup();
202 setup -= n;
203 n = (setup > BUFFERSZ) ? BUFFERSZ : setup;
204 } while (setup > 0);
206 load(&kernelmem, syssize);
207 }
209 void loadinitrd(void)
210 {
211 if (version)
212 load(&initrdmem, isofilesize);
213 }
215 void bootlinux(char *cmdline)
216 {
217 #asm
218 push #SETUP_SEGMENT
219 pop es
220 mov eax, _initrd_addr
221 or eax, eax
222 jz no_initrd
223 mov di, #0x218
224 stosd
225 mov eax, _initrd_size
226 stosd
227 no_initrd:
228 #endasm
229 if (cmdline) {
230 if (version <= 0x201) {
231 #asm
232 mov di, #0x0020
233 mov ax, #0xA33F
234 stosw
235 mov ax, #CMDLINE_OFFSET
236 stosw
237 #endasm
238 }
239 else {
240 #asm
241 mov di, #0x0228
242 mov eax, #SETUP_SEGMENT*16+CMDLINE_OFFSET
243 stosd
244 #endasm
245 }
246 #asm
247 xchg ax, di
248 mov si, .bootlinux.cmdline[bp]
249 copy:
250 lodsb
251 stosb
252 or al,al
253 jne copy
254 #endasm
255 }
256 #asm
257 push es
258 pop ds
259 push ds
260 pop ss
261 mov sp, #CMDLINE_OFFSET
262 jmpi 0, #0x9020
263 #endasm
264 }