1 2 ;----------------------------------------------------------------------------- 3 ; ElTorito.asm 4 ; 5 ; El Torito Bootable CD-ROM driver which does not reset the CD-ROM drive upon 6 ; loading, but instead accesses the drive through BIOS system calls 7 ; 8 ; MIT License 9 ; 10 ; (c) 2000 by Gary Tong 11 ; (c) 2001-2009 by Bart Lagerweij 12 ; 13 ; Permission is hereby granted, free of charge, to any person obtaining a copy 14 ; of this software and associated documentation files (the "Software"), to deal 15 ; in the Software without restriction, including without limitation the rights 16 ; to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 17 ; copies of the Software, and to permit persons to whom the Software is 18 ; furnished to do so, subject to the following conditions: 19 ; 20 ; The above copyright notice and this permission notice shall be included in 21 ; all copies or substantial portions of the Software. 22 ; 23 ; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 24 ; IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 25 ; FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 26 ; AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 27 ; LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 28 ; OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 29 ; THE SOFTWARE. 30 ; 31 ;----------------------------------------------------------------------------- 32 33 ; To assemble and link, use these commands with NASM 2.x: 34 ; nasm -Ox -f bin -o eltorito.sys eltorito.asm 35 36 ; To enable Trace markers uncomment the line below 37 ; DEBUG_TRACERS=1 38 39 ; To enable debug info uncomment the line below 40 ; DEBUG=1 41 42 %ifdef DEBUG_TRACERS 43 %macro TRACER 1 44 call debug_tracer 45 db %1 46 %endmacro 47 %else 48 %macro TRACER 1 49 %endmacro 50 %endif ; DEBUG_TRACERS 51 52 %define Ver '1.5' 53 %define CR 0DH, 0Ah 54 RPolyH equ 0EDB8h 55 RPolyL equ 08320h 56 57 section .text align=16 58 org 0 59 60 ;============================================================================= 61 62 Cdrom: 63 64 NextDriver dd -1 ;-+ 65 Attributes dw 0C800h ; | 66 Pointers dw Strategy ; | 67 dw Commands ; | MSCDEX requires this 68 DeviceName db 'ELTORITO' ; | data in these locations 69 dw 0 ; | 70 DriveLetter db 0 ; | 71 NumUnitsSupp db 1 ;-+ 72 73 DriverName db 'El-Torito CD-ROM Device Driver',0 74 align 4, db 0 75 ReqHdrLoc dd 0 76 XferAddr dd 0 77 Checksum dd -1 78 DriveNumber db 0 79 ReadBytes db 0 ;0 --> 2048 bytes/sector 80 ;1 --> 1024 bytes/sector 81 ;2 --> 512 bytes/sector 82 83 Routines dw Init ;Init ;0 84 dw Unsupported ;MediaCheck ;1 85 dw Unsupported ;BuildBPB ;2 86 dw IoctlInput ;IoctlInput ;3 87 dw Unsupported ;Input ;4 88 dw Unsupported ;NonDesInput ;5 89 dw Unsupported ;InputStatus ;6 90 dw Unsupported ;InputFlush ;7 91 dw Unsupported ;Output ;8 92 dw Unsupported ;OutputVerify ;9 93 dw Unsupported ;OutputStatus ;10 94 dw Unsupported ;OutputFlush ;11 95 dw IoctlOutput ;IoctlOutput ;12 96 dw DoNothing ;DeviceOpen ;13 97 dw DoNothing ;DeviceClose ;14 98 dw ReadL ;ReadL ;128 99 100 IoctlICtrl dw Raddr ;Raddr ;0 101 dw Unsupported ;LocHead ;1 102 dw Unsupported ;(Reserved) ;2 103 dw Unsupported ;ErrStat ;3 104 dw Unsupported ;AudInfo ;4 105 dw DrvBytes ;DrvBytes ;5 106 dw DevStat ;DevStat ;6 107 dw SectSize ;SectSize ;7 108 dw VolSize ;VolSize ;8 109 dw MedChng ;MedChng ;9 110 111 SpecPkt times 19 db 0 ; offset 77h in 1.4 112 times 13 db 0 ; unknown extra 00s in 1.4 113 114 Greeting db 'El-Torito Bootable CD-ROM Driver for Dos v',Ver,', http://www.nu2.nu/eltorito/',CR 115 db ' (c) 2000 by Gary Tong',CR 116 db ' (c) 2001-2002 by Bart Lagerweij',CR,0 117 DblSpace db ' ',0 118 119 ;============================================================================= 120 121 Strategy: 122 123 mov word [cs:ReqHdrLoc],bx 124 mov word [cs:ReqHdrLoc+2],es 125 retf 126 127 128 ;============================================================================= 129 130 Commands: 131 132 push ax 133 push bx 134 push cx 135 push dx 136 push si 137 push di 138 push bp 139 ; pushad 140 push ds 141 push es 142 TRACER 'C' 143 144 cld ;Clear direction 145 sti ;Enable interrupts 146 147 mov ax, cs ;ds=cs 148 mov ds, ax 149 150 les bx,[ReqHdrLoc] ;seg:offset ptr into es:bx 151 xor ax,ax 152 mov al,[es:bx+2] ;Get Command code 153 %ifdef DEBUG 154 call print_hex8 155 %endif 156 cmp al,15 157 jb Mult2 ;If 0-14 158 cmp al,128 159 jb UnknownCmd ;If 15-127 160 cmp al,129 161 jb ShiftDown ;If 128 162 UnknownCmd: mov al,121 ;8 = Unsupported (Reserved) 163 ShiftDown: sub al,113 ;128 --> 15, 121 --> 8 164 Mult2: shl al,1 ;Convert into offset (*2) 165 mov di,Routines 166 add di,ax 167 call word [di] ;Execute desired command 168 or ax,100h ;Set Return Status's Done bit 169 lds bx,[ReqHdrLoc] ;seg:offset ptr into ds:bx 170 mov [bx+3],ax ;Save Status 171 172 %ifdef DEBUG 173 cmp byte [cs:buffer+2048], 96h 174 je buffer_ok 175 mov al, '!' 176 call print_char 177 jmp $ 178 buffer_ok: 179 %endif 180 181 TRACER 'c' 182 pop es 183 pop ds 184 ; popad 185 pop bp 186 pop di 187 pop si 188 pop dx 189 pop cx 190 pop bx 191 pop ax 192 retf 193 194 195 ;============================================================================= 196 197 Unsupported: ;Unsupported Command 198 199 mov ax,8003h ;Set Status Error bit, 200 TRACER 'U' 201 TRACER 'C' 202 retn ; Error 3 = Unknown Command 203 204 205 ;============================================================================= 206 207 IoctlInput: ;IOCTL Input Routine 208 209 mov di,[es:bx+14] ;es:bx --> Request Header 210 mov es,[es:bx+16] ;Get Xfer Address into es:di 211 xor ax,ax ;Get Control Block Code 212 mov al,[es:di] 213 %ifdef DEBUG 214 TRACER 'I' 215 TRACER 'O' 216 call print_hex8 217 %endif 218 cmp al,10 219 jb UnkIoctlI ;If 0-9 220 mov al,2 ;Map to Unsupported 221 UnkIoctlI: shl al,1 ;Convert into offset (*2) 222 mov si,IoctlICtrl 223 add si,ax 224 call word [si] ;Execute desired command 225 retn 226 227 228 ;============================================================================= 229 230 Raddr: ;Return Device Header Address 231 232 TRACER 'A' 233 mov word [es:di+1],0 234 mov [es:di+3],cs 235 xor ax, ax ;Set Return Status = success 236 TRACER 'a' 237 retn 238 239 240 ;============================================================================= 241 242 DrvBytes: ;Read Drive Bytes 243 244 TRACER 'B' 245 push di ;Save original Xfer Addr 246 add di,2 ;Point to 1st dest byte 247 mov si,Greeting ;Point to Greeting 248 DrvB: movsb ;Copy over a byte 249 cmp byte [si],13 ;Is next char a CR? 250 jne DrvB ;Loop if not 251 252 sub di,2 ;Get #bytes copied into ax 253 mov ax,di 254 pop di ;Retrieve original Xfer Addr 255 sub ax,di 256 mov byte [es:di+1],al ;and save it 257 mov ax,0 ;Set Return Status = success 258 TRACER 'b' 259 retn 260 261 262 ;============================================================================= 263 264 DevStat: ;Return Device Status 265 266 TRACER 'D' 267 mov word [es:di+1],202h ;Door closed 268 mov word [es:di+3],0 ;Door unlocked 269 ;Supports only cooked reading 270 ;Read only 271 ;Data read only 272 ;No interleaving 273 ;No prefetching 274 ;No audio channel manipulation 275 ;Supports both HSG and Redbook 276 ; addressing modes 277 278 xor ax, ax ;Set Return Status = success 279 TRACER 'd' 280 retn 281 282 283 ;============================================================================= 284 285 SectSize: ;Return Sector Size 286 287 TRACER 'S' 288 mov word [es:di+2],2048 289 mov ax,0 ;Set Return Status = success 290 TRACER 's' 291 retn 292 293 294 ;============================================================================= 295 296 VolSize: ;Return Volume Size 297 298 TRACER 'V' 299 call PriVolDesc ;Get and Check Primary Volume 300 ; Descriptor 301 mov ax,800Fh ;Assume Invalid Disk Change 302 jc VolExit ;If Read Failure 303 304 mov ax,word [Buffer+80] ;Read Successful 305 mov word [es:di+1],ax ;Copy over Volume Size 306 mov ax,word [Buffer+82] 307 mov word [es:di+3],ax 308 mov ax,0 ;Set Return Status = success 309 VolExit: 310 TRACER 'v' 311 retn 312 313 314 ;============================================================================= 315 316 MedChng: ;Return Media Changed Status 317 318 TRACER 'M' 319 call PriVolDesc ;Get and Check Primary Volume 320 ; Descriptor 321 mov byte [es:di+1],-1 ;Assume Media Changed 322 mov ax,800Fh ; and Invalid Disk Change 323 jc MedExit ;If Media Changed or Bad 324 325 mov byte [es:di+1],1 ;Media has not changed 326 mov ax,0 ;Set Return Status = success 327 MedExit: 328 TRACER 'm' 329 retn 330 331 332 ;============================================================================= 333 334 PriVolDesc: ;Get and Check Primary Volume 335 ; Descriptor 336 TRACER 'P' 337 mov ax,cs ;Set ds:si --> SpecPkt 338 mov ds,ax 339 340 mov cx, 5 341 PriVolAgain: 342 mov byte [SpecPkt],16 ;SpecPkt Size 343 mov byte [SpecPkt+1],0 ;Reserved 344 mov word [SpecPkt+2],1 ;Transfer one 2048-byte sector 345 push cx 346 mov cl,byte [ReadBytes] ;Multiply by 4 if reading 512 347 shl word [SpecPkt+2],cl ; bytes at a time 348 pop cx 349 mov word [SpecPkt+6],cs ;Into our Buffer 350 mov word [SpecPkt+4], Buffer 351 mov word [SpecPkt+8],16 ;From CD Sector 16 352 mov word [SpecPkt+10],0 353 mov word [SpecPkt+12],0 354 mov word [SpecPkt+14],0 355 356 mov si, SpecPkt 357 mov dl, [DriveNumber] 358 mov ah, 42h ;Extended Read 359 int 13h 360 jnc PriVolPass ;If success 361 362 ; TRACER '1' 363 ; read error 364 loop PriVolAgain 365 366 TRACER '2' 367 ; read retries exhausted 368 ; flow into below 369 jmp PriReadErr 370 371 PriVolPass: 372 mov si,Buffer ;Point input to Buffer 373 mov ax,-1 ;Init Checksum registers 374 mov bx,ax ; bx,ax = 0FFFFFFFFh 375 jc PriNew ;If Read Failure 376 377 push di ;Read Successful, 378 ; so Calculate Checksum 379 mov di,1024 ;Init Word counter 380 PriWord: mov dx,[cs:si] ;Grab next word from buffer 381 mov cx,16 ;Init bit counter 382 PriBit: shr dx,1 ;Shift everything right 1 bit 383 rcr bx,1 384 rcr ax,1 385 jnc NoMult ;If a zero shifted out 386 387 xor bx,RPolyH ;A one shifted out, so XOR 388 xor ax,RPolyL ; Checksum with RPoly 389 NoMult: 390 loop PriBit 391 392 add si,2 ;Inc Word Pointer 393 dec di 394 ja PriWord 395 TRACER '3' 396 397 pop di ;Checksum calculation complete 398 cmp bx,[Checksum+2] ;Has Checksum changed? 399 jne PriNew ;If Checksum Changed 400 401 cmp ax,[Checksum] 402 jne PriNew ;If Checksum Changed 403 404 clc ;Checksum not changed, CF=0 405 mov ax,0 ;Status = success 406 jmp PriOld 407 408 PriReadErr: 409 mov WORD [Checksum+2],bx ;Save New Checksum 410 mov [Checksum],ax ; or 0FFFFFFFFh if bad read 411 stc ;Checksum change, CF=1 412 mov ax, 800bh ;Status = read fault 413 jmp PriOld 414 415 PriNew: mov WORD [Checksum+2],bx ;Save New Checksum 416 mov [Checksum],ax ; or 0FFFFFFFFh if bad read 417 stc ;Checksum Changed, CF=1 418 mov ax,800Fh ;Status = Invalid Media Change 419 PriOld: 420 TRACER 'p' 421 retn 422 423 424 ;============================================================================= 425 426 IoctlOutput: ;IOCTL Output Routine 427 428 TRACER 'O' 429 mov di,[es:bx+14] ;es:bx --> Request Header 430 mov es,[es:bx+16] ;Get Xfer Address into es:di 431 xor ax,ax ;Get Control Block Code 432 mov al,[es:di] 433 cmp al,2 434 jne UnkIoctlO ;If not 2 (ResetDrv) 435 call DoNothing ;Reset Drive 436 jmp IoctlODone 437 UnkIoctlO: 438 call Unsupported ;Unsupported command 439 IoctlODone: 440 TRACER 'o' 441 retn 442 443 444 ;============================================================================= 445 446 DoNothing: ;Do Nothing Command 447 448 mov ax,0 ;Set Return Status = success 449 retn 450 451 452 ;============================================================================= 453 454 ReadL: ;Read Long Command 455 456 TRACER 'R' 457 mov ax,cs ;Set ds=cs 458 mov ds,ax 459 ;es:bx --> Request Header 460 cmp byte [es:bx+24],0 ;Check Data Read Mode 461 jne ReadLErr ;If Cooked Mode 462 463 cmp byte [es:bx+13],2 ;Check Addressing Mode 464 jb ReadLOK ;If HSG or Redbook Mode 465 466 ReadLErr: 467 TRACER '8' 468 mov ax,8003h ;Set Return Status = Unknown 469 jmp ReadLExit ; Command Error and exit 470 471 ReadLOK: 472 mov ax,[es:bx+20] ;Get Starting Sector Number, 473 mov dx,[es:bx+22] ; Assume HSG Addressing Mode 474 cmp byte [es:bx+13],0 ;Check Addressing Mode again 475 je ReadLHSG ;If HSG Addressing Mode 476 477 TRACER '7' 478 ;Using Redbook Addressing Mode. Convert to HSG format 479 mov al,dl ;Get Minutes 480 mov dl,60 481 mul dl ;ax = Minutes * 60 482 add al,byte [es:bx+21] ;Add in Seconds 483 adc ah,0 484 mov dx,75 ;dx:ax = 485 mul dx ; ((Min * 60) + Sec) * 75 486 add al,byte [es:bx+20] ;Add in Frames 487 adc ah,0 488 adc dx,0 489 sub ax,150 ;Subtract 2-Second offset 490 sbb dx,0 ;dx:ax = HSG Starting Sector 491 492 ReadLHSG: 493 mov word [SpecPkt+8], ax ;Store Starting 494 mov word [SpecPkt+10], dx ; Sector Number 495 mov word [SpecPkt+12], 0 ; (HSG Format) 496 mov word [SpecPkt+14], 0 497 498 mov ax,[es:bx+14] ;Get Transfer Address 499 mov word [SpecPkt+4],ax 500 mov ax,[es:bx+16] 501 mov word [SpecPkt+6],ax 502 503 mov byte [SpecPkt],16 ;Size of Disk Address Packet 504 mov byte [SpecPkt+1],0 ;Reserved 505 506 mov cx, 5 507 ReadLAgain: 508 mov ax,[es:bx+18] ;Get number of sectors to read 509 mov word [SpecPkt+2],ax 510 cmp ax, 3FFFh ;Too large? 511 ja ReadLBad ;If yes 512 513 push cx 514 mov cl,byte [ReadBytes] ;Multiply by 4 if reading 512 515 shl word [SpecPkt+2],cl ; bytes at a time 516 pop cx 517 518 %ifdef DEBUG 519 push ax 520 push cx 521 push si 522 mov cx, 16 523 mov si,SpecPkt 524 ReadDump: mov al, ' ' 525 call print_char 526 mov al, byte [si] ;Hexdump a SpecPkt byte 527 call print_hex8 528 inc si ;Point to next byte 529 loop ReadDump 530 pop si 531 pop cx 532 pop ax 533 %endif 534 mov si,SpecPkt 535 mov dl,[DriveNumber] 536 mov ah,42h ;Extended Read 537 int 13h 538 jnc ReadLGd ;If success 539 540 ;hang: 541 ; jmp hang 542 ; TRACER '1' 543 loop ReadLAgain 544 TRACER '2' 545 jmp short ReadLBad 546 ReadLGd: 547 TRACER '3' 548 xor ax, ax ;Status 0 = success 549 jmp short ReadLExit 550 551 ReadLBad: 552 TRACER '9' 553 mov ax, 800Bh ;Set Read Fault Error 554 ; flow into ReadLExit 555 ReadLExit: 556 TRACER 'r' 557 retn 558 559 560 561 %ifdef DEBUG_TRACERS 562 debug_tracer: pushad 563 pushfd 564 565 mov al, '[' 566 mov ah,0Eh ;BIOS video teletype output 567 xor bh, bh 568 int 10h ;Print it 569 570 mov bp,sp 571 mov bx,[bp+9*4] ; Get return address 572 mov al,[cs:bx] ; Get data byte 573 inc word [bp+9*4] ; Return to after data byte 574 575 mov ah,0Eh ;BIOS video teletype output 576 xor bh, bh 577 int 10h ;Print it 578 579 mov al, ']' 580 mov ah,0Eh ;BIOS video teletype output 581 xor bh, bh 582 int 10h ;Print it 583 584 popfd 585 popad 586 retn 587 %endif 588 589 ;----------------------------------------------------------------------------- 590 ; PRINT_HEX4 591 ;----------------------------------------------------------------------------- 592 ; print a 4 bits integer in hex 593 ; 594 ; Input: 595 ; AL - 4 bits integer to print (low) 596 ; 597 ; Output: None 598 ; 599 ; Registers destroyed: None 600 ; 601 print_hex4: 602 603 push ax 604 and al, 0fh ; we only need the first nibble 605 cmp al, 10 606 jae hex_A_F 607 add al, '0' 608 jmp hex_0_9 609 hex_A_F: 610 add al, 'A'-10 611 hex_0_9: 612 call print_char 613 pop ax 614 retn 615 616 617 ;----------------------------------------------------------------------------- 618 ; print_hex8 619 ;----------------------------------------------------------------------------- 620 ; print a 8 bits integer in hex 621 ; 622 ; Input: 623 ; AL - 8 bits integer to print 624 ; 625 ; Output: None 626 ; 627 ; Registers destroyed: None 628 ; 629 print_hex8: 630 631 push ax 632 push bx 633 634 mov ah, al 635 shr al, 4 636 call print_hex4 637 638 mov al, ah 639 and al, 0fh 640 call print_hex4 641 642 pop bx 643 pop ax 644 retn 645 646 647 ;============================================================================= 648 ; print_hex16 - print a 16 bits integer in hex 649 ; 650 ; Input: 651 ; AX - 16 bits integer to print 652 ; 653 ; Output: None 654 ; 655 ; Registers destroyed: None 656 ;============================================================================= 657 print_hex16: 658 659 push ax 660 push bx 661 push cx 662 663 mov cx, 4 664 print_hex16_loop: 665 rol ax, 4 666 call print_hex4 667 loop print_hex16_loop 668 669 pop cx 670 pop bx 671 pop ax 672 retn 673 674 ;============================================================================= 675 ; print_hex32 - print a 32 bits integer in hex 676 ; 677 ; Input: 678 ; EAX - 32 bits integer to print 679 ; 680 ; Output: None 681 ; 682 ; Registers destroyed: None 683 ;============================================================================= 684 print_hex32: 685 686 push eax 687 push bx 688 push cx 689 690 mov cx, 8 691 print_hex32_loop: 692 rol eax, 4 693 call print_hex4 694 loop print_hex32_loop 695 696 pop cx 697 pop bx 698 pop eax 699 retn 700 701 ;============================================================================= 702 ; print_string - print string at current cursor location 703 ; 704 ; Input: 705 ; DS:SI - ASCIIZ string to print 706 ; 707 ; Output: None 708 ; 709 ; Registers destroyed: None 710 ;============================================================================= 711 print_string: 712 push ax 713 push si 714 715 print_string_again: 716 mov al, [si] 717 or al, al 718 jz print_string_exit 719 call print_char 720 inc si 721 jmp print_string_again 722 723 print_string_exit: 724 pop si 725 pop ax 726 retn 727 728 ;----------------------------------------------------------------------------- 729 ; PRINT_CHAR 730 ;----------------------------------------------------------------------------- 731 ; Print's a character at current cursor position 732 ; 733 ; Input: 734 ; AL - Character to print 735 ; 736 ; Output: None 737 ; 738 ; Registers destroyed: None 739 ; 740 print_char: 741 742 push ax 743 push bx 744 745 mov ah,0Eh ;BIOS video teletype output 746 xor bh, bh 747 int 10h ;Print it 748 749 print_char_exit: 750 pop bx 751 pop ax 752 retn 753 754 755 ;============================================================================= 756 757 ;This space is used as a 2048-byte read buffer plus one test byte. 758 ;The 96h data is used for testing the number of bytes returned by an Extended 759 ; CD-ROM sector read 760 761 align 16, db 0 762 Buffer times 2049 db 96h 763 764 ;============================================================================= 765 766 Init: ;Initialization Routine 767 768 TRACER 'I' 769 mov ax,cs ;ds=cs 770 mov ds,ax 771 772 %ifdef DEBUG 773 ; print CS value (load segment) 774 call print_hex16 775 %endif 776 777 mov si, Greeting ;Display Greeting 778 call print_string 779 780 mov ax,Unsupported ;Init is executed only once 781 mov [Routines],ax 782 783 mov ax, 5400h 784 int 13h ; Get diskemu status 785 jc FindBoot ; If CF=1 no diskemu loaded 786 787 mov [DriveNumber], cl ; Store drive number 788 789 call keyflag 790 and al, 8 ; alt key ? 791 jz extread 792 793 mov si, DrvNumMsg ; Display "drive number=" 794 call print_string 795 mov al, [DriveNumber] 796 call print_hex8 797 mov si, LineEnd ; CR/LF 798 call print_string 799 jmp extread 800 801 ; Diskemu is not loaded 802 ; so loop to find drive number 803 ; *** start of 1.4 changes *** 804 ; ??? mov dl, 0ffh ;Start at Drive 0xff 805 ; *** FindBoot at c47 in 1.4, at c0c in 1.3 *** 806 FindBoot: call ScanDrives ; call new helper in 1.4 807 jnc FoundBoot ; ded*df3 808 ; mov si,offset SpecPkt ;Locate booted CD-ROM drive 809 ; mov [SpecPkt],0 ;Clear 1st byte of SpecPkt 810 ; mov ax,4B01h ;Get Bootable CD-ROM Status 811 ; int 13h 812 ; jnc FindPass ;If booted CD found 813 ; 814 ; Carry is not cleared in buggy Dell BIOSes, 815 ; so I'm checking packet size byte 816 ; some bogus bioses (Dell Inspiron 2500) returns packet size 0xff when failed 817 ; Dell Dimension XPsT returns packet size 0x14 when OK 818 819 ; cmp [SpecPkt], 0 820 ; jne FoundBoot 821 822 ; cmp [SpecPkt], 13h ; anything between 13h and 20h should be OK 823 ; jb FindFail 824 ; cmp [SpecPkt], 20h 825 ; ja FindFail 826 ; jmp short FoundBoot 827 ; 828 ; FindFail: 829 ; dec dl ;Next drive 830 ; cmp dl, 80h 831 ; jae FindBoot ;Check from ffh..80h 832 ; *** end of 1.4 changes *** 833 834 mov si,NoBootCD ;No booted CD found, 835 call print_string 836 jmp NoEndAddr ;Do not install driver 837 838 FoundBoot: 839 ; mov dl, [SpecPkt+2] ; 1.4 change 840 ; *** next line at c57 in 1.4, at c3d in 1.3 *** 841 mov [DriveNumber],dl ;Booted CD-ROM found, 842 ; so save Drive # 843 844 call keyflag 845 and al, 8 ; alt key ? 846 jz extread 847 848 mov si, CDStat 849 call print_string 850 mov si, SpecPkt ;Point to returned CD SpecPkt 851 mov cx, 19 ; containing 19 bytes 852 StatDump: mov al, ' ' ;Print a space 853 call print_char 854 mov al, byte [si] ;Hexdump a SpecPkt byte 855 call print_hex8 856 inc si ;Point to next byte 857 loop StatDump 858 859 mov si, LineEnd ;Print a CR/LF 860 call print_string 861 862 extread: 863 ;See how many CD Sector bytes are returned by an Extended Read 864 mov byte [SpecPkt],16 ;SpecPkt Size 865 mov byte [SpecPkt+1],0 ;Reserved 866 mov word [SpecPkt+2],1 ;Transfer one sector 867 mov word [SpecPkt+6],cs ;Into our Buffer 868 mov word [SpecPkt+4],Buffer 869 mov word [SpecPkt+8],16 ;From CD Sector 16 870 mov word [SpecPkt+10],0 871 mov word [SpecPkt+12],0 872 mov word [SpecPkt+14],0 873 874 mov si, SpecPkt ;Set ds:si --> SpecPkt 875 mov dl, [DriveNumber] 876 mov ah, 42h ;Extended Read 877 int 13h 878 jnc SecSize ;If success 879 880 mov ah, 42h ;Always make 2 read attempts 881 int 13h 882 ;How many bytes did we get? 883 SecSize: std ;Count down 884 mov ax,cs ;Point to end of Buffer 885 mov es,ax 886 mov di,Buffer+2047 ;Find end of read data 887 mov si,Buffer+2048 888 mov cx,2049 889 repe cmpsb ;cx = number of bytes read 890 891 cld ;Restore count direction to up 892 mov si,CDBytes ;Display number of bytes read 893 call print_string 894 895 mov al, [DriveNumber] 896 call print_hex8 897 898 mov si,CDBytesA ;Remainder A of message 899 call print_string 900 901 mov al,ch ;Hex-dump cx 902 and al,0Fh ;Second nibble 903 call print_hex8 ; (don't need the First) 904 mov al,cl 905 call print_hex8 ; (don't need the First) 906 907 mov si,CDBytesB ;Remainder B of message 908 call print_string 909 910 cmp cx,2048 ;Did we read 2048 bytes? 911 je ParseParm ;If yes <-- O.K. 912 913 mov byte [ReadBytes],1 914 cmp cx,1024 ;Did we read 1024 bytes? 915 je ParseParm ;If yes <-- O.K. 916 917 mov byte [ReadBytes],2 918 cmp cx,512 ;Did we read 512 bytes? 919 jne NoEndAddr ;If not, do not load driver 920 921 ParseParm: mov bx,word [cs:ReqHdrLoc] ;Parse command line 922 mov es,word [cs:ReqHdrLoc+2] ; parameters 923 mov si,[es:bx+18] ;Get BPB array ptr into DS:SI 924 mov ds,[es:bx+20] 925 FindParm: inc si 926 FindParm1: cmp byte [si],0Dh ;CR? (End of parameters) 927 je EndOfParms 928 929 cmp byte [si],0Ah ;LF? 930 je EndOfParms 931 932 cmp byte [si],'/' ;A parameter? 933 jne FindParm 934 935 inc si 936 cmp byte [si],'D' ;Device Name parameter? 937 jne FindParm1 938 939 inc si 940 cmp byte [si],':' 941 jne FindParm1 942 943 ;bbb 944 push si 945 mov si, DevName ;Device Name is at ds:si 946 push ds ;Keep ptr to Device Name 947 mov ax, cs 948 mov ds, ax 949 call print_string 950 pop ds ;Retrieve Device Name ptr 951 pop si 952 mov cx, 8 ;Get next 8 chars 953 inc si ; = Device Name 954 mov ax, cs 955 mov es, ax 956 mov di, DeviceName 957 NextChar: cmp byte [si],' ' 958 ja AboveSpace 959 960 mov ax,cs ;Pad end of Device Name with 961 mov ds,ax ; spaces if necessary 962 mov si,DblSpace ;A space 963 AboveSpace: mov al, [si] 964 call print_char 965 movsb ;ds:[si] --> es:[di] 966 loop NextChar 967 968 mov si,LineEnd 969 mov ax,cs 970 mov ds,ax 971 call print_string 972 973 mov ax,Init-2 ;Last byte of driver to keep 974 jmp EndAddr ;Install driver 975 976 EndOfParms: 977 mov ax, cs ; Restore segment registers (fix) 978 mov ds, ax 979 mov es, ax 980 981 mov si,NoDevName ;No Device Name Found 982 call print_string 983 984 NoEndAddr: mov ax,0 ;Do not install driver 985 986 EndAddr: mov es,[ReqHdrLoc+2] ;Write End Address 987 mov bx,[ReqHdrLoc] 988 mov [es:bx+14],ax 989 mov [es:bx+16],cs 990 mov bx,ax ;Hold onto install status 991 992 mov si, DrvInst ;Display driver install status 993 call print_string 994 mov si, DrvInst1 ;Assume driver installed 995 cmp bx,0 ;Was driver installed? 996 jne DrvStatus ;If yes 997 mov si, NoDrvInst ;Driver not installed 998 DrvStatus: call print_string 999 1000 mov ax,0 ;Set Return Status = success 1001 cmp bx,0 ;Was INIT successful? 1002 jne InitStat ;If yes 1003 mov ax,800Ch ;Status = General Failure 1004 InitStat: 1005 push ax ;Save Return Status 1006 1007 call keyflag 1008 and al, 8 ; alt key ? 1009 jz InitExit 1010 1011 WaitHere: 1012 mov si, WaitMsg ;Display Halted message 1013 call print_string 1014 1015 AltWait: 1016 call keyflag 1017 and al, 8 ; Alt key? 1018 jnz AltWait ; Pressed? yes -> wait 1019 1020 InitExit: 1021 pop ax ;Retrieve Return Status 1022 TRACER 'i' 1023 retn ;That's it for Init! 1024 1025 ; *** start 1.4 changes at ded *** 1026 SpecGo: mov si,SpecPkt 1027 int 13h 1028 retn 1029 1030 ScanDrives: push ax ; at df3 in 1.4 1031 push si 1032 mov dl, 7fh ;Start at Drive 0x80 1033 NextDrv: inc dl 1034 clc 1035 mov ax,4B01h ;Get Bootable CD-ROM Status 1036 mov BYTE [SpecPkt],0 ;Clear 1st byte of SpecPkt 1037 call SpecGo 1038 ; Carry is not cleared in buggy Dell BIOSes, 1039 ; so I'm checking packet size byte 1040 ; some bogus bioses (Dell Inspiron 2500) returns packet size 0xff when failed 1041 ; Dell Dimension XPsT returns packet size 0x14 when OK 1042 1043 cmp BYTE [SpecPkt], 13h ; anything between 13h and 20h should be OK 1044 jb FindFail 1045 cmp BYTE [SpecPkt], 20h 1046 ja FindFail ; in 1.4 at e16 1047 jmp short SendFound ; in 1.4 at e26 1048 1049 FindFail: cmp dl, 0ffh 1050 je SendFail ; Check from 80h..ffh 1051 jmp short NextDrv ;Next drive 1052 SendFail: xor dl,dl 1053 stc 1054 jmp short ThingDone 1055 SendFound: mov dl, [SpecPkt+2] 1056 clc 1057 ThingDone: pop si 1058 pop ax 1059 retn 1060 ; *** end 1.4 changes *** 1061 1062 ;============================================================================= 1063 1064 ;------------------------------------------------------------ 1065 ; keyboard flags - return keyboard flags in AL 1066 ; bit 3 = ALT key 1067 keyflag: ; at dbc in 1.3, at e2e in 1.4 1068 push bx 1069 mov ah, 2 1070 int 16h 1071 pop bx 1072 retn 1073 1074 ;============================================================================= 1075 1076 DrvNumMsg db ' Diskemxx.bin returned drive number=', 0 1077 NoBootCD db ' No booted CD-ROM found.',CR,0 1078 1079 CDStat db ' INT 13h / AX=4B01h Specification Packet for ' 1080 db 'Booted CD-ROM:',CR,' ', 0 1081 1082 CDBytes db ' Drive ', 0 1083 CDBytesA db ' returns ', 0 1084 CDBytesB db 'h bytes per Sector.',CR,0 1085 1086 DevName db ' Device Name: ', 0 1087 NoDevName db ' No Device Name found. ' 1088 db 'Usage: device=eltorito.sys /D:<DevName>',CR,0 1089 1090 DrvInst db ' Driver ', 0 1091 NoDrvInst db 7,'not ' ;7 = Ctrl-G = Beep 1092 DrvInst1 db 'installed',CR,0 1093 1094 WaitMsg db ' Alt pressed, waiting...', CR, 0 1095 ;ContMsg db ' Continuing...' 1096 LineEnd db CR,0 1097 1098 1099 ;============================================================================= 1100