wok-current annotate syslinux/stuff/iso2exe/bootlinux.c @ rev 16069

syslinux/iso2exe: add a20 support
author Pascal Bellard <pascal.bellard@slitaz.org>
date Thu Mar 13 08:22:47 2014 +0000 (2014-03-13)
parents 8cf93f4aedd1
children 3e7ad70145ce
rev   line source
pascal@13691 1 #include <stdio.h>
pascal@13691 2 #include "iso9660.h"
pascal@13691 3
pascal@16022 4 static unsigned setup_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@16069 22 #define SYSTEM_SEGMENT 0x1000
pascal@13691 23 #define SETUP_SEGMENT 0x9000
pascal@13691 24 #define CMDLINE_OFFSET 0x9E00
pascal@16069 25 #define SETUP_END 0x8200
pascal@13691 26
pascal@13733 27 #define PAGE_BITS 12
pascal@13733 28 #define PAGE_SIZE 4096
pascal@16025 29 #define BUFFERSZ 2048 // lower than min setup
pascal@13691 30 static char buffer[BUFFERSZ];
pascal@16022 31 static unsigned long initrd_addr = 0, initrd_size;
pascal@13691 32
pascal@13691 33 static int may_exit_dos = 1;
pascal@13691 34 static void die(char *msg)
pascal@13691 35 {
pascal@13691 36 printf("%s.\n", msg);
pascal@13691 37 if (may_exit_dos)
pascal@13691 38 exit(1);
pascal@13691 39 while (1);
pascal@13691 40 }
pascal@13691 41
pascal@13691 42 static int vm86(void)
pascal@13691 43 {
pascal@13691 44 #asm
pascal@13691 45 smsw ax
pascal@13691 46 and ax, #1 // 0:realmode 1:vm86
pascal@13691 47 #endasm
pascal@13691 48 }
pascal@13691 49
pascal@16022 50 static struct {
pascal@13691 51 unsigned long base;
pascal@13691 52 int align;
pascal@16022 53 } mem = { 0x100000, 0 };
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@16022 64 push dword [_mem] // 1A mem.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@16008 86 xchg [si+0x1F], al // bits 24..31
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@16022 93 #define ZIMAGE_SUPPORT
pascal@16022 94
pascal@16022 95 #ifdef ZIMAGE_SUPPORT
pascal@16041 96 static unsigned zimage = 0;
pascal@16069 97 #ifndef FULL_ZIMAGE
pascal@16022 98 static unsigned getss(void)
pascal@16022 99 {
pascal@16022 100 #asm
pascal@16022 101 mov ax, ss
pascal@16022 102 #endasm
pascal@16022 103 }
pascal@16022 104 #endif
pascal@16069 105 #endif
pascal@13733 106
pascal@13699 107 static int versiondos;
pascal@13699 108 static int dosversion(void)
pascal@13699 109 {
pascal@13699 110 #asm
pascal@13699 111 mov ah, #0x30
pascal@13699 112 int 0x21
pascal@13699 113 cbw
pascal@13699 114 mov _versiondos, ax
pascal@13699 115 #endasm
pascal@13699 116 }
pascal@13699 117
pascal@15981 118 static unsigned extendedramsizeinkb(void)
pascal@15981 119 {
pascal@15981 120 #asm
pascal@15981 121 mov ah, #0x88
pascal@15981 122 int 0x15
pascal@15981 123 jnc gottop
pascal@15981 124 xor ax, ax
pascal@15981 125 gottop:
pascal@15981 126 #endasm
pascal@15981 127 }
pascal@15981 128
pascal@16069 129
pascal@16069 130 #include "a20.c"
pascal@16069 131
pascal@16022 132 static void load(unsigned long size)
pascal@13691 133 {
pascal@13691 134 if (vm86())
pascal@13691 135 die("Need real mode");
pascal@16022 136 switch (mem.align) {
pascal@13691 137 case 0: // kernel
pascal@16069 138 if ((unsigned) (dosversion() - 3) > 7 - 3) {
pascal@13699 139 printf("DOS %d not supported.\nTrying anyway...\n",
pascal@13699 140 versiondos);
pascal@13699 141 }
pascal@16022 142 mem.align = PAGE_SIZE;
pascal@13691 143 break;
pascal@16008 144 case PAGE_SIZE: // first initrd : keep 16M..48M for the kernel
pascal@16022 145 if (extendedramsizeinkb() > 0xF000U && mem.base < 0x3000000)
pascal@16022 146 mem.base = 0x3000000;
pascal@16022 147 initrd_addr = mem.base;
pascal@16022 148 mem.align = 4;
pascal@13691 149 }
pascal@16069 150 #ifdef ALLOCMEM
pascal@16069 151 ALLOCMEM(size);
pascal@16069 152 #endif
pascal@13691 153 while (size) {
pascal@13691 154 int n, s = sizeof(buffer);
pascal@13691 155 for (n = 0; n < s; n++) buffer[n] = 0;
pascal@13691 156 if (s > size) s = size;
pascal@16022 157 if ((n = isoread(buffer, s)) < 0) break;
pascal@13691 158 movehi();
pascal@16022 159 mem.base += n;
pascal@16022 160 size -= n;
pascal@16022 161 if (s != n) break; // end of file
pascal@13691 162 }
pascal@16022 163 initrd_size = mem.base - initrd_addr;
pascal@16022 164 mem.base += mem.align - 1;
pascal@16022 165 mem.base &= - mem.align;
pascal@13691 166 }
pascal@13691 167
pascal@13691 168 static unsigned setupofs = 0;
pascal@13691 169
pascal@13691 170 void movesetup(void)
pascal@13691 171 {
pascal@13691 172 #asm
pascal@13691 173 pusha
pascal@13691 174 push #SETUP_SEGMENT
pascal@13691 175 pop es
pascal@13691 176 mov si, #_buffer
pascal@13691 177 mov di, _setupofs
pascal@13691 178 mov cx, #BUFFERSZ/2
pascal@13691 179 rep
pascal@13691 180 movsw
pascal@13691 181 mov _setupofs, di
pascal@13691 182 popa
pascal@13691 183 #endasm
pascal@13691 184 }
pascal@13691 185
pascal@14257 186 static unsigned getcs(void)
pascal@14257 187 {
pascal@14257 188 #asm
pascal@14257 189 mov ax, cs
pascal@14257 190 #endasm
pascal@14257 191 }
pascal@14257 192
pascal@14257 193 unsigned long loadkernel(void)
pascal@13691 194 {
pascal@13691 195 unsigned setup, n = BUFFERSZ;
pascal@14268 196 unsigned long syssize = 0, kernel_version = 0;
pascal@13691 197
pascal@13691 198 do {
pascal@13691 199 isoread(buffer, n);
pascal@13691 200 if (setupofs == 0) {
pascal@13691 201 if (* (unsigned short *) (buffer + BOOTFLAG) != 0xAA55)
pascal@13691 202 die("The kernel is not bootable");
pascal@13691 203 setup = (1 + buffer[SETUPSECTORS]) << 9;
pascal@13691 204 if (setup == 512) setup = 5 << 9;
pascal@13691 205 syssize = * (unsigned long *) (buffer + SYSSIZE) << 4;
pascal@16022 206 setup_version = * (unsigned short *) (buffer + VERSION);
pascal@13691 207 #define HDRS 0x53726448
pascal@13691 208 if (* (unsigned long *) (buffer + HEADER) != HDRS)
pascal@16022 209 setup_version = 0;
pascal@16022 210 if (setup_version < 0x204)
pascal@13733 211 syssize &= 0x000FFFFFUL;
pascal@16022 212 if (setup_version) {
pascal@13733 213 #ifdef REALMODE_SWITCH
pascal@13733 214 extern int far_realmode_switch();
pascal@13733 215 #asm
pascal@13733 216 jmp end_realmode_switch
pascal@13733 217 _far_realmode_switch:
pascal@14257 218 call REALMODE_SWITCH
pascal@13733 219 cli
pascal@13733 220 mov al, #0x80 // Disable NMI
pascal@13733 221 out 0x70, al
pascal@13733 222 retf
pascal@13733 223 end_realmode_switch:
pascal@13733 224 #endasm
pascal@13733 225 * (unsigned short *) (buffer + RMSWOFS) =
pascal@13733 226 far_realmode_switch;
pascal@13733 227 * (unsigned short *) (buffer + RMSWSEG) =
pascal@13733 228 getcs();
pascal@13733 229 #endif
pascal@16022 230 mem.base =
pascal@13733 231 * (unsigned long *) (buffer + SYSTEMCODE);
pascal@13733 232 * (unsigned short *) (buffer + HEAPPTR) =
pascal@13733 233 0x9B00;
pascal@13733 234 // buffer[LOADFLAGS] |= 0x80;
pascal@13733 235 * (unsigned short *) (buffer + LOADERTYPE) |=
pascal@13733 236 0x80FF;
pascal@13733 237 }
pascal@16022 238 if (!setup_version || !(buffer[LOADFLAGS] & 1)) {
pascal@13691 239 #ifdef ZIMAGE_SUPPORT
pascal@16069 240 #ifndef FULL_ZIMAGE
pascal@16041 241 zimage = getss() + 0x1000;
pascal@16041 242 mem.base = zimage * 16L;
pascal@16022 243 if (mem.base + syssize > SETUP_SEGMENT*16L - 32)
pascal@16022 244 die("Out of memory");
pascal@16022 245 #else
pascal@16069 246 zimage = 0x11;
pascal@16069 247 mem.base = 0x110000L; // 1M + 64K HMA
pascal@16069 248
pascal@16069 249 #endif
pascal@16069 250 #else
pascal@16022 251 die("Not a bzImage format");
pascal@13691 252 #endif
pascal@13691 253 }
pascal@13691 254 }
pascal@13691 255 movesetup();
pascal@13691 256 setup -= n;
pascal@13691 257 n = (setup > BUFFERSZ) ? BUFFERSZ : setup;
pascal@13691 258 } while (setup > 0);
pascal@13691 259
pascal@14257 260 #asm
pascal@14257 261 push ds
pascal@14257 262 push #SETUP_SEGMENT
pascal@14257 263 pop ds
pascal@14257 264 mov si, #0x200
pascal@14257 265 mov eax, #0x53726448 // HdrS
pascal@14257 266 cdq // clear edx
pascal@14257 267 cmp [si+2], eax
pascal@14257 268 jne noversion
pascal@14257 269 add si, [si+14]
pascal@14257 270 mov cx, #3
pascal@14257 271 xor ax, ax
pascal@14257 272 nextdigit:
pascal@14264 273 shl al, #4
pascal@14264 274 shl ax, #4
pascal@14257 275 next:
pascal@14257 276 lodsb
pascal@14257 277 sub al, #0x30
pascal@14257 278 cmp al, #9
pascal@14257 279 jbe nextdigit
pascal@14264 280 shl eax, #16
pascal@14264 281 shld edx, eax, #8
pascal@14257 282 loop next
pascal@14257 283 pop ds
pascal@14268 284 mov .loadkernel.kernel_version[bp], edx
pascal@16022 285 push ds
pascal@14257 286 noversion:
pascal@16022 287 pop ds
pascal@14257 288 #endasm
pascal@16022 289 load(syssize);
pascal@14268 290 return kernel_version;
pascal@13691 291 }
pascal@13691 292
pascal@13691 293 void loadinitrd(void)
pascal@13691 294 {
pascal@16022 295 if (setup_version && zimage == 0)
pascal@16022 296 load(isofilesize);
pascal@13691 297 }
pascal@13691 298
pascal@13691 299 void bootlinux(char *cmdline)
pascal@13691 300 {
pascal@13691 301 #asm
pascal@13691 302 push #SETUP_SEGMENT
pascal@13691 303 pop es
pascal@13691 304 #endasm
pascal@13691 305 if (cmdline) {
pascal@16022 306 if (setup_version <= 0x201) {
pascal@13691 307 #asm
pascal@13691 308 mov di, #0x0020
pascal@13691 309 mov ax, #0xA33F
pascal@13691 310 stosw
pascal@13691 311 mov ax, #CMDLINE_OFFSET
pascal@13691 312 stosw
pascal@13691 313 #endasm
pascal@13691 314 }
pascal@13691 315 else {
pascal@13691 316 #asm
pascal@13691 317 mov di, #0x0228
pascal@13691 318 mov eax, #SETUP_SEGMENT*16+CMDLINE_OFFSET
pascal@13691 319 stosd
pascal@13691 320 #endasm
pascal@13691 321 }
pascal@13691 322 #asm
pascal@13691 323 xchg ax, di
pascal@13691 324 mov si, .bootlinux.cmdline[bp]
pascal@13691 325 copy:
pascal@13691 326 lodsb
pascal@13691 327 stosb
pascal@13691 328 or al,al
pascal@13691 329 jne copy
pascal@13691 330 #endasm
pascal@13691 331 }
pascal@16025 332 if (setup_version >= 0x200) {
pascal@16025 333 #asm
pascal@16025 334 mov eax, _initrd_addr
pascal@16025 335 mov di, #0x218
pascal@16025 336 stosd
pascal@16025 337 mov eax, _initrd_size
pascal@16025 338 stosd
pascal@16025 339 #endasm
pascal@16025 340 }
pascal@16025 341 #asm
pascal@16025 342 push es
pascal@16025 343 pop ss
pascal@16025 344 mov sp, #CMDLINE_OFFSET
pascal@16025 345 #endasm
pascal@16022 346 #ifdef ZIMAGE_SUPPORT
pascal@13691 347 #asm
pascal@16041 348 mov bx, _zimage
pascal@16041 349 or bx, bx
pascal@16041 350 jz notzimage
pascal@16022 351 mov eax, _mem
pascal@16069 352 #ifndef FULL_ZIMAGE
pascal@16022 353 shr eax, #4 // top
pascal@16069 354 mov dx, #SYSTEM_SEGMENT
pascal@16069 355 #else
pascal@16069 356 dec eax
pascal@16069 357 shr eax, #16
pascal@16069 358 inc ax
pascal@16069 359 mov dx, #SYSTEM_SEGMENT/0x1000
pascal@16069 360 #endif
pascal@16022 361 push cs
pascal@16022 362 pop ds
pascal@16069 363 push ss
pascal@16069 364 pop es
pascal@16022 365 push es
pascal@16022 366 mov si, #sysmove
pascal@16069 367 mov di, #SETUP_END
pascal@16022 368 push di
pascal@16022 369 mov cx, #endsysmove-sysmove
pascal@16069 370 cld
pascal@16022 371 rep
pascal@16022 372 movsb
pascal@16022 373 retf
pascal@16022 374 sysmove:
pascal@16069 375 #ifndef FULL_ZIMAGE
pascal@16022 376 mov ds, bx
pascal@16022 377 mov es, dx
pascal@16022 378 xor di, di
pascal@16022 379 xor si, si
pascal@16022 380 mov cl, #8
pascal@16022 381 rep
pascal@16022 382 movsw
pascal@16022 383 inc bx
pascal@16022 384 inc dx
pascal@16069 385 cmp ax, bx
pascal@16022 386 jne sysmove
pascal@16069 387 #else
pascal@16069 388 xchg ax, cx
pascal@16069 389 mov si, di
pascal@16069 390 push es
pascal@16069 391 pop ds
pascal@16069 392 push cx
pascal@16069 393 mov cx, #0x18
pascal@16069 394 rep
pascal@16069 395 stosw
pascal@16069 396 dec cx
pascal@16069 397 mov [si+0x10], cx
pascal@16069 398 mov [si+0x18], cx
pascal@16069 399 pop cx
pascal@16069 400 mov bh, #0x93
pascal@16069 401 mov dh, #0x93
pascal@16069 402 mvdown:
pascal@16069 403 mov [si+0x12+2], bx // srce
pascal@16069 404 mov [si+0x1A+2], dx // dest
pascal@16069 405 pusha
pascal@16069 406 mov cx, #0x8000
pascal@16069 407 mov ah, #0x87
pascal@16069 408 int 0x15 // catched by himem.sys: may need dos=high,umb
pascal@16069 409 popa
pascal@16069 410 inc bx
pascal@16069 411 inc dx
pascal@16069 412 cmp cl, bl
pascal@16069 413 jne mvdown
pascal@16069 414 #endif
pascal@16041 415 notzimage:
pascal@16022 416 #endasm
pascal@16022 417 #endif
pascal@16022 418 #asm
pascal@16022 419 push ss
pascal@13691 420 pop ds
pascal@13691 421 push ds
pascal@16022 422 pop es
pascal@13691 423 jmpi 0, #0x9020
pascal@16022 424 endsysmove:
pascal@13691 425 #endasm
pascal@13691 426 }