wok annotate syslinux/stuff/iso2exe/bootlinux.c @ rev 17473

syslinux/iso2exe: add 64bits support
author Pascal Bellard <pascal.bellard@slitaz.org>
date Sat Dec 27 17:56:57 2014 +0100 (2014-12-27)
parents 188b82599301
children 054f70cb9bec
rev   line source
pascal@13691 1 #include <stdio.h>
pascal@17160 2 #include "libdos.h"
pascal@13691 3 #include "iso9660.h"
pascal@17473 4 #asm
pascal@17473 5 use16 86
pascal@17473 6 #endasm
pascal@13691 7
pascal@17160 8 #define ELKSSIG 0x1E6
pascal@13691 9 #define SETUPSECTORS 0x1F1
pascal@13691 10 #define ROFLAG 0x1F2
pascal@13691 11 #define SYSSIZE 0x1F4
pascal@13691 12 #define VIDEOMODE 0x1FA
pascal@13691 13 #define BOOTFLAG 0x1FE
pascal@13691 14 #define HEADER 0x202
pascal@13691 15 #define VERSION 0x206
pascal@13691 16 #define RMSWOFS 0x208
pascal@13691 17 #define RMSWSEG 0x20A
pascal@13691 18 #define LOADERTYPE 0x210
pascal@13691 19 #define LOADFLAGS 0x211
pascal@13691 20 #define SYSTEMCODE 0x214
pascal@13691 21 #define INITRDCODE 0x218
pascal@13691 22 #define INITRDSIZE 0x21C
pascal@13691 23 #define HEAPPTR 0x224
pascal@13691 24 #define CMDLINE 0x228
pascal@13691 25
pascal@16069 26 #define SYSTEM_SEGMENT 0x1000
pascal@13691 27 #define SETUP_SEGMENT 0x9000
pascal@13691 28 #define CMDLINE_OFFSET 0x9E00
pascal@16069 29 #define SETUP_END 0x8200
pascal@13691 30
pascal@13733 31 #define PAGE_BITS 12
pascal@13733 32 #define PAGE_SIZE 4096
pascal@16025 33 #define BUFFERSZ 2048 // lower than min setup
pascal@13691 34 static char buffer[BUFFERSZ];
pascal@16022 35 static unsigned long initrd_addr = 0, initrd_size;
pascal@13691 36
pascal@13691 37 static int may_exit_dos = 1;
pascal@13691 38 static void die(char *msg)
pascal@13691 39 {
pascal@13691 40 printf("%s.\n", msg);
pascal@13691 41 if (may_exit_dos)
pascal@13691 42 exit(1);
pascal@13691 43 while (1);
pascal@13691 44 }
pascal@13691 45
pascal@17160 46 static int iselks;
pascal@13691 47 static int vm86(void)
pascal@13691 48 {
pascal@13691 49 #asm
pascal@17450 50 mov ax, _iselks
pascal@17450 51 dec ax
pascal@17450 52 je fakerealmode // elks may run on a 8086
pascal@17473 53 use16 286
pascal@17160 54 smsw ax // 286+
pascal@13691 55 and ax, #1 // 0:realmode 1:vm86
pascal@17473 56 use16 86
pascal@17160 57 fakerealmode:
pascal@13691 58 #endasm
pascal@13691 59 }
pascal@13691 60
pascal@16022 61 static struct {
pascal@13691 62 unsigned long base;
pascal@13691 63 int align;
pascal@16022 64 } mem = { 0x100000, 0 };
pascal@13691 65
pascal@17450 66 #ifdef __MSDOS__
pascal@17450 67 #define A20HOLDBUFFER 0x80000
pascal@17450 68 static int a20buffer = 0;
pascal@17450 69 #endif
pascal@17450 70
pascal@13691 71 static void movehi(void)
pascal@13691 72 {
pascal@13691 73 #asm
pascal@17160 74 push si
pascal@17160 75 push di
pascal@17160 76
pascal@17450 77 xor ax, ax
pascal@17160 78 mov si, #_mem
pascal@17160 79 cmp word ptr [si+2], #0x10
pascal@17450 80 #ifdef __MSDOS__
pascal@17450 81 jne nota20
pascal@17450 82 mov ax, #A20HOLDBUFFER/16
pascal@17450 83 mov _a20buffer, ax
pascal@17450 84 mov di, [si] // mem.base & 0xFFFF
pascal@17450 85 jmp mvbuffer
pascal@17450 86 nota20:
pascal@17450 87 #endif
pascal@17160 88 jnc movehiz
pascal@17450 89 lodsb
pascal@17450 90 xchg ax, di
pascal@17450 91 lodsw
pascal@17160 92 mov cl, #4
pascal@17160 93 shl ax, cl // 8086 support for elks
pascal@17450 94 mvbuffer:
pascal@17160 95 mov es, ax
pascal@17160 96 mov si, #_buffer
pascal@17450 97 cld
pascal@17160 98 mov cx, #BUFFERSZ/2
pascal@17160 99 rep
pascal@17160 100 movw
pascal@17160 101 jmp movedone
pascal@17450 102 movehiz: // 30
pascal@17473 103 use16 286 // more than 1Mb => 286+
pascal@13691 104 mov cx, #9 // 2E..1E
pascal@13691 105 zero1:
pascal@17450 106 push ax
pascal@13691 107 loop zero1
pascal@17473 108 push word [si+2]
pascal@17473 109 push word [si] // 1A mem.base
pascal@13691 110 push #-1 // 18
pascal@17450 111 push ax // 16
pascal@17473 112 mov ax, ds
pascal@17473 113 mov dx, ax
pascal@17473 114 shl ax, #4
pascal@17473 115 shr dx, #12
pascal@17473 116 add ax, #_buffer
pascal@17473 117 adc dx, #0
pascal@17473 118 push dx
pascal@17473 119 push ax
pascal@13691 120 push #-1 // 10
pascal@13691 121 mov cl, #8 // 0E..00
pascal@13691 122 zero2:
pascal@17450 123 push #0
pascal@13691 124 loop zero2
pascal@13691 125 mov ch, #BUFFERSZ/512
pascal@13691 126 push ss
pascal@13691 127 pop es
pascal@13691 128 mov si, sp
pascal@13691 129 mov ax, #0x8793
pascal@13691 130 mov [si+0x15], al
pascal@13691 131 xchg [si+0x1D], al
pascal@16008 132 xchg [si+0x1F], al // bits 24..31
pascal@13691 133 int 0x15
pascal@13691 134 add sp, #0x30
pascal@17473 135 use16 86
pascal@17160 136 movedone:
pascal@17160 137 pop di
pascal@17160 138 pop si
pascal@13691 139 #endasm
pascal@13691 140 }
pascal@13691 141
pascal@16041 142 static unsigned zimage = 0;
pascal@16022 143 static unsigned getss(void)
pascal@16022 144 {
pascal@16022 145 #asm
pascal@16022 146 mov ax, ss
pascal@16022 147 #endasm
pascal@16022 148 }
pascal@13699 149
pascal@15981 150 static unsigned extendedramsizeinkb(void)
pascal@15981 151 {
pascal@15981 152 #asm
pascal@15981 153 mov ah, #0x88
pascal@15981 154 int 0x15
pascal@15981 155 jnc gottop
pascal@15981 156 xor ax, ax
pascal@15981 157 gottop:
pascal@15981 158 #endasm
pascal@15981 159 }
pascal@15981 160
pascal@16069 161
pascal@16069 162 #include "a20.c"
pascal@16069 163
pascal@16022 164 static void load(unsigned long size)
pascal@13691 165 {
pascal@13691 166 if (vm86())
pascal@13691 167 die("Need real mode");
pascal@16022 168 switch (mem.align) {
pascal@13691 169 case 0: // kernel
pascal@17160 170 #ifdef __MSDOS__
pascal@16069 171 if ((unsigned) (dosversion() - 3) > 7 - 3) {
pascal@13699 172 printf("DOS %d not supported.\nTrying anyway...\n",
pascal@13699 173 versiondos);
pascal@13699 174 }
pascal@17160 175 #endif
pascal@16022 176 mem.align = PAGE_SIZE;
pascal@13691 177 break;
pascal@16008 178 case PAGE_SIZE: // first initrd : keep 16M..48M for the kernel
pascal@16022 179 if (extendedramsizeinkb() > 0xF000U && mem.base < 0x3000000)
pascal@16022 180 mem.base = 0x3000000;
pascal@16022 181 initrd_addr = mem.base;
pascal@16022 182 mem.align = 4;
pascal@13691 183 }
pascal@16069 184 #ifdef ALLOCMEM
pascal@16069 185 ALLOCMEM(size);
pascal@16069 186 #endif
pascal@13691 187 while (size) {
pascal@13691 188 int n, s = sizeof(buffer);
pascal@13691 189 for (n = 0; n < s; n++) buffer[n] = 0;
pascal@13691 190 if (s > size) s = size;
pascal@16022 191 if ((n = isoread(buffer, s)) < 0) break;
pascal@13691 192 movehi();
pascal@16022 193 mem.base += n;
pascal@16022 194 size -= n;
pascal@16022 195 if (s != n) break; // end of file
pascal@13691 196 }
pascal@16022 197 initrd_size = mem.base - initrd_addr;
pascal@16022 198 mem.base += mem.align - 1;
pascal@16022 199 mem.base &= - mem.align;
pascal@13691 200 }
pascal@13691 201
pascal@17160 202 static unsigned setupseg = SETUP_SEGMENT;
pascal@13691 203 static unsigned setupofs = 0;
pascal@13691 204
pascal@13691 205 void movesetup(void)
pascal@13691 206 {
pascal@13691 207 #asm
pascal@17160 208 push si
pascal@17160 209 mov es, _setupseg
pascal@17450 210 xchg di, _setupofs
pascal@13691 211 mov si, #_buffer
pascal@17450 212 cld
pascal@13691 213 mov cx, #BUFFERSZ/2
pascal@13691 214 rep
pascal@13691 215 movsw
pascal@17450 216 xchg di, _setupofs
pascal@17160 217 pop si
pascal@13691 218 #endasm
pascal@13691 219 }
pascal@13691 220
pascal@14257 221 static unsigned getcs(void)
pascal@14257 222 {
pascal@14257 223 #asm
pascal@14257 224 mov ax, cs
pascal@14257 225 #endasm
pascal@14257 226 }
pascal@14257 227
pascal@17450 228 #define WORD(x) * (unsigned short *) (x)
pascal@17450 229 #define LONG(x) * (unsigned long *) (x)
pascal@17450 230 static unsigned setup_version = 0;
pascal@17160 231 static unsigned long kernel_version = 0;
pascal@14257 232 unsigned long loadkernel(void)
pascal@13691 233 {
pascal@17450 234 unsigned setup;
pascal@17450 235 #define LINUX001_SUPPORT
pascal@17450 236 #ifdef LINUX001_SUPPORT
pascal@17450 237 unsigned n = 512;
pascal@17450 238 #else
pascal@17450 239 unsigned n = BUFFERSZ;
pascal@17450 240 #endif
pascal@17160 241 unsigned long syssize = 0;
pascal@13691 242
pascal@13691 243 do {
pascal@13691 244 isoread(buffer, n);
pascal@13691 245 if (setupofs == 0) {
pascal@17450 246 if (WORD(buffer + BOOTFLAG) != 0xAA55)
pascal@13691 247 die("The kernel is not bootable");
pascal@17160 248 #asm
pascal@17160 249 int 0x12
pascal@17160 250 jc has640k
pascal@17160 251 dec ax
pascal@17160 252 and al, #0xC0
pascal@17160 253 mov cl, #6
pascal@17160 254 shl ax, cl
pascal@17160 255 cmp ax, _setupseg
pascal@17160 256 jnc has640k
pascal@17160 257 mov _setupseg, ax
pascal@17160 258 has640k:
pascal@17160 259 #endasm
pascal@17450 260 syssize = LONG(buffer + SYSSIZE) << 4;
pascal@17450 261 if (!syssize) syssize = 0x7F000;
pascal@13691 262 setup = (1 + buffer[SETUPSECTORS]) << 9;
pascal@17450 263 if (setup == 512) {
pascal@17450 264 #ifdef LINUX001_SUPPORT
pascal@17450 265 if (WORD(buffer + 0x3F) == 0x3AE8) /* linux 0.01 */
pascal@17450 266 goto linux001;
pascal@17450 267 #endif
pascal@17450 268 setup = 5 << 9;
pascal@17450 269 }
pascal@17450 270 #ifdef LINUX001_SUPPORT
pascal@17450 271 n = BUFFERSZ;
pascal@17450 272 isoread(buffer+512, BUFFERSZ-512);
pascal@17450 273 #endif
pascal@13691 274 #define HDRS 0x53726448
pascal@17450 275 if (LONG(buffer + HEADER) == HDRS)
pascal@17450 276 setup_version = WORD(buffer + VERSION);
pascal@17160 277 #define ELKS 0x534B4C45
pascal@17450 278 if (LONG(buffer + ELKSSIG) == ELKS)
pascal@17160 279 iselks = 1;
pascal@16022 280 if (setup_version < 0x204)
pascal@13733 281 syssize &= 0x000FFFFFUL;
pascal@16022 282 if (setup_version) {
pascal@13733 283 #ifdef REALMODE_SWITCH
pascal@13733 284 extern int far_realmode_switch();
pascal@13733 285 #asm
pascal@13733 286 jmp end_realmode_switch
pascal@13733 287 _far_realmode_switch:
pascal@14257 288 call REALMODE_SWITCH
pascal@13733 289 cli
pascal@13733 290 mov al, #0x80 // Disable NMI
pascal@13733 291 out 0x70, al
pascal@13733 292 retf
pascal@13733 293 end_realmode_switch:
pascal@13733 294 #endasm
pascal@17450 295 WORD(buffer + RMSWOFS) = far_realmode_switch;
pascal@17450 296 WORD(buffer + RMSWSEG) = getcs();
pascal@13733 297 #endif
pascal@17450 298 mem.base = LONG(buffer + SYSTEMCODE);
pascal@17450 299 WORD(buffer + HEAPPTR) = 0x9B00;
pascal@13733 300 // buffer[LOADFLAGS] |= 0x80;
pascal@17450 301 WORD(buffer + LOADERTYPE) |= 0x80FF;
pascal@13733 302 }
pascal@17450 303 #ifdef LINUX001_SUPPORT
pascal@17450 304 linux001:
pascal@17450 305 #endif
pascal@16022 306 if (!setup_version || !(buffer[LOADFLAGS] & 1)) {
pascal@16041 307 zimage = getss() + 0x1000;
pascal@16041 308 mem.base = zimage * 16L;
pascal@17160 309 if (mem.base + syssize > setupseg*16L - 32) {
pascal@17450 310 zimage = 0x9311;
pascal@17160 311 mem.base = 0x110000L; // 1M + 64K HMA
pascal@17160 312 }
pascal@13691 313 }
pascal@13691 314 }
pascal@13691 315 movesetup();
pascal@13691 316 setup -= n;
pascal@13691 317 n = (setup > BUFFERSZ) ? BUFFERSZ : setup;
pascal@13691 318 } while (setup > 0);
pascal@13691 319
pascal@14257 320 #asm
pascal@17160 321 push si
pascal@17160 322 mov si, #0x200
pascal@17160 323 cmp si, _setup_version
pascal@17160 324 jae noversion
pascal@17450 325 mov es, _setupseg
pascal@17450 326 seg es
pascal@14257 327 add si, [si+14]
pascal@17450 328 mov bx, #2
pascal@17450 329 mov cl, #4
pascal@17450 330 nextnumber:
pascal@17450 331 xor ax, ax
pascal@14257 332 nextdigit:
pascal@17450 333 shl al, cl
pascal@17450 334 shl ax, cl
pascal@17450 335 seg es
pascal@14257 336 lodsb
pascal@14257 337 sub al, #0x30
pascal@14257 338 cmp al, #9
pascal@14257 339 jbe nextdigit
pascal@17450 340 mov [bx+_kernel_version], ah
pascal@17450 341 dec bx
pascal@17450 342 jns nextnumber
pascal@14257 343 noversion:
pascal@17160 344 pop si
pascal@14257 345 #endasm
pascal@16022 346 load(syssize);
pascal@14268 347 return kernel_version;
pascal@13691 348 }
pascal@13691 349
pascal@13691 350 void loadinitrd(void)
pascal@13691 351 {
pascal@17160 352 if (setup_version)
pascal@16022 353 load(isofilesize);
pascal@13691 354 }
pascal@13691 355
pascal@13691 356 void bootlinux(char *cmdline)
pascal@13691 357 {
pascal@17160 358 dosshutdown();
pascal@13691 359 #asm
pascal@17450 360 cld
pascal@17160 361 mov es, _setupseg
pascal@17450 362 mov ax, _setup_version
pascal@17450 363 cmp ax, #0x200
pascal@17450 364 jb noinitrd
pascal@17450 365 mov di, #0x218
pascal@17450 366 mov si, #_initrd_addr
pascal@17450 367 movsw
pascal@17450 368 movsw
pascal@17450 369 mov si, #_initrd_size
pascal@17450 370 movsw
pascal@17450 371 movsw
pascal@17450 372 noinitrd:
pascal@17460 373 mov si, [bp+4] // .bootlinux.cmdline[bp]
pascal@17450 374 or si, si
pascal@17450 375 jz nocmdline
pascal@17450 376 cmp ax, #0x201
pascal@13691 377 mov di, #0x0020
pascal@13691 378 mov ax, #0xA33F
pascal@17450 379 mov bx, #CMDLINE_OFFSET
pascal@17450 380 push bx
pascal@17450 381 jbe oldcmdline
pascal@17450 382 mov di, #0x0228
pascal@17450 383 mov ax, es
pascal@17450 384 mov cl, #12
pascal@17450 385 shr ax, cl
pascal@17450 386 xchg ax, bx
pascal@17450 387 oldcmdline:
pascal@13691 388 stosw
pascal@17450 389 xchg ax, bx
pascal@13691 390 stosw
pascal@17450 391 pop di
pascal@13691 392 copy:
pascal@13691 393 lodsb
pascal@13691 394 stosb
pascal@13691 395 or al,al
pascal@13691 396 jne copy
pascal@17450 397 nocmdline:
pascal@16025 398 push es
pascal@16025 399 pop ss
pascal@16025 400 mov sp, #CMDLINE_OFFSET
pascal@17160 401 mov ax, _mem
pascal@17160 402 mov dx, _mem+2
pascal@16041 403 mov bx, _zimage
pascal@17160 404 mov bp, _iselks
pascal@17160 405 mov si, #sysmove
pascal@17160 406 mov di, #SETUP_END
pascal@17160 407 mov cx, #endsysmove-sysmove
pascal@16041 408 or bx, bx
pascal@16041 409 jz notzimage
pascal@16022 410 push cs
pascal@16022 411 pop ds
pascal@16022 412 push es
pascal@16022 413 push di
pascal@16022 414 rep
pascal@16022 415 movsb
pascal@16022 416 retf
pascal@16022 417 sysmove:
pascal@17160 418 cmp dx, #0x0010
pascal@17160 419 jb lowsys
pascal@17160 420 // bx first 64k page, dx:ax last byte+1
pascal@17160 421 xchg ax, cx // clear ax
pascal@17160 422 jcxz aligned
pascal@16022 423 inc dx
pascal@17160 424 aligned:
pascal@16069 425 mov si, di
pascal@16069 426 mov cx, #0x18
pascal@16069 427 rep
pascal@16069 428 stosw
pascal@17160 429 push es
pascal@17160 430 pop ds
pascal@16069 431 dec cx
pascal@17160 432 mov [si+0x10], cx // limit = -1
pascal@17160 433 mov [si+0x18], cx // limit = -1
pascal@17160 434 mov cx, #0x9300+SYSTEM_SEGMENT/0x1000
pascal@17450 435 //mov bh, #0x93
pascal@16069 436 mvdown:
pascal@16069 437 mov [si+0x12+2], bx // srce
pascal@17160 438 mov [si+0x1A+2], cx // dest
pascal@17473 439 use16 286 // more than 1Mb => 286+
pascal@17473 440 pusha
pascal@16069 441 mov cx, #0x8000
pascal@16069 442 mov ah, #0x87
pascal@17160 443 int 0x15
pascal@16069 444 popa
pascal@17473 445 use16 86
pascal@16069 446 inc bx
pascal@17160 447 inc cx
pascal@17160 448 cmp dl, bl
pascal@17161 449 ja mvdown
pascal@17160 450 jmp notzimage
pascal@17160 451 lowsys:
pascal@17160 452 // bx first segment, dx:ax last byte+1 (paragraph aligned)
pascal@17450 453 mov cl, #4 // elks may run on a 8086
pascal@17160 454 shr ax, cl
pascal@17160 455 shl dx, cl
pascal@17450 456 or ah, dl // last segment+1
pascal@17160 457 mov dx, #SYSTEM_SEGMENT
pascal@17160 458 sub ax, bx // ax = paragraph count
pascal@17160 459 sub bx, dx
pascal@17160 460 jnc sysmovelp
pascal@17160 461 add dx, ax // top down
pascal@17160 462 dec dx
pascal@17160 463 sysmovelp: // move ax paragraphs from bx+dx:0 to dx:0
pascal@17160 464 mov es, dx
pascal@17450 465 mov si, dx
pascal@17450 466 add si, bx
pascal@17450 467 mov ds, si
pascal@17450 468 sbb si, si // si = 0 : -1
pascal@17160 469 cmc // C = 1 : 0
pascal@17450 470 adc dx, si
pascal@17450 471 mov cl, #8
pascal@17160 472 xor di, di
pascal@17160 473 xor si, si
pascal@17160 474 rep
pascal@17160 475 movsw
pascal@17160 476 dec ax
pascal@17160 477 jne sysmovelp
pascal@16041 478 notzimage:
pascal@17450 479 mov ax, ss
pascal@17450 480 mov ds, ax
pascal@17450 481 dec bp
pascal@17450 482 jnz notelks
pascal@17450 483 mov ah, #0x1
pascal@17450 484 mov ss, ax
pascal@17450 485 notelks:
pascal@17160 486 push ss
pascal@17450 487 pop es
pascal@17450 488 xor di, di
pascal@17160 489 xor si, si
pascal@17450 490 #ifdef LINUX001_SUPPORT
pascal@17450 491 mov cx, #0x0042
pascal@17450 492 cmp word ptr [si+0x3F], #0x3AE8
pascal@17450 493 je islinux001
pascal@17450 494 #endif
pascal@17450 495 mov cx, #0x7800 // do not overload SYSTEM_SEGMENT
pascal@17160 496 rep
pascal@17160 497 movsw
pascal@17450 498 push es
pascal@17450 499 pop ds
pascal@17450 500 xor al, #0x20
pascal@17450 501 islinux001:
pascal@17160 502 push ax
pascal@17450 503 push cx
pascal@17160 504 retf
pascal@16022 505 endsysmove:
pascal@13691 506 #endasm
pascal@13691 507 }