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

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