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

syslinux/iso2exe: check ISO md5
author Pascal Bellard <pascal.bellard@slitaz.org>
date Sat Jan 03 21:41:48 2015 +0100 (2015-01-03)
parents 6aed6fc5819d
children
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@17489 142 static unsigned vgamode, 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@17489 263 vgamode = WORD(buffer + VIDEOMODE);
pascal@17450 264 if (setup == 512) {
pascal@17450 265 #ifdef LINUX001_SUPPORT
pascal@17450 266 if (WORD(buffer + 0x3F) == 0x3AE8) /* linux 0.01 */
pascal@17450 267 goto linux001;
pascal@17450 268 #endif
pascal@17450 269 setup = 5 << 9;
pascal@17450 270 }
pascal@17450 271 #ifdef LINUX001_SUPPORT
pascal@17450 272 n = BUFFERSZ;
pascal@17450 273 isoread(buffer+512, BUFFERSZ-512);
pascal@17450 274 #endif
pascal@13691 275 #define HDRS 0x53726448
pascal@17450 276 if (LONG(buffer + HEADER) == HDRS)
pascal@17450 277 setup_version = WORD(buffer + VERSION);
pascal@17160 278 #define ELKS 0x534B4C45
pascal@17450 279 if (LONG(buffer + ELKSSIG) == ELKS)
pascal@17160 280 iselks = 1;
pascal@16022 281 if (setup_version < 0x204)
pascal@13733 282 syssize &= 0x000FFFFFUL;
pascal@16022 283 if (setup_version) {
pascal@13733 284 #ifdef REALMODE_SWITCH
pascal@13733 285 extern int far_realmode_switch();
pascal@13733 286 #asm
pascal@13733 287 jmp end_realmode_switch
pascal@13733 288 _far_realmode_switch:
pascal@14257 289 call REALMODE_SWITCH
pascal@13733 290 cli
pascal@13733 291 mov al, #0x80 // Disable NMI
pascal@13733 292 out 0x70, al
pascal@13733 293 retf
pascal@13733 294 end_realmode_switch:
pascal@13733 295 #endasm
pascal@17450 296 WORD(buffer + RMSWOFS) = far_realmode_switch;
pascal@17450 297 WORD(buffer + RMSWSEG) = getcs();
pascal@13733 298 #endif
pascal@17450 299 mem.base = LONG(buffer + SYSTEMCODE);
pascal@17450 300 WORD(buffer + HEAPPTR) = 0x9B00;
pascal@13733 301 // buffer[LOADFLAGS] |= 0x80;
pascal@17450 302 WORD(buffer + LOADERTYPE) |= 0x80FF;
pascal@13733 303 }
pascal@17450 304 #ifdef LINUX001_SUPPORT
pascal@17450 305 linux001:
pascal@17450 306 #endif
pascal@16022 307 if (!setup_version || !(buffer[LOADFLAGS] & 1)) {
pascal@16041 308 zimage = getss() + 0x1000;
pascal@16041 309 mem.base = zimage * 16L;
pascal@17160 310 if (mem.base + syssize > setupseg*16L - 32) {
pascal@17450 311 zimage = 0x9311;
pascal@17160 312 mem.base = 0x110000L; // 1M + 64K HMA
pascal@17160 313 }
pascal@13691 314 }
pascal@13691 315 }
pascal@13691 316 movesetup();
pascal@13691 317 setup -= n;
pascal@13691 318 n = (setup > BUFFERSZ) ? BUFFERSZ : setup;
pascal@13691 319 } while (setup > 0);
pascal@13691 320
pascal@14257 321 #asm
pascal@17160 322 push si
pascal@17160 323 mov si, #0x200
pascal@17160 324 cmp si, _setup_version
pascal@17160 325 jae noversion
pascal@17450 326 mov es, _setupseg
pascal@17450 327 seg es
pascal@14257 328 add si, [si+14]
pascal@17450 329 mov bx, #2
pascal@17450 330 mov cl, #4
pascal@17450 331 nextnumber:
pascal@17450 332 xor ax, ax
pascal@14257 333 nextdigit:
pascal@17450 334 shl al, cl
pascal@17450 335 shl ax, cl
pascal@17450 336 seg es
pascal@14257 337 lodsb
pascal@14257 338 sub al, #0x30
pascal@14257 339 cmp al, #9
pascal@14257 340 jbe nextdigit
pascal@17450 341 mov [bx+_kernel_version], ah
pascal@17450 342 dec bx
pascal@17450 343 jns nextnumber
pascal@14257 344 noversion:
pascal@17160 345 pop si
pascal@14257 346 #endasm
pascal@16022 347 load(syssize);
pascal@14268 348 return kernel_version;
pascal@13691 349 }
pascal@13691 350
pascal@13691 351 void loadinitrd(void)
pascal@13691 352 {
pascal@17160 353 if (setup_version)
pascal@16022 354 load(isofilesize);
pascal@13691 355 }
pascal@13691 356
pascal@13691 357 void bootlinux(char *cmdline)
pascal@13691 358 {
pascal@17489 359 char *s;
pascal@17489 360
pascal@17489 361 s = strstr(cmdline," vga=");
pascal@17489 362 if (s) {
pascal@17489 363 vgamode = -1;
pascal@17489 364 s += 5;
pascal@17489 365 switch (*s | 0x20) {
pascal@17489 366 case 'a' : vgamode--;
pascal@17489 367 case 'e' : vgamode--;
pascal@17489 368 case 'n' : break;
pascal@17489 369 default : vgamode = atoi(s);
pascal@17489 370 }
pascal@17489 371 }
pascal@17160 372 dosshutdown();
pascal@13691 373 #asm
pascal@17450 374 cld
pascal@17160 375 mov es, _setupseg
pascal@17489 376 mov ax, _vgamode
pascal@17489 377 seg es
pascal@17489 378 mov VIDEOMODE, ax
pascal@17450 379 mov ax, _setup_version
pascal@17450 380 cmp ax, #0x200
pascal@17450 381 jb noinitrd
pascal@17450 382 mov di, #0x218
pascal@17450 383 mov si, #_initrd_addr
pascal@17450 384 movsw
pascal@17450 385 movsw
pascal@17450 386 mov si, #_initrd_size
pascal@17450 387 movsw
pascal@17450 388 movsw
pascal@17450 389 noinitrd:
pascal@17460 390 mov si, [bp+4] // .bootlinux.cmdline[bp]
pascal@17450 391 or si, si
pascal@17450 392 jz nocmdline
pascal@17450 393 cmp ax, #0x201
pascal@13691 394 mov di, #0x0020
pascal@13691 395 mov ax, #0xA33F
pascal@17450 396 mov bx, #CMDLINE_OFFSET
pascal@17450 397 push bx
pascal@17450 398 jbe oldcmdline
pascal@17450 399 mov di, #0x0228
pascal@17450 400 mov ax, es
pascal@17450 401 mov cl, #12
pascal@17450 402 shr ax, cl
pascal@17450 403 xchg ax, bx
pascal@17450 404 oldcmdline:
pascal@13691 405 stosw
pascal@17450 406 xchg ax, bx
pascal@13691 407 stosw
pascal@17450 408 pop di
pascal@13691 409 copy:
pascal@13691 410 lodsb
pascal@13691 411 stosb
pascal@13691 412 or al,al
pascal@13691 413 jne copy
pascal@17450 414 nocmdline:
pascal@16025 415 push es
pascal@16025 416 pop ss
pascal@16025 417 mov sp, #CMDLINE_OFFSET
pascal@17160 418 mov ax, _mem
pascal@17160 419 mov dx, _mem+2
pascal@16041 420 mov bx, _zimage
pascal@17160 421 mov bp, _iselks
pascal@17160 422 mov si, #sysmove
pascal@17160 423 mov di, #SETUP_END
pascal@17160 424 mov cx, #endsysmove-sysmove
pascal@16041 425 or bx, bx
pascal@16041 426 jz notzimage
pascal@16022 427 push cs
pascal@16022 428 pop ds
pascal@16022 429 push es
pascal@16022 430 push di
pascal@16022 431 rep
pascal@16022 432 movsb
pascal@16022 433 retf
pascal@16022 434 sysmove:
pascal@17160 435 cmp dx, #0x0010
pascal@17160 436 jb lowsys
pascal@17160 437 // bx first 64k page, dx:ax last byte+1
pascal@17160 438 xchg ax, cx // clear ax
pascal@17160 439 jcxz aligned
pascal@16022 440 inc dx
pascal@17160 441 aligned:
pascal@16069 442 mov si, di
pascal@16069 443 mov cx, #0x18
pascal@16069 444 rep
pascal@16069 445 stosw
pascal@17160 446 push es
pascal@17160 447 pop ds
pascal@16069 448 dec cx
pascal@17160 449 mov [si+0x10], cx // limit = -1
pascal@17160 450 mov [si+0x18], cx // limit = -1
pascal@17160 451 mov cx, #0x9300+SYSTEM_SEGMENT/0x1000
pascal@17450 452 //mov bh, #0x93
pascal@16069 453 mvdown:
pascal@16069 454 mov [si+0x12+2], bx // srce
pascal@17160 455 mov [si+0x1A+2], cx // dest
pascal@17473 456 use16 286 // more than 1Mb => 286+
pascal@17473 457 pusha
pascal@16069 458 mov cx, #0x8000
pascal@16069 459 mov ah, #0x87
pascal@17160 460 int 0x15
pascal@16069 461 popa
pascal@17473 462 use16 86
pascal@16069 463 inc bx
pascal@17160 464 inc cx
pascal@17160 465 cmp dl, bl
pascal@17161 466 ja mvdown
pascal@17160 467 jmp notzimage
pascal@17160 468 lowsys:
pascal@17160 469 // bx first segment, dx:ax last byte+1 (paragraph aligned)
pascal@17450 470 mov cl, #4 // elks may run on a 8086
pascal@17160 471 shr ax, cl
pascal@17160 472 shl dx, cl
pascal@17450 473 or ah, dl // last segment+1
pascal@17160 474 mov dx, #SYSTEM_SEGMENT
pascal@17160 475 sub ax, bx // ax = paragraph count
pascal@17160 476 sub bx, dx
pascal@17160 477 jnc sysmovelp
pascal@17160 478 add dx, ax // top down
pascal@17160 479 dec dx
pascal@17160 480 sysmovelp: // move ax paragraphs from bx+dx:0 to dx:0
pascal@17160 481 mov es, dx
pascal@17450 482 mov si, dx
pascal@17450 483 add si, bx
pascal@17450 484 mov ds, si
pascal@17450 485 sbb si, si // si = 0 : -1
pascal@17160 486 cmc // C = 1 : 0
pascal@17450 487 adc dx, si
pascal@17450 488 mov cl, #8
pascal@17160 489 xor di, di
pascal@17160 490 xor si, si
pascal@17160 491 rep
pascal@17160 492 movsw
pascal@17160 493 dec ax
pascal@17160 494 jne sysmovelp
pascal@16041 495 notzimage:
pascal@17450 496 mov ax, ss
pascal@17450 497 mov ds, ax
pascal@17450 498 dec bp
pascal@17450 499 jnz notelks
pascal@17450 500 mov ah, #0x1
pascal@17450 501 mov ss, ax
pascal@17450 502 notelks:
pascal@17160 503 push ss
pascal@17450 504 pop es
pascal@17450 505 xor di, di
pascal@17160 506 xor si, si
pascal@17450 507 #ifdef LINUX001_SUPPORT
pascal@17450 508 mov cx, #0x0042
pascal@17450 509 cmp word ptr [si+0x3F], #0x3AE8
pascal@17450 510 je islinux001
pascal@17450 511 #endif
pascal@17450 512 mov cx, #0x7800 // do not overload SYSTEM_SEGMENT
pascal@17160 513 rep
pascal@17160 514 movsw
pascal@17450 515 push es
pascal@17450 516 pop ds
pascal@17450 517 xor al, #0x20
pascal@17450 518 islinux001:
pascal@17160 519 push ax
pascal@17450 520 push cx
pascal@17160 521 retf
pascal@16022 522 endsysmove:
pascal@13691 523 #endasm
pascal@13691 524 }