asm { #define BOOT_ADDRESS 0x040000 #define BLK_SIZE 0x200 #define CD_BLK_SIZE 2048 #define BOOT_HIGH_LOC ((0xA0000-5*BLK_SIZE)>>4) #define BOOT_CODE_FLOPPY 1 #define BOOT_CODE_HARDDRIVE 2 #define BOOT_CODE_CDROM 3 #define BOOT_CODE_RAM 4 #define WIN_NOP 0x00 #define WIN_DEV_RESET 0x08 #define WIN_PACKETCMD 0xA0 /* Send a packet cmd. */ #define ERR_STAT 0x01 #define DRQ_STAT 0x08 #define SEEK_STAT 0x10 #define READY_STAT 0x40 #define BUSY_STAT 0x80 #define DRIVE_READY (READY_STAT | SEEK_STAT) #define DATA_READY (DRQ_STAT) #define IDE_PRIMARY_BASE 0x1F0 #define IDE_SECONDARY_BASE 0x170 #define IDE_DATA_REG (0) #define IDE_FEATURE_REG (1) #define IDE_NSECTOR_REG (2) #define IDE_SECTOR_REG (3) #define IDE_LCYL_REG (4) #define IDE_HCYL_REG (5) #define IDE_SELECT_REG (6) #define IDE_STATUS (7) #define IDE_CMD (7) #define IDE_CONTROL_REG (0x3F6-0x1F0) USE16 BCD2_START:: CLD MOV AX,BOOT_HIGH_LOC MOV ES,AX MOV SS,AX MOV SP,5*BLK_SIZE CALL U2 GET_IP GET_IP: POP BX SUB BX,GET_IP SHR BX,4 MOV AX,CS //COPY HIGH ADD AX,BX MOV DS,AX MOV CX,CD_BLK_SIZE XOR SI,SI XOR DI,DI REP_MOVSB MOV AX,SS MOV DS,AX MOV AX,BOOT_ADDRESS/16 MOV ES,AX XOR DI,DI //ES:[DI]=DEST MOV SI,MSG_PS CALL BCD2_PUTS XOR AH,AH INT 0x16 MOV SI,IDE_SECONDARY_BASE CMP AL,'S' JE @@12 CMP AL,'s' JE @@12 MOV SI,IDE_PRIMARY_BASE @@12: /********** PUSH ES XOR AX,AX MOV ES,AX MOV AL,U1 ES:[0x3EE] POP ES *******/ PUSH SI MOV SI,MSG_UNIT CALL BCD2_PUTS XOR AH,AH INT 0x16 POP SI SHL AL,4 OR AL,0xE0 MOV U1 [BCD2_UNIT_VALUE+1],AL CLI DU1 0xEA; DU2 BCD2_MAIN,BOOT_HIGH_LOC; MSG_PS:: DU1 "\r\n\r\n\r\n\r\n" "\r\nBooting LoseThos Operating System from CD-ROM..." "\r\n\r\nPlease specify the location of the CD-ROM" "\r\ndrive you are booting from. (I don't know how" "\r\nto detect it.) Typically, CD-ROMs are on the" "\r\nsecondary controller, so press 's' if this is the case." "\r\n\r\n (p)rimary or (s)econdary IDE controller:",0; MSG_UNIT:: DU1 "\r\n\r\nTypically, CD-ROMs are the master unit, so" "\r\npress '0' if this is the case." "\r\n\r\n Unit (0=Master or 1=Slave):",0; BCD2_PUTS:: LODSB OR AL,AL JZ BCD2_RET MOV AH,0x0E MOV BX,0x07 INT 0x10 JMP BCD2_PUTS BCD2_STAT:: MOV DX,SI ADD DX,IDE_STATUS IN AL,DX BCD2_RET: RET BCD2_SELECT_UNIT:: MOV DX,SI ADD DX,IDE_SELECT_REG BCD2_UNIT_VALUE:: MOV AL,0xF0 //Gets patched OUT DX,AL RET BCD2_CMD:: MOV AH,AL XOR AL,AL MOV DX,SI ADD DX,IDE_FEATURE_REG OUT DX,AL MOV AL,AH MOV DX,SI ADD DX,IDE_CMD OUT DX,AL RET BCD2_WAIT_NOT_BUSY:: CALL BCD2_STAT AND AL,BUSY_STAT JNZ BCD2_WAIT_NOT_BUSY RET BCD2_WAIT_DRQ:: CALL BCD2_STAT AND AL,DRQ_STAT JZ BCD2_WAIT_DRQ RET BCD2_PKT:: PUSH AX CALL BCD2_WAIT_DRQ POP BX MOV AL,BH MOV AH,BL MOV DX,SI ADD DX,IDE_DATA_REG OUT DX,AX RET BCD2_RESET:: CALL BCD2_SELECT_UNIT MOV AL,WIN_DEV_RESET CALL BCD2_CMD CALL BCD2_WAIT_NOT_BUSY RET BCD2_MAIN:: CALL BCD2_RESET BCD2_WAIT_READY:: MOV ECX,100000 //Busy wait MOV DX,0x379 //Par Port @@1: IN AL,DX DEC ECX JNZ @@1 BCD2_WAIT_READY2:: CALL BCD2_SELECT_UNIT MOV AL,WIN_NOP CALL BCD2_CMD CALL BCD2_WAIT_NOT_BUSY CALL BCD2_STAT AND AL,READY_STAT JNZ @@1 CALL BCD2_RESET JMP BCD2_WAIT_READY @@1: CALL BCD2_SELECT_UNIT MOV AL,WIN_PACKETCMD CALL BCD2_CMD MOV AX,0x1B00 CALL BCD2_PKT XOR AX,AX CALL BCD2_PKT MOV AX,0x0100 CALL BCD2_PKT XOR AX,AX CALL BCD2_PKT XOR AX,AX CALL BCD2_PKT XOR AX,AX CALL BCD2_PKT CALL BCD2_WAIT_NOT_BUSY MOV DX,SI ADD DX,IDE_FEATURE_REG IN AL,DX OR AL,AL JNZ BCD2_WAIT_READY BCD2_SEND_READ:: MOV AL,8 MOV DX,SI ADD DX,IDE_CONTROL_REG OUT DX,AL CALL BCD2_SELECT_UNIT MOV AL,0 MOV DX,SI ADD DX,IDE_LCYL_REG OUT DX,AL MOV AL,8 INC DX //IDE_HCYL_REG OUT DX,AL MOV AL,WIN_PACKETCMD CALL BCD2_CMD MOV AX,0xA800 CALL BCD2_PKT BCD2_BLK_HI:: MOV AX,512 CALL BCD2_PKT BCD2_BLK_LO:: MOV AX,512 CALL BCD2_PKT XOR AX,AX //cnt_hi CALL BCD2_PKT BCD2_BLK_CNT:: MOV AX,512 PUSH AX CALL BCD2_PKT XOR EAX,EAX CALL BCD2_PKT POP AX //cnt SHL EAX,10 MOV EBX,EAX @@10: CALL BCD2_WAIT_DRQ XOR ECX,ECX MOV DX,SI ADD DX,IDE_HCYL_REG IN AL,DX MOV CH,AL MOV DX,SI ADD DX,IDE_LCYL_REG IN AL,DX MOV CL,AL SHR1 CX JZ @@10 CMP CX,0x7F00 JB @@20 MOV CX,0x7F00 @@20: PUSH CX MOV DX,SI ADD DX,IDE_DATA_REG REP_INSW MOV AX,DI SHR AX,4 MOV DX,AX MOV AX,ES ADD AX,DX MOV ES,AX AND DI,0xF POP CX SUB EBX,ECX JZ @@100 //TODO look-up branch JNC @@10 @@100: CALL BCD2_WAIT_NOT_BUSY MOV AX,SI SHL EAX,16 MOV AH,U1 [BCD2_UNIT_VALUE+1] MOV AL,BOOT_CODE_CDROM MOV EBX,EAX DU1 0xEA; BCD2_JMP_START:: DU2 0,BOOT_ADDRESS/16; BCD2_END:: END }