!************************************************************************** !* !* Boot-ROM-Code to load an operating system across a TCP/IP network. !* !* Module: utility.S !* Purpose: Various functions for the image loader routines, which are !* better written in assembler !* Entries: _convmem, _extmem, _exec_image !* !************************************************************************** !* !* 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: utility.S,v 1.6 2003/03/09 00:24:27 gkminix Exp $ !* ! !************************************************************************** ! ! Include assembler macros: ! #include ! !************************************************************************** ! ! Layout of descriptors in GDT: ! gdt_length equ $0000 ! length of segment gdt_base_low equ $0002 ! base of segment (low 3 bytes) gdt_flags equ $0005 ! descriptor flags gdt_res equ $0006 ! reserved gdt_base_high equ $0007 ! base of segment (high byte) gdt_size equ 8 ! size of descriptor gdt_stdflag equ $93 ! standard flags for GDT entries ! !************************************************************************** ! ! Start code segment. ! .text public _convmem ! define entry points public _extmem public _exec_image extrn datseg extrn exitrom ! !************************************************************************** ! ! Get amount of conventional memory in bytes. ! Input: none ! Output: memory amount ! _convmem: int INT_MEMORY ! just call the BIOS jmp extm1 ! !************************************************************************** ! ! Get amount of extended memory in bytes. ! Input: none ! Output: memory amount ! _extmem: ! Detecting the amount of extended memory is almost an art. Ralph Browns ! interrupt list describes various different methods. We first use function ! $E801, and if its not supported we fall back to $88. Function $E881 should ! also be possible, but it seems to be implemented with a bug in various ! BIOS versions and completely hangs the system. After all, for more modern ! systems we should use $E820, but that call requires a whole lot of ! programming. mov ax,#$E801 ! try 16-bit version int INT_MISC jc extm7 mov cx,ax ! some BIOS return incorrect or cx,bx ! values jnz extm1 mov ax,cx mov bx,dx extm1: #ifdef IS386 and eax,#$0000FFFF ! clear upper word and ebx,#$0000FFFF extm2: shl ebx,#6 ! multiply by 64 add eax,ebx ! and add to amount below 16M shl eax,#10 ! convert into number of bytes # ifndef OPT386 mov edx,eax ! prepare correct return value shr edx,#16 ! if not optimizing # endif #else mov cx,bx shr cx,#10 ! multiply by 64 shl bx,#6 add ax,bx ! and add to amount below 64M adc cx,#0 mov bx,cx mov dx,ax shift (shr,dx,6) ! multiply value with 1024 to get shift (shl,ax,10) ! number of bytes shift (shl,bx,10) add dx,bx #endif jmp extm9 extm7: mov ah,#$88 ! use old BIOS call clc int INT_MISC jnc extm8 #ifdef OPT386 xor eax,eax ! no extended memory found #else xor ax,ax ! no extended memory found xor dx,dx #endif jmp extm9 extm8: #ifdef OPT386 shl eax,#16 ! delete the upper 6 bits and then shr eax,#6 ! multiply by 1024 #else mov dx,ax shift (shr,dx,6) ! multiply value with 1024 to get shift (shl,ax,10) ! number of bytes #endif extm9: ret ! !************************************************************************** ! ! Execute the boot image ! Input: 1. arg - load mode ! 2. arg - far pointer to execution point ! 3. arg - far pointer to header ! 4. arg - near pointer to parameter block ! 5. arg - drive number (with disk boot) ! Output: A non-zero value in AX means to reload a new image. ! _exec_image: penter (0) push si ! save index registers for return push di ! to C code push ds push es getcarg (es,2) ! get the execution pointer getcarg (di,1) ! into ES:DI getcarg (ax,5) ! get the parameter pointer push ds push ax ! push the parameter pointer getcarg (bx,4) ! get the header pointer getcarg (si,3) ! into BX:SI push bx push si ! push the header pointer getcarg (dx,6) ! get drive number into DX getcarg (ax,0) ! get load mode into AX mov cx,#4 ! copy 4 words to image stack call exitrom ! now call the image add sp,#4 pop es pop ds ! restore all previously saved pop di ! registers pop si pleave ret ! !************************************************************************** ! end