; disk.S - inquire of BIOS and display disk parameters ; ; Copyright 1999-2004 John Coffman ; Copyright 2009-2011 Joachim Wiedorn ; All rights reserved. ; ; Licensed under the terms contained in the file 'COPYING' ; in the source directory. ; #define DEBUG 0 #define DELL_DIRTY_HACK SYSSEG = 0x1000 ; DEF_SYSSEG SETUPSEG = 0x9020 ; DEF_SETUPSEG .text #if 1 .globl _main _main: #endif .globl zero zero: ; we want this to look like a bootable kernel image ; so we include the following header ; jmp begin .ascii "HdrS" ; Signature for Setup header .word 0x0201 ; header format version number .word 0,0 ; realmode switch, SETUPSEG .word SYSSEG ; SYSSEG -- load at 1000:0000 .word id_string .byte 0 ; type of loader .byte 0 ; flags 0=load low .word 0x200 ; move size dd 0x1000 ; load us here dd 0 ; ramdisk image .word bs_helper,SETUPSEG ; kludge??? .word modelist+1024 ; heap end pointer ;----------end of header------------ begin: mov ax,cs cli ;make purists happy mov ss,ax mov sp,#0x7FFE sti ; *** call start ;do not separate from the instruction below start: pop bx ;this MUST immediately follow the 'call' sub bx,#start-zero lea bp,zero sub bx,bp ;BX=100h under DOS, BX=0h under BIOS mov cl,#4 sar bx,cl add ax,bx mov ds,ax mov dx_save,dx ;save DX we received cld #ifdef DELL_DIRTY_HACK mov ah,#15 ; get video mode int 0x10 cbw int 0x10 ; set video mode #endif call say .ascii "\n>>>> Disk Detection and Parameter Display <<<<\n" .ascii "Version 1.6, Copyright (C) 1999-2005 John Coffman.\n" .ascii "Re-use and redistribution rights set forth" .ascii " in the file \"COPYING\".\n\n" .byte 0 cmp magic,#0xAA55 je sane ;check that we got the DS set right call say .ascii "\n\nCS/DS sanity check failed.\n" .byte 0 hlti: hlt jmp hlti ;;; nop ;spacer magic: .word 0xAA55 dx_save: .word 0 sane: #if 0 xor ax,ax mov dl,al int 0x13 mov ah,#8 int 0x13 #endif smsw ax test al,#1 jnz v86mode br realmode v86mode: call say .ascii "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n" .ascii "!!! *** Warning: DOS is not running in REAL mode *** !!!\n" .ascii "!!! *** Reported results may not be accurate *** !!!\n" .ascii "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n" .byte 0 call pause realmode: call say .ascii "There " .byte 0 int 0x11 ; get equipment configuration test al,#1 mov ah,#-1 jz noflop shl ax,1 shl ax,1 and ah,#3 jz flop1 noflop: call say .ascii "are " .byte 0 jmp flop2 flop1: call say .ascii "is " .byte 0 flop2: inc ah mov nflop,ah mov al,ah add al,#0x30 call putc call say .ascii " floppy drive" .byte 0 mov al,#'s dec ah jz flop3 call putc flop3: inc ah call say .ascii " with BIOS support.\n" .byte 0 ; now probe for floppy drives mov dl,#-1 fprobe: mov ah,#8 inc dl push dx xor cx,cx int 0x13 pop dx jc fstop or cx,cx jnz fprobe fstop: mov ah,nflop cmp ah,dl je fdisplay call say .ascii "But probing has found " .byte 0 mov al,dl add al,#'0 call putc call say .ascii "!!!\n" .byte 0 cmp ah,dl jae fdisplay xchg ah,dl fdisplay: mov dl,#0 ;start with drive 0x00 xor cx,cx mov cl,ah jcxz floppy1 floppy: call drive inc dl loop floppy floppy1: mov al,#10 call putc call say .ascii "There is " .byte 0 int 0x12 ;get amount of low memory ;;; mov ax,#640 ;debug xor dx,dx call print call say .ascii "K of low memory" .byte 0 mov bx,#640 sub bx,ax jnz ebda1 call say .ascii " with no EBDA." .byte 0 br ebda2 ebda1: push ax mov ax,bx xor bx,bx call say .ascii ". EBDA size = " .byte 0 call dec3 call say .ascii "K EBDA starts at 0x" .byte 0 pop ax mov cl,#6 shl ax,cl call wout call say .ascii "0" .byte 0 ebda2: call say .ascii "\n" .byte 0 ; post-floppy pause call pause mov ah,#0 mov dl,#0x80 int 0x13 mov ah,#8 int 0x13 mov ah,#0 jc nohard mov ah,dl nohard: mov nhard,ah call say .ascii "There " .byte 0 dec ah jz hard1 call say .ascii "are " .byte 0 jmp hard2 hard1: call say .ascii "is " .byte 0 hard2: inc ah mov al,ah add al,#'0 call putc call say .ascii " hard drive" .byte 0 mov al,#'s dec ah jz hard3 call putc hard3: inc ah call say .ascii " with BIOS support.\n" .byte 0 ; probe for hard drives mov dl,#0x80-1 hprobe: mov ah,#8 inc dl push dx xor cx,cx int 0x13 pop dx jc hstop or cx,cx jnz hprobe hstop: and dl,#0x7f mov ah,nhard cmp ah,dl je hdisplay call say .ascii "But probing has found " .byte 0 mov al,dl add al,#'0 call putc call say .ascii "!!!\n" .byte 0 cmp ah,dl jae hdisplay xchg ah,dl hdisplay: mov dl,#0x80 ;start with drive 0x80 xor cx,cx mov cl,ah jcxz hdd1 hard: call drive inc dl loop hard hdd1: test byte ptr bigflag,#0xFF jz hdd2 br big hdd2: test byte ptr bigcyl,#0xFF jz hdd3 br big2 hdd3: call say .ascii "\nEither your BIOS does not support EDD" .ascii " packet calls, or you have no large\n" .ascii "disks. You do not need to use LILO with" .ascii " the 'lba32' global option (or '-L'\n" .ascii "switch).\n" .byte 0 br exit big: call say .ascii "\nYou have " .byte 0 cmp byte bigflag,#1 je noS call say .ascii "disks" .byte 0 jmp goOn noS: call say .ascii "a disk" .byte 0 goOn: call say .ascii " bigger than 8.4Gb" .byte 0 big1c: call say .ascii " with Enhanced BIOS support.\n" .ascii "Using LILO with the 'lba32' global option" .ascii " (or '-L' switch) is recommended.\n" .byte 0 br exit big2: call say .ascii "\nYou have " .byte 0 cmp byte bigcyl,#1 je big2a call say .ascii "disks" .byte 0 jmp big2b big2a: call say .ascii "a disk" .byte 0 big2b: call say .ascii " with more than 1023 cylinders" .byte 0 br big1c nflop: .byte 0 nhard: .byte 0 bigflag: .byte 0 bigcyl: db 0 nlimit: dd 1024*255*63, 0 ; inquire whether EDD drive BIOS calls are valid ; Carry clear says NO, Carry set says YES, CX=device bits & ; SI = pointer to dparam table inqedd: push ax push bx push dx push si mov ah,#0x41 mov bx,#0x55aa int 0x13 jc edd7 cmp bx,#0xaa55 jne edd7 test cl,#7 stc jz edd8 lea si,dparam mov word (si),#dlth ;;; nop ;spacer ;;; nop ;spacer mov dh,ah ;save version number mov ah,#0x48 ;get drive parameters int 0x13 jc edd7 stc pop ax ;discard saved SI mov (si+1),dh ;save version info jmp edd9 ;return SI, too edd7: xor cx,cx ;carry is clear edd8: pop si edd9: pop dx pop bx pop ax ret ; pause for the user to look at the screen pause: call say .ascii "Hit any key to continue..." .byte 0 mov ah,#0 int 0x16 call say .ascii "\r \n" .byte 0 ret ; print out the IBM BIOS drive parameters for the drive in DL drive: push bp push ax push bx push cx push es push di push si push dx call say .ascii "Drive 0x" .byte 0 mov al,dl call bout call say .ascii " Cyl:Head:Sec = " .byte 0 mov ah,#8 int 0x13 #if DEBUG mov cx,#0xFAFF mov dh,#0xFF ; 0xFE is the max. #endif push cx push dx rol cl,1 mov di,#1000 rol cl,1 xor bh,bh and cl,#3 xchg ch,cl inc cx mov ax,cx xor dx,dx div di mov bp,cx or ax,ax jz cyl2 call say .ascii "1" .byte 0 mov bh,#0x80 cyl2: xchg ax,dx call dec3 call punct pop dx xor ax,ax mov al,dh xor bh,bh inc ax call dec3 mov dx,ax call punct ;;; pop cx ;;; and cl,#0x3F ;;; mov al,cl pop ax #if 0 ; sectors = [1..63] and ax,#0x3F #else ;; version 1.6 ;; avoid Davide bug: Sectors == 0 dec ax and ax,#0x3F inc ax ; now sectors = [1..64] ;; version 1.6 end #endif call dec3 call say .ascii " (" .byte 0 ;;; mul dl mul dx mul bp push ds pop es lea di,ac0 push di stosw mov ax,dx stosw xor ax,ax stosw stosw pop si call dprint call say .ascii " sectors) --> " .byte 0 call sizeit call say .byte 10,0 pop dx push dx call inqedd jc xdd1 br xdd4 xdd1: call say .ascii " EDD rev " .byte 0 mov al,(si+1) mov cl,#4 mov ah,al shr al,cl add al,#'0 call putc mov al,#'. call putc mov al,ah and al,#0x0F add al,#'0 call putc call say .ascii " geometry = " .byte 0 test byte (si+2),#2 jz xdd2 mov ax,(si+4) mov dx,(si+6) or dx,dx jnz xdd1a cmp ax,#1024 jb xdd1b xdd1a: inc byte (bigcyl) xdd1b: call print call punct mov ax,(si+8) mov dx,(si+10) call print call punct mov ax,(si+12) mov dx,(si+14) call print call say .ascii " " .byte 0 xdd2: call say .ascii "(" .byte 0 lea si,(si+16) call dprint call say .ascii " sectors) --> " .byte 0 mov ax,(si+6) cmp ax,nlimit+6 jb xdd3 ja xdd2a mov ax,(si+4) cmp ax,nlimit+4 jb xdd3 ja xdd2a mov ax,(si+2) cmp ax,nlimit+2 jb xdd3 ja xdd2a mov ax,(si) cmp ax,nlimit jb xdd3 xdd2a: inc byte bigflag xdd3: mov dl,#1 call sizeit call say .byte 10,0 xdd4: pop dx pop si pop di pop es pop cx pop bx pop ax pop bp ret punct: mov al,#': call putc ret chars: .ascii " KMGTxyz" sizeit: push ax push bx push cx push dx push si push es push di lea bx,chars-1 mov di,si push ds pop es mov ax,#512 or dx,dx jz dpr5 ;handle small disks call intmul jmp dpr6 dpr5: mov ax,#2 call intdiv inc bx dpr6: mov ax,#1000 lea di,ac1 dpr7: lea bx,(bx+1) mov cx,dx call intdiv xchg si,di jnz dpr7 mov si,bx mov ax,dx xor bx,bx call dec3 cmp byte ptr (si),#'K je dpr8 mov al,#'. call putc mov ax,cx #if 1 mov bx,#0x800a cmp ax,#995 jae no_add add ax,#5 no_add: div bl xor ah,ah div bl add al,#'0 call putc xchg al,ah #else mov bx,#0x8000+100 add ax,#50 div bl #endif add al,#'0 call putc dpr8: mov al,(si) call putc pop di pop es pop si pop dx pop cx pop bx pop ax ret ; print the decimal double word number in DX:AX ; print: push ds push si xor si,si push si push si push dx push ax push ss pop ds mov si,sp call dprint lea sp,(si+8) pop si pop ds ret ; print the decimal quad-word number in [DS:SI] ; dprint: push ax push bx push dx push es push di push ds push si sub sp,#8 mov di,sp push ss pop es xor bx,bx mov ax,#1000 dpr1: inc bx call intdiv mov si,di push es pop ds push dx jnz dpr1 jmp dpr3 dpr2: mov al,#', call putc dpr3: pop ax call dec3 mov bh,#0x80 dec bl jnz dpr2 lea sp,(di+8) pop si pop ds pop di pop es pop dx pop bx pop ax ret ; multiply the number in the ac pointed at by [DS:SI] by the AX, putting ; the result in the ac pointed to by [ES:SI]. Return overflow in AX. ; SI and DI may be the same intmul: push bp push si push di push bx push cx push dx mov cx,#4 mov bp,ax xor dx,dx im4: mov bx,dx lodsw mul bp add ax,bx adc dx,#0 ;;; nop ;spacer stosw loop im4 mov ax,dx pop dx pop cx pop bx pop di pop si pop bp ret ; divide the ac pointed at by [DS:SI] by the AX, producing a result ; in [ES:DI], and a remainder in DX; the Z flag reflects the quotient ; DI may equal SI for in-place division intdiv: push bx push cx push bp push di push si mov cx,#4 mov bx,cx dec bx add bx,bx lea si,(si+bx) lea di,(di+bx) xor dx,dx xor bp,bp std mov bx,ax id2: lodsw div bx or bp,ax ;sets the Z flag stosw loop id2 cld mov ax,bx pop si pop di pop bp pop cx pop bx ret ; write the number < 1000 in AX as 3 decimal digits ; BH flags whether leading zeroes are printed (0x80=yes, 0=no) dec3: push bx push ax push cx mov cx,#2 mov bl,#100 dec32: div bl xor al,bh jz dec36 xor al,bh mov bh,#0x80 dec34: add al,#'0 call putc mov bh,#0x80 dec36: mov al,ah mov ah,#0 mov bl,#10 dec cx jg dec32 jz dec34 pop cx pop ax pop bx ret ; write the terminated string which follows the call ; no registers altered say: push bp mov bp,sp push ds push si push ax mov si,(bp+2) push cs pop ds say1: lodsb or al,al jz say2 call putc jmp say1 say2: mov (bp+2),si pop ax pop si pop ds pop bp ret ; write the word in AX in hex wout: xchg ah,al call bout xchg ah,al call bout ret ; write the byte in AL in hex bout: push ax push cx push ax mov cx,#0x204 shr al,cl bout1: add al,#'0 cmp al,#'9 jbe bout2 add al,#'A-'0-10 bout2: call putc dec ch jz bout4 pop ax and al,#0xF jmp bout1 bout4: pop cx pop ax ret ; write the character in AL in teletype mode ; all registers are preserved putc: push bx push ax mov ah,#14 xor bh,bh cmp al,#10 ;test for new-line jne putc2 mov al,#13 ;get int 0x10 mov al,#10 putc2: int 0x10 pop ax pop bx ret #define LILO_ASM #include "lilo.h" #include "read.S" #include "bdata.h" #define BD_VERBOSE #include "biosdata.S" exit: mov ax,cs mov dx,ds cmp ax,dx jae bd_test exit_dos: mov ax,#0x4c00 int 0x21 bd_test: call pause call say .ascii "BIOS data collection test.\n" .ascii "Failure of this test will require booting all Linux\n" .ascii "kernels with the 'nobd' command-line option.\n" .ascii "Hit to bypass, any other key to continue..." .byte 0 mov ah,#0 int 0x16 call say .byte 10,10,0 cmp al,#0x1b ; je bd_test_skip #if 1 mov ax,cs mov bx,#SYSSEG cmp ax,bx jae collect mov es,bx mov di,#theend-1 std lea cx,(di+1) mov si,di rep movsb mov ss,bx mov ds,bx cld push es push #collect retf collect: #endif mov dx,dx_save ; DX passed in on boot call io_biosdata call say .ascii "\nALL OKAY\n\n" .byte 0 bd_test_skip: call say .ascii "Remove the floppy disk from the drive.\n" .ascii "Hit any key to reboot..." .byte 0 mov ah,#0 int 0x16 call say .byte 10,10,10,0 bs_helper: int 0x19 ;label here for kludge id_string: .ascii "Disk.Com" .byte 0 ac0: .word 0,0,0,0 ac1: .word 0,0,0,0 dparam: .word dlth dflags: .word 0 dcyl: dd 0 dhead: dd 0 dsec: dd 0 dsecs: dd 0,0 ssize: .word 0 dptp: dd 0 dlthe: dlth = dlthe-dparam modelist: theend: