!************************************************************************** !* !* Boot-ROM-Code to load an operating system across a TCP/IP network. !* !* Module: lddisk.S !* Purpose: Load a boot sector from a disk !* Entries: _loaddisk !* !************************************************************************** !* !* Copyright (C) 1995-2003 Gero Kuhlmann !* !* This program is free software; you can redistribute it and/or modify !* it under the terms of the GNU General Public License as published by !* the Free Software Foundation; either version 2 of the License, or !* any later version. !* !* This program is distributed in the hope that it will be useful, !* but WITHOUT ANY WARRANTY; without even the implied warranty of !* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the !* GNU General Public License for more details. !* !* You should have received a copy of the GNU General Public License !* along with this program; if not, write to the Free Software !* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. !* !* $Id: lddisk.S,v 1.4 2003/01/25 23:29:41 gkminix Exp $ !* ! !************************************************************************** ! ! Include assembler macros: ! #include #include #include ! !************************************************************************** ! ! Miscellaneous definitions ! HD_BASE equ $80 ! base number for all harddisks FD_BASE equ $00 ! base number for all floppy disks BOOT_SIG equ $AA55 ! boot block signature BOOT_SIG_OFS equ $01FE ! offset to boot block signature PART_BUF_OFS equ $0200 ! offset to partition table buffer PART_OFS equ $01BE ! offset to partition table PART_HEAD_OFS equ $0001 ! offset to head number in part entry PART_SECT_OFS equ $0002 ! offset to sector number in part entry PART_TYPE_OFS equ $0004 ! offset to partition type indicator SECTSIZE equ 512 ! size of one sector ENTRY_LEN equ $0010 ! size of one partition table entry ENTRY_NUM equ 4 ! maximum number of entries in part tab EXT_PART_TYPE equ 5 ! type ID for extended partition ! !************************************************************************** ! ! BSS segment ! .bss .lcomm partnum,1 ! partition number ! !************************************************************************** ! ! Start code segment. ! .text public _loaddisk ! define entry points ! !************************************************************************** ! ! Load a disk boot sector into memory ! Input: 1. arg - pointer to name of device to load from ! 2. arg - far pointer to load buffer ! 3. arg - near pointer to far header pointer ! 4. arg - near pointer to drive number ! Output: error code ! _loaddisk: penter (0) push es push si getcarg (bx,0) call decodestr ! decode device string mov ax,#PXENV_STATUS_TFTP_ACCESS jc load8 mov [partnum],cl xor ah,ah int INT_DISK ! reset disk system ! First load the master boot record. getcarg (bx,1) ! get buffer pointer getcarg (es,2) or cl,cl jz load4 add bx,#PART_BUF_OFS load4: mov cx,#$0001 ! load first sector on track 0 xor dh,dh ! head 0 call reads1 ! load the sector jc load7 ! Next load the first sector of the partition. If we are to load from a ! partition in an extended partition, we have to read the extended partition ! table first. xor si,si mov al,[partnum] or al,al ! check if thats all jz load3 cmp al,#5 ! check if we have to load from an jb load6 ! extended partition mov cx,#ENTRY_NUM ! search for an extended partition lea si,PART_OFS[bx] load1: seg es cmp byte ptr PART_TYPE_OFS[si],#EXT_PART_TYPE je load2 add si,#ENTRY_LEN ! continue with next entry loop load1 load5: mov ax,#PXENV_STATUS_TFTP_CANNOT_OPEN load8: jmp load9 load2: call readsect ! read extended partition table jc load7 mov al,[partnum] ! compute partition number in extended sub al,#4 ! table cmp al,#5 jae load5 ! Now really load the first sector of the boot partition load6: dec al ! partition numbers start with 1 xor ah,ah shift (shl,ax,4) ! compute offset into partition table lea si,PART_OFS[bx] add si,bx sub bx,#PART_BUF_OFS call readsect ! read first sector of boot partition jnc load3 load7: mov ax,#PXENV_STATUS_TFTP_CANNOT_READ jmp load9 ! The boot block has been loaded successfully, so we can return the drive ! number and the pointer to the partition table entry. load3: getcarg (bx,4) xor dh,dh mov word ptr [bx],dx getcarg (bx,3) mov word ptr [bx + 0],si mov word ptr [bx + 2],es xor ax,ax load9: pop si ! return in case of error pop es pleave ret ! !************************************************************************** ! ! Decode device string ! Input: BX - pointer to string ! Output: DL - disk drive ID ! CL - partition number ! Carry flag set if error ! Registers changed: AL, BX, CL, DL ! decodestr: ! First decode the first two letters. The string has to start either ! with 'fd' or 'hd'. We dont any other devices yet. mov al,[bx + 2] mov dl,#HD_BASE cmp word ptr [bx],#$6468 ! check for hard disk 'hd' je decod1 mov dl,#FD_BASE cmp word ptr [bx],#$6466 ! check for floppy disk 'fd' jne decod8 ! OK, we have to look for a floppy device. After the initial 'fd' a number ! has to follow. The maximum is 4 disk drives, so check that its in the ! range 0 to 3. sub al,#$30 ! check for correct number jb decod8 cmp al,#3 ja decod8 add dl,al ! compute final device number xor cl,cl ! partition number is always zero add bx,#3 ! let BX point after last character jmp decod7 ! Now decode the harddisk description. The initial 'hd' has to be followed ! by a letter from 'a' to 'd' indicating the drive number, followed by a ! number indicating the partition number. If the number is missing, 0 is ! assumed, which means the whole disk, e.g. the master boot block. decod1: sub al,#$61 ! check for correct letter jb decod8 cmp al,#3 ja decod8 add dl,al ! compute final device number add bx,#3 ! let BX point after last character mov cl,[bx] or cl,cl ! end of string means "zero" jz decod7 sub cl,#$30 ! check for correct partition jb decod8 cmp cl,#8 ! maximum number of 8 partitions ja decod8 inc bx decod7: cmp byte ptr [bx],#0 ! string has to be followed by a null je decod9 ! return without error decod8: stc ! return with error decod9: ret ! !************************************************************************** ! ! Read first sector of partition. reads1 is an additional subroutine entry ! point! ! Input: ES:SI - pointer to partition table entry ! ES:BX - pointer to sector buffer ! DL - disk drive ID ! Output: Carry flag set if error ! Registers changed: AX, CX, DH readsect: seg es mov al,PART_TYPE_OFS[si] or al,al ! check if partition table entry jz reads8 ! is valid seg es mov cx,PART_SECT_OFS[si] ! get sector, track and head seg es ! number from partition table mov dh,PART_HEAD_OFS[si] reads1: mov ax,#$0201 ! actually read the sector int INT_DISK jc reads8 seg es cmp word ptr BOOT_SIG_OFS[bx],#BOOT_SIG je reads9 reads8: stc reads9: ret ! !************************************************************************** ! end