Changes in v1.7.10 (11/24/2002) (brianp)

- Added assembler versions of memcmp() memcpy() memset()
- Implemented Int386() so that real-mode interrupts can be called from C-code
- Removed unnecessary call in DbgPrint() macro (freeldr.sys is ~16k smaller now)
- 64-bit lba sector addressing for disk calls
- Re-coded biosdisk.S as i386disk.c
- Re-coded mem.S as i386mem.c
- Re-coded rtlcode.S as i386rtl.c
- Cleaned up i386trap.S so that it only saves the registers once.
- Re-coded biosvid.S as i386vid.c
- Video fade in/out
- VESA text modes supported now
- Offscreen buffering to remove flicker
- Standardized format of boot sector so that BootPartition is stored right before 0xaa55
- Prefixed all file system functions with 'Fs'

svn path=/trunk/; revision=3782
This commit is contained in:
Brian Palmer 2002-11-24 19:10:06 +00:00
parent 787724058b
commit 425bbb1543
54 changed files with 3851 additions and 2424 deletions

View file

@ -29,7 +29,7 @@ start:
nop
BootDrive db 0x80
BootPartition db 0
;BootPartition db 0 ; Moved to end of boot sector to have a standard format across all boot sectors
;SectorsPerTrack db 63 ; Moved to [bp-SECTORS_PER_TRACK]
;NumberOfHeads dw 16 ; Moved to [bp-NUMBER_OF_HEADS]
;BiosCHSDriveSize dd (1024 * 1024 * 63) ; Moved to [bp-BIOS_CHS_DRIVE_SIZE]
@ -274,8 +274,8 @@ ReadSectorsCHSLoop:
mov dh,dl ; Head in DH
mov dl,[BYTE bp+BootDrive] ; Drive number in DL
mov ch,al ; Cylinder in CX
ror ah,1 ; Low 8 bits of cylinder in CH, high 2 bits
ror ah,1 ; in CL shifted to bits 6 & 7
ror ah,2 ; Low 8 bits of cylinder in CH, high 2 bits
; in CL shifted to bits 6 & 7
or cl,ah ; Or with sector number
mov ax,0201h
int 13h ; DISK - READ SECTORS INTO MEMORY
@ -336,7 +336,10 @@ Done:
msgDiskError db 'Disk error',0
msgAnyKey db 'Press any key to restart',0
times 510-($-$$) db 0 ; Pad to 510 bytes
times 509-($-$$) db 0 ; Pad to 509 bytes
BootPartition db 0
dw 0aa55h ; BootSector signature

View file

@ -272,7 +272,7 @@ msgDiskError db 'Disk error',0dh,0ah,0
msgFileSystemError db 'File system error',0dh,0ah,0
msgAnyKey db 'Press any key to restart',0dh,0ah,0
times 509-($-$$) db 0 ; Pad to 510 bytes
times 509-($-$$) db 0 ; Pad to 509 bytes
BootPartition:
db 0

View file

@ -1,3 +1,20 @@
Changes in v1.7.10 (11/24/2002) (brianp)
- Added assembler versions of memcmp() memcpy() memset()
- Implemented Int386() so that real-mode interrupts can be called from C-code
- Removed unnecessary call in DbgPrint() macro (freeldr.sys is ~16k smaller now)
- 64-bit lba sector addressing for disk calls
- Re-coded biosdisk.S as i386disk.c
- Re-coded mem.S as i386mem.c
- Re-coded rtlcode.S as i386rtl.c
- Cleaned up i386trap.S so that it only saves the registers once.
- Re-coded biosvid.S as i386vid.c
- Video fade in/out
- VESA text modes supported now
- Offscreen buffering to remove flicker
- Standardized format of boot sector so that BootPartition is stored right before 0xaa55
- Prefixed all file system functions with 'Fs'
Changes in v1.7.9 (9/30/2002) (brianp)
- Fix for bug in BiosInt13ReadExtended() (biosdisk.S)

View file

@ -23,9 +23,9 @@
#
TARGET = i386
# Debugging information on (bigger binary)
DEBUG = yes
#DEBUG = yes
# Debugging information off (smaller binary)
#DEBUG = no
DEBUG = no
OBJDIR = obj
OUTPUT_DIR = $(OBJDIR)/$(TARGET)
@ -192,17 +192,20 @@ ARCH_OBJS = fathelp.o \
boot.o \
linux.o \
mb.o \
mem.o \
biosdisk.o \
rtlcode.o \
biosvid.o \
drvmap.o
i386mem.o \
i386rtl.o \
i386vid.o \
drvmap.o \
int386.o \
i386disk.o
RTL_OBJS = memory.o \
print.o \
RTL_OBJS = print.o \
stdlib.o \
string.o \
list.o
list.o \
memcmp.o \
memcpy.o \
memset.o
FS_OBJS = fs.o \
fat.o \
@ -238,7 +241,11 @@ INIFILE_OBJS= inifile.o \
parse.o
VIDEO_OBJS = video.o \
vidmode.o
vidmode.o \
fade.o \
palette.o \
pixel.o \
bank.o
# libgcc2.o contains code (__udivdi3, __umoddi3) necessary to do
# 64-bit division on the i386 (and other 32-bit) architectures

View file

@ -74,6 +74,19 @@ EXTERN(switch_to_prot)
cli /* None of these */
/* We don't know what values are currently */
/* in the segment registers. So we are */
/* going to reload them with sane values. */
/* Of course CS has to already be valid. */
/* We are currently in real-mode so we */
/* need real-mode segment values. */
movw $0x0000,%ax
movw %ax,%ds
movw %ax,%es
movw %ax,%fs
movw %ax,%gs
movw %ax,%ss
/* Get the return address off the stack */
popw (code32ret)
@ -120,6 +133,19 @@ EXTERN(switch_to_real)
.code32
/* We don't know what values are currently */
/* in the segment registers. So we are */
/* going to reload them with sane values. */
/* Of course CS has to already be valid. */
/* We are currently in protected-mode so we */
/* need protected-mode segment values. */
movw $PMODE_DS,%ax
movw %ax,%ds
movw %ax,%es
movw %ax,%fs
movw %ax,%gs
movw %ax,%ss
/* Get the return address off the stack */
popl (code16ret)
@ -157,9 +183,9 @@ inrmode:
movw %ax,%ss
/* Clear out the high 16-bits of ESP */
/* This is needed because I have a stupid */
/* MS-Win98 boot disk that hangs if there is */
/* anything other than 0x0000 in the high */
/* This is needed because I have one */
/* machine that hangs when booted to dos if */
/* anything other than 0x0000 is in the high */
/* 16-bits of ESP. Even though real-mode */
/* code should only use SP and not ESP. */
xorl %esp,%esp

View file

@ -1,549 +0,0 @@
/*
* FreeLoader
* Copyright (C) 1998-2002 Brian Palmer <brianp@sginet.com>
*
* 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
* (at your option) 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.
*/
.text
.code16
#define ASM
#include <arch.h>
/*
* BOOL BiosInt13Read(ULONG Drive, ULONG Head, ULONG Track, ULONG Sector, ULONG SectorCount, PVOID Buffer);
*/
_biosdisk_drive:
.long 0
_biosdisk_head:
.long 0
_biosdisk_track:
.long 0
_biosdisk_sector:
.long 0
_biosdisk_nsects:
.long 0
_biosdisk_buffer:
.long 0
_biosdisk_retval:
.long 0
_biosdisk_retrycount:
.byte 0
_biosdisk_error_code:
.byte 0
EXTERN(_BiosInt13Read)
.code32
pushal
/* Get parameters */
movl 0x24(%esp),%eax
movl %eax,_biosdisk_drive
movl 0x28(%esp),%eax
movl %eax,_biosdisk_head
movl 0x2c(%esp),%eax
movl %eax,_biosdisk_track
movl 0x30(%esp),%eax
movl %eax,_biosdisk_sector
movl 0x34(%esp),%eax
movl %eax,_biosdisk_nsects
movl 0x38(%esp),%eax
movl %eax,_biosdisk_buffer
call switch_to_real
.code16
pushw %es // Save this just in case
movb $3,_biosdisk_retrycount // Set the retry count to 3
_biosdisk_read:
movl _biosdisk_buffer,%eax // Get buffer address in eax
shrl $4,%eax // Make linear address into segment
movw %ax,%es // Load ES with segment
movl _biosdisk_buffer,%ebx // and BX with offset
andl $0x0f,%ebx // so that data gets loaded to [ES:BX]
movb _biosdisk_sector,%cl // Get the sector in CL
movw _biosdisk_track,%ax // Cylinder in AX
movb %al,%ch // Now put it in CH
rorb $1,%ah // Low 8 bits of cylinder in CH, high 2 bits
rorb $1,%ah // in CL shifted to bits 6 & 7
andb $0xc0,%ah // Clear out low six bits
orb %ah,%cl // Or with sector number
movb _biosdisk_head,%dh // Get the head
movb _biosdisk_drive,%dl // Get the drive
movb $2,%ah // BIOS int 0x13, function 2 - Read Disk Sectors
movb _biosdisk_nsects,%al // Number of sectors to read
int $0x13 // Read a sector
// I have recently learned that not all bioses return
// the sector read count in the AL register (at least mine doesn't)
// even if the sectors were read correctly. So instead
// of checking the sector read count we will rely solely
// on the carry flag being set on error
//jmp _biosdisk_done
//cmpb _biosdisk_nsects,%al // See how many sectors we actually read
//jne _biosdisk_error // Jump if no error
movb $1,%al // Set the return value to be one (will be set to zero later if needed)
jc _biosdisk_error // Jump if error (CF = 1 on error)
jmp _biosdisk_done
_biosdisk_error:
movb %ah,_biosdisk_error_code// Save the error code
cmpb $0x11,%ah // Check and see if it was a corrected ECC error
je _biosdisk_done // If so then the data is still good, if not fail
movb _biosdisk_retrycount,%al// Get the current retry count
decb %al // Decrement it
movb %al,_biosdisk_retrycount// Save it
cmpb $0,%al // Is it zero?
jz _biosdisk_zero // Yes, return zero
movb $0,%ah // BIOS int 0x13, function 0 - Reset Disk System
movb _biosdisk_drive,%dl // Get the drive
int $0x13 // Reset the disk system
jmp _biosdisk_read // Try reading again
_biosdisk_zero:
movb $0,%al // We will return zero
_biosdisk_done:
movzbl %al,%eax // Put the number of sectors read into EAX
movl %eax,_biosdisk_retval // Save it as the return value
popw %es // Restore ES
call switch_to_prot
.code32
popal
movl _biosdisk_retval,%eax // Get return value
//movl $1,%eax
ret
/*
* BOOL BiosInt13ReadExtended(ULONG Drive, ULONG Sector, ULONG SectorCount, PVOID Buffer);
*/
_disk_address_packet:
_packet_size:
.byte 0x10
_packet_reserved:
.byte 0
_packet_sector_count:
.word 0
_packet_transfer_buffer_offset:
.word 0
_packet_transfer_buffer_segment:
.word 0
_packet_lba_sector_number:
.quad 0
_packet_64bit_flat_address:
.quad 0
_int13_extended_drive:
.long 0
_int13_extended_sector_count:
.long 0
_int13_extended_retval:
.long 0
_int13_extended_retrycount:
.byte 0
EXTERN(_BiosInt13ReadExtended)
.code32
pushal
/* Get parameters */
movl 0x24(%esp),%eax
movl %eax,_int13_extended_drive
movl 0x28(%esp),%eax
movl %eax,_packet_lba_sector_number
movl 0x2c(%esp),%eax
movw %ax,_packet_sector_count
movl %eax,_int13_extended_sector_count
movl 0x30(%esp),%eax // Get buffer address in eax
shrl $4,%eax // Make linear address into segment
movw %ax,_packet_transfer_buffer_segment // Save segment
movl 0x30(%esp),%eax // Get buffer address in eax
andl $0x0f,%eax // Make linear address into offset
movw %ax,_packet_transfer_buffer_offset // Save offset
call switch_to_real
.code16
pushw %es // Save this just in case
movb $3,_int13_extended_retrycount // Set the retry count to 3
_int13_extended_read:
movb _int13_extended_drive,%dl // Get the drive
movb $0x42,%ah // BIOS int 0x13, function 42h - IBM/MS INT 13 Extensions - EXTENDED READ
movw $_disk_address_packet,%si // DS:SI -> disk address packet
int $0x13 // Read sectors
jc _int13_extended_error // Jump if error (CF = 1 on error)
movl _int13_extended_sector_count,%eax // Get the sector count in eax
cmpw _packet_sector_count,%ax // See how many sectors we actually read (returned in disk address packet sector count)
jne _int13_extended_error // Jump if not equal
jmp _int13_extended_done
_int13_extended_error:
movb %ah,_biosdisk_error_code // Save the error code
cmpb $0x11,%ah // Check and see if it was a corrected ECC error
je _int13_extended_done // If so then the data is still good, if not fail
movb _int13_extended_retrycount,%al // Get the current retry count
decb %al // Decrement it
movb %al,_int13_extended_retrycount // Save it
cmpb $0,%al // Is it zero?
jz _int13_extended_zero // Yes, return zero
movb $0,%ah // BIOS int 0x13, function 0 - Reset Disk System
movb _int13_extended_drive,%dl // Get the drive
int $0x13 // Reset the disk system
jmp _int13_extended_read // Try reading again
_int13_extended_zero:
movb $0,%al // We will return zero
_int13_extended_done:
movzbl %al,%eax // Put the number of sectors read into EAX
movl %eax,_int13_extended_retval // Save it as the return value
popw %es // Restore ES
call switch_to_prot
.code32
popal
movl _int13_extended_retval,%eax // Get return value
ret
/*
* BOOL BiosInt13ExtensionsSupported(ULONG Drive);
*/
_int13_extension_check_drive:
.long 0
_int13_extension_check_retval:
.long 0
EXTERN(_BiosInt13ExtensionsSupported)
.code32
pushal
/* Get parameters */
movl 0x24(%esp),%eax
movl %eax,_int13_extension_check_drive
call switch_to_real
.code16
// Now make sure this computer supports extended reads
movb $0x41,%ah // AH = 41h
movw $0x55aa,%bx // BX = 55AAh
movb _int13_extension_check_drive,%dl // DL = drive (80h-FFh)
int $0x13 // IBM/MS INT 13 Extensions - INSTALLATION CHECK
jc _int13_extension_check_error // CF set on error (extensions not supported)
cmpw $0xaa55,%bx // BX = AA55h if installed
jne _int13_extension_check_error
testb $1,%cl // CX = API subset support bitmap
jz _int13_extension_check_error // Bit 0, extended disk access functions (AH=42h-44h,47h,48h) supported
// If we get here then we passed all the int13 extension tests
movl $1,_int13_extension_check_retval // Set return value to TRUE
jmp _int13_extension_check_done
_int13_extension_check_error:
movl $0,_int13_extension_check_retval // The tests failed so return FALSE
_int13_extension_check_done:
call switch_to_prot
.code32
popal
movl _int13_extension_check_retval,%eax // Get return value
ret
/*
* ULONG BiosInt13GetLastErrorCode(VOID);
*/
EXTERN(_BiosInt13GetLastErrorCode)
.code32
movzbl _biosdisk_error_code,%eax // Get return value
ret
/*
* void StopFloppyMotor(void);
*
* Stops the floppy drive from spinning, so that other software is
* jumped to with a known state.
*/
EXTERN(_StopFloppyMotor)
.code32
pushal
call switch_to_real
.code16
movw $0x3F2, %dx
xorb %al, %al
outb %al, %dx
call switch_to_prot
.code32
popal
ret
/*
* int get_heads(int drive);
*/
EXTERN(_get_heads)
.code32
pushal
push %es
/* Get drive */
movl 0x28(%esp),%eax
movl %eax,_biosdisk_drive
call switch_to_real
.code16
movb $0x08,%ah
movb _biosdisk_drive,%dl
int $0x13
jc _get_heads_error
movzbl %dh,%edx
incl %edx
movl %edx,_biosdisk_retval
jmp _get_heads_done
_get_heads_error:
movl $0xff,_biosdisk_retval
_get_heads_done:
call switch_to_prot
.code32
pop %es
popal
movl _biosdisk_retval,%eax // Get return value
ret
/*
* int get_cylinders(int drive);
*/
EXTERN(_get_cylinders)
.code32
pushal
push %es
/* Get drive */
movl 0x28(%esp),%eax
movl %eax,_biosdisk_drive
call switch_to_real
.code16
movb $0x08,%ah
movb _biosdisk_drive,%dl
int $0x13
jc _get_cylinders_error
xorl %edx,%edx
andb $0xc0,%cl
shrb $0x06,%cl
movb %cl,%dh
movb %ch,%dl
incl %edx
movl %edx,_biosdisk_retval
jmp _get_cylinders_done
_get_cylinders_error:
movl $0xff,_biosdisk_retval
_get_cylinders_done:
call switch_to_prot
.code32
pop %es
popal
movl _biosdisk_retval,%eax // Get return value
ret
/*
* int get_sectors(int drive);
*/
EXTERN(_get_sectors)
.code32
pushal
push %es
/* Get drive */
movl 0x28(%esp),%eax
movl %eax,_biosdisk_drive
call switch_to_real
.code16
movb $0x08,%ah
movb _biosdisk_drive,%dl
int $0x13
jc _get_sectors_error
andb $0x3f,%cl
movzbl %cl,%ecx
movl %ecx,_biosdisk_retval
jmp _get_sectors_done
_get_sectors_error:
movl $0xff,_biosdisk_retval
_get_sectors_done:
call switch_to_prot
.code32
pop %es
popal
movl _biosdisk_retval,%eax // Get return value
ret
/*
* BOOL BiosInt13GetDriveParameters(ULONG Drive, PGEOMETRY Geometry);
*/
_bios_int13_cylinders:
.long 0
_bios_int13_heads:
.long 0
_bios_int13_sectors:
.long 0
_bios_int13_bytes_per_sector:
.long 0
_bios_int13_drive_parameters_struct_address:
.long 0
EXTERN(_BiosInt13GetDriveParameters)
.code32
pushal
push %es
/* Get drive */
movl 0x28(%esp),%eax
movl %eax,_biosdisk_drive
movl 0x2c(%esp),%eax
movl %eax,_bios_int13_drive_parameters_struct_address
call switch_to_real
.code16
movb $0x08,%ah
movb _biosdisk_drive,%dl
int $0x13
jc _BiosInt13GetDriveParameters_Error
// Get the heads
movzbl %dh,%eax
incl %eax
movl %eax,_bios_int13_heads
// Get the sectors
movw %cx,%dx
andb $0x3f,%dl
movzbl %dl,%edx
movl %edx,_bios_int13_sectors
// Get the cylinders
xorl %edx,%edx
andb $0xc0,%cl
shrb $0x06,%cl
movb %cl,%dh
movb %ch,%dl
incl %edx
movl %edx,_bios_int13_cylinders
// Get the bytes per sector
movl $512,_bios_int13_bytes_per_sector // Just assume 512 bytes per sector
movl $0x01,_biosdisk_retval
jmp _BiosInt13GetDriveParameters_Done
_BiosInt13GetDriveParameters_Error:
movl $0x00,_biosdisk_retval
_BiosInt13GetDriveParameters_Done:
call switch_to_prot
.code32
// Copy drive parameters to structure
movl $_bios_int13_cylinders,%esi
movl _bios_int13_drive_parameters_struct_address,%edi
movl $0x04,%ecx
cld
rep movsl
pop %es
popal
movl _biosdisk_retval,%eax // Get return value
ret

View file

@ -1,622 +0,0 @@
/*
* FreeLoader
* Copyright (C) 1998-2002 Brian Palmer <brianp@sginet.com>
* Portions from Linux video.S - Display adapter & video mode setup, version 2.13 (14-May-99)
* Copyright (C) 1995 -- 1999 Martin Mares <mj@ucw.cz>
* Based on the original setup.S code (C) Linus Torvalds and Mats Anderson
*
* 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
* (at your option) 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.
*/
.text
.code16
#define ASM
#include <arch.h>
/*
* VOID BiosSetVideoMode(ULONG VideoMode);
*/
BiosVideoMode:
.long 0
EXTERN(_BiosSetVideoMode)
.code32
pushal
/* Get BIOS video mode */
movl 0x24(%esp),%eax
movl %eax,BiosVideoMode
call switch_to_real
.code16
/* Int 0x10, AH = 0x00 - Set Current Video Mode, also clears the screen */
movb $0x00,%ah
movb BiosVideoMode,%al
int $0x10
call switch_to_prot
.code32
popal
ret
/*
* VOID BiosSetVideoFont8x8(VOID);
*/
EXTERN(_BiosSetVideoFont8x8)
.code32
pushal
call switch_to_real
.code16
/* Int 0x10, AX = 0x1112 - Load 8x8 Font */
movw $0x1112,%ax
xorb %bl,%bl
int $0x10
call switch_to_prot
.code32
popal
ret
/*
* VOID BiosSetVideoFont8x14(VOID);
*/
EXTERN(_BiosSetVideoFont8x14)
.code32
pushal
call switch_to_real
.code16
/* Int 0x10, AX = 0x1111 - Load 8x16 Font */
movw $0x1111,%ax
xorb %bl,%bl
int $0x10
call switch_to_prot
.code32
popal
ret
/*
* VOID BiosSetVideoFont8x16(VOID);
*/
EXTERN(_BiosSetVideoFont8x16)
.code32
pushal
call switch_to_real
.code16
/* Int 0x10, AX = 0x1114 - Load 8x16 Font */
movw $0x1114,%ax
xorb %bl,%bl
int $0x10
call switch_to_prot
.code32
popal
ret
/*
* VOID BiosSelectAlternatePrintScreen(VOID);
*/
EXTERN(_BiosSelectAlternatePrintScreen)
.code32
pushal
call switch_to_real
.code16
/* Int 0x10, AH = 0x12 - Select alternate print screen routine */
movb $0x12,%ah
movb $0x20,%bl
int $0x10
call switch_to_prot
.code32
popal
ret
/*
* VOID BiosDisableCursorEmulation(VOID);
*/
EXTERN(_BiosDisableCursorEmulation)
.code32
pushal
call switch_to_real
.code16
/* Int 0x10, AH = 0x12 - Disable cursor emulation */
movw $0x1201,%ax
movb $0x34,%bl
int $0x10
call switch_to_prot
.code32
popal
ret
/*
* VOID BiosDefineCursor(ULONG StartScanLine, ULONG EndScanLine);
*/
BiosDefineCursorStartScanLine:
.long 0
BiosDefineCursorEndScanLine:
.long 0
EXTERN(_BiosDefineCursor)
.code32
pushal
/* Get cursor scan line positions */
movl 0x24(%esp),%eax
movl %eax,BiosDefineCursorStartScanLine
movl 0x28(%esp),%eax
movl %eax,BiosDefineCursorEndScanLine
call switch_to_real
.code16
/* Int 0x10, AH = 0x01 - Set Text-Mode Cursor Shape */
movb $0x01,%ah
movb $0x03,%al // Current video mode in AL for buggy AMI 386 BIOS
movb BiosDefineCursorStartScanLine,%ch
movb BiosDefineCursorEndScanLine,%cl
int $0x10
call switch_to_prot
.code32
popal
ret
/*
* ULONG BiosDetectVideoCard(VOID);
*/
BiosDetectVideoCardReturnValue:
.long 0
EXTERN(_BiosDetectVideoCard)
.code32
pushal
movl $0x00,BiosDetectVideoCardReturnValue
call switch_to_real
.code16
/* Int 0x10, AH = 0x12 - Get EGA Info */
movb $0x12,%ah
movb $0x10,%bl
int $0x10
movl $0x00,BiosDetectVideoCardReturnValue
cmpb $0x10,%bl
je BiosDetectVideoCardDone
/* Int 0x10, AX = 0x1A00 - Get Display Combination Code */
movw $0x1a00,%ax
int $0x10
cmpb $0x1a,%al
je BiosDetectVideoCardVga
movl $0x01,BiosDetectVideoCardReturnValue
jmp BiosDetectVideoCardDone
BiosDetectVideoCardVga:
movl $0x02,BiosDetectVideoCardReturnValue
BiosDetectVideoCardDone:
call switch_to_prot
.code32
popal
movl BiosDetectVideoCardReturnValue,%eax
ret
/*
* VOID BiosSet200ScanLines(VOID);
*/
EXTERN(_BiosSet200ScanLines)
.code32
pushal
call switch_to_real
.code16
/* Int 0x10, AX = 0x1200 - Set Vertical Resolution */
movw $0x1200,%ax
movb $0x30,%bl
int $0x10
call switch_to_prot
.code32
popal
ret
/*
* VOID BiosSet350ScanLines(VOID);
*/
EXTERN(_BiosSet350ScanLines)
.code32
pushal
call switch_to_real
.code16
/* Int 0x10, AX = 0x1201 - Set Vertical Resolution */
movw $0x1201,%ax
movb $0x30,%bl
int $0x10
call switch_to_prot
.code32
popal
ret
/*
* VOID BiosSet400ScanLines(VOID);
*/
EXTERN(_BiosSet400ScanLines)
.code32
pushal
call switch_to_real
.code16
/* Int 0x10, AX = 0x1202 - Set Vertical Resolution */
movw $0x1202,%ax
movb $0x30,%bl
int $0x10
call switch_to_prot
.code32
popal
ret
/*
* VOID BiosSet480ScanLines(VOID);
*/
EXTERN(_BiosSet480ScanLines)
.code32
pushal
call switch_to_real
.code16
movw $0x03CC,%dx // Get CRTC port
inb %dx,%al
movb $0xD4,%dl
rorb $0x01,%al
jc set48a
movb $0xB4,%dl
set48a:
movw $0x0C11,%ax // Vertical sync end (also unlocks CR0-7)
call outidx
movw $0x0B06,%ax // Vertical total
call outidx
movw $0x3E07,%ax // (vertical) overflow
call outidx
movw $0xEA10,%ax // Vertical sync start
call outidx
movw $0xDF12,%ax // Vertical display end
call outidx
movw $0xE715,%ax // Vertical blank start
call outidx
movw $0x0416,%ax // Vertical blank end
call outidx
push %dx
movb $0xCC,%dl // Misc output register (read)
inb %dx,%al
movb $0xC2,%dl // (write)
andb $0x0D,%al // Preserve clock select bits and color bit
orb $0xE2,%al // Set correct sync polarity
outb %al,%dx
pop %dx
call switch_to_prot
.code32
popal
ret
/*
* VOID BiosSetVideoDisplayEnd(VOID);
*/
EXTERN(_BiosSetVideoDisplayEnd)
.code32
pushal
call switch_to_real
.code16
movw $0x03CC,%dx // Get CRTC port
inb %dx,%al
movb $0xD4,%dl
rorb $0x01,%al
jc set48a
movb $0xB4,%dl
setvde:
movw $0xDF12,%ax // Vertical display end
call outidx
call switch_to_prot
.code32
popal
ret
/*
* Write to indexed VGA register (AL=index, AH=data, DX=index reg. port)
*/
outidx:
.code16
outb %al,%dx
push %ax
movb %ah,%al
incw %dx
outb %al,%dx
decw %dx
pop %ax
ret
/*
* VOID VideoSetTextCursorPosition(ULONG X, ULONG Y);
*/
EXTERN(_VideoSetTextCursorPosition)
.code32
pushal
/* Get cursor positions */
movb 0x24(%esp),%dl
movb 0x28(%esp),%dh
call switch_to_real
.code16
/* Update the cursor position */
movb $2,%ah
movb $0,%bh
int $0x10
call switch_to_prot
.code32
popal
ret
/*
* VOID VideoHideTextCursor(VOID);
*/
EXTERN(_VideoHideTextCursor)
.code32
pushal
call switch_to_real
.code16
/* Hide the cursor */
movb $1,%ah
movw $0x2000,%cx
int $0x10
call switch_to_prot
.code32
popal
ret
/*
* VOID VideoShowTextCursor(VOID);
*/
EXTERN(_VideoShowTextCursor)
.code32
pushal
call switch_to_real
.code16
/* Show the cursor */
movb $1,%ah
movb $0x0d,%ch
movb $0x0e,%cl
int $0x10
call switch_to_prot
.code32
popal
ret
/*
* ULONG VideoGetTextCursorPositionX(VOID);
*/
VideoGetTextCursorPositionXReturnValue:
.long 0
EXTERN(_VideoGetTextCursorPositionX)
.code32
pushal
movl $0x00,VideoGetTextCursorPositionXReturnValue
call switch_to_real
.code16
/* Get the cursor position */
movb $3,%ah
movb $0,%bh
int $0x10
/* Save return value */
movzbl %dl,%edx
movl %edx,VideoGetTextCursorPositionXReturnValue
call switch_to_prot
.code32
popal
/* Restore return value */
movl VideoGetTextCursorPositionXReturnValue,%eax
ret
/*
* ULONG VideoGetTextCursorPositionY(VOID);
*/
VideoGetTextCursorPositionYReturnValue:
.long 0
EXTERN(_VideoGetTextCursorPositionY)
.code32
pushal
movl $0x00,VideoGetTextCursorPositionYReturnValue
call switch_to_real
.code16
/* Get the cursor position */
movb $3,%ah
movb $0,%bh
int $0x10
/* Save return value */
movzbl %dh,%edx
movl %edx,VideoGetTextCursorPositionYReturnValue
call switch_to_prot
.code32
popal
/* Restore return value */
movl VideoGetTextCursorPositionYReturnValue,%eax
ret
/*
* VOID BiosVideoDisableBlinkBit(VOID);
*/
EXTERN(_BiosVideoDisableBlinkBit)
.code32
pushal
call switch_to_real
.code16
/* Toggle Intensity/Blinking Bit */
/* AX = 1003h */
/* BL = new state */
/* 00h background intensity enabled */
/* 01h blink enabled */
/* Note: although there is no function to get */
/* the current status, bit 5 of 0040h:0065h */
/* indicates the state. */
movw $0x1003,%ax
movb $0x00,%bl
int $0x10
call switch_to_prot
.code32
popal
ret

View file

@ -0,0 +1,431 @@
/*
* FreeLoader
* Copyright (C) 1998-2002 Brian Palmer <brianp@sginet.com>
*
* 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
* (at your option) 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.
*/
#include <freeldr.h>
#include <disk.h>
#include <rtl.h>
#include <arch.h>
#include <debug.h>
#include <comm.h>
typedef struct
{
U8 PacketSize; // 00h - Size of packet (10h or 18h)
U8 Reserved; // 01h - Reserved (0)
U16 LBABlockCount; // 02h - Number of blocks to transfer (max 007Fh for Phoenix EDD)
U16 TransferBufferOffset; // 04h - Transfer buffer offset (seg:off)
U16 TransferBufferSegment; // Transfer buffer segment (seg:off)
U64 LBAStartBlock; // 08h - Starting absolute block number
U64 TransferBuffer64; // 10h - (EDD-3.0, optional) 64-bit flat address of transfer buffer
// used if DWORD at 04h is FFFFh:FFFFh
} PACKED I386_DISK_ADDRESS_PACKET, *PI386_DISK_ADDRESS_PACKET;
/////////////////////////////////////////////////////////////////////////////////////////////
// FUNCTIONS
/////////////////////////////////////////////////////////////////////////////////////////////
#ifdef __i386__
BOOL DiskReadLogicalSectors(U32 DriveNumber, U64 SectorNumber, U32 SectorCount, PVOID Buffer)
{
DbgPrint((DPRINT_DISK, "DiskReadLogicalSectors() DriveNumber: 0x%x SectorNumber: %d%d SectorCount: %d Buffer: 0x%x\n", DriveNumber, (U32)SectorNumber, SectorCount, Buffer));
//
// Check to see if it is a fixed disk drive
// If so then check to see if Int13 extensions work
// If they do then use them, otherwise default back to BIOS calls
//
if ((DriveNumber >= 0x80) && (IsSetupLdr || DiskInt13ExtensionsSupported(DriveNumber)))
{
DbgPrint((DPRINT_DISK, "Using Int 13 Extensions for read. DiskInt13ExtensionsSupported(%d) = %s\n", DriveNumber, DiskInt13ExtensionsSupported(DriveNumber) ? "TRUE" : "FALSE"));
//
// LBA is easy, nothing to calculate
// Just do the read
//
return DiskReadLogicalSectorsLBA(DriveNumber, SectorNumber, SectorCount, Buffer);
}
else
{
// LBA is not supported default to the CHS calls
return DiskReadLogicalSectorsCHS(DriveNumber, SectorNumber, SectorCount, Buffer);
}
return TRUE;
}
BOOL DiskReadLogicalSectorsLBA(U32 DriveNumber, U64 SectorNumber, U32 SectorCount, PVOID Buffer)
{
REGS RegsIn;
REGS RegsOut;
U32 RetryCount;
PI386_DISK_ADDRESS_PACKET Packet = (PI386_DISK_ADDRESS_PACKET)(BIOSCALLBUFFER);
DbgPrint((DPRINT_DISK, "DiskReadLogicalSectorsLBA()\n"));
// BIOS int 0x13, function 42h - IBM/MS INT 13 Extensions - EXTENDED READ
RegsIn.b.ah = 0x42; // Subfunction 42h
RegsIn.b.dl = DriveNumber; // Drive number in DL (0 - floppy, 0x80 - harddisk)
RegsIn.x.ds = BIOSCALLBUFSEGMENT; // DS:SI -> disk address packet
RegsIn.w.si = BIOSCALLBUFOFFSET;
// Setup disk address packet
RtlZeroMemory(Packet, sizeof(I386_DISK_ADDRESS_PACKET));
Packet->PacketSize = sizeof(I386_DISK_ADDRESS_PACKET);
Packet->Reserved = 0;
Packet->LBABlockCount = SectorCount;
Packet->TransferBufferOffset = ((U32)Buffer) & 0x0F;
Packet->TransferBufferSegment = ((U32)Buffer) >> 4;
Packet->LBAStartBlock = SectorNumber;
Packet->TransferBuffer64 = 0;
// BIOS int 0x13, function 42h - IBM/MS INT 13 Extensions - EXTENDED READ
// Return:
// CF clear if successful
// AH = 00h
// CF set on error
// AH = error code
// disk address packet's block count field set to the
// number of blocks successfully transferred
// Retry 3 times
for (RetryCount=0; RetryCount<3; RetryCount++)
{
Int386(0x13, &RegsIn, &RegsOut);
// If it worked return TRUE
if (INT386_SUCCESS(RegsOut))
{
return TRUE;
}
// If it was a corrected ECC error then the data is still good
else if (RegsOut.b.ah == 0x11)
{
return TRUE;
}
// If it failed the do the next retry
else
{
DiskResetController(DriveNumber);
continue;
}
}
// If we get here then the read failed
DiskError("Disk Read Failed", RegsOut.b.ah);
return FALSE;
}
BOOL DiskReadLogicalSectorsCHS(U32 DriveNumber, U64 SectorNumber, U32 SectorCount, PVOID Buffer)
{
U32 PhysicalSector;
U32 PhysicalHead;
U32 PhysicalTrack;
GEOMETRY DriveGeometry;
U32 NumberOfSectorsToRead;
REGS RegsIn;
REGS RegsOut;
U32 RetryCount;
DbgPrint((DPRINT_DISK, "DiskReadLogicalSectorsCHS()\n"));
//
// Get the drive geometry
//
if (!DiskGetDriveGeometry(DriveNumber, &DriveGeometry))
{
return FALSE;
}
while (SectorCount)
{
//
// Calculate the physical disk offsets
//
PhysicalSector = 1 + (SectorNumber % DriveGeometry.Sectors);
PhysicalHead = (SectorNumber / DriveGeometry.Sectors) % DriveGeometry.Heads;
PhysicalTrack = (SectorNumber / DriveGeometry.Sectors) / DriveGeometry.Heads;
//
// Calculate how many sectors we need to read this round
//
if (PhysicalSector > 1)
{
if (SectorCount >= (DriveGeometry.Sectors - (PhysicalSector - 1)))
NumberOfSectorsToRead = (DriveGeometry.Sectors - (PhysicalSector - 1));
else
NumberOfSectorsToRead = SectorCount;
}
else
{
if (SectorCount >= DriveGeometry.Sectors)
NumberOfSectorsToRead = DriveGeometry.Sectors;
else
NumberOfSectorsToRead = SectorCount;
}
//
// Make sure the read is within the geometry boundaries
//
if ((PhysicalHead >= DriveGeometry.Heads) ||
(PhysicalTrack >= DriveGeometry.Cylinders) ||
((NumberOfSectorsToRead + PhysicalSector) > (DriveGeometry.Sectors + 1)) ||
(PhysicalSector > DriveGeometry.Sectors))
{
DiskError("Disk read exceeds drive geometry limits.", 0);
return FALSE;
}
// BIOS Int 13h, function 2 - Read Disk Sectors
// AH = 02h
// AL = number of sectors to read (must be nonzero)
// CH = low eight bits of cylinder number
// CL = sector number 1-63 (bits 0-5)
// high two bits of cylinder (bits 6-7, hard disk only)
// DH = head number
// DL = drive number (bit 7 set for hard disk)
// ES:BX -> data buffer
// Return:
// CF set on error
// if AH = 11h (corrected ECC error), AL = burst length
// CF clear if successful
// AH = status
// AL = number of sectors transferred
// (only valid if CF set for some BIOSes)
RegsIn.b.ah = 0x02;
RegsIn.b.al = NumberOfSectorsToRead;
RegsIn.b.ch = (PhysicalTrack & 0xFF);
RegsIn.b.cl = (PhysicalSector + ((PhysicalTrack & 0x300) >> 2));
RegsIn.b.dh = PhysicalHead;
RegsIn.b.dl = DriveNumber;
RegsIn.w.es = ((U32)Buffer) >> 4;
RegsIn.w.bx = ((U32)Buffer) & 0x0F;
//
// Perform the read
// Retry 3 times
//
for (RetryCount=0; RetryCount<3; RetryCount++)
{
Int386(0x13, &RegsIn, &RegsOut);
// If it worked break out
if (INT386_SUCCESS(RegsOut))
{
break;
}
// If it was a corrected ECC error then the data is still good
else if (RegsOut.b.ah == 0x11)
{
break;
}
// If it failed the do the next retry
else
{
DiskResetController(DriveNumber);
continue;
}
}
// If we retried 3 times then fail
if (RetryCount >= 3)
{
DiskError("Disk Read Failed", RegsOut.b.ah);
return FALSE;
}
// I have learned that not all bioses return
// the sector read count in the AL register (at least mine doesn't)
// even if the sectors were read correctly. So instead
// of checking the sector read count we will rely solely
// on the carry flag being set on error
Buffer += (NumberOfSectorsToRead * DriveGeometry.BytesPerSector);
SectorCount -= NumberOfSectorsToRead;
SectorNumber += NumberOfSectorsToRead;
}
return TRUE;
}
BOOL DiskResetController(U32 DriveNumber)
{
REGS RegsIn;
REGS RegsOut;
DbgPrint((DPRINT_DISK, "DiskResetController(0x%x) DISK OPERATION FAILED -- RESETTING CONTROLLER\n", DriveNumber));
// BIOS Int 13h, function 0 - Reset disk system
// AH = 00h
// DL = drive (if bit 7 is set both hard disks and floppy disks reset)
// Return:
// AH = status
// CF clear if successful
// CF set on error
RegsIn.b.ah = 0x02;
RegsIn.b.dl = DriveNumber;
// Reset the disk controller
Int386(0x13, &RegsIn, &RegsOut);
return INT386_SUCCESS(RegsOut);
}
BOOL DiskInt13ExtensionsSupported(U32 DriveNumber)
{
REGS RegsIn;
REGS RegsOut;
DbgPrint((DPRINT_DISK, "DiskInt13ExtensionsSupported()\n"));
// IBM/MS INT 13 Extensions - INSTALLATION CHECK
// AH = 41h
// BX = 55AAh
// DL = drive (80h-FFh)
// Return:
// CF set on error (extensions not supported)
// AH = 01h (invalid function)
// CF clear if successful
// BX = AA55h if installed
// AH = major version of extensions
// 01h = 1.x
// 20h = 2.0 / EDD-1.0
// 21h = 2.1 / EDD-1.1
// 30h = EDD-3.0
// AL = internal use
// CX = API subset support bitmap
// DH = extension version (v2.0+ ??? -- not present in 1.x)
//
// Bitfields for IBM/MS INT 13 Extensions API support bitmap
// Bit 0, extended disk access functions (AH=42h-44h,47h,48h) supported
// Bit 1, removable drive controller functions (AH=45h,46h,48h,49h,INT 15/AH=52h) supported
// Bit 2, enhanced disk drive (EDD) functions (AH=48h,AH=4Eh) supported
// extended drive parameter table is valid
// Bits 3-15 reserved
RegsIn.b.ah = 0x41;
RegsIn.w.bx = 0x55AA;
RegsIn.b.dl = DriveNumber;
// Reset the disk controller
Int386(0x13, &RegsIn, &RegsOut);
if (!INT386_SUCCESS(RegsOut))
{
// CF set on error (extensions not supported)
return FALSE;
}
if (RegsOut.w.bx != 0xAA55)
{
// BX = AA55h if installed
return FALSE;
}
if (!(RegsOut.w.cx & 0x01))
{
// CX = API subset support bitmap
// Bit 0, extended disk access functions (AH=42h-44h,47h,48h) supported
return FALSE;
}
return TRUE;
}
VOID DiskStopFloppyMotor(VOID)
{
WRITE_PORT_UCHAR((PUCHAR)0x3F2, 0);
}
BOOL DiskGetDriveParameters(U32 DriveNumber, PGEOMETRY Geometry)
{
REGS RegsIn;
REGS RegsOut;
U32 Cylinders;
DbgPrint((DPRINT_DISK, "DiskGetDriveParameters()\n"));
// BIOS Int 13h, function 08h - Get drive parameters
// AH = 08h
// DL = drive (bit 7 set for hard disk)
// ES:DI = 0000h:0000h to guard against BIOS bugs
// Return:
// CF set on error
// AH = status (07h)
// CF clear if successful
// AH = 00h
// AL = 00h on at least some BIOSes
// BL = drive type (AT/PS2 floppies only)
// CH = low eight bits of maximum cylinder number
// CL = maximum sector number (bits 5-0)
// high two bits of maximum cylinder number (bits 7-6)
// DH = maximum head number
// DL = number of drives
// ES:DI -> drive parameter table (floppies only)
RegsIn.b.ah = 0x08;
RegsIn.b.dl = DriveNumber;
RegsIn.w.es = 0x0000;
RegsIn.w.di = 0x0000;
// Get drive parameters
Int386(0x13, &RegsIn, &RegsOut);
if (!INT386_SUCCESS(RegsOut))
{
return FALSE;
}
Cylinders = (RegsOut.b.cl & 0xC0) << 2;
Cylinders += RegsOut.b.ch;
Cylinders++;
Geometry->Cylinders = Cylinders;
Geometry->Heads = RegsOut.b.dh + 1;
Geometry->Sectors = RegsOut.b.cl & 0x3F;
Geometry->BytesPerSector = 512; // Just assume 512 bytes per sector
return TRUE;
}
U32 DiskGetCacheableBlockCount(U32 DriveNumber)
{
GEOMETRY Geometry;
// Get the disk geometry
// If this fails then we will just return 1 sector to be safe
if (!DiskGetDriveParameters(DriveNumber, &Geometry))
{
return 1;
}
// If LBA is supported then the block size will be 64 sectors (32k)
// If not then the block size is the size of one track
if (DiskInt13ExtensionsSupported)
{
return 64;
}
else
{
return Geometry.Sectors;
}
}
#endif // defined __i386__

View file

@ -0,0 +1,208 @@
/*
* FreeLoader
* Copyright (C) 1998-2002 Brian Palmer <brianp@sginet.com>
*
* 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
* (at your option) 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.
*/
#include <freeldr.h>
#include <arch.h>
#include <mm.h>
#include <debug.h>
#include <rtl.h>
#include <comm.h>
U32 GetExtendedMemorySize(VOID)
{
REGS RegsIn;
REGS RegsOut;
U32 MemorySize;
DbgPrint((DPRINT_MEMORY, "GetExtendedMemorySize()\n"));
// Int 15h AX=E801h
// Phoenix BIOS v4.0 - GET MEMORY SIZE FOR >64M CONFIGURATIONS
//
// AX = E801h
// Return:
// CF clear if successful
// AX = extended memory between 1M and 16M, in K (max 3C00h = 15MB)
// BX = extended memory above 16M, in 64K blocks
// CX = configured memory 1M to 16M, in K
// DX = configured memory above 16M, in 64K blocks
// CF set on error
RegsIn.w.ax = 0xE801;
Int386(0x15, &RegsIn, &RegsOut);
DbgPrint((DPRINT_MEMORY, "Int15h AX=E801h\n"));
DbgPrint((DPRINT_MEMORY, "AX = 0x%x\n", RegsOut.w.ax));
DbgPrint((DPRINT_MEMORY, "BX = 0x%x\n", RegsOut.w.bx));
DbgPrint((DPRINT_MEMORY, "CX = 0x%x\n", RegsOut.w.cx));
DbgPrint((DPRINT_MEMORY, "DX = 0x%x\n", RegsOut.w.dx));
DbgPrint((DPRINT_MEMORY, "CF set = %s\n\n", (RegsOut.x.eflags & I386FLAG_CF) ? "TRUE" : "FALSE"));
if (INT386_SUCCESS(RegsOut))
{
// If AX=BX=0000h the use CX and DX
if (RegsOut.w.ax == 0)
{
// Return extended memory size in K
MemorySize = RegsOut.w.dx * 64;
MemorySize += RegsOut.w.cx;
return MemorySize;
}
else
{
// Return extended memory size in K
MemorySize = RegsOut.w.bx * 64;
MemorySize += RegsOut.w.ax;
return MemorySize;
}
}
// If we get here then Int15 Func E801h didn't work
// So try Int15 Func 88h
// Int 15h AH=88h
// SYSTEM - GET EXTENDED MEMORY SIZE (286+)
//
// AH = 88h
// Return:
// CF clear if successful
// AX = number of contiguous KB starting at absolute address 100000h
// CF set on error
// AH = status
// 80h invalid command (PC,PCjr)
// 86h unsupported function (XT,PS30)
RegsIn.b.ah = 0x88;
Int386(0x15, &RegsIn, &RegsOut);
DbgPrint((DPRINT_MEMORY, "Int15h AH=88h\n"));
DbgPrint((DPRINT_MEMORY, "AX = 0x%x\n", RegsOut.w.ax));
DbgPrint((DPRINT_MEMORY, "CF set = %s\n\n", (RegsOut.x.eflags & I386FLAG_CF) ? "TRUE" : "FALSE"));
if (INT386_SUCCESS(RegsOut) && RegsOut.w.ax != 0)
{
MemorySize = RegsOut.w.ax;
return MemorySize;
}
// If we get here then Int15 Func 88h didn't work
// So try reading the CMOS
WRITE_PORT_UCHAR((PUCHAR)0x70, 0x31);
MemorySize = READ_PORT_UCHAR((PUCHAR)0x71);
MemorySize = (MemorySize & 0xFFFF);
MemorySize = (MemorySize << 8);
DbgPrint((DPRINT_MEMORY, "Int15h Failed\n"));
DbgPrint((DPRINT_MEMORY, "CMOS reports: 0x%x\n", MemorySize));
return MemorySize;
}
U32 GetConventionalMemorySize(VOID)
{
REGS Regs;
DbgPrint((DPRINT_MEMORY, "GetConventionalMemorySize()\n"));
// Int 12h
// BIOS - GET MEMORY SIZE
//
// Return:
// AX = kilobytes of contiguous memory starting at absolute address 00000h
//
// This call returns the contents of the word at 0040h:0013h;
// in PC and XT, this value is set from the switches on the motherboard
Regs.w.ax = 0;
Int386(0x12, &Regs, &Regs);
DbgPrint((DPRINT_MEMORY, "Int12h\n"));
DbgPrint((DPRINT_MEMORY, "AX = 0x%x\n\n", Regs.w.ax));
return (U32)Regs.w.ax;
}
U32 GetBiosMemoryMap(BIOS_MEMORY_MAP BiosMemoryMap[32])
{
REGS Regs;
U32 MapCount;
DbgPrint((DPRINT_MEMORY, "GetBiosMemoryMap()\n"));
// Int 15h AX=E820h
// Newer BIOSes - GET SYSTEM MEMORY MAP
//
// AX = E820h
// EAX = 0000E820h
// EDX = 534D4150h ('SMAP')
// EBX = continuation value or 00000000h to start at beginning of map
// ECX = size of buffer for result, in bytes (should be >= 20 bytes)
// ES:DI -> buffer for result
// Return:
// CF clear if successful
// EAX = 534D4150h ('SMAP')
// ES:DI buffer filled
// EBX = next offset from which to copy or 00000000h if all done
// ECX = actual length returned in bytes
// CF set on error
// AH = error code (86h)
Regs.x.eax = 0x0000E820;
Regs.x.edx = 0x534D4150; // ('SMAP')
Regs.x.ebx = 0x00000000;
Regs.x.ecx = sizeof(BIOS_MEMORY_MAP);
Regs.w.es = BIOSCALLBUFSEGMENT;
Regs.w.di = BIOSCALLBUFOFFSET;
for (MapCount=0; MapCount<32; MapCount++)
{
Int386(0x15, &Regs, &Regs);
DbgPrint((DPRINT_MEMORY, "Memory Map Entry %d\n", MapCount));
DbgPrint((DPRINT_MEMORY, "Int15h AX=E820h\n"));
DbgPrint((DPRINT_MEMORY, "EAX = 0x%x\n", Regs.x.eax));
DbgPrint((DPRINT_MEMORY, "EBX = 0x%x\n", Regs.x.ebx));
DbgPrint((DPRINT_MEMORY, "ECX = 0x%x\n", Regs.x.ecx));
DbgPrint((DPRINT_MEMORY, "CF set = %s\n", (Regs.x.eflags & I386FLAG_CF) ? "TRUE" : "FALSE"));
// If the BIOS didn't return 'SMAP' in EAX then
// it doesn't support this call
if (Regs.x.eax != 0x534D4150)
{
break;
}
// Copy data to caller's buffer
RtlCopyMemory(&BiosMemoryMap[MapCount], (PVOID)BIOSCALLBUFFER, Regs.x.ecx);
DbgPrint((DPRINT_MEMORY, "BaseAddress: 0x%x%x\n", BiosMemoryMap[MapCount].BaseAddress));
DbgPrint((DPRINT_MEMORY, "Length: 0x%x%x\n", BiosMemoryMap[MapCount].Length));
DbgPrint((DPRINT_MEMORY, "Type: 0x%x\n", BiosMemoryMap[MapCount].Type));
DbgPrint((DPRINT_MEMORY, "Reserved: 0x%x\n", BiosMemoryMap[MapCount].Reserved));
DbgPrint((DPRINT_MEMORY, "\n"));
// If the continuation value is zero or the
// carry flag is set then this was
// the last entry so we're done
if (Regs.x.ebx == 0x00000000 || !INT386_SUCCESS(Regs))
{
MapCount++;
DbgPrint((DPRINT_MEMORY, "End Of System Memory Map!\n\n"));
break;
}
}
return MapCount;
}

View file

@ -0,0 +1,328 @@
/*
* FreeLoader
* Copyright (C) 1998-2002 Brian Palmer <brianp@sginet.com>
*
* 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
* (at your option) 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.
*/
#include <freeldr.h>
#include <arch.h>
void putchar(int ch)
{
REGS Regs;
/* If we are displaying a CR '\n' then do a LF also */
if (ch == '\n')
{
/* Display the LF */
putchar('\r');
}
/* If we are displaying a TAB '\t' then display 8 spaces ' ' */
if (ch == '\t')
{
/* Display the 8 spaces ' ' */
putchar(' ');
putchar(' ');
putchar(' ');
putchar(' ');
putchar(' ');
putchar(' ');
putchar(' ');
putchar(' ');
return;
}
// Int 10h AH=0Eh
// VIDEO - TELETYPE OUTPUT
//
// AH = 0Eh
// AL = character to write
// BH = page number
// BL = foreground color (graphics modes only)
Regs.b.ah = 0x0E;
Regs.b.al = ch;
Regs.w.bx = 1;
Int386(0x10, &Regs, &Regs);
}
int kbhit(void)
{
REGS Regs;
// Int 16h AH=01h
// KEYBOARD - CHECK FOR KEYSTROKE
//
// AH = 01h
// Return:
// ZF set if no keystroke available
// ZF clear if keystroke available
// AH = BIOS scan code
// AL = ASCII character
Regs.b.ah = 0x01;
Int386(0x16, &Regs, &Regs);
if (Regs.x.eflags & I386FLAG_ZF)
{
return 0;
}
return 1;
}
int getch(void)
{
REGS Regs;
static BOOL ExtendedKey = FALSE;
static char ExtendedScanCode = 0;
// If the last time we were called an
// extended key was pressed then return
// that keys scan code.
if (ExtendedKey)
{
ExtendedKey = FALSE;
return ExtendedScanCode;
}
// Int 16h AH=00h
// KEYBOARD - GET KEYSTROKE
//
// AH = 00h
// Return:
// AH = BIOS scan code
// AL = ASCII character
Regs.b.ah = 0x00;
Int386(0x16, &Regs, &Regs);
// Check for an extended keystroke
if (Regs.b.al == 0)
{
ExtendedKey = TRUE;
ExtendedScanCode = Regs.b.ah;
}
// Return keystroke
return Regs.b.al;
}
int getyear(void)
{
REGS Regs;
U16 Digit1;
U16 Digit2;
U16 Cent1;
U16 Cent2;
U16 Year;
// Some BIOSes, such es the 1998/07/25 system ROM
// in the Compaq Deskpro EP/SB, leave CF unchanged
// if successful, so CF should be cleared before
// calling this function.
__asm__ ("clc");
// Int 1Ah AH=04h
// TIME - GET REAL-TIME CLOCK DATE (AT,XT286,PS)
//
// AH = 04h
// CF clear to avoid bug
// Return:
// CF clear if successful
// CH = century (BCD)
// CL = year (BCD)
// DH = month (BCD)
// DL = day (BCD)
// CF set on error
Regs.b.ah = 0x04;
Int386(0x1A, &Regs, &Regs);
/* Convert from BCD to normal */
Digit1 = Regs.b.cl & 0x0F;
Digit2 = ((Regs.b.cl >> 4) & 0x0F) * 10;
Cent1 = Regs.b.ch & 0x0F;
Cent2 = ((Regs.b.ch >> 4) & 0x0F) * 10;
Year = Cent1 + Cent2;
Year *= 100;
Year += Digit1 + Digit2;
return Year;
}
int getday(void)
{
REGS Regs;
U16 Digit1;
U16 Digit2;
// Some BIOSes, such es the 1998/07/25 system ROM
// in the Compaq Deskpro EP/SB, leave CF unchanged
// if successful, so CF should be cleared before
// calling this function.
__asm__ ("clc");
// Int 1Ah AH=04h
// TIME - GET REAL-TIME CLOCK DATE (AT,XT286,PS)
//
// AH = 04h
// CF clear to avoid bug
// Return:
// CF clear if successful
// CH = century (BCD)
// CL = year (BCD)
// DH = month (BCD)
// DL = day (BCD)
// CF set on error
Regs.b.ah = 0x04;
Int386(0x1A, &Regs, &Regs);
/* Convert from BCD to normal */
Digit1 = Regs.b.dl & 0x0F;
Digit2 = ((Regs.b.dl >> 4) & 0x0F) * 10;
return (Digit1 + Digit2);
}
int getmonth(void)
{
REGS Regs;
U16 Digit1;
U16 Digit2;
// Some BIOSes, such es the 1998/07/25 system ROM
// in the Compaq Deskpro EP/SB, leave CF unchanged
// if successful, so CF should be cleared before
// calling this function.
__asm__ ("clc");
// Int 1Ah AH=04h
// TIME - GET REAL-TIME CLOCK DATE (AT,XT286,PS)
//
// AH = 04h
// CF clear to avoid bug
// Return:
// CF clear if successful
// CH = century (BCD)
// CL = year (BCD)
// DH = month (BCD)
// DL = day (BCD)
// CF set on error
Regs.b.ah = 0x04;
Int386(0x1A, &Regs, &Regs);
/* Convert from BCD to normal */
Digit1 = Regs.b.dh & 0x0F;
Digit2 = ((Regs.b.dh >> 4) & 0x0F) * 10;
return (Digit1 + Digit2);
}
int gethour(void)
{
REGS Regs;
U16 Digit1;
U16 Digit2;
// Some BIOSes leave CF unchanged if successful,
// so CF should be cleared before calling this function.
__asm__ ("clc");
// Int 1Ah AH=02h
// TIME - GET REAL-TIME CLOCK TIME (AT,XT286,PS)
//
// AH = 02h
// CF clear to avoid bug
// Return:
// CF clear if successful
// CH = hour (BCD)
// CL = minutes (BCD)
// DH = seconds (BCD)
// DL = daylight savings flag (00h standard time, 01h daylight time)
// CF set on error (i.e. clock not running or in middle of update)
Regs.b.ah = 0x02;
Int386(0x1A, &Regs, &Regs);
/* Convert from BCD to normal */
Digit1 = Regs.b.ch & 0x0F;
Digit2 = ((Regs.b.ch >> 4) & 0x0F) * 10;
return (Digit1 + Digit2);
}
int getminute(void)
{
REGS Regs;
U16 Digit1;
U16 Digit2;
// Some BIOSes leave CF unchanged if successful,
// so CF should be cleared before calling this function.
__asm__ ("clc");
// Int 1Ah AH=02h
// TIME - GET REAL-TIME CLOCK TIME (AT,XT286,PS)
//
// AH = 02h
// CF clear to avoid bug
// Return:
// CF clear if successful
// CH = hour (BCD)
// CL = minutes (BCD)
// DH = seconds (BCD)
// DL = daylight savings flag (00h standard time, 01h daylight time)
// CF set on error (i.e. clock not running or in middle of update)
Regs.b.ah = 0x02;
Int386(0x1A, &Regs, &Regs);
/* Convert from BCD to normal */
Digit1 = Regs.b.cl & 0x0F;
Digit2 = ((Regs.b.cl >> 4) & 0x0F) * 10;
return (Digit1 + Digit2);
}
int getsecond(void)
{
REGS Regs;
U16 Digit1;
U16 Digit2;
// Some BIOSes leave CF unchanged if successful,
// so CF should be cleared before calling this function.
__asm__ ("clc");
// Int 1Ah AH=02h
// TIME - GET REAL-TIME CLOCK TIME (AT,XT286,PS)
//
// AH = 02h
// CF clear to avoid bug
// Return:
// CF clear if successful
// CH = hour (BCD)
// CL = minutes (BCD)
// DH = seconds (BCD)
// DL = daylight savings flag (00h standard time, 01h daylight time)
// CF set on error (i.e. clock not running or in middle of update)
Regs.b.ah = 0x02;
Int386(0x1A, &Regs, &Regs);
/* Convert from BCD to normal */
Digit1 = Regs.b.dh & 0x0F;
Digit2 = ((Regs.b.dh >> 4) & 0x0F) * 10;
return (Digit1 + Digit2);
}

View file

@ -76,59 +76,6 @@
str i386_TR
.endm
.macro SAVE_CPU_REGS_ERROR_CODE
movl %eax,i386_EAX
movl %ebx,i386_EBX
movl %ecx,i386_ECX
movl %edx,i386_EDX
movl %esp,i386_ESP
movl %ebp,i386_EBP
movl %esi,i386_ESI
movl %edi,i386_EDI
movw %ds,%ax
movw %ax,i386_DS
movw %es,%ax
movw %ax,i386_ES
movw %fs,%ax
movw %ax,i386_FS
movw %gs,%ax
movw %ax,i386_GS
movw %ss,%ax
movw %ax,i386_SS
popl %eax
movl %eax,i386_ERROR_CODE
popl %eax
movl %eax,i386_EIP
popl %eax
movw %ax,i386_CS
popl %eax
movl %eax,i386_EFLAGS
movl %cr0,%eax
movl %eax,i386_CR0
//movl %cr1,%eax
//movl %eax,i386_CR1
movl %cr2,%eax
movl %eax,i386_CR2
movl %cr3,%eax
movl %eax,i386_CR3
movl %dr0,%eax
movl %eax,i386_DR0
movl %dr1,%eax
movl %eax,i386_DR1
movl %dr2,%eax
movl %eax,i386_DR2
movl %dr3,%eax
movl %eax,i386_DR3
movl %dr6,%eax
movl %eax,i386_DR6
movl %dr7,%eax
movl %eax,i386_DR7
sgdt i386_GDTR
sidt i386_IDTR
sldt i386_LDTR
str i386_TR
.endm
i386ExceptionHandlerText:
@ -317,6 +264,8 @@ i386_ScreenPosY:
i386CommonExceptionHandler:
.code32
SAVE_CPU_REGS
call i386ClearScreenToBlue
movl $i386ExceptionHandlerText,%esi
@ -630,8 +579,6 @@ i386PrintHexByte1:
EXTERN(i386DivideByZero)
.code32
SAVE_CPU_REGS
movl $i386DivideByZeroText,i386ExceptionDescriptionText
jmp i386CommonExceptionHandler
@ -639,8 +586,6 @@ EXTERN(i386DivideByZero)
EXTERN(i386DebugException)
.code32
SAVE_CPU_REGS
movl $i386DebugExceptionText,i386ExceptionDescriptionText
jmp i386CommonExceptionHandler
@ -648,8 +593,6 @@ EXTERN(i386DebugException)
EXTERN(i386NMIException)
.code32
SAVE_CPU_REGS
movl $i386NMIExceptionText,i386ExceptionDescriptionText
jmp i386CommonExceptionHandler
@ -657,8 +600,6 @@ EXTERN(i386NMIException)
EXTERN(i386Breakpoint)
.code32
SAVE_CPU_REGS
movl $i386BreakpointText,i386ExceptionDescriptionText
jmp i386CommonExceptionHandler
@ -666,8 +607,6 @@ EXTERN(i386Breakpoint)
EXTERN(i386Overflow)
.code32
SAVE_CPU_REGS
movl $i386OverflowText,i386ExceptionDescriptionText
jmp i386CommonExceptionHandler
@ -675,8 +614,6 @@ EXTERN(i386Overflow)
EXTERN(i386BoundException)
.code32
SAVE_CPU_REGS
movl $i386BoundExceptionText,i386ExceptionDescriptionText
jmp i386CommonExceptionHandler
@ -684,8 +621,6 @@ EXTERN(i386BoundException)
EXTERN(i386InvalidOpcode)
.code32
SAVE_CPU_REGS
movl $i386InvalidOpcodeText,i386ExceptionDescriptionText
jmp i386CommonExceptionHandler
@ -693,8 +628,6 @@ EXTERN(i386InvalidOpcode)
EXTERN(i386FPUNotAvailable)
.code32
SAVE_CPU_REGS
movl $i386FPUNotAvailableText,i386ExceptionDescriptionText
jmp i386CommonExceptionHandler
@ -702,7 +635,8 @@ EXTERN(i386FPUNotAvailable)
EXTERN(i386DoubleFault)
.code32
SAVE_CPU_REGS_ERROR_CODE
popl %eax
movl %eax,i386_ERROR_CODE
movl $i386DoubleFaultText,i386ExceptionDescriptionText
jmp i386CommonExceptionHandler
@ -711,8 +645,6 @@ EXTERN(i386DoubleFault)
EXTERN(i386CoprocessorSegment)
.code32
SAVE_CPU_REGS
movl $i386CoprocessorSegmentText,i386ExceptionDescriptionText
jmp i386CommonExceptionHandler
@ -720,7 +652,8 @@ EXTERN(i386CoprocessorSegment)
EXTERN(i386InvalidTSS)
.code32
SAVE_CPU_REGS_ERROR_CODE
popl %eax
movl %eax,i386_ERROR_CODE
movl $i386InvalidTSSText,i386ExceptionDescriptionText
jmp i386CommonExceptionHandler
@ -729,7 +662,8 @@ EXTERN(i386InvalidTSS)
EXTERN(i386SegmentNotPresent)
.code32
SAVE_CPU_REGS_ERROR_CODE
popl %eax
movl %eax,i386_ERROR_CODE
movl $i386SegmentNotPresentText,i386ExceptionDescriptionText
jmp i386CommonExceptionHandler
@ -738,7 +672,8 @@ EXTERN(i386SegmentNotPresent)
EXTERN(i386StackException)
.code32
SAVE_CPU_REGS_ERROR_CODE
popl %eax
movl %eax,i386_ERROR_CODE
movl $i386StackExceptionText,i386ExceptionDescriptionText
jmp i386CommonExceptionHandler
@ -747,7 +682,8 @@ EXTERN(i386StackException)
EXTERN(i386GeneralProtectionFault)
.code32
SAVE_CPU_REGS_ERROR_CODE
popl %eax
movl %eax,i386_ERROR_CODE
movl $i386GeneralProtectionFaultText,i386ExceptionDescriptionText
jmp i386CommonExceptionHandler
@ -756,7 +692,8 @@ EXTERN(i386GeneralProtectionFault)
EXTERN(i386PageFault)
.code32
SAVE_CPU_REGS_ERROR_CODE
popl %eax
movl %eax,i386_ERROR_CODE
movl $i386PageFaultText,i386ExceptionDescriptionText
jmp i386CommonExceptionHandler
@ -765,8 +702,6 @@ EXTERN(i386PageFault)
EXTERN(i386CoprocessorError)
.code32
SAVE_CPU_REGS
movl $i386CoprocessorErrorText,i386ExceptionDescriptionText
jmp i386CommonExceptionHandler
@ -774,8 +709,6 @@ EXTERN(i386CoprocessorError)
EXTERN(i386AlignmentCheck)
.code32
SAVE_CPU_REGS
movl $i386AlignmentCheckText,i386ExceptionDescriptionText
jmp i386CommonExceptionHandler
@ -783,8 +716,6 @@ EXTERN(i386AlignmentCheck)
EXTERN(i386MachineCheck)
.code32
SAVE_CPU_REGS
movl $i386MachineCheckText,i386ExceptionDescriptionText
jmp i386CommonExceptionHandler

View file

@ -0,0 +1,807 @@
/*
* FreeLoader
* Copyright (C) 1998-2002 Brian Palmer <brianp@sginet.com>
* Portions from Linux video.S - Display adapter & video mode setup, version 2.13 (14-May-99)
* Copyright (C) 1995 -- 1999 Martin Mares <mj@ucw.cz>
* Based on the original setup.S code (C) Linus Torvalds and Mats Anderson
*
* 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
* (at your option) 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.
*/
#include <freeldr.h>
#include <arch.h>
#include <video.h>
#include <comm.h>
#include <rtl.h>
#include <debug.h>
typedef struct
{
U8 Signature[4]; // (ret) signature ("VESA")
// (call) VESA 2.0 request signature ("VBE2"), required to receive
// version 2.0 info
U16 VesaVersion; // VESA version number (one-digit minor version -- 0102h = v1.2)
U32 OemNamePtr; // pointer to OEM name
// "761295520" for ATI
U32 Capabilities; // capabilities flags (see #00078)
U32 SupportedModeListPtr; // pointer to list of supported VESA and OEM video modes
// (list of words terminated with FFFFh)
U16 TotalVideoMemory; // total amount of video memory in 64K blocks
// ---VBE v1.x ---
//U8 Reserved[236];
// ---VBE v2.0 ---
U16 OemSoftwareVersion; // OEM software version (BCD, high byte = major, low byte = minor)
U32 VendorNamePtr; // pointer to vendor name
U32 ProductNamePtr; // pointer to product name
U32 ProductRevisionStringPtr; // pointer to product revision string
U16 VBE_AF_Version; // (if capabilities bit 3 set) VBE/AF version (BCD)
// 0100h for v1.0P
U32 AcceleratedModeListPtr; // (if capabilities bit 3 set) pointer to list of supported
// accelerated video modes (list of words terminated with FFFFh)
U8 Reserved[216]; // reserved for VBE implementation
U8 ScratchPad[256]; // OEM scratchpad (for OEM strings, etc.)
} PACKED VESA_SVGA_INFO, *PVESA_SVGA_INFO;
// Bitfields for VESA capabilities:
//
// Bit(s) Description (Table 00078)
// 0 DAC can be switched into 8-bit mode
// 1 non-VGA controller
// 2 programmed DAC with blank bit (i.e. only during blanking interval)
// 3 (VBE v3.0) controller supports hardware stereoscopic signalling
// 3 controller supports VBE/AF v1.0P extensions
// 4 (VBE v3.0) if bit 3 set:
// =0 stereo signalling via external VESA stereo connector
// =1 stereo signalling via VESA EVC connector
// 4 (VBE/AF v1.0P) must call EnableDirectAccess to access framebuffer
// 5 (VBE/AF v1.0P) controller supports hardware mouse cursor
// 6 (VBE/AF v1.0P) controller supports hardware clipping
// 7 (VBE/AF v1.0P) controller supports transparent BitBLT
// 8-31 reserved (0)
// Notes: The list of supported video modes is stored in the reserved
// portion of the SuperVGA information record by some implementations,
// and it may thus be necessary to either copy the mode list or use a
// different buffer for all subsequent VESA calls. Not all of the video
// modes in the list of mode numbers may be supported, e.g. if they require
// more memory than currently installed or are not supported by the
// attached monitor. Check any mode you intend to use through AX=4F01h first..
// The 1.1 VESA document specifies 242 reserved bytes at the end, so the
// buffer should be 262 bytes to ensure that it is not overrun; for v2.0,
// the buffer should be 512 bytes. The S3 specific video modes will most
// likely follow the FFFFh terminator at the end of the standard modes.
// A search must then be made to find them, FFFFh will also terminate this
// second list. In some cases, only a "stub" VBE may be present, supporting
// only AX=4F00h; this case may be assumed if the list of supported video modes
// is empty (consisting of a single word of FFFFh)
VOID BiosSetVideoMode(U32 VideoMode)
{
REGS Regs;
// Int 10h AH=00h
// VIDEO - SET VIDEO MODE
//
// AH = 00h
// AL = desired video mode
// Return:
// AL = video mode flag (Phoenix, AMI BIOS)
// 20h mode > 7
// 30h modes 0-5 and 7
// 3Fh mode 6
// AL = CRT controller mode byte (Phoenix 386 BIOS v1.10)
Regs.b.ah = 0x00;
Regs.b.al = VideoMode;
Int386(0x10, &Regs, &Regs);
}
VOID BiosSetVideoFont8x8(VOID)
{
REGS Regs;
// Int 10h AX=1112h
// VIDEO - TEXT-MODE CHARGEN - LOAD ROM 8x8 DBL-DOT PATTERNS (PS,EGA,VGA)
//
// AX = 1112h
// BL = block to load
// Return:
// Nothing
Regs.w.ax = 0x1112;
Regs.b.bl = 0x00;
Int386(0x10, &Regs, &Regs);
}
VOID BiosSetVideoFont8x14(VOID)
{
REGS Regs;
// Int 10h AX=1111h
// VIDEO - TEXT-MODE CHARGEN - LOAD ROM MONOCHROME PATTERNS (PS,EGA,VGA)
//
// AX = 1111h
// BL = block to load
// Return:
// Nothing
Regs.w.ax = 0x1111;
Regs.b.bl = 0;
Int386(0x10, &Regs, &Regs);
}
VOID BiosSetVideoFont8x16(VOID)
{
REGS Regs;
// Int 10h AX=1114h
// VIDEO - TEXT-MODE CHARGEN - LOAD ROM 8x16 CHARACTER SET (VGA)
//
// AX = 1114h
// BL = block to load
// Return:
// Nothing
Regs.w.ax = 0x1114;
Regs.b.bl = 0;
Int386(0x10, &Regs, &Regs);
}
VOID BiosSelectAlternatePrintScreen(VOID)
{
REGS Regs;
// Int 10h AH=12h BL=20h
// VIDEO - ALTERNATE FUNCTION SELECT (PS,EGA,VGA,MCGA) - ALTERNATE PRTSC
//
// AH = 12h
// BL = 20h select alternate print screen routine
// Return:
// Nothing
//
// Installs a PrtSc routine from the video card's BIOS to replace the
// default PrtSc handler from the ROM BIOS, which usually does not
// understand screen heights other than 25 lines.
//
// Some adapters disable print-screen instead of enhancing it.
Regs.b.ah = 0x12;
Regs.b.bl = 0x20;
Int386(0x10, &Regs, &Regs);
}
VOID BiosDisableCursorEmulation(VOID)
{
REGS Regs;
// Int 10h AH=12h BL=34h
// VIDEO - ALTERNATE FUNCTION SELECT (VGA) - CURSOR EMULATION
//
// AH = 12h
// BL = 34h
// AL = new state
// 00h enable alphanumeric cursor emulation
// 01h disable alphanumeric cursor emulation
// Return:
// AL = 12h if function supported
//
// Specify whether the BIOS should automatically remap cursor start/end
// according to the current character height in text modes.
Regs.b.ah = 0x12;
Regs.b.bl = 0x34;
Regs.b.al = 0x01;
Int386(0x10, &Regs, &Regs);
}
VOID BiosDefineCursor(U32 StartScanLine, U32 EndScanLine)
{
REGS Regs;
// Int 10h AH=01h
// VIDEO - SET TEXT-MODE CURSOR SHAPE
//
// AH = 01h
// CH = cursor start and options
// CL = bottom scan line containing cursor (bits 0-4)
// Return:
// Nothing
//
// Specify the starting and ending scan lines to be occupied
// by the hardware cursor in text modes.
//
// AMI 386 BIOS and AST Premier 386 BIOS will lock up the
// system if AL is not equal to the current video mode.
//
// Bitfields for cursor start and options:
//
// Bit(s) Description
// 7 should be zero
// 6,5 cursor blink
// (00=normal, 01=invisible, 10=erratic, 11=slow).
// (00=normal, other=invisible on EGA/VGA)
// 4-0 topmost scan line containing cursor
Regs.b.ah = 0x01;
Regs.b.al = 0x03;
Regs.b.ch = StartScanLine;
Regs.b.cl = EndScanLine;
Int386(0x10, &Regs, &Regs);
}
U32 BiosDetectVideoCard(VOID)
{
REGS Regs;
// Int 10h AH=12h BL=10h
// VIDEO - ALTERNATE FUNCTION SELECT (PS,EGA,VGA,MCGA) - GET EGA INFO
//
// AH = 12h
// BL = 10h
// Return:
// BH = video state
// 00h color mode in effect (I/O port 3Dxh)
// 01h mono mode in effect (I/O port 3Bxh)
// BL = installed memory (00h = 64K, 01h = 128K, 02h = 192K, 03h = 256K)
// CH = feature connector bits
// CL = switch settings
// AH destroyed (at least by Tseng ET4000 BIOS v8.00n)
//
// Installation check;EGA
Regs.b.ah = 0x12;
Regs.b.bl = 0x10;
Int386(0x10, &Regs, &Regs);
// If BL is still equal to 0x10 then there is no EGA/VGA present
if (Regs.b.bl == 0x10)
{
return VIDEOCARD_CGA_OR_OTHER;
}
// Int 10h AX=1A00h
// VIDEO - GET DISPLAY COMBINATION CODE (PS,VGA/MCGA)
//
// AX = 1A00h
// Return:
// AL = 1Ah if function was supported
// BL = active display code
// BH = alternate display code
//
// This function is commonly used to check for the presence of a VGA.
//
// Installation check;VGA
//
// Values for display combination code:
// 00h no display
// 01h monochrome adapter w/ monochrome display
// 02h CGA w/ color display
// 03h reserved
// 04h EGA w/ color display
// 05h EGA w/ monochrome display
// 06h PGA w/ color display
// 07h VGA w/ monochrome analog display
// 08h VGA w/ color analog display
// 09h reserved
// 0Ah MCGA w/ digital color display
// 0Bh MCGA w/ monochrome analog display
// 0Ch MCGA w/ color analog display
// FFh unknown display type
Regs.b.ah = 0x12;
Regs.b.bl = 0x10;
Int386(0x10, &Regs, &Regs);
if (Regs.b.al == 0x1A)
{
return VIDEOCARD_VGA;
}
else
{
return VIDEOCARD_EGA;
}
}
VOID BiosSetVerticalResolution(U32 ScanLines)
{
REGS Regs;
// Int 10h AH=12h BL=30h
// VIDEO - ALTERNATE FUNCTION SELECT (VGA) - SELECT VERTICAL RESOLUTION
//
// AH = 12h
// BL = 30h
// AL = vertical resolution
// 00h 200 scan lines
// 01h 350 scan lines
// 02h 400 scan lines
// Return:
// AL = 12h if function supported
//
// Specifiy the number of scan lines used to display text modes.
//
// The specified resolution will take effect on the next mode set.
Regs.b.ah = 0x12;
Regs.b.bl = 0x30;
Regs.b.al = ScanLines;
Int386(0x10, &Regs, &Regs);
}
VOID BiosSet480ScanLines(VOID)
{
int CRTC;
// Read CRTC port
CRTC = READ_PORT_UCHAR((PUCHAR)0x03CC);
if (CRTC & 1)
{
CRTC = 0x3D4;
}
else
{
CRTC = 0x3B4;
}
// Vertical sync end (also unlocks CR0-7)
WRITE_PORT_UCHAR((PUCHAR)CRTC, 0x11);
WRITE_PORT_UCHAR((PUCHAR)CRTC+1, 0x0C);
// Vertical total
WRITE_PORT_UCHAR((PUCHAR)CRTC, 0x06);
WRITE_PORT_UCHAR((PUCHAR)CRTC+1, 0x0B);
// (vertical) overflow
WRITE_PORT_UCHAR((PUCHAR)CRTC, 0x07);
WRITE_PORT_UCHAR((PUCHAR)CRTC+1, 0x3E);
// Vertical sync start
WRITE_PORT_UCHAR((PUCHAR)CRTC, 0x10);
WRITE_PORT_UCHAR((PUCHAR)CRTC+1, 0xEA);
// Vertical display end
WRITE_PORT_UCHAR((PUCHAR)CRTC, 0x12);
WRITE_PORT_UCHAR((PUCHAR)CRTC+1, 0xDF);
// Vertical blank start
WRITE_PORT_UCHAR((PUCHAR)CRTC, 0x15);
WRITE_PORT_UCHAR((PUCHAR)CRTC+1, 0xE7);
// Vertical blank end
WRITE_PORT_UCHAR((PUCHAR)CRTC, 0x16);
WRITE_PORT_UCHAR((PUCHAR)CRTC+1, 0x04);
// Misc output register (read)
CRTC = READ_PORT_UCHAR((PUCHAR)0x03CC);
// Preserve clock select bits and color bit
CRTC = (CRTC & 0x0D);
// Set correct sync polarity
CRTC = (CRTC | 0xE2);
// (write)
WRITE_PORT_UCHAR((PUCHAR)0x03C2, CRTC);
}
VOID BiosSetVideoDisplayEnd(VOID)
{
int CRTC;
// Read CRTC port
CRTC = READ_PORT_UCHAR((PUCHAR)0x03CC);
if (CRTC & 1)
{
CRTC = 0x3D4;
}
else
{
CRTC = 0x3B4;
}
// Vertical display end
WRITE_PORT_UCHAR((PUCHAR)CRTC, 0x12);
WRITE_PORT_UCHAR((PUCHAR)CRTC+1, 0xDF);
}
VOID VideoSetTextCursorPosition(U32 X, U32 Y)
{
REGS Regs;
// Int 10h AH=02h
// VIDEO - SET CURSOR POSITION
//
// AH = 02h
// BH = page number
// 0-3 in modes 2&3
// 0-7 in modes 0&1
// 0 in graphics modes
// DH = row (00h is top)
// DL = column (00h is left)
// Return:
// Nothing
Regs.b.ah = 0x01;
Regs.b.bh = 0x00;
Regs.b.dh = Y;
Regs.b.dl = X;
Int386(0x10, &Regs, &Regs);
}
VOID VideoHideTextCursor(VOID)
{
BiosDefineCursor(0x20, 0x00);
}
VOID VideoShowTextCursor(VOID)
{
BiosDefineCursor(0x0D, 0x0E);
}
U32 VideoGetTextCursorPositionX(VOID)
{
REGS Regs;
// Int 10h AH=03h
// VIDEO - GET CURSOR POSITION AND SIZE
//
// AH = 03h
// BH = page number
// 0-3 in modes 2&3
// 0-7 in modes 0&1
// 0 in graphics modes
// Return:
// AX = 0000h (Phoenix BIOS)
// CH = start scan line
// CL = end scan line
// DH = row (00h is top)
// DL = column (00h is left)
Regs.b.ah = 0x03;
Regs.b.bh = 0x00;
Int386(0x10, &Regs, &Regs);
return Regs.b.dl;
}
U32 VideoGetTextCursorPositionY(VOID)
{
REGS Regs;
// Int 10h AH=03h
// VIDEO - GET CURSOR POSITION AND SIZE
//
// AH = 03h
// BH = page number
// 0-3 in modes 2&3
// 0-7 in modes 0&1
// 0 in graphics modes
// Return:
// AX = 0000h (Phoenix BIOS)
// CH = start scan line
// CL = end scan line
// DH = row (00h is top)
// DL = column (00h is left)
Regs.b.ah = 0x03;
Regs.b.bh = 0x00;
Int386(0x10, &Regs, &Regs);
return Regs.b.dh;
}
VOID BiosVideoDisableBlinkBit(VOID)
{
REGS Regs;
// Int 10h AX=1003h
// VIDEO - TOGGLE INTENSITY/BLINKING BIT (Jr, PS, TANDY 1000, EGA, VGA)
//
// AX = 1003h
// BL = new state
// 00h background intensity enabled
// 01h blink enabled
// BH = 00h to avoid problems on some adapters
// Return:
// Nothing
//
// Note: although there is no function to get
// the current status, bit 5 of 0040h:0065h
// indicates the state.
Regs.w.ax = 0x1003;
Regs.w.bx = 0x0000;
Int386(0x10, &Regs, &Regs);
}
VOID BiosVideoEnableBlinkBit(VOID)
{
REGS Regs;
// Int 10h AX=1003h
// VIDEO - TOGGLE INTENSITY/BLINKING BIT (Jr, PS, TANDY 1000, EGA, VGA)
//
// AX = 1003h
// BL = new state
// 00h background intensity enabled
// 01h blink enabled
// BH = 00h to avoid problems on some adapters
// Return:
// Nothing
//
// Note: although there is no function to get
// the current status, bit 5 of 0040h:0065h
// indicates the state.
Regs.w.ax = 0x1003;
Regs.w.bx = 0x0001;
Int386(0x10, &Regs, &Regs);
}
U16 BiosIsVesaSupported(VOID)
{
REGS Regs;
PVESA_SVGA_INFO SvgaInfo = (PVESA_SVGA_INFO)BIOSCALLBUFFER;
#ifdef DEBUG
//U16* VideoModes;
//U16 Index;
#endif // defined DEBUG
DbgPrint((DPRINT_UI, "BiosIsVesaSupported()\n"));
RtlZeroMemory(SvgaInfo, sizeof(VESA_SVGA_INFO));
// Make sure we receive version 2.0 info
SvgaInfo->Signature[0] = 'V';
SvgaInfo->Signature[1] = 'B';
SvgaInfo->Signature[2] = 'E';
SvgaInfo->Signature[3] = '2';
// Int 10h AX=4F00h
// VESA SuperVGA BIOS (VBE) - GET SuperVGA INFORMATION
//
// AX = 4F00h
// ES:DI -> buffer for SuperVGA information (see #00077)
// Return:
// AL = 4Fh if function supported
// AH = status
// 00h successful
// ES:DI buffer filled
// 01h failed
// ---VBE v2.0---
// 02h function not supported by current hardware configuration
// 03h function invalid in current video mode
//
// Determine whether VESA BIOS extensions are present and the
// capabilities supported by the display adapter
//
// Installation check;VESA SuperVGA
Regs.w.ax = 0x4F00;
Regs.w.es = BIOSCALLBUFSEGMENT;
Regs.w.di = BIOSCALLBUFOFFSET;
Int386(0x10, &Regs, &Regs);
DbgPrint((DPRINT_UI, "AL = 0x%x\n", Regs.b.al));
DbgPrint((DPRINT_UI, "AH = 0x%x\n", Regs.b.ah));
if (Regs.w.ax != 0x004F)
{
DbgPrint((DPRINT_UI, "Failed.\n"));
return 0x0000;
}
#ifdef DEBUG
DbgPrint((DPRINT_UI, "Supported.\n"));
DbgPrint((DPRINT_UI, "SvgaInfo->Signature[4] = %c%c%c%c\n", SvgaInfo->Signature[0], SvgaInfo->Signature[1], SvgaInfo->Signature[2], SvgaInfo->Signature[3]));
DbgPrint((DPRINT_UI, "SvgaInfo->VesaVersion = v%d.%d\n", ((SvgaInfo->VesaVersion >> 8) & 0xFF), (SvgaInfo->VesaVersion & 0xFF)));
DbgPrint((DPRINT_UI, "SvgaInfo->OemNamePtr = 0x%x\n", SvgaInfo->OemNamePtr));
DbgPrint((DPRINT_UI, "SvgaInfo->Capabilities = 0x%x\n", SvgaInfo->Capabilities));
DbgPrint((DPRINT_UI, "SvgaInfo->VideoMemory = %dK\n", SvgaInfo->TotalVideoMemory * 64));
DbgPrint((DPRINT_UI, "---VBE v2.0 ---\n"));
DbgPrint((DPRINT_UI, "SvgaInfo->OemSoftwareVersion = v%d.%d\n", ((SvgaInfo->OemSoftwareVersion >> 8) & 0x0F) + (((SvgaInfo->OemSoftwareVersion >> 12) & 0x0F) * 10), (SvgaInfo->OemSoftwareVersion & 0x0F) + (((SvgaInfo->OemSoftwareVersion >> 4) & 0x0F) * 10)));
DbgPrint((DPRINT_UI, "SvgaInfo->VendorNamePtr = 0x%x\n", SvgaInfo->VendorNamePtr));
DbgPrint((DPRINT_UI, "SvgaInfo->ProductNamePtr = 0x%x\n", SvgaInfo->ProductNamePtr));
DbgPrint((DPRINT_UI, "SvgaInfo->ProductRevisionStringPtr = 0x%x\n", SvgaInfo->ProductRevisionStringPtr));
DbgPrint((DPRINT_UI, "SvgaInfo->VBE/AF Version = 0x%x (BCD WORD)\n", SvgaInfo->VBE_AF_Version));
//DbgPrint((DPRINT_UI, "\nSupported VESA and OEM video modes:\n"));
//VideoModes = (U16*)SvgaInfo->SupportedModeListPtr;
//for (Index=0; VideoModes[Index]!=0xFFFF; Index++)
//{
// DbgPrint((DPRINT_UI, "Mode %d: 0x%x\n", Index, VideoModes[Index]));
//}
//if (SvgaInfo->VesaVersion >= 0x0200)
//{
// DbgPrint((DPRINT_UI, "\nSupported accelerated video modes (VESA v2.0):\n"));
// VideoModes = (U16*)SvgaInfo->AcceleratedModeListPtr;
// for (Index=0; VideoModes[Index]!=0xFFFF; Index++)
// {
// DbgPrint((DPRINT_UI, "Mode %d: 0x%x\n", Index, VideoModes[Index]));
// }
//}
DbgPrint((DPRINT_UI, "\n"));
//getch();
#endif // defined DEBUG
return SvgaInfo->VesaVersion;
}
BOOL BiosVesaSetBank(U16 Bank)
{
REGS Regs;
// Int 10h AX=4F05h
// VESA SuperVGA BIOS - CPU VIDEO MEMORY CONTROL
//
// AX = 4F05h
// BH = subfunction
// 00h select video memory window
// 01h get video memory window
// DX = window address in video memory (in granularity units)
// Return:
// DX = window address in video memory (in gran. units)
// BL = window number
// 00h window A
// 01h window B.
// Return:
// AL = 4Fh if function supported
// AH = status
// 00h successful
// 01h failed
Regs.w.ax = 0x4F05;
Regs.w.bx = 0x0000;
Regs.w.dx = Bank;
Int386(0x10, &Regs, &Regs);
if (Regs.w.ax != 0x004F)
{
return FALSE;
}
return TRUE;
}
BOOL BiosVesaSetVideoMode(U16 Mode)
{
REGS Regs;
// Int 10h AX=4F02h
// VESA SuperVGA BIOS - SET SuperVGA VIDEO MODE
//
// AX = 4F02h
// BX = new video mode
// ES:DI -> (VBE 3.0+) CRTC information block, bit mode bit 11 set
// Return:
// AL = 4Fh if function supported
// AH = status
// 00h successful
// 01h failed
//
// Values for VESA video mode:
// 00h-FFh OEM video modes (see #00010 at AH=00h)
// 100h 640x400x256
// 101h 640x480x256
// 102h 800x600x16
// 103h 800x600x256
// 104h 1024x768x16
// 105h 1024x768x256
// 106h 1280x1024x16
// 107h 1280x1024x256
// 108h 80x60 text
// 109h 132x25 text
// 10Ah 132x43 text
// 10Bh 132x50 text
// 10Ch 132x60 text
// ---VBE v1.2+ ---
// 10Dh 320x200x32K
// 10Eh 320x200x64K
// 10Fh 320x200x16M
// 110h 640x480x32K
// 111h 640x480x64K
// 112h 640x480x16M
// 113h 800x600x32K
// 114h 800x600x64K
// 115h 800x600x16M
// 116h 1024x768x32K
// 117h 1024x768x64K
// 118h 1024x768x16M
// 119h 1280x1024x32K (1:5:5:5)
// 11Ah 1280x1024x64K (5:6:5)
// 11Bh 1280x1024x16M
// ---VBE 2.0+ ---
// 120h 1600x1200x256
// 121h 1600x1200x32K
// 122h 1600x1200x64K
// 81FFh special full-memory access mode
// Notes: The special mode 81FFh preserves the contents of the video memory and gives
// access to all of the memory; VESA recommends that the special mode be a packed-pixel
// mode. For VBE 2.0+, it is required that the VBE implement the mode, but not place it
// in the list of available modes (mode information for this mode can be queried
// directly, however).. As of VBE 2.0, VESA will no longer define video mode numbers
Regs.w.ax = 0x4F02;
Regs.w.bx = Mode;
Int386(0x10, &Regs, &Regs);
if (Regs.w.ax != 0x004F)
{
return FALSE;
}
return TRUE;
}
BOOL BiosVesaGetSVGAModeInformation(U16 Mode, PSVGA_MODE_INFORMATION ModeInformation)
{
REGS Regs;
RtlZeroMemory((PVOID)BIOSCALLBUFFER, 256);
// VESA SuperVGA BIOS - GET SuperVGA MODE INFORMATION
// AX = 4F01h
// CX = SuperVGA video mode (see #04082 for bitfields)
// ES:DI -> 256-byte buffer for mode information (see #00079)
// Return:
// AL = 4Fh if function supported
// AH = status
// 00h successful
// ES:DI buffer filled
// 01h failed
//
// Desc: Determine the attributes of the specified video mode
//
// Note: While VBE 1.1 and higher will zero out all unused bytes
// of the buffer, v1.0 did not, so applications that want to be
// backward compatible should clear the buffer before calling
Regs.w.ax = 0x4F01;
Regs.w.cx = Mode;
Regs.w.es = BIOSCALLBUFSEGMENT;
Regs.w.di = BIOSCALLBUFOFFSET;
Int386(0x10, &Regs, &Regs);
if (Regs.w.ax != 0x004F)
{
return FALSE;
}
RtlCopyMemory(ModeInformation, (PVOID)BIOSCALLBUFFER, sizeof(SVGA_MODE_INFORMATION));
DbgPrint((DPRINT_UI, "\n"));
DbgPrint((DPRINT_UI, "BiosVesaGetSVGAModeInformation() mode 0x%x\n", Mode));
DbgPrint((DPRINT_UI, "ModeAttributes = 0x%x\n", ModeInformation->ModeAttributes));
DbgPrint((DPRINT_UI, "WindowAttributesA = 0x%x\n", ModeInformation->WindowAttributesA));
DbgPrint((DPRINT_UI, "WindowAttributesB = 0x%x\n", ModeInformation->WindowsAttributesB));
DbgPrint((DPRINT_UI, "WindowGranularity = %dKB\n", ModeInformation->WindowGranularity));
DbgPrint((DPRINT_UI, "WindowSize = %dKB\n", ModeInformation->WindowSize));
DbgPrint((DPRINT_UI, "WindowAStartSegment = 0x%x\n", ModeInformation->WindowAStartSegment));
DbgPrint((DPRINT_UI, "WindowBStartSegment = 0x%x\n", ModeInformation->WindowBStartSegment));
DbgPrint((DPRINT_UI, "WindowPositioningFunction = 0x%x\n", ModeInformation->WindowPositioningFunction));
DbgPrint((DPRINT_UI, "BytesPerScanLine = %d\n", ModeInformation->BytesPerScanLine));
DbgPrint((DPRINT_UI, "WidthInPixels = %d\n", ModeInformation->WidthInPixels));
DbgPrint((DPRINT_UI, "HeightInPixels = %d\n", ModeInformation->HeightInPixels));
DbgPrint((DPRINT_UI, "CharacterWidthInPixels = %d\n", ModeInformation->CharacterWidthInPixels));
DbgPrint((DPRINT_UI, "CharacterHeightInPixels = %d\n", ModeInformation->CharacterHeightInPixels));
DbgPrint((DPRINT_UI, "NumberOfMemoryPlanes = %d\n", ModeInformation->NumberOfMemoryPlanes));
DbgPrint((DPRINT_UI, "BitsPerPixel = %d\n", ModeInformation->BitsPerPixel));
DbgPrint((DPRINT_UI, "NumberOfBanks = %d\n", ModeInformation->NumberOfBanks));
DbgPrint((DPRINT_UI, "MemoryModel = %d\n", ModeInformation->MemoryModel));
DbgPrint((DPRINT_UI, "BankSize = %d\n", ModeInformation->BankSize));
DbgPrint((DPRINT_UI, "NumberOfImagePlanes = %d\n", ModeInformation->NumberOfImagePanes));
DbgPrint((DPRINT_UI, "---VBE v1.2+ ---\n"));
DbgPrint((DPRINT_UI, "RedMaskSize = %d\n", ModeInformation->RedMaskSize));
DbgPrint((DPRINT_UI, "RedMaskPosition = %d\n", ModeInformation->RedMaskPosition));
DbgPrint((DPRINT_UI, "GreenMaskSize = %d\n", ModeInformation->GreenMaskSize));
DbgPrint((DPRINT_UI, "GreenMaskPosition = %d\n", ModeInformation->GreenMaskPosition));
DbgPrint((DPRINT_UI, "BlueMaskSize = %d\n", ModeInformation->BlueMaskSize));
DbgPrint((DPRINT_UI, "BlueMaskPosition = %d\n", ModeInformation->BlueMaskPosition));
DbgPrint((DPRINT_UI, "ReservedMaskSize = %d\n", ModeInformation->ReservedMaskSize));
DbgPrint((DPRINT_UI, "ReservedMaskPosition = %d\n", ModeInformation->ReservedMaskPosition));
DbgPrint((DPRINT_UI, "\n"));
return TRUE;
}

View file

@ -0,0 +1,155 @@
/*
* FreeLoader
* Copyright (C) 1998-2002 Brian Palmer <brianp@sginet.com>
*
* 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
* (at your option) 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.
*/
.text
.code16
#define ASM
#include <arch.h>
Int386_REGS:
Int386_eax:
.long 0
Int386_ebx:
.long 0
Int386_ecx:
.long 0
Int386_edx:
.long 0
Int386_esi:
.long 0
Int386_edi:
.long 0
Int386_ds:
.word 0
Int386_es:
.word 0
Int386_fs:
.word 0
Int386_gs:
.word 0
Int386_eflags:
.long 0
Int386_vector:
.long 0
Int386_regsin:
.long 0
Int386_regsout:
.long 0
/*
* int Int386(int ivec, REGS* in, REGS* out);
*/
EXTERN(_Int386)
.code32
/* Get the function parameters */
movl 0x04(%esp),%eax
movl %eax,Int386_vector
movb %al,Int386_vector_opcode
movl 0x08(%esp),%eax
movl %eax,Int386_regsin
movl 0x0c(%esp),%eax
movl %eax,Int386_regsout
pushal
/* Copy the input regs to our variables */
movl $Int386_REGS,%edi
movl Int386_regsin,%esi
movl $0x24,%ecx
rep
movsb
call switch_to_real
.code16
/* Setup the registers */
movw %cs:Int386_ds,%ax
movw %ax,%ds /* DS register */
movw %cs:Int386_es,%ax
movw %ax,%es /* ES register */
movw %cs:Int386_fs,%ax
movw %ax,%fs /* FS register */
movw %cs:Int386_gs,%ax
movw %ax,%gs /* GS register */
movl %cs:Int386_eax,%eax /* EAX register */
movl %cs:Int386_ebx,%ebx /* EBX register */
movl %cs:Int386_ecx,%ecx /* ECX register */
movl %cs:Int386_edx,%edx /* EDX register */
movl %cs:Int386_esi,%esi /* ESI register */
movl %cs:Int386_edi,%edi /* EDI register */
/* Do not set the flags register */
/* only return its value in regsout */
//pushl Int386_eflags
//popfl /* EFLAGS register */
/* Call the interrupt vector */
/*int Int386_vector*/
Int386_int_opcode:
.byte 0xcd
Int386_vector_opcode:
.byte 0x00
/* Save the registers */
movl %eax,%cs:Int386_eax /* EAX register */
movl %ebx,%cs:Int386_ebx /* EBX register */
movl %ecx,%cs:Int386_ecx /* ECX register */
movl %edx,%cs:Int386_edx /* EDX register */
movl %esi,%cs:Int386_esi /* ESI register */
movl %edi,%cs:Int386_edi /* EDI register */
movw %ds,%ax /* DS register */
movw %ax,%cs:Int386_ds
movw %es,%ax /* ES register */
movw %ax,%cs:Int386_es
movw %fs,%ax /* FS register */
movw %ax,%cs:Int386_fs
movw %gs,%ax /* GS register */
movw %ax,%cs:Int386_gs
pushf
popw %cs:Int386_eflags /* EFLAGS register */
call switch_to_prot
.code32
/* Copy the variables to the output regs */
movl $Int386_REGS,%esi
movl Int386_regsout,%edi
movl $0x24,%ecx
rep
movsb
popal
/* Get return value */
movl Int386_eax,%eax
ret

View file

@ -1,213 +0,0 @@
/*
* FreeLoader
* Copyright (C) 1998-2002 Brian Palmer <brianp@sginet.com>
*
* 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
* (at your option) 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.
*/
.text
.code16
#define ASM
#include <arch.h>
#include <multiboot.h>
/*
* ULONG GetExtendedMemorySize(VOID);
*/
ExtendedMemorySize:
.long 0
EXTERN(_GetExtendedMemorySize)
.code32
pushal
movl $0,ExtendedMemorySize
call switch_to_real
.code16
movw $0xE801,%ax
int $0x15
jc GetExtendedMemorySizeTryInt15Func88
cmpw $0,%ax
je GetExtendedMemorySizeUseCXDX
movzwl %bx,%ebx
shll $6,%ebx
movzwl %ax,%eax
addl %ebx,%eax
movl %eax,ExtendedMemorySize
jmp GetExtendedMemorySizeDone
GetExtendedMemorySizeUseCXDX:
cmpw $0,%cx
je GetExtendedMemorySizeTryInt15Func88
movzwl %dx,%edx
shll $6,%edx
movzwl %cx,%ecx
addl %ecx,%edx
movl %edx,ExtendedMemorySize
jmp GetExtendedMemorySizeDone
GetExtendedMemorySizeTryInt15Func88:
movb $0x88,%ah
int $0x15
jc GetExtendedMemorySizeTryCMOS
cmpw $0,%ax
je GetExtendedMemorySizeTryCMOS
movzwl %ax,%eax
movl %eax,ExtendedMemorySize
jmp GetExtendedMemorySizeDone
GetExtendedMemorySizeTryCMOS:
xorl %eax,%eax
movb $0x31,%al
outb %al,$0x70
inb $0x71,%al
andl $0xffff,%eax
shll $8,%eax
movl %eax,ExtendedMemorySize
GetExtendedMemorySizeDone:
call switch_to_prot
.code32
popal
/* Restore return value */
movl ExtendedMemorySize,%eax
ret
/*
* ULONG GetConventionalMemorySize(VOID);
*/
ConventionalMemorySize:
.long 0
EXTERN(_GetConventionalMemorySize)
.code32
pushal
movl $0,ConventionalMemorySize
call switch_to_real
.code16
xorl %eax,%eax
int $0x12
/* Save return value */
movzwl %ax,%eax
movl %eax,ConventionalMemorySize
call switch_to_prot
.code32
popal
/* Restore return value */
movl ConventionalMemorySize,%eax
ret
/*
* ULONG GetBiosMemoryMap(PBIOS_MEMORY_MAP_ARRAY BiosMemoryMap);
*/
_gbmm_mem_map_length:
.long 0
_gbmm_memory_map_addr:
.long 0
_gbmm_memory_map:
.rept 32
.quad 0
.quad 0
.long 0
.long 0
.endr
EXTERN(_GetBiosMemoryMap)
.code32
pushal
movl $0,_gbmm_mem_map_length
/* Get memory map structure array address off stack */
movl 0x24(%esp),%eax
movl %eax,_gbmm_memory_map_addr
call switch_to_real
.code16
xorl %ebx,%ebx
movl $_gbmm_memory_map,%edi
GetBiosMemoryMapNext:
movl $0x534D4150,%edx // 'SMAP'
movl $24,%ecx
movl $0xE820,%eax
int $0x15
jc GetBiosMemoryMapDone
// If the BIOS didn't return 'SMAP' in EAX then
// it doesn't support this call
cmpl $0x534D4150,%eax // 'SMAP'
jne GetBiosMemoryMapDone
// Increment our count of items and the offset in the array
addl $24,%edi
incl _gbmm_mem_map_length
// If we have copied 32 items then we can't hold any
// more in our array so we're done
cmpl $32,_gbmm_mem_map_length
jae GetBiosMemoryMapDone
// If the continuation value is zero then this was
// the last entry so we're done
cmpl $0,%ebx
jne GetBiosMemoryMapNext
GetBiosMemoryMapDone:
call switch_to_prot
.code32
// Copy the memory map data into the supplied buffer
movl $_gbmm_memory_map,%esi
movl _gbmm_memory_map_addr,%edi
movl $(24 * 32),%ecx
rep movsb
popal
/* Get return value */
movl _gbmm_mem_map_length,%eax
ret

View file

@ -1,470 +0,0 @@
/*
* FreeLoader
* Copyright (C) 1998-2002 Brian Palmer <brianp@sginet.com>
*
* 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
* (at your option) 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.
*/
.text
.code16
#define ASM
#include <arch.h>
/*
* void putchar(int ch);
*/
EXTERN(_putchar)
.code32
pushal
/* Get character to display */
movb 0x24(%esp),%bl
/* If we are displaying a CR '\n' then do a LF also */
cmpb $0x0a,%bl
jnz putchar_1
/* Display the LF */
pushl $0x0d
call _putchar
popl %eax
putchar_1:
/* If we are displaying a TAB '\t' then display 8 spaces ' ' */
cmpb $0x09,%bl
jnz putchar_2
/* Display the 8 spaces ' ' */
pushl $0x20
call _putchar
call _putchar
call _putchar
call _putchar
call _putchar
call _putchar
call _putchar
call _putchar
popl %eax
popal
ret
putchar_2:
call switch_to_real
.code16
/* Display the character via BIOS int 0x10 function 0x0e */
movb $0x0e,%ah
movb %bl,%al
movw $1,%bx
int $0x10
call switch_to_prot
.code32
popal
ret
/*
* int kbhit(void);
*/
_kbhit_retval:
.long 0
EXTERN(_kbhit)
.code32
pushal
movl $0x00,_kbhit_retval
call switch_to_real
.code16
/* Int 0x16, AH = 0x01 - Get Keyboard Status */
movb $0x01,%ah
int $0x16
jz kbhit_1 // ZF=0 if no key is available
/* Return value is non-zero if a key is available */
movl $1,_kbhit_retval
jmp kbhit_done
kbhit_1:
/* Return value is zero if no key is available */
movl $0,_kbhit_retval
kbhit_done:
call switch_to_prot
.code32
popal
/* Get return value */
movl _kbhit_retval,%eax
ret
/*
* int getch(void);
*/
extended_scancode:
.byte 0
EXTERN(_getch)
.code32
push %ebp
push %ebx
call switch_to_real
.code16
/* Check and see if we have an extended scancode to return */
movb extended_scancode,%al
movb $0,extended_scancode
movzbl %al,%ebx
cmpb $0,%al
jnz getch_done
/* Int 0x16, AH = 0x00 - Wait for keypress */
movb $0,%ah
int $0x16
/* If al is zero then it is an extended key */
cmp $0,%al
jnz getch_1
/* Save the scan code to be returned on the next call to getch() */
movb %ah,extended_scancode
getch_1:
/* Store character in ebx */
movzbl %al,%ebx
getch_done:
call switch_to_prot
.code32
/* Get return value from ebx */
movl %ebx,%eax
pop %ebx
pop %ebp
ret
/*
* int getyear(void);
*/
EXTERN(_getyear)
.code32
push %ebp
push %ebx
push %ecx
push %edx
call switch_to_real
.code16
/* Get the date */
movb $4,%ah
int $0x1a
/* Convert from BCD to normal */
movb %ch,%al
andb $0x0f,%al
movb %al,%dl
movb %ch,%al
shrb $0x04,%al
andb $0x0f,%al
movb $0x0a,%bl
mulb %bl
addb %al,%dl
movb %dl,%dh
movb %cl,%al
andb $0x0f,%al
movb %al,%dl
movb %cl,%al
shrb $0x04,%al
andb $0x0f,%al
movb $0x0a,%bl
mulb %bl
addb %al,%dl
movb %dl,%cl
movzbl %dh,%eax
movl $100,%ebx
mull %ebx
movl %eax,%edx
addb %cl,%dl
/* Save return value */
movl %edx,%edx
call switch_to_prot
.code32
/* Restore return value */
movl %edx,%eax
pop %edx
pop %ecx
pop %ebx
pop %ebp
ret
/*
* int getday(void);
*/
EXTERN(_getday)
.code32
push %ebp
push %ebx
push %ecx
push %edx
call switch_to_real
.code16
/* Get the date */
movb $4,%ah
int $0x1a
/* Convert from BCD to normal */
movb %dl,%al
andb $0x0f,%al
movb %al,%cl
movb %dl,%al
shrb $0x04,%al
andb $0x0f,%al
movb $0x0a,%bl
mulb %bl
addb %al,%cl
/* Save return value */
movzbl %cl,%edx
call switch_to_prot
.code32
/* Restore return value */
movl %edx,%eax
pop %edx
pop %ecx
pop %ebx
pop %ebp
ret
/*
* int getmonth(void);
*/
EXTERN(_getmonth)
.code32
push %ebp
push %ebx
push %ecx
push %edx
call switch_to_real
.code16
/* Get the date */
movb $4,%ah
int $0x1a
/* Convert from BCD to normal */
movb %dh,%al
andb $0x0f,%al
movb %al,%dl
movb %dh,%al
shrb $0x04,%al
andb $0x0f,%al
movb $0x0a,%bl
mulb %bl
addb %al,%dl
/* Save return value */
movzbl %dl,%edx
call switch_to_prot
.code32
/* Restore return value */
movl %edx,%eax
pop %edx
pop %ecx
pop %ebx
pop %ebp
ret
/*
* int gethour(void);
*/
EXTERN(_gethour)
.code32
push %ebp
push %ebx
push %ecx
push %edx
call switch_to_real
.code16
/* Get the time */
movb $2,%ah
int $0x1a
/* Convert from BCD to normal */
movb %ch,%al
andb $0x0f,%al
movb %al,%dl
movb %ch,%al
shrb $0x04,%al
andb $0x0f,%al
movb $0x0a,%bl
mulb %bl
addb %al,%dl
/* Save return value */
movzbl %dl,%edx
call switch_to_prot
.code32
/* Restore return value */
movl %edx,%eax
pop %edx
pop %ecx
pop %ebx
pop %ebp
ret
/*
* int getminute(void);
*/
EXTERN(_getminute)
.code32
push %ebp
push %ebx
push %ecx
push %edx
call switch_to_real
.code16
/* Get the time */
movb $2,%ah
int $0x1a
/* Convert from BCD to normal */
movb %cl,%al
andb $0x0f,%al
movb %al,%dl
movb %cl,%al
shrb $0x04,%al
andb $0x0f,%al
movb $0x0a,%bl
mulb %bl
addb %al,%dl
/* Save return value */
movzbl %dl,%edx
call switch_to_prot
.code32
/* Restore return value */
movl %edx,%eax
pop %edx
pop %ecx
pop %ebx
pop %ebp
ret
/*
* int getsecond(void);
*/
EXTERN(_getsecond)
.code32
push %ebp
push %ebx
push %ecx
push %edx
call switch_to_real
.code16
/* Get the time */
movb $2,%ah
int $0x1a
/* Convert from BCD to normal */
movb %dh,%al
andb $0x0f,%al
movb %al,%dl
movb %dh,%al
shrb $0x04,%al
andb $0x0f,%al
movb $0x0a,%bl
mulb %bl
addb %al,%dl
/* Save return value */
movzbl %dl,%edx
call switch_to_prot
.code32
/* Restore return value */
movl %edx,%eax
pop %edx
pop %ecx
pop %ebx
pop %ebp
ret

View file

@ -214,7 +214,6 @@ VOID CacheInternalDumpBlockList(PCACHE_DRIVE CacheDrive)
PCACHE_BLOCK CacheBlock;
DbgPrint((DPRINT_CACHE, "Dumping block list for BIOS drive 0x%x.\n", CacheDrive->DriveNumber));
DbgPrint((DPRINT_CACHE, "LbaSupported = %s.\n", CacheDrive->LbaSupported ? "TRUE" : "FALSE"));
DbgPrint((DPRINT_CACHE, "Cylinders: %d.\n", CacheDrive->DriveGeometry.Cylinders));
DbgPrint((DPRINT_CACHE, "Heads: %d.\n", CacheDrive->DriveGeometry.Heads));
DbgPrint((DPRINT_CACHE, "Sectors: %d.\n", CacheDrive->DriveGeometry.Sectors));

View file

@ -82,25 +82,13 @@ BOOL CacheInitializeDrive(U32 DriveNumber)
// Initialize the structure
RtlZeroMemory(&CacheManagerDrive, sizeof(CACHE_DRIVE));
CacheManagerDrive.DriveNumber = DriveNumber;
CacheManagerDrive.LbaSupported = BiosInt13ExtensionsSupported(DriveNumber);
if (!DiskGetDriveGeometry(DriveNumber, &CacheManagerDrive.DriveGeometry))
{
return FALSE;
}
// If LBA is supported then the block size will be 128 sectors (64k)
// If not then the block size is the size of one track
if (CacheManagerDrive.LbaSupported)
{
// FIXME: Temporarily reduced this to
// 64 sectors since not all BIOS calls
// support reading as many as 128 sectors
CacheManagerDrive.BlockSize = 64;//128;
}
else
{
CacheManagerDrive.BlockSize = CacheManagerDrive.DriveGeometry.Sectors;
}
// Get the number of sectors in each cache block
CacheManagerDrive.BlockSize = DiskGetCacheableBlockCount(DriveNumber);
CacheBlockCount = 0;
CacheSizeLimit = GetSystemMemorySize() / 8;
@ -113,7 +101,6 @@ BOOL CacheInitializeDrive(U32 DriveNumber)
CacheManagerInitialized = TRUE;
DbgPrint((DPRINT_CACHE, "Initializing BIOS drive 0x%x.\n", DriveNumber));
DbgPrint((DPRINT_CACHE, "LbaSupported = %s.\n", CacheManagerDrive.LbaSupported ? "TRUE" : "FALSE"));
DbgPrint((DPRINT_CACHE, "Cylinders: %d.\n", CacheManagerDrive.DriveGeometry.Cylinders));
DbgPrint((DPRINT_CACHE, "Heads: %d.\n", CacheManagerDrive.DriveGeometry.Heads));
DbgPrint((DPRINT_CACHE, "Sectors: %d.\n", CacheManagerDrive.DriveGeometry.Sectors));

View file

@ -56,7 +56,6 @@ typedef struct
typedef struct
{
U32 DriveNumber;
BOOL LbaSupported;
GEOMETRY DriveGeometry;
U32 BlockSize; // Block size (in sectors)

View file

@ -24,13 +24,13 @@
#ifdef DEBUG
//#define DEBUG_ULTRA
#define DEBUG_ALL
//#define DEBUG_INIFILE
//#define DEBUG_REACTOS
//#define DEBUG_CUSTOM
#define DEBUG_NONE
#if defined (DEBUG_ULTRA)
#if defined (DEBUG_ALL)
U32 DebugPrintMask = DPRINT_WARNING | DPRINT_MEMORY | DPRINT_FILESYSTEM |
DPRINT_UI | DPRINT_DISK | DPRINT_CACHE | DPRINT_REACTOS |
DPRINT_LINUX;
@ -55,8 +55,8 @@ U32 DebugPrintMask = 0;
#define BOCHS_OUTPUT_PORT 0xe9
//U32 DebugPort = RS232;
U32 DebugPort = SCREEN;
U32 DebugPort = RS232;
//U32 DebugPort = SCREEN;
//U32 DebugPort = BOCHS;
U32 ComPort = COM1;
//U32 BaudRate = 19200;

View file

@ -19,126 +19,95 @@
#include <freeldr.h>
#include <disk.h>
#include <fs.h>
#include <arch.h>
#include <rtl.h>
#include <ui.h>
#include <arch.h>
#include <debug.h>
#undef UNIMPLEMENTED
#define UNIMPLEMENTED BugCheck((DPRINT_WARNING, "Unimplemented\n"));
/////////////////////////////////////////////////////////////////////////////////////////////
// FUNCTIONS
/////////////////////////////////////////////////////////////////////////////////////////////
VOID DiskError(PUCHAR ErrorString)
VOID DiskError(PUCHAR ErrorString, U32 ErrorCode)
{
UCHAR ErrorCodeString[80];
sprintf(ErrorCodeString, "%s\nError Code: 0x%x", ErrorString, BiosInt13GetLastErrorCode());
sprintf(ErrorCodeString, "%s\n\nError Code: 0x%x", ErrorString, ErrorCode);
DbgPrint((DPRINT_DISK, "%s\n", ErrorCodeString));
UiMessageBox(ErrorCodeString);
}
BOOL DiskReadLogicalSectors(U32 DriveNumber, U32 SectorNumber, U32 SectorCount, PVOID Buffer)
// This function is in arch/i386/i386disk.c
//BOOL DiskReadLogicalSectors(U32 DriveNumber, U64 SectorNumber, U32 SectorCount, PVOID Buffer)
BOOL DiskIsDriveRemovable(U32 DriveNumber)
{
U32 PhysicalSector;
U32 PhysicalHead;
U32 PhysicalTrack;
GEOMETRY DriveGeometry;
U32 NumberOfSectorsToRead;
DbgPrint((DPRINT_DISK, "ReadLogicalSectors() DriveNumber: 0x%x SectorNumber: %d SectorCount: %d Buffer: 0x%x\n", DriveNumber, SectorNumber, SectorCount, Buffer));
//
// Check to see if it is a fixed disk drive
// If so then check to see if Int13 extensions work
// If they do then use them, otherwise default back to BIOS calls
//
if ((DriveNumber >= 0x80) && (IsSetupLdr || BiosInt13ExtensionsSupported(DriveNumber)))
// Hard disks use drive numbers >= 0x80
// So if the drive number indicates a hard disk
// then return FALSE
if (DriveNumber >= 0x80)
{
DbgPrint((DPRINT_DISK, "Using Int 13 Extensions for read. BiosInt13ExtensionsSupported(%d) = %s\n", DriveNumber, BiosInt13ExtensionsSupported(DriveNumber) ? "TRUE" : "FALSE"));
//
// LBA is easy, nothing to calculate
// Just do the read
//
if (!BiosInt13ReadExtended(DriveNumber, SectorNumber, SectorCount, Buffer))
{
DiskError("Disk read error.");
return FALSE;
}
}
else
{
//
// Get the drive geometry
//
if (!DiskGetDriveGeometry(DriveNumber, &DriveGeometry))
{
return FALSE;
}
while (SectorCount)
{
//
// Calculate the physical disk offsets
//
PhysicalSector = 1 + (SectorNumber % DriveGeometry.Sectors);
PhysicalHead = (SectorNumber / DriveGeometry.Sectors) % DriveGeometry.Heads;
PhysicalTrack = (SectorNumber / DriveGeometry.Sectors) / DriveGeometry.Heads;
//
// Calculate how many sectors we are supposed to read
//
if (PhysicalSector > 1)
{
if (SectorCount >= (DriveGeometry.Sectors - (PhysicalSector - 1)))
NumberOfSectorsToRead = (DriveGeometry.Sectors - (PhysicalSector - 1));
else
NumberOfSectorsToRead = SectorCount;
}
else
{
if (SectorCount >= DriveGeometry.Sectors)
NumberOfSectorsToRead = DriveGeometry.Sectors;
else
NumberOfSectorsToRead = SectorCount;
}
DbgPrint((DPRINT_DISK, "Calling BiosInt13Read() with PhysicalHead: %d\n", PhysicalHead));
DbgPrint((DPRINT_DISK, "Calling BiosInt13Read() with PhysicalTrack: %d\n", PhysicalTrack));
DbgPrint((DPRINT_DISK, "Calling BiosInt13Read() with PhysicalSector: %d\n", PhysicalSector));
DbgPrint((DPRINT_DISK, "Calling BiosInt13Read() with NumberOfSectorsToRead: %d\n", NumberOfSectorsToRead));
//
// Make sure the read is within the geometry boundaries
//
if ((PhysicalHead >= DriveGeometry.Heads) ||
(PhysicalTrack >= DriveGeometry.Cylinders) ||
((NumberOfSectorsToRead + PhysicalSector) > (DriveGeometry.Sectors + 1)) ||
(PhysicalSector > DriveGeometry.Sectors))
{
DiskError("Disk read exceeds drive geometry limits.");
return FALSE;
}
//
// Perform the read
//
if (!BiosInt13Read(DriveNumber, PhysicalHead, PhysicalTrack, PhysicalSector, NumberOfSectorsToRead, Buffer))
{
DiskError("Disk read error.");
return FALSE;
}
Buffer += (NumberOfSectorsToRead * DriveGeometry.BytesPerSector);
SectorCount -= NumberOfSectorsToRead;
SectorNumber += NumberOfSectorsToRead;
}
return FALSE;
}
// Drive is a floppy diskette so return TRUE
return TRUE;
}
BOOL DiskIsDriveCdRom(U32 DriveNumber)
{
PUCHAR Sector = (PUCHAR)DISKREADBUFFER;
// FIXME:
// I need to move this code to somewhere else
// probably in the file system code.
// I don't like the fact that the disk code
// reads the on-disk structures to determine
// if it's a CD-ROM drive. Only the file system
// should interpret on-disk data.
// The disk code should use some other method
// to determine if it's a CD-ROM drive.
// Hard disks use drive numbers >= 0x80
// So if the drive number indicates a hard disk
// then return FALSE
//
// We first check if we are running as a SetupLoader
// If so then we are probably booting from a CD-ROM
// So we shouldn't call i386DiskInt13ExtensionsSupported()
// because apparently it screws up some BIOSes
if ((DriveNumber >= 0x80) && (IsSetupLdr || DiskInt13ExtensionsSupported(DriveNumber)))
{
// We are a CD-ROM drive so we should only
// use the extended Int13 disk functions
if (!DiskReadLogicalSectorsLBA(DriveNumber, 16, 1, Sector))
{
DiskError("Disk read error.", 0);
return FALSE;
}
return (Sector[0] == 1 &&
Sector[1] == 'C' &&
Sector[2] == 'D' &&
Sector[3] == '0' &&
Sector[4] == '0' &&
Sector[5] == '1');
}
// Drive is not CdRom so return FALSE
return FALSE;
}
// This function is in arch/i386/i386disk.c
//VOID DiskStopFloppyMotor(VOID)
// This function is in arch/i386/i386disk.c
//U32 DiskGetCacheableBlockCount(U32 DriveNumber)

View file

@ -23,15 +23,22 @@
#include <mm.h>
#ifdef __i386__
BOOL DiskGetDriveGeometry(U32 DriveNumber, PGEOMETRY DriveGeometry)
{
// For now just return the geometry as the BIOS reports it
// BytesPerSector is always set to 512 by BiosInt13GetDriveParameters()
if (!BiosInt13GetDriveParameters(DriveNumber, DriveGeometry))
// BytesPerSector is always set to 512 by i386DiskGetDriveParameters()
if (!DiskGetDriveParameters(DriveNumber, DriveGeometry))
{
DiskError("Drive geometry unknown.");
DiskError("Drive geometry unknown.", 0);
return FALSE;
}
return TRUE;
}
#else
BOOL DiskGetDriveGeometry(U32 DriveNumber, PGEOMETRY DriveGeometry)
{
UNIMPLEMENTED();
}
#endif

View file

@ -25,51 +25,6 @@
#include <arch.h>
BOOL DiskIsDriveRemovable(U32 DriveNumber)
{
// Hard disks use drive numbers >= 0x80
// So if the drive number indicates a hard disk
// then return FALSE
if (DriveNumber >= 0x80)
{
return FALSE;
}
// Drive is a floppy diskette so return TRUE
return TRUE;
}
BOOL DiskIsDriveCdRom(U32 DriveNumber)
{
PUCHAR Sector = (PUCHAR)DISKREADBUFFER;
// Hard disks use drive numbers >= 0x80
// So if the drive number indicates a hard disk
// then return FALSE
if ((DriveNumber >= 0x80) && (IsSetupLdr || BiosInt13ExtensionsSupported(DriveNumber)))
{
if (!BiosInt13ReadExtended(DriveNumber, 16, 1, Sector))
{
DiskError("Disk read error.");
return FALSE;
}
return (Sector[0] == 1 &&
Sector[1] == 'C' &&
Sector[2] == 'D' &&
Sector[3] == '0' &&
Sector[4] == '0' &&
Sector[5] == '1');
}
// Drive is not CdRom so return FALSE
return FALSE;
}
BOOL DiskGetActivePartitionEntry(U32 DriveNumber, PPARTITION_TABLE_ENTRY PartitionTableEntry)
{
U32 BootablePartitionCount = 0;
@ -106,12 +61,12 @@ BOOL DiskGetActivePartitionEntry(U32 DriveNumber, PPARTITION_TABLE_ENTRY Partiti
// Make sure there was only one bootable partition
if (BootablePartitionCount == 0)
{
DiskError("No bootable (active) partitions found.");
DiskError("No bootable (active) partitions found.", 0);
return FALSE;
}
else if (BootablePartitionCount != 1)
{
DiskError("Too many bootable (active) partitions found.");
DiskError("Too many bootable (active) partitions found.", 0);
return FALSE;
}
@ -235,7 +190,7 @@ BOOL DiskGetFirstExtendedPartitionEntry(PMASTER_BOOT_RECORD MasterBootRecord, PP
return FALSE;
}
BOOL DiskReadBootRecord(U32 DriveNumber, U32 LogicalSectorNumber, PMASTER_BOOT_RECORD BootRecord)
BOOL DiskReadBootRecord(U32 DriveNumber, U64 LogicalSectorNumber, PMASTER_BOOT_RECORD BootRecord)
{
#ifdef DEBUG
U32 Index;
@ -276,7 +231,7 @@ BOOL DiskReadBootRecord(U32 DriveNumber, U32 LogicalSectorNumber, PMASTER_BOOT_R
// Check the partition table magic value
if (BootRecord->MasterBootRecordMagic != 0xaa55)
{
DiskError("Invalid partition table magic (0xaa55)");
DiskError("Invalid partition table magic (0xaa55)", 0);
return FALSE;
}

View file

@ -33,7 +33,7 @@
// DATA
/////////////////////////////////////////////////////////////////////////////////////////////
U32 FileSystemType = 0; // Type of filesystem on boot device, set by OpenDiskDrive()
U32 FileSystemType = 0; // Type of filesystem on boot device, set by FsOpenVolume()
/////////////////////////////////////////////////////////////////////////////////////////////
// FUNCTIONS
@ -48,9 +48,9 @@ VOID FileSystemError(PUCHAR ErrorString)
/*
*
* BOOL OpenDiskDrive(U32 DriveNumber, U32 PartitionNumber);
* BOOL FsOpenVolume(U32 DriveNumber, U32 PartitionNumber);
*
* This function is called to open a disk drive for file access.
* This function is called to open a disk volume for file access.
* It must be called before any of the file functions will work.
* It takes two parameters:
*
@ -61,12 +61,12 @@ VOID FileSystemError(PUCHAR ErrorString)
* If it is zero then it opens the active (bootable) partition
*
*/
BOOL OpenDiskDrive(U32 DriveNumber, U32 PartitionNumber)
BOOL FsOpenVolume(U32 DriveNumber, U32 PartitionNumber)
{
PARTITION_TABLE_ENTRY PartitionTableEntry;
UCHAR ErrorText[80];
DbgPrint((DPRINT_FILESYSTEM, "OpenDiskDrive() DriveNumber: 0x%x PartitionNumber: 0x%x\n", DriveNumber, PartitionNumber));
DbgPrint((DPRINT_FILESYSTEM, "FsOpenVolume() DriveNumber: 0x%x PartitionNumber: 0x%x\n", DriveNumber, PartitionNumber));
// Check and see if it is a floppy drive
// If so then just assume FAT12 file system type
@ -141,7 +141,7 @@ BOOL OpenDiskDrive(U32 DriveNumber, U32 PartitionNumber)
return TRUE;
}
PFILE OpenFile(PUCHAR FileName)
PFILE FsOpenFile(PUCHAR FileName)
{
PFILE FileHandle = NULL;
@ -183,18 +183,18 @@ PFILE OpenFile(PUCHAR FileName)
//
if (FileHandle != NULL)
{
DbgPrint((DPRINT_FILESYSTEM, "OpenFile() succeeded. FileHandle: 0x%x\n", FileHandle));
DbgPrint((DPRINT_FILESYSTEM, "FsOpenFile() succeeded. FileHandle: 0x%x\n", FileHandle));
}
else
{
DbgPrint((DPRINT_FILESYSTEM, "OpenFile() failed.\n"));
DbgPrint((DPRINT_FILESYSTEM, "FsOpenFile() failed.\n"));
}
#endif // defined DEBUG
return FileHandle;
}
VOID CloseFile(PFILE FileHandle)
VOID FsCloseFile(PFILE FileHandle)
{
}
@ -202,12 +202,15 @@ VOID CloseFile(PFILE FileHandle)
* ReadFile()
* returns number of bytes read or EOF
*/
BOOL ReadFile(PFILE FileHandle, U32 BytesToRead, U32* BytesRead, PVOID Buffer)
BOOL FsReadFile(PFILE FileHandle, U32 BytesToRead, U32* BytesRead, PVOID Buffer)
{
U64 BytesReadBig;
BOOL Success;
//
// Set the number of bytes read equal to zero
//
if (BytesRead !=NULL)
if (BytesRead != NULL)
{
*BytesRead = 0;
}
@ -224,7 +227,10 @@ BOOL ReadFile(PFILE FileHandle, U32 BytesToRead, U32* BytesRead, PVOID Buffer)
case FS_EXT2:
return Ext2ReadFile(FileHandle, BytesToRead, BytesRead, Buffer);
//return Ext2ReadFile(FileHandle, BytesToRead, BytesRead, Buffer);
Success = Ext2ReadFile(FileHandle, BytesToRead, &BytesReadBig, Buffer);
*BytesRead = (U32)BytesReadBig;
return Success;
default:
@ -235,7 +241,7 @@ BOOL ReadFile(PFILE FileHandle, U32 BytesToRead, U32* BytesRead, PVOID Buffer)
return FALSE;
}
U32 GetFileSize(PFILE FileHandle)
U32 FsGetFileSize(PFILE FileHandle)
{
switch (FileSystemType)
{
@ -259,7 +265,7 @@ U32 GetFileSize(PFILE FileHandle)
return 0;
}
VOID SetFilePointer(PFILE FileHandle, U32 NewFilePointer)
VOID FsSetFilePointer(PFILE FileHandle, U32 NewFilePointer)
{
switch (FileSystemType)
{
@ -284,7 +290,7 @@ VOID SetFilePointer(PFILE FileHandle, U32 NewFilePointer)
}
}
U32 GetFilePointer(PFILE FileHandle)
U32 FsGetFilePointer(PFILE FileHandle)
{
switch (FileSystemType)
{
@ -311,9 +317,9 @@ U32 GetFilePointer(PFILE FileHandle)
return 0;
}
BOOL IsEndOfFile(PFILE FileHandle)
BOOL FsIsEndOfFile(PFILE FileHandle)
{
if (GetFilePointer(FileHandle) >= GetFileSize(FileHandle))
if (FsGetFilePointer(FileHandle) >= FsGetFileSize(FileHandle))
{
return TRUE;
}

View file

@ -16,7 +16,10 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifndef __ARCH_H
#define __ARCH_H
/* Defines needed for switching between real and protected mode */
#define NULL_DESC 0x00 /* NULL descriptor */
@ -36,15 +39,14 @@
#define CR0_PE_SET 0x00000001 /* OR this value with CR0 to enable pmode */
#define CR0_PE_CLR 0xFFFFFFFE /* AND this value with CR0 to disable pmode */
#define NR_TASKS 128 /* Space reserved in the GDT for TSS descriptors */
#define STACK16ADDR 0x7000 /* The 16-bit stack top will be at 0000:7000 */
#define STACK32ADDR 0x80000 /* The 32-bit stack top will be at 7000:FFFF, or 0x7FFFF */
#define STACK32ADDR 0x78000 /* The 32-bit stack top will be at 7000:8000, or 0x78000 */
#define MAXLOWMEMADDR 0x78000 /* The highest usuable low memory address for our memory allocator */
#define FILESYSBUFFER 0x80000 /* Buffer to store file system data (e.g. cluster buffer for FAT) */
#define DISKREADBUFFER 0x90000 /* Buffer to store data read in from the disk via the BIOS */
#define BIOSCALLBUFFER 0x78000 /* Buffer to store temporary data for any Int386() call */
#define BIOSCALLBUFSEGMENT 0x7800 /* Buffer to store temporary data for any Int386() call */
#define BIOSCALLBUFOFFSET 0x0000 /* Buffer to store temporary data for any Int386() call */
#define FILESYSBUFFER 0x80000 /* Buffer to store file system data (e.g. cluster buffer for FAT) */
#define DISKREADBUFFER 0x90000 /* Buffer to store data read in from the disk via the BIOS */
/* Makes "x" a global variable or label */
#define EXTERN(x) .global x; x:
@ -54,7 +56,111 @@
#ifndef ASM
typedef struct
{
unsigned long eax;
unsigned long ebx;
unsigned long ecx;
unsigned long edx;
unsigned long esi;
unsigned long edi;
unsigned short ds;
unsigned short es;
unsigned short fs;
unsigned short gs;
unsigned long eflags;
} PACKED DWORDREGS;
typedef struct
{
unsigned short ax, _upper_ax;
unsigned short bx, _upper_bx;
unsigned short cx, _upper_cx;
unsigned short dx, _upper_dx;
unsigned short si, _upper_si;
unsigned short di, _upper_di;
unsigned short ds;
unsigned short es;
unsigned short fs;
unsigned short gs;
unsigned short flags, _upper_flags;
} PACKED WORDREGS;
typedef struct
{
unsigned char al;
unsigned char ah;
unsigned short _upper_ax;
unsigned char bl;
unsigned char bh;
unsigned short _upper_bx;
unsigned char cl;
unsigned char ch;
unsigned short _upper_cx;
unsigned char dl;
unsigned char dh;
unsigned short _upper_dx;
unsigned short si, _upper_si;
unsigned short di, _upper_di;
unsigned short ds;
unsigned short es;
unsigned short fs;
unsigned short gs;
unsigned short flags, _upper_flags;
} PACKED BYTEREGS;
typedef union
{
DWORDREGS x;
DWORDREGS d;
WORDREGS w;
BYTEREGS b;
} REGS;
// Int386()
//
// Real mode interrupt vector interface
//
// (E)FLAGS can *only* be returned by this function, not set.
// Make sure all memory pointers are in SEG:OFFS format and
// not linear addresses, unless the interrupt handler
// specifically handles linear addresses.
int Int386(int ivec, REGS* in, REGS* out);
// Flag Masks
#define I386FLAG_CF 0x0001 // Carry Flag
#define I386FLAG_RESV1 0x0002 // Reserved - Must be 1
#define I386FLAG_PF 0x0004 // Parity Flag
#define I386FLAG_RESV2 0x0008 // Reserved - Must be 0
#define I386FLAG_AF 0x0010 // Auxiliary Flag
#define I386FLAG_RESV3 0x0020 // Reserved - Must be 0
#define I386FLAG_ZF 0x0040 // Zero Flag
#define I386FLAG_SF 0x0080 // Sign Flag
#define I386FLAG_TF 0x0100 // Trap Flag (Single Step)
#define I386FLAG_IF 0x0200 // Interrupt Flag
#define I386FLAG_DF 0x0400 // Direction Flag
#define I386FLAG_OF 0x0800 // Overflow Flag
// This macro tests the Carry Flag
// If CF is set then the call failed (usually)
#define INT386_SUCCESS(regs) ((regs.x.eflags & I386FLAG_CF) == 0)
void EnableA20(void);
void StopFloppyMotor(void);
#endif /* ! ASM */
#endif // #defined __ARCH_H

View file

@ -23,7 +23,7 @@
#ifdef DEBUG
#define DPRINT_NONE 0x00000000 // Simple debug print
#define DPRINT_NONE 0x00000000 // No debug print
#define DPRINT_WARNING 0x00000001 // OR this with DebugPrintMask to enable debugger messages and other misc stuff
#define DPRINT_MEMORY 0x00000002 // OR this with DebugPrintMask to enable memory management messages
#define DPRINT_FILESYSTEM 0x00000004 // OR this with DebugPrintMask to enable file system messages
@ -39,8 +39,8 @@
VOID DebugPrint(U32 Mask, char *format, ...);
VOID DebugDumpBuffer(U32 Mask, PVOID Buffer, U32 Length);
#define DbgPrint(_x_) { DebugPrint(DPRINT_NONE, "%s:%d(%s)\n", __FILE__, __LINE__, __FUNCTION__); DebugPrint _x_ ; }
#define BugCheck(_x_) { DebugPrint(DPRINT_WARNING, "Fatal Error: %s:%d(%s)\n", __FILE__, __LINE__, __FUNCTION__); DebugPrint _x_ ; for (;;); }
#define DbgPrint(_x_) DebugPrint _x_ ;
#define BugCheck(_x_) { DebugPrint(DPRINT_WARNING, "Fatal Error: %s:%d(%s)\n", __FILE__, __LINE__, __FUNCTION__); DebugPrint _x_ ; for (;;); }
#define DbgDumpBuffer(_x_, _y_, _z_) DebugDumpBuffer(_x_, _y_, _z_)
#ifdef __i386__
@ -78,6 +78,6 @@ void MEMORY_WRITE_BREAKPOINT4(unsigned long addr);
#endif // defined DEBUG
#define UNIMPLEMENTED BugCheck((DPRINT_WARNING, "Unimplemented\n"));
#define UNIMPLEMENTED() BugCheck((DPRINT_WARNING, "This function is unimplemented!\n"))
#endif // defined __DEBUG_H

View file

@ -23,10 +23,10 @@
typedef struct _GEOMETRY
{
U32 Cylinders;
U32 Heads;
U32 Sectors;
U32 BytesPerSector;
U32 Cylinders; // Number of cylinders on the disk
U32 Heads; // Number of heads on the disk
U32 Sectors; // Number of sectors per track
U32 BytesPerSector; // Number of bytes per sector
} GEOMETRY, *PGEOMETRY;
@ -83,42 +83,44 @@ typedef struct _MASTER_BOOT_RECORD
///////////////////////////////////////////////////////////////////////////////////////
//
// BIOS Disk Functions
// i386 BIOS Disk Functions (i386disk.c)
//
///////////////////////////////////////////////////////////////////////////////////////
int biosdisk(int cmd, int drive, int head, int track, int sector, int nsects, void *buffer); // Implemented in asmcode.S
#ifdef __i386__
BOOL BiosInt13Read(U32 Drive, U32 Head, U32 Track, U32 Sector, U32 SectorCount, PVOID Buffer); // Implemented in asmcode.S
BOOL BiosInt13ReadExtended(U32 Drive, U32 Sector, U32 SectorCount, PVOID Buffer); // Implemented in asmcode.S
BOOL BiosInt13ExtensionsSupported(U32 Drive);
U32 BiosInt13GetLastErrorCode(VOID);
//BOOL DiskReadLogicalSectors(U32 DriveNumber, U64 SectorNumber, U32 SectorCount, PVOID Buffer);
BOOL DiskReadLogicalSectorsLBA(U32 DriveNumber, U64 SectorNumber, U32 SectorCount, PVOID Buffer);
BOOL DiskReadLogicalSectorsCHS(U32 DriveNumber, U64 SectorNumber, U32 SectorCount, PVOID Buffer);
BOOL DiskResetController(U32 DriveNumber);
BOOL DiskInt13ExtensionsSupported(U32 DriveNumber);
//VOID DiskStopFloppyMotor(VOID);
BOOL DiskGetDriveParameters(U32 DriveNumber, PGEOMETRY Geometry);
//U32 DiskGetCacheableBlockCount(U32 DriveNumber);
void StopFloppyMotor(void); // Implemented in asmcode.S
int get_heads(int drive); // Implemented in asmcode.S
int get_cylinders(int drive); // Implemented in asmcode.S
int get_sectors(int drive); // Implemented in asmcode.S
BOOL BiosInt13GetDriveParameters(U32 Drive, PGEOMETRY Geometry); // Implemented in disk.S
#endif // defined __i386__
///////////////////////////////////////////////////////////////////////////////////////
//
// FreeLoader Disk Functions
//
///////////////////////////////////////////////////////////////////////////////////////
VOID DiskError(PUCHAR ErrorString);
VOID DiskError(PUCHAR ErrorString, U32 ErrorCode);
BOOL DiskGetDriveGeometry(U32 DriveNumber, PGEOMETRY DriveGeometry);
BOOL DiskReadLogicalSectors(U32 DriveNumber, U32 SectorNumber, U32 SectorCount, PVOID Buffer);
BOOL DiskReadLogicalSectors(U32 DriveNumber, U64 SectorNumber, U32 SectorCount, PVOID Buffer); // Implemented in i386disk.c
BOOL DiskIsDriveRemovable(U32 DriveNumber);
BOOL DiskIsDriveCdRom(U32 DriveNumber);
VOID DiskStopFloppyMotor(VOID); // Implemented in i386disk.c
U32 DiskGetCacheableBlockCount(U32 DriveNumber); // Implemented in i386disk.c
///////////////////////////////////////////////////////////////////////////////////////
//
// Fixed Disk Partition Management Functions
//
///////////////////////////////////////////////////////////////////////////////////////
BOOL DiskIsDriveRemovable(U32 DriveNumber);
BOOL DiskIsDriveCdRom(U32 DriveNumber);
BOOL DiskGetActivePartitionEntry(U32 DriveNumber, PPARTITION_TABLE_ENTRY PartitionTableEntry);
BOOL DiskGetPartitionEntry(U32 DriveNumber, U32 PartitionNumber, PPARTITION_TABLE_ENTRY PartitionTableEntry);
BOOL DiskGetFirstPartitionEntry(PMASTER_BOOT_RECORD MasterBootRecord, PPARTITION_TABLE_ENTRY PartitionTableEntry);
BOOL DiskGetFirstExtendedPartitionEntry(PMASTER_BOOT_RECORD MasterBootRecord, PPARTITION_TABLE_ENTRY PartitionTableEntry);
BOOL DiskReadBootRecord(U32 DriveNumber, U32 LogicalSectorNumber, PMASTER_BOOT_RECORD BootRecord);
BOOL DiskReadBootRecord(U32 DriveNumber, U64 LogicalSectorNumber, PMASTER_BOOT_RECORD BootRecord);
#endif // defined __DISK_H

View file

@ -33,14 +33,14 @@
#define PFILE FILE *
VOID FileSystemError(PUCHAR ErrorString);
BOOL OpenDiskDrive(U32 DriveNumber, U32 PartitionNumber);
PFILE OpenFile(PUCHAR FileName);
VOID CloseFile(PFILE FileHandle);
BOOL ReadFile(PFILE FileHandle, U32 BytesToRead, U32* BytesRead, PVOID Buffer);
U32 GetFileSize(PFILE FileHandle);
VOID SetFilePointer(PFILE FileHandle, U32 NewFilePointer);
U32 GetFilePointer(PFILE FileHandle);
BOOL IsEndOfFile(PFILE FileHandle);
BOOL FsOpenVolume(U32 DriveNumber, U32 PartitionNumber);
PFILE FsOpenFile(PUCHAR FileName);
VOID FsCloseFile(PFILE FileHandle);
BOOL FsReadFile(PFILE FileHandle, U32 BytesToRead, U32* BytesRead, PVOID Buffer);
U32 FsGetFileSize(PFILE FileHandle);
VOID FsSetFilePointer(PFILE FileHandle, U32 NewFilePointer);
U32 FsGetFilePointer(PFILE FileHandle);
BOOL FsIsEndOfFile(PFILE FileHandle);
U32 FsGetNumPathParts(PUCHAR Path);
VOID FsGetFirstNameFromPath(PUCHAR Buffer, PUCHAR Path);

View file

@ -127,6 +127,6 @@ BOOL LinuxReadBootSector(PFILE LinuxKernelFile);
BOOL LinuxReadSetupSector(PFILE LinuxKernelFile);
BOOL LinuxReadKernel(PFILE LinuxKernelFile);
BOOL LinuxCheckKernelVersion(VOID);
BOOL LinuxReadInitrd(VOID);
BOOL LinuxReadInitrd(PFILE LinuxInitrdFile);
#endif // defined __LINUX_H

View file

@ -35,18 +35,13 @@ typedef struct
U32 Reserved;
} PACKED BIOS_MEMORY_MAP, *PBIOS_MEMORY_MAP;
typedef struct
{
BIOS_MEMORY_MAP BiosMemoryMapArray[32];
} PACKED BIOS_MEMORY_MAP_ARRAY, *PBIOS_MEMORY_MAP_ARRAY;
U32 GetSystemMemorySize(VOID); // Returns the amount of total memory in the system
// These functions are implemented in mem.S
U32 GetExtendedMemorySize(VOID); // Returns extended memory size in KB
U32 GetConventionalMemorySize(VOID); // Returns conventional memory size in KB
U32 GetBiosMemoryMap(PBIOS_MEMORY_MAP_ARRAY BiosMemoryMap); // Fills structure with BIOS memory map and returns memory map item count
U32 GetBiosMemoryMap(BIOS_MEMORY_MAP BiosMemoryMap[32]); // Fills structure with BIOS memory map and returns memory map item count

View file

@ -44,14 +44,14 @@ int strnicmp(const char *string1, const char *string2, size_t length);
// Memory Functions
//
///////////////////////////////////////////////////////////////////////////////////////
int RtlCompareMemory(const PVOID Source1, const PVOID Source2, U32 Length);
VOID RtlCopyMemory(PVOID Destination, const PVOID Source, U32 Length);
VOID RtlFillMemory(PVOID Destination, U32 Length, UCHAR Fill);
VOID RtlZeroMemory(PVOID Destination, U32 Length);
int memcmp(const void *buf1, const void *buf2, size_t count);
void * memcpy(void *to, const void *from, size_t count);
void * memset(void *src, int val, size_t count);
#define memcmp(buf1, buf2, count) RtlCompareMemory(buf1, buf2, count)
#define memcpy(dest, src, count) RtlCopyMemory(dest, src,count)
#define memset(dest, c, count) RtlFillMemory(dest,count, c)
#define RtlCompareMemory(Source1, Source2, Length) memcmp(Source1, Source2, Length)
#define RtlCopyMemory(Destination, Source, Length) memcpy(Destination, Source, Length)
#define RtlFillMemory(Destination, Length, Fill) memset(Destination, Fill, Length)
#define RtlZeroMemory(Destination, Length) memset(Destination, 0, Length)
///////////////////////////////////////////////////////////////////////////////////////
//

View file

@ -44,6 +44,8 @@ extern PUCHAR UiMessageBoxLineText;
extern BOOL UserInterfaceUp; // Tells us if the user interface is displayed
extern BOOL UiUseSpecialEffects; // Tells us if we should use fade effects
extern UCHAR UiMonthNames[12][15];
///////////////////////////////////////////////////////////////////////////////////////
@ -52,6 +54,7 @@ extern UCHAR UiMonthNames[12][15];
//
///////////////////////////////////////////////////////////////////////////////////////
BOOL UiInitialize(VOID); // Initialize User-Interface
VOID UiUnInitialize(PUCHAR BootText); // Un-initialize User-Interface
VOID UiDrawBackdrop(VOID); // Fills the entire screen with a backdrop
VOID UiFillArea(U32 Left, U32 Top, U32 Right, U32 Bottom, UCHAR FillChar, UCHAR Attr /* Color Attributes */); // Fills the area specified with FillChar and Attr
VOID UiDrawShadow(U32 Left, U32 Top, U32 Right, U32 Bottom); // Draws a shadow on the bottom and right sides of the area specified
@ -60,6 +63,7 @@ VOID UiDrawText(U32 X, U32 Y, PUCHAR Text, UCHAR Attr); // Draws text at coordin
VOID UiDrawCenteredText(U32 Left, U32 Top, U32 Right, U32 Bottom, PUCHAR TextString, UCHAR Attr); // Draws centered text at the coordinates specified and clips the edges
VOID UiDrawStatusText(PUCHAR StatusText); // Draws text at the very bottom line on the screen
VOID UiUpdateDateTime(VOID); // Updates the date and time
VOID UiInfoBox(PUCHAR MessageText); // Displays a info box on the screen
VOID UiMessageBox(PUCHAR MessageText); // Displays a message box on the screen with an ok button
VOID UiMessageBoxCritical(PUCHAR MessageText); // Displays a message box on the screen with an ok button using no system resources
VOID UiMessageLine(PUCHAR MessageText); // Adds a line of text to the message box buffer
@ -72,6 +76,9 @@ UCHAR UiTextToFillStyle(PUCHAR FillStyleText); // Converts the text fill into
VOID UiTruncateStringEllipsis(PUCHAR StringText, U32 MaxChars); // Truncates a string to MaxChars by adding an ellipsis on the end '...'
VOID UiFadeInBackdrop(VOID); // Draws the backdrop and fades the screen in
VOID UiFadeOut(VOID); // Fades the screen out
///////////////////////////////////////////////////////////////////////////////////////
//
// Menu Functions

View file

@ -21,10 +21,18 @@
#define __VIDEO_H
#define VIDEOCARD_CGA_OR_OTHER 0
#define VIDEOCARD_EGA 1
#define VIDEOCARD_VGA 2
#define VERTRES_200_SCANLINES 0x00
#define VERTRES_350_SCANLINES 0x01
#define VERTRES_400_SCANLINES 0x02
#define MODETYPE_TEXT 0
#define MODETYPE_GRAPHICS 1
#define VIDEOMODE_NORMAL_TEXT 0
#define VIDEOMODE_EXTENDED_TEXT 1
#define VIDEOMODE_80X28 0x501C
@ -32,32 +40,114 @@
#define VIDEOMODE_80X34 0x5022
#define VIDEOMODE_80X43 0x502B
#define VIDEOMODE_80X60 0x503C
#define VIDEOMODE_132X25 0x8419
#define VIDEOMODE_132X43 0x842B
#define VIDEOMODE_132X50 0x8432
#define VIDEOMODE_132X60 0x843C
#define VIDEOPORT_PALETTE_READ 0x03C7
#define VIDEOPORT_PALETTE_WRITE 0x03C8
#define VIDEOPORT_PALETTE_DATA 0x03C9
#define VIDEOPORT_VERTICAL_RETRACE 0x03DA
VOID BiosSetVideoMode(U32 VideoMode); // Implemented in biosvid.S
VOID BiosSetVideoFont8x8(VOID); // Implemented in biosvid.S
VOID BiosSetVideoFont8x14(VOID); // Implemented in biosvid.S
VOID BiosSetVideoFont8x16(VOID); // Implemented in biosvid.S
VOID BiosSelectAlternatePrintScreen(VOID); // Implemented in biosvid.S
VOID BiosDisableCursorEmulation(VOID); // Implemented in biosvid.S
VOID BiosDefineCursor(U32 StartScanLine, U32 EndScanLine); // Implemented in biosvid.S
U32 BiosDetectVideoCard(VOID); // Implemented in biosvid.S
VOID BiosSet200ScanLines(VOID); // Implemented in biosvid.S, must be called right before BiosSetVideoMode()
VOID BiosSet350ScanLines(VOID); // Implemented in biosvid.S, must be called right before BiosSetVideoMode()
VOID BiosSet400ScanLines(VOID); // Implemented in biosvid.S, must be called right before BiosSetVideoMode()
VOID BiosSet480ScanLines(VOID); // Implemented in biosvid.S, must be called right after BiosSetVideoMode()
VOID BiosSetVideoDisplayEnd(VOID); // Implemented in biosvid.S
VOID BiosVideoDisableBlinkBit(VOID); // Implemented in biosvid.S
#define VIDEOVGA_MEM_ADDRESS 0xA0000
#define VIDEOTEXT_MEM_ADDRESS 0xB8000
VOID VideoSetTextCursorPosition(U32 X, U32 Y); // Implemented in biosvid.S
VOID VideoHideTextCursor(VOID); // Implemented in biosvid.S
VOID VideoShowTextCursor(VOID); // Implemented in biosvid.S
U32 VideoGetTextCursorPositionX(VOID); // Implemented in biosvid.S
U32 VideoGetTextCursorPositionY(VOID); // Implemented in biosvid.S
typedef struct
{
U8 Red;
U8 Green;
U8 Blue;
} PACKED PALETTE_ENTRY, *PPALETTE_ENTRY;
typedef struct
{
U16 ModeAttributes; // mode attributes (see #00080)
U8 WindowAttributesA; // window attributes, window A (see #00081)
U8 WindowsAttributesB; // window attributes, window B (see #00081)
U16 WindowGranularity; // window granularity in KB
U16 WindowSize; // window size in KB
U16 WindowAStartSegment; // start segment of window A (0000h if not supported)
U16 WindowBStartSegment; // start segment of window B (0000h if not supported)
U32 WindowPositioningFunction; // -> FAR window positioning function (equivalent to AX=4F05h)
U16 BytesPerScanLine; // bytes per scan line
//---remainder is optional for VESA modes in v1.0/1.1, needed for OEM modes---
U16 WidthInPixels; // width in pixels (graphics) or characters (text)
U16 HeightInPixels; // height in pixels (graphics) or characters (text)
U8 CharacterWidthInPixels; // width of character cell in pixels
U8 CharacterHeightInPixels; // height of character cell in pixels
U8 NumberOfMemoryPlanes; // number of memory planes
U8 BitsPerPixel; // number of bits per pixel
U8 NumberOfBanks; // number of banks
U8 MemoryModel; // memory model type (see #00082)
U8 BankSize; // size of bank in KB
U8 NumberOfImagePanes; // number of image pages (less one) that will fit in video RAM
U8 Reserved1; // reserved (00h for VBE 1.0-2.0, 01h for VBE 3.0)
//---VBE v1.2+ ---
U8 RedMaskSize; // red mask size
U8 RedMaskPosition; // red field position
U8 GreenMaskSize; // green mask size
U8 GreenMaskPosition; // green field size
U8 BlueMaskSize; // blue mask size
U8 BlueMaskPosition; // blue field size
U8 ReservedMaskSize; // reserved mask size
U8 ReservedMaskPosition; // reserved mask position
U8 DirectColorModeInfo; // direct color mode info
// bit 0:Color ramp is programmable
// bit 1:Bytes in reserved field may be used by application
//---VBE v2.0+ ---
U32 LinearVideoBufferAddress; // physical address of linear video buffer
U32 OffscreenMemoryPointer; // pointer to start of offscreen memory
U16 OffscreenMemorySize; // KB of offscreen memory
//---VBE v3.0 ---
U16 LinearBytesPerScanLine; // bytes per scan line in linear modes
U8 BankedNumberOfImages; // number of images (less one) for banked video modes
U8 LinearNumberOfImages; // number of images (less one) for linear video modes
U8 LinearRedMaskSize; // linear modes:Size of direct color red mask (in bits)
U8 LinearRedMaskPosition; // linear modes:Bit position of red mask LSB (e.g. shift count)
U8 LinearGreenMaskSize; // linear modes:Size of direct color green mask (in bits)
U8 LinearGreenMaskPosition; // linear modes:Bit position of green mask LSB (e.g. shift count)
U8 LinearBlueMaskSize; // linear modes:Size of direct color blue mask (in bits)
U8 LinearBlueMaskPosition; // linear modes:Bit position of blue mask LSB (e.g. shift count)
U8 LinearReservedMaskSize; // linear modes:Size of direct color reserved mask (in bits)
U8 LinearReservedMaskPosition; // linear modes:Bit position of reserved mask LSB
U32 MaximumPixelClock; // maximum pixel clock for graphics video mode, in Hz
U8 Reserved2[190]; // 190 BYTEs reserved (0)
} PACKED SVGA_MODE_INFORMATION, *PSVGA_MODE_INFORMATION;
extern U32 CurrentMemoryBank;
extern SVGA_MODE_INFORMATION VesaVideoModeInformation;
extern PVOID VideoOffScreenBuffer;
VOID BiosSetVideoMode(U32 VideoMode); // Implemented in i386vid.S
VOID BiosSetVideoFont8x8(VOID); // Implemented in i386vid.S
VOID BiosSetVideoFont8x14(VOID); // Implemented in i386vid.S
VOID BiosSetVideoFont8x16(VOID); // Implemented in i386vid.S
VOID BiosSelectAlternatePrintScreen(VOID); // Implemented in i386vid.S
VOID BiosDisableCursorEmulation(VOID); // Implemented in i386vid.S
VOID BiosDefineCursor(U32 StartScanLine, U32 EndScanLine); // Implemented in i386vid.S
U32 BiosDetectVideoCard(VOID); // Implemented in i386vid.S
VOID BiosSetVerticalResolution(U32 ScanLines); // Implemented in i386vid.S, must be called right before BiosSetVideoMode()
VOID BiosSet480ScanLines(VOID); // Implemented in i386vid.S, must be called right after BiosSetVideoMode()
VOID BiosSetVideoDisplayEnd(VOID); // Implemented in i386vid.S
VOID BiosVideoDisableBlinkBit(VOID); // Implemented in i386vid.S
VOID BiosVideoEnableBlinkBit(VOID); // Implemented in i386vid.S
U16 BiosIsVesaSupported(VOID); // Implemented in i386vid.S, returns the VESA version
BOOL BiosVesaSetBank(U16 Bank); // Implemented in i386vid.S
BOOL BiosVesaSetVideoMode(U16 Mode); // Implemented in i386vid.S
BOOL BiosVesaGetSVGAModeInformation(U16 Mode, PSVGA_MODE_INFORMATION ModeInformation); // Implemented in i386vid.S
VOID VideoSetTextCursorPosition(U32 X, U32 Y); // Implemented in i386vid.S
VOID VideoHideTextCursor(VOID); // Implemented in i386vid.S
VOID VideoShowTextCursor(VOID); // Implemented in i386vid.S
U32 VideoGetTextCursorPositionX(VOID); // Implemented in i386vid.S
U32 VideoGetTextCursorPositionY(VOID); // Implemented in i386vid.S
BOOL VideoSetMode(U32 VideoMode);
BOOL VideoSetMode80x25(VOID); // Sets 80x25
@ -69,12 +159,39 @@ BOOL VideoSetMode80x34(VOID); // Sets 80x34. Works on all VGA's. 480 scanli
BOOL VideoSetMode80x60(VOID); // Sets 80x60. Works on all VGA's. 480 scanlines, 8-pixel font.
U32 VideoGetCurrentModeResolutionX(VOID);
U32 VideoGetCurrentModeResolutionY(VOID);
U32 VideoGetBytesPerScanLine(VOID);
U32 VideoGetCurrentMode(VOID);
U32 VideoGetCurrentModeType(VOID); // MODETYPE_TEXT or MODETYPE_GRAPHICS
BOOL VideoIsCurrentModeVesa(VOID);
U32 VideoGetCurrentModeColorDepth(VOID); // Returns 0 for text mode, 16 for 4-bit, 256 for 8-bit, 32768 for 15-bit, 65536 for 16-bit, etc.
VOID VideoClearScreen(VOID);
VOID VideoWaitForVerticalRetrace(VOID);
VOID VideoSetPaletteColor(UCHAR Color, UCHAR Red, UCHAR Green, UCHAR Blue);
VOID VideoGetPaletteColor(UCHAR Color, PUCHAR Red, PUCHAR Green, PUCHAR Blue);
PVOID VideoAllocateOffScreenBuffer(VOID); // Returns a pointer to an off-screen buffer sufficient for the current video mode
U32 VideoGetMemoryBankForPixel(U32 X, U32 Y);
U32 VideoGetMemoryBankForPixel16(U32 X, U32 Y);
U32 VideoGetBankOffsetForPixel(U32 X, U32 Y);
U32 VideoGetBankOffsetForPixel16(U32 X, U32 Y);
VOID VideoSetMemoryBank(U16 BankNumber);
U32 VideoGetOffScreenMemoryOffsetForPixel(U32 X, U32 Y);
VOID VideoCopyOffScreenBufferToVRAM(VOID);
VOID VideoSetPaletteColor(U8 Color, U8 Red, U8 Green, U8 Blue);
VOID VideoGetPaletteColor(U8 Color, U8* Red, U8* Green, U8* Blue);
VOID VideoSavePaletteState(PPALETTE_ENTRY Palette, U32 ColorCount);
VOID VideoRestorePaletteState(PPALETTE_ENTRY Palette, U32 ColorCount);
VOID VideoSetPixel16(U32 X, U32 Y, U8 Color);
VOID VideoSetPixel256(U32 X, U32 Y, U8 Color);
VOID VideoSetPixelRGB(U32 X, U32 Y, U8 Red, U8 Green, U8 Blue);
VOID VideoSetPixel16_OffScreen(U32 X, U32 Y, U8 Color);
VOID VideoSetPixel256_OffScreen(U32 X, U32 Y, U8 Color);
VOID VideoSetPixelRGB_OffScreen(U32 X, U32 Y, U8 Red, U8 Green, U8 Blue);
VOID VideoSetAllColorsToBlack(U32 ColorCount);
VOID VideoFadeIn(PPALETTE_ENTRY Palette, U32 ColorCount);
VOID VideoFadeOut(U32 ColorCount);
#endif // defined __VIDEO_H

View file

@ -58,26 +58,26 @@ BOOL IniFileInitialize(VOID)
}
// Get the file size & allocate enough memory for it
FreeLoaderIniFileSize = GetFileSize(Freeldr_Ini);
FreeLoaderIniFileSize = FsGetFileSize(Freeldr_Ini);
FreeLoaderIniFileData = MmAllocateMemory(FreeLoaderIniFileSize);
// If we are out of memory then return FALSE
if (FreeLoaderIniFileData == NULL)
{
printf("Out of memory while loading freeldr.ini.\n");
CloseFile(Freeldr_Ini);
FsCloseFile(Freeldr_Ini);
return FALSE;
}
// Read freeldr.ini off the disk
if (!ReadFile(Freeldr_Ini, FreeLoaderIniFileSize, NULL, FreeLoaderIniFileData))
if (!FsReadFile(Freeldr_Ini, FreeLoaderIniFileSize, NULL, FreeLoaderIniFileData))
{
CloseFile(Freeldr_Ini);
FsCloseFile(Freeldr_Ini);
MmFreeMemory(FreeLoaderIniFileData);
return FALSE;
}
CloseFile(Freeldr_Ini);
FsCloseFile(Freeldr_Ini);
// Parse the .ini file data
Success = IniParseFile(FreeLoaderIniFileData, FreeLoaderIniFileSize);
@ -91,7 +91,7 @@ PFILE IniOpenIniFile(U8 BootDriveNumber, U8 BootPartitionNumber)
{
PFILE IniFileHandle; // File handle for freeldr.ini
if (!OpenDiskDrive(BootDriveNumber, BootPartitionNumber))
if (!FsOpenVolume(BootDriveNumber, BootPartitionNumber))
{
if (BootPartitionNumber == 0)
{
@ -106,7 +106,7 @@ PFILE IniOpenIniFile(U8 BootDriveNumber, U8 BootPartitionNumber)
}
// Try to open freeldr.ini
IniFileHandle = OpenFile("freeldr.ini");
IniFileHandle = FsOpenFile("freeldr.ini");
return IniFileHandle;
}

View file

@ -20,6 +20,7 @@
#include <freeldr.h>
#include <arch.h>
#include <disk.h>
#include <miscboot.h>
#include <rtl.h>
#include <fs.h>
@ -31,11 +32,17 @@
#include <oslist.h> // For RemoveQuotes()
#include <video.h>
#define LINUX_READ_CHUNK_SIZE 0x20000 // Read 128k at a time
PLINUX_BOOTSECTOR LinuxBootSector = NULL;
PLINUX_SETUPSECTOR LinuxSetupSector = NULL;
U32 SetupSectorSize = 0;
BOOL NewStyleLinuxKernel = FALSE;
U32 LinuxKernelSize = 0;
U32 LinuxInitrdSize = 0;
UCHAR LinuxKernelName[260];
UCHAR LinuxInitrdName[260];
BOOL LinuxHasInitrd = FALSE;
@ -47,10 +54,14 @@ PVOID LinuxInitrdLoadAddress = NULL;
VOID LoadAndBootLinux(PUCHAR OperatingSystemName)
{
PFILE LinuxKernel = NULL;
PFILE LinuxInitrdFile = NULL;
UCHAR TempString[260];
UiDrawBackdrop();
UiDrawStatusText("Loading Linux...");
UiDrawProgressBarCenter(0, 100);
// Parse the .ini file section
if (!LinuxParseIniSection(OperatingSystemName))
{
@ -58,14 +69,14 @@ VOID LoadAndBootLinux(PUCHAR OperatingSystemName)
}
// Open the boot volume
if (!OpenDiskDrive(BootDrive, BootPartition))
if (!FsOpenVolume(BootDrive, BootPartition))
{
UiMessageBox("Failed to open boot drive.");
goto LinuxBootFailed;
}
// Open the kernel
LinuxKernel = OpenFile(LinuxKernelName);
LinuxKernel = FsOpenFile(LinuxKernelName);
if (LinuxKernel == NULL)
{
sprintf(TempString, "Linux kernel \'%s\' not found.", LinuxKernelName);
@ -73,6 +84,18 @@ VOID LoadAndBootLinux(PUCHAR OperatingSystemName)
goto LinuxBootFailed;
}
// Open the initrd file image (if necessary)
if (LinuxHasInitrd)
{
LinuxInitrdFile = FsOpenFile(LinuxInitrdName);
if (LinuxInitrdFile == NULL)
{
sprintf(TempString, "Linux initrd image \'%s\' not found.", LinuxInitrdName);
UiMessageBox(TempString);
goto LinuxBootFailed;
}
}
// Read the boot sector
if (!LinuxReadBootSector(LinuxKernel))
{
@ -85,6 +108,12 @@ VOID LoadAndBootLinux(PUCHAR OperatingSystemName)
goto LinuxBootFailed;
}
// Calc kernel size
LinuxKernelSize = FsGetFileSize(LinuxKernel) - (512 + SetupSectorSize);
// Get the file size
LinuxInitrdSize = FsGetFileSize(LinuxInitrdFile);
// Read the kernel
if (!LinuxReadKernel(LinuxKernel))
{
@ -94,7 +123,7 @@ VOID LoadAndBootLinux(PUCHAR OperatingSystemName)
// Read the initrd (if necessary)
if (LinuxHasInitrd)
{
if (!LinuxReadInitrd())
if (!LinuxReadInitrd(LinuxInitrdFile))
{
goto LinuxBootFailed;
}
@ -122,10 +151,9 @@ VOID LoadAndBootLinux(PUCHAR OperatingSystemName)
RtlCopyMemory((PVOID)0x90200, LinuxSetupSector, SetupSectorSize);
RtlCopyMemory((PVOID)0x99000, LinuxCommandLine, LinuxCommandLineSize);
VideoShowTextCursor();
VideoClearScreen();
UiUnInitialize("Booting Linux...");
StopFloppyMotor();
DiskStopFloppyMotor();
if (LinuxSetupSector->LoadFlags & LINUX_FLAG_LOAD_HIGH)
{
@ -141,7 +169,11 @@ LinuxBootFailed:
if (LinuxKernel != NULL)
{
CloseFile(LinuxKernel);
FsCloseFile(LinuxKernel);
}
if (LinuxInitrdFile != NULL)
{
FsCloseFile(LinuxInitrdFile);
}
if (LinuxBootSector != NULL)
@ -237,8 +269,8 @@ BOOL LinuxReadBootSector(PFILE LinuxKernelFile)
}
// Read linux boot sector
SetFilePointer(LinuxKernelFile, 0);
if (!ReadFile(LinuxKernelFile, 512, NULL, LinuxBootSector))
FsSetFilePointer(LinuxKernelFile, 0);
if (!FsReadFile(LinuxKernelFile, 512, NULL, LinuxBootSector))
{
return FALSE;
}
@ -271,8 +303,8 @@ BOOL LinuxReadSetupSector(PFILE LinuxKernelFile)
LinuxSetupSector = (PLINUX_SETUPSECTOR)TempLinuxSetupSector;
// Read first linux setup sector
SetFilePointer(LinuxKernelFile, 512);
if (!ReadFile(LinuxKernelFile, 512, NULL, TempLinuxSetupSector))
FsSetFilePointer(LinuxKernelFile, 512);
if (!FsReadFile(LinuxKernelFile, 512, NULL, TempLinuxSetupSector))
{
return FALSE;
}
@ -303,8 +335,8 @@ BOOL LinuxReadSetupSector(PFILE LinuxKernelFile)
RtlCopyMemory(LinuxSetupSector, TempLinuxSetupSector, 512);
// Read in the rest of the linux setup sectors
SetFilePointer(LinuxKernelFile, 1024);
if (!ReadFile(LinuxKernelFile, SetupSectorSize - 512, NULL, ((PVOID)LinuxSetupSector) + 512))
FsSetFilePointer(LinuxKernelFile, 1024);
if (!FsReadFile(LinuxKernelFile, SetupSectorSize - 512, NULL, ((PVOID)LinuxSetupSector) + 512))
{
return FALSE;
}
@ -338,10 +370,6 @@ BOOL LinuxReadKernel(PFILE LinuxKernelFile)
sprintf(StatusText, "Loading %s", LinuxKernelName);
UiDrawStatusText(StatusText);
UiDrawProgressBarCenter(0, 100);
// Calc kernel size
LinuxKernelSize = GetFileSize(LinuxKernelFile) - (512 + SetupSectorSize);
// Allocate memory for Linux kernel
LinuxKernelLoadAddress = MmAllocateMemoryAtAddress(LinuxKernelSize, (PVOID)LINUX_KERNEL_LOAD_ADDRESS);
@ -353,18 +381,18 @@ BOOL LinuxReadKernel(PFILE LinuxKernelFile)
LoadAddress = LinuxKernelLoadAddress;
// Read linux kernel to 0x100000 (1mb)
SetFilePointer(LinuxKernelFile, 512 + SetupSectorSize);
FsSetFilePointer(LinuxKernelFile, 512 + SetupSectorSize);
for (BytesLoaded=0; BytesLoaded<LinuxKernelSize; )
{
if (!ReadFile(LinuxKernelFile, 0x4000, NULL, LoadAddress))
if (!FsReadFile(LinuxKernelFile, LINUX_READ_CHUNK_SIZE, NULL, LoadAddress))
{
return FALSE;
}
BytesLoaded += 0x4000;
LoadAddress += 0x4000;
BytesLoaded += LINUX_READ_CHUNK_SIZE;
LoadAddress += LINUX_READ_CHUNK_SIZE;
UiDrawProgressBarCenter(BytesLoaded, LinuxKernelSize);
UiDrawProgressBarCenter(BytesLoaded, LinuxKernelSize + LinuxInitrdSize);
}
return TRUE;
@ -407,29 +435,13 @@ BOOL LinuxCheckKernelVersion(VOID)
return TRUE;
}
BOOL LinuxReadInitrd(VOID)
BOOL LinuxReadInitrd(PFILE LinuxInitrdFile)
{
PFILE LinuxInitrdFile;
UCHAR TempString[260];
U32 LinuxInitrdSize;
U32 BytesLoaded;
UCHAR StatusText[260];
sprintf(StatusText, "Loading %s", LinuxInitrdName);
UiDrawStatusText(StatusText);
UiDrawProgressBarCenter(0, 100);
// Open the initrd file image
LinuxInitrdFile = OpenFile(LinuxInitrdName);
if (LinuxInitrdFile == NULL)
{
sprintf(TempString, "Linux initrd image \'%s\' not found.", LinuxInitrdName);
UiMessageBox(TempString);
return FALSE;
}
// Get the file size
LinuxInitrdSize = GetFileSize(LinuxInitrdFile);
// Allocate memory for the ramdisk
LinuxInitrdLoadAddress = MmAllocateMemory(LinuxInitrdSize);
@ -445,15 +457,15 @@ BOOL LinuxReadInitrd(VOID)
// Read in the ramdisk
for (BytesLoaded=0; BytesLoaded<LinuxInitrdSize; )
{
if (!ReadFile(LinuxInitrdFile, 0x4000, NULL, (PVOID)LinuxInitrdLoadAddress))
if (!FsReadFile(LinuxInitrdFile, LINUX_READ_CHUNK_SIZE, NULL, (PVOID)LinuxInitrdLoadAddress))
{
return FALSE;
}
BytesLoaded += 0x4000;
LinuxInitrdLoadAddress += 0x4000;
BytesLoaded += LINUX_READ_CHUNK_SIZE;
LinuxInitrdLoadAddress += LINUX_READ_CHUNK_SIZE;
UiDrawProgressBarCenter(BytesLoaded, LinuxInitrdSize);
UiDrawProgressBarCenter(BytesLoaded + LinuxKernelSize, LinuxInitrdSize + LinuxKernelSize);
}
return TRUE;

View file

@ -26,7 +26,6 @@
#include <ui.h>
#include <inifile.h>
#include <disk.h>
#include <video.h>
VOID LoadAndBootBootSector(PUCHAR OperatingSystemName)
{
@ -68,13 +67,13 @@ VOID LoadAndBootBootSector(PUCHAR OperatingSystemName)
return;
}
if (!OpenDiskDrive(BootDrive, BootPartition))
if (!FsOpenVolume(BootDrive, BootPartition))
{
UiMessageBox("Failed to open boot drive.");
return;
}
FilePointer = OpenFile(FileName);
FilePointer = FsOpenFile(FileName);
if (FilePointer == NULL)
{
strcat(FileName, " not found.");
@ -83,7 +82,7 @@ VOID LoadAndBootBootSector(PUCHAR OperatingSystemName)
}
// Read boot sector
if (!ReadFile(FilePointer, 512, &BytesRead, (void*)0x7c00) || (BytesRead != 512))
if (!FsReadFile(FilePointer, 512, &BytesRead, (void*)0x7c00) || (BytesRead != 512))
{
return;
}
@ -95,8 +94,7 @@ VOID LoadAndBootBootSector(PUCHAR OperatingSystemName)
return;
}
VideoClearScreen();
VideoShowTextCursor();
UiUnInitialize("Booting...");
// Don't stop the floppy drive motor when we
// are just booting a bootsector, or drive, or partition.
// If we were to stop the floppy motor then
@ -104,7 +102,7 @@ VOID LoadAndBootBootSector(PUCHAR OperatingSystemName)
// next read is to a floppy then the BIOS will
// still think the motor is on and this will
// result in a read error.
//StopFloppyMotor();
//DiskStopFloppyMotor();
//DisableA20();
ChainLoadBiosBootSectorCode();
}
@ -165,8 +163,7 @@ VOID LoadAndBootPartition(PUCHAR OperatingSystemName)
return;
}
VideoClearScreen();
VideoShowTextCursor();
UiUnInitialize("Booting...");
// Don't stop the floppy drive motor when we
// are just booting a bootsector, or drive, or partition.
// If we were to stop the floppy motor then
@ -174,7 +171,7 @@ VOID LoadAndBootPartition(PUCHAR OperatingSystemName)
// next read is to a floppy then the BIOS will
// still think the motor is on and this will
// result in a read error.
//StopFloppyMotor();
//DiskStopFloppyMotor();
//DisableA20();
ChainLoadBiosBootSectorCode();
}
@ -218,8 +215,7 @@ VOID LoadAndBootDrive(PUCHAR OperatingSystemName)
return;
}
VideoClearScreen();
VideoShowTextCursor();
UiUnInitialize("Booting...");
// Don't stop the floppy drive motor when we
// are just booting a bootsector, or drive, or partition.
// If we were to stop the floppy motor then
@ -227,7 +223,7 @@ VOID LoadAndBootDrive(PUCHAR OperatingSystemName)
// next read is to a floppy then the BIOS will
// still think the motor is on and this will
// result in a read error.
//StopFloppyMotor();
//DiskStopFloppyMotor();
//DisableA20();
ChainLoadBiosBootSectorCode();
}

View file

@ -63,7 +63,7 @@ BOOL MmInitializeMemoryManager(VOID)
RtlZeroMemory(BiosMemoryMap, sizeof(BIOS_MEMORY_MAP) * 32);
BiosMemoryMapEntryCount = GetBiosMemoryMap((PBIOS_MEMORY_MAP_ARRAY)BiosMemoryMap);
BiosMemoryMapEntryCount = GetBiosMemoryMap(BiosMemoryMap);
ExtendedMemorySize = GetExtendedMemorySize();
ConventionalMemorySize = GetConventionalMemorySize();
@ -97,7 +97,7 @@ BOOL MmInitializeMemoryManager(VOID)
// to handle just a flat extended memory size I'm going
// to create a 'fake' memory map entry out of the
// extended memory size if GetBiosMemoryMap() fails.
if (BiosMemoryMapEntryCount == 0)
//if (BiosMemoryMapEntryCount == 0)
{
BiosMemoryMap[0].BaseAddress = 0x100000; // Start at 1MB
BiosMemoryMap[0].Length = ExtendedMemorySize * 1024;
@ -385,7 +385,7 @@ VOID MmFixupSystemMemoryMap(BIOS_MEMORY_MAP BiosMemoryMap[32], U32* MapCount)
// If the entry type isn't usable then remove
// it from the memory map (this will help reduce
// the size of our lookup table)
if (BiosMemoryMap[Index].Type != 0)
if (BiosMemoryMap[Index].Type != MEMTYPE_USABLE)
{
// Slide every entry after this down one
for (Index2=Index; Index2<(*MapCount - 1); Index2++)

View file

@ -51,7 +51,7 @@ BOOL MultiBootLoadKernel(FILE *KernelImage)
* Load the first 8192 bytes of the kernel image
* so we can search for the multiboot header
*/
if (!ReadFile(KernelImage, 8192, NULL, ImageHeaders))
if (!FsReadFile(KernelImage, 8192, NULL, ImageHeaders))
{
MmFreeMemory(ImageHeaders);
return FALSE;
@ -111,13 +111,13 @@ BOOL MultiBootLoadKernel(FILE *KernelImage)
* Get the file offset, this should be 0, and move the file pointer
*/
dwFileLoadOffset = (Idx * sizeof(U32)) - (mb_header.header_addr - mb_header.load_addr);
SetFilePointer(KernelImage, dwFileLoadOffset);
FsSetFilePointer(KernelImage, dwFileLoadOffset);
/*
* Load the file image
*/
dwDataSize = (mb_header.load_end_addr - mb_header.load_addr);
ReadFile(KernelImage, dwDataSize, NULL, (void*)mb_header.load_addr);
FsReadFile(KernelImage, dwDataSize, NULL, (void*)mb_header.load_addr);
/*
* Initialize bss area
@ -150,7 +150,7 @@ BOOL MultiBootLoadModule(FILE *ModuleImage, char *ModuleName)
ModuleNameString = multiboot_module_strings[mb_info.mods_count];
dwModuleSize = GetFileSize(ModuleImage);
dwModuleSize = FsGetFileSize(ModuleImage);
pModule->mod_start = next_module_load_base;
pModule->mod_end = next_module_load_base + dwModuleSize;
strcpy(ModuleNameString, ModuleName);
@ -159,7 +159,7 @@ BOOL MultiBootLoadModule(FILE *ModuleImage, char *ModuleName)
/*
* Load the file image
*/
ReadFile(ModuleImage, dwModuleSize, NULL, (void*)next_module_load_base);
FsReadFile(ModuleImage, dwModuleSize, NULL, (void*)next_module_load_base);
next_module_load_base = ROUND_UP(pModule->mod_end, /*PAGE_SIZE*/4096);
mb_info.mods_count++;
@ -187,7 +187,7 @@ PVOID MultiBootLoadModule(FILE *ModuleImage, char *ModuleName, U32* ModuleSize)
ModuleNameString = multiboot_module_strings[mb_info.mods_count];
dwModuleSize = GetFileSize(ModuleImage);
dwModuleSize = FsGetFileSize(ModuleImage);
pModule->mod_start = next_module_load_base;
pModule->mod_end = next_module_load_base + dwModuleSize;
strcpy(ModuleNameString, ModuleName);
@ -196,7 +196,7 @@ PVOID MultiBootLoadModule(FILE *ModuleImage, char *ModuleName, U32* ModuleSize)
/*
* Load the file image
*/
ReadFile(ModuleImage, dwModuleSize, NULL, (void*)next_module_load_base);
FsReadFile(ModuleImage, dwModuleSize, NULL, (void*)next_module_load_base);
next_module_load_base = ROUND_UP(pModule->mod_end, /*PAGE_SIZE*/4096);
mb_info.mods_count++;

View file

@ -23,6 +23,7 @@
#include <arch.h>
#include <reactos.h>
#include <rtl.h>
#include <disk.h>
#include <fs.h>
#include <ui.h>
#include <multiboot.h>
@ -49,7 +50,7 @@ LoadKernel(PCHAR szFileName, int nPos)
else
szShortName = szShortName + 1;
FilePointer = OpenFile(szFileName);
FilePointer = FsOpenFile(szFileName);
if (FilePointer == NULL)
{
strcpy(szBuffer, szShortName);
@ -108,7 +109,7 @@ LoadSymbolFile(PCHAR szSystemRoot,
strncat(SymbolFileName, Start, Length);
strcat(SymbolFileName, ".sym");
FilePointer = OpenFile((PCHAR)&SymbolFileName[0]);
FilePointer = FsOpenFile((PCHAR)&SymbolFileName[0]);
if (FilePointer == NULL)
{
DbgPrint((DPRINT_REACTOS, "Symbol file %s not loaded.\n", SymbolFileName));
@ -146,7 +147,7 @@ LoadDriver(PCHAR szFileName, int nPos)
char value[256];
char *p;
FilePointer = OpenFile(szFileName);
FilePointer = FsOpenFile(szFileName);
if (FilePointer == NULL)
{
strcpy(value, szFileName);
@ -185,7 +186,7 @@ LoadNlsFile(PCHAR szFileName, PCHAR szModuleName)
char value[256];
char *p;
FilePointer = OpenFile(szFileName);
FilePointer = FsOpenFile(szFileName);
if (FilePointer == NULL)
{
strcpy(value, szFileName);
@ -463,7 +464,7 @@ LoadAndBootReactOS(PUCHAR OperatingSystemName)
mb_info.cmdline = (unsigned long)multiboot_kernel_cmdline;
mb_info.mods_count = 0;
mb_info.mods_addr = (unsigned long)multiboot_modules;
mb_info.mmap_length = (unsigned long)GetBiosMemoryMap((PBIOS_MEMORY_MAP_ARRAY)&multiboot_memory_map) * sizeof(memory_map_t);
mb_info.mmap_length = (unsigned long)GetBiosMemoryMap((PBIOS_MEMORY_MAP)&multiboot_memory_map) * sizeof(memory_map_t);
if (mb_info.mmap_length)
{
mb_info.mmap_addr = (unsigned long)&multiboot_memory_map;
@ -531,7 +532,7 @@ LoadAndBootReactOS(PUCHAR OperatingSystemName)
/*
* Try to open boot drive
*/
if (!OpenDiskDrive(BootDrive, BootPartition))
if (!FsOpenVolume(BootDrive, BootPartition))
{
UiMessageBox("Failed to open boot drive.");
return;
@ -629,7 +630,7 @@ LoadAndBootReactOS(PUCHAR OperatingSystemName)
DbgPrint((DPRINT_REACTOS, "SystemHive: '%s'", szFileName));
FilePointer = OpenFile(szFileName);
FilePointer = FsOpenFile(szFileName);
if (FilePointer == NULL)
{
strcat(value, " not found.");
@ -708,10 +709,13 @@ LoadAndBootReactOS(PUCHAR OperatingSystemName)
strcat(name, ".");
//MessageBox(name);
UiUnInitialize("Booting ReactOS...");
/*
* Now boot the kernel
*/
StopFloppyMotor();
DiskStopFloppyMotor();
boot_reactos();
}

View file

@ -225,7 +225,7 @@ getKeyValueTypeFromChunk (PCHAR regChunk, PCHAR dataFormat, int *keyValueType)
}
else
{
UNIMPLEMENTED;
UNIMPLEMENTED();
}
return *regChunk ? regChunk : 0;
@ -311,7 +311,7 @@ computeKeyValueDataSize (PCHAR regChunk, PCHAR dataFormat)
}
else
{
UNIMPLEMENTED;
UNIMPLEMENTED();
}
return dataSize;
@ -425,7 +425,7 @@ getKeyValueDataFromChunk (PCHAR regChunk, PCHAR dataFormat, PCHAR data)
}
else
{
UNIMPLEMENTED;
UNIMPLEMENTED();
}
return *regChunk ? regChunk : 0;

View file

@ -21,6 +21,7 @@
#include <freeldr.h>
#include <debug.h>
#include <arch.h>
#include <disk.h>
#include <reactos.h>
#include <rtl.h>
#include <fs.h>
@ -44,7 +45,7 @@ LoadKernel(PCHAR szFileName)
else
szShortName = szShortName + 1;
FilePointer = OpenFile(szFileName);
FilePointer = FsOpenFile(szFileName);
if (FilePointer == NULL)
{
printf("Could not find %s\n", szShortName);
@ -78,7 +79,7 @@ LoadDriver(PCHAR szFileName)
szShortName = szShortName + 1;
FilePointer = OpenFile(szFileName);
FilePointer = FsOpenFile(szFileName);
if (FilePointer == NULL)
{
printf("Could not find %s\n", szFileName);
@ -108,7 +109,7 @@ VOID RunLoader(VOID)
mb_info.cmdline = (unsigned long)multiboot_kernel_cmdline;
mb_info.mods_count = 0;
mb_info.mods_addr = (unsigned long)multiboot_modules;
mb_info.mmap_length = (unsigned long)GetBiosMemoryMap((PBIOS_MEMORY_MAP_ARRAY)&multiboot_memory_map);
mb_info.mmap_length = (unsigned long)GetBiosMemoryMap((PBIOS_MEMORY_MAP)&multiboot_memory_map);
if (mb_info.mmap_length)
{
mb_info.mmap_addr = (unsigned long)&multiboot_memory_map;
@ -146,7 +147,7 @@ VOID RunLoader(VOID)
(unsigned int)BootDrive);
/* Open boot drive */
if (!OpenDiskDrive(BootDrive, BootPartition))
if (!FsOpenVolume(BootDrive, BootPartition))
{
printf("Failed to open boot drive.");
return;
@ -247,7 +248,7 @@ VOID RunLoader(VOID)
/*
* Now boot the kernel
*/
StopFloppyMotor();
DiskStopFloppyMotor();
boot_reactos();

View file

@ -19,13 +19,13 @@
#include <freeldr.h>
int RtlCompareMemory(const PVOID Source1, const PVOID Source2, U32 Length)
int memcmp(const void *buf1, const void *buf2, size_t count)
{
U32 i;
const PCHAR buffer1 = Source1;
const PCHAR buffer2 = Source2;
unsigned int i;
const char* buffer1 = buf1;
const char* buffer2 = buf2;
for (i=0; i<Length; i++)
for (i=0; i<count; i++)
{
if(buffer1[i] == buffer2[i])
continue;
@ -35,33 +35,3 @@ int RtlCompareMemory(const PVOID Source1, const PVOID Source2, U32 Length)
return 0;
}
VOID RtlCopyMemory(PVOID Destination, const PVOID Source, U32 Length)
{
U32 i;
PCHAR buf1 = Destination;
const PCHAR buf2 = Source;
for (i=0; i<Length; i++)
{
buf1[i] = buf2[i];
}
}
VOID RtlFillMemory(PVOID Destination, U32 Length, UCHAR Fill)
{
U32 i;
PUCHAR buf1 = Destination;
for (i=0; i<Length; i++)
{
buf1[i] = Fill;
}
}
VOID RtlZeroMemory(PVOID Destination, U32 Length)
{
RtlFillMemory(Destination, Length, 0);
}

View file

@ -0,0 +1,50 @@
/*
* FreeLoader
* Copyright (C) 1998-2002 Brian Palmer <brianp@sginet.com>
*
* 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
* (at your option) 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.
*/
#include <freeldr.h>
#ifdef __i386__
void *memcpy(void *to, const void *from, size_t count)
{
__asm__( \
"or %%ecx,%%ecx\n\t"\
"jz .L1\n\t" \
"cld\n\t" \
"rep\n\t" \
"movsb\n\t" \
".L1:\n\t"
:
: "D" (to), "S" (from), "c" (count));
return to;
}
#else
void *memcpy(void *to, const void *from, size_t count)
{
unsigned int i;
char* buf1 = to;
const char* buf2 = from;
for (i=0; i<count; i++)
{
buf1[i] = buf2[i];
}
return to;
}
#endif

View file

@ -0,0 +1,49 @@
/*
* FreeLoader
* Copyright (C) 1998-2002 Brian Palmer <brianp@sginet.com>
*
* 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
* (at your option) 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.
*/
#include <freeldr.h>
#ifdef __i386__
void *memset(void *src, int val, size_t count)
{
__asm__( \
"or %%ecx,%%ecx\n\t"\
"jz .L1\n\t" \
"cld\t\n" \
"rep\t\n" \
"stosb\t\n" \
".L1:\n\t"
:
: "D" (src), "c" (count), "a" (val));
return src;
}
#else
void *memset(void *src, int val, size_t count)
{
unsigned int i;
unsigned char* buf1 = src;
for (i=0; i<count; i++)
{
buf1[i] = val;
}
return src;
}
#endif

View file

@ -26,6 +26,42 @@
#include <debug.h>
#include <inifile.h>
#include <version.h>
#include <video.h>
PVOID TextVideoBuffer = NULL;
BOOL TuiInitialize(VOID)
{
VideoClearScreen();
VideoHideTextCursor();
BiosVideoDisableBlinkBit();
TextVideoBuffer = VideoAllocateOffScreenBuffer();
if (TextVideoBuffer == NULL)
{
return FALSE;
}
return TRUE;
}
VOID TuiUnInitialize(VOID)
{
if (UiUseSpecialEffects)
{
TuiFadeOut();
}
else
{
VideoSetMode(VIDEOMODE_NORMAL_TEXT);
}
//VideoClearScreen();
VideoSetMode(VIDEOMODE_NORMAL_TEXT);
VideoShowTextCursor();
BiosVideoEnableBlinkBit();
}
VOID TuiDrawBackdrop(VOID)
{
@ -88,12 +124,14 @@ VOID TuiDrawBackdrop(VOID)
//
// Draw status bar
//
TuiDrawStatusText("");
TuiDrawStatusText("Welcome to FreeLoader!");
//
// Update the date & time
//
TuiUpdateDateTime();
VideoCopyOffScreenBufferToVRAM();
}
/*
@ -102,7 +140,7 @@ VOID TuiDrawBackdrop(VOID)
*/
VOID TuiFillArea(U32 Left, U32 Top, U32 Right, U32 Bottom, UCHAR FillChar, UCHAR Attr /* Color Attributes */)
{
PUCHAR ScreenMemory = (PUCHAR)TUI_SCREEN_MEM;
PUCHAR ScreenMemory = (PUCHAR)TextVideoBuffer;
U32 i, j;
// Clip the area to the screen
@ -138,7 +176,7 @@ VOID TuiFillArea(U32 Left, U32 Top, U32 Right, U32 Bottom, UCHAR FillChar, UCHAR
*/
VOID TuiDrawShadow(U32 Left, U32 Top, U32 Right, U32 Bottom)
{
PUCHAR ScreenMemory = (PUCHAR)TUI_SCREEN_MEM;
PUCHAR ScreenMemory = (PUCHAR)TextVideoBuffer;
U32 Idx;
// Shade the bottom of the area
@ -270,7 +308,7 @@ VOID TuiDrawBox(U32 Left, U32 Top, U32 Right, U32 Bottom, UCHAR VertStyle, UCHAR
*/
VOID TuiDrawText(U32 X, U32 Y, PUCHAR Text, UCHAR Attr)
{
PUCHAR ScreenMemory = (PUCHAR)TUI_SCREEN_MEM;
PUCHAR ScreenMemory = (PUCHAR)TextVideoBuffer;
U32 i, j;
// Draw the text
@ -283,6 +321,63 @@ VOID TuiDrawText(U32 X, U32 Y, PUCHAR Text, UCHAR Attr)
VOID TuiDrawCenteredText(U32 Left, U32 Top, U32 Right, U32 Bottom, PUCHAR TextString, UCHAR Attr)
{
U32 TextLength;
U32 BoxWidth;
U32 BoxHeight;
U32 LineBreakCount;
U32 Index;
U32 LastIndex;
U32 RealLeft;
U32 RealTop;
U32 X;
U32 Y;
UCHAR Temp[2];
TextLength = strlen(TextString);
// Count the new lines and the box width
LineBreakCount = 0;
BoxWidth = 0;
LastIndex = 0;
for (Index=0; Index<TextLength; Index++)
{
if (TextString[Index] == '\n')
{
LastIndex = Index;
LineBreakCount++;
}
else
{
if ((Index - LastIndex) > BoxWidth)
{
BoxWidth = (Index - LastIndex);
}
}
}
BoxHeight = LineBreakCount + 1;
RealLeft = (((Right - Left) - BoxWidth) / 2) + Left;
RealTop = (((Bottom - Top) - BoxHeight) / 2) + Top;
LastIndex = 0;
for (Index=0; Index<TextLength; Index++)
{
if (TextString[Index] == '\n')
{
RealTop++;
LastIndex = 0;
}
else
{
X = RealLeft + LastIndex;
Y = RealTop;
LastIndex++;
Temp[0] = TextString[Index];
Temp[1] = 0;
TuiDrawText(X, Y, Temp, Attr);
}
}
}
VOID TuiDrawStatusText(PUCHAR StatusText)
@ -296,6 +391,8 @@ VOID TuiDrawStatusText(PUCHAR StatusText)
{
TuiDrawText(i, UiScreenHeight-1, " ", ATTR(UiStatusBarFgColor, UiStatusBarBgColor));
}
VideoCopyOffScreenBufferToVRAM();
}
VOID TuiUpdateDateTime(VOID)
@ -380,11 +477,13 @@ VOID TuiUpdateDateTime(VOID)
// Draw the time
TuiDrawText(UiScreenWidth-strlen(TimeString)-2, 2, TimeString, ATTR(UiTitleBoxFgColor, UiTitleBoxBgColor));
VideoCopyOffScreenBufferToVRAM();
}
VOID TuiSaveScreen(PUCHAR Buffer)
{
PUCHAR ScreenMemory = (PUCHAR)TUI_SCREEN_MEM;
PUCHAR ScreenMemory = (PUCHAR)TextVideoBuffer;
U32 i;
for (i=0; i < (UiScreenWidth * UiScreenHeight * 2); i++)
@ -395,7 +494,7 @@ VOID TuiSaveScreen(PUCHAR Buffer)
VOID TuiRestoreScreen(PUCHAR Buffer)
{
PUCHAR ScreenMemory = (PUCHAR)TUI_SCREEN_MEM;
PUCHAR ScreenMemory = (PUCHAR)TextVideoBuffer;
U32 i;
for (i=0; i < (UiScreenWidth * UiScreenHeight * 2); i++)
@ -483,6 +582,8 @@ VOID TuiMessageBoxCritical(PUCHAR MessageText)
// Draw status text
UiDrawStatusText("Press ENTER to continue");
VideoCopyOffScreenBufferToVRAM();
for (;;)
{
if (kbhit())
@ -500,6 +601,8 @@ VOID TuiMessageBoxCritical(PUCHAR MessageText)
}
TuiUpdateDateTime();
VideoCopyOffScreenBufferToVRAM();
}
}
@ -549,6 +652,8 @@ VOID TuiDrawProgressBar(U32 Left, U32 Top, U32 Right, U32 Bottom, U32 Position,
}
TuiUpdateDateTime();
VideoCopyOffScreenBufferToVRAM();
}
UCHAR TuiTextToColor(PUCHAR ColorText)
@ -606,3 +711,57 @@ UCHAR TuiTextToFillStyle(PUCHAR FillStyleText)
return LIGHT_FILL;
}
VOID TuiFadeInBackdrop(VOID)
{
PPALETTE_ENTRY TuiFadePalette = NULL;
if (UiUseSpecialEffects)
{
TuiFadePalette = (PPALETTE_ENTRY)MmAllocateMemory(sizeof(PALETTE_ENTRY) * 64);
if (TuiFadePalette != NULL)
{
VideoSavePaletteState(TuiFadePalette, 64);
VideoSetAllColorsToBlack(64);
}
}
// Draw the backdrop and title box
TuiDrawBackdrop();
if (UiUseSpecialEffects && TuiFadePalette != NULL)
{
VideoFadeIn(TuiFadePalette, 64);
MmFreeMemory(TuiFadePalette);
}
}
VOID TuiFadeOut(VOID)
{
PPALETTE_ENTRY TuiFadePalette = NULL;
if (UiUseSpecialEffects)
{
TuiFadePalette = (PPALETTE_ENTRY)MmAllocateMemory(sizeof(PALETTE_ENTRY) * 64);
if (TuiFadePalette != NULL)
{
VideoSavePaletteState(TuiFadePalette, 64);
}
}
if (UiUseSpecialEffects && TuiFadePalette != NULL)
{
VideoFadeOut(64);
}
VideoSetMode(VIDEOMODE_NORMAL_TEXT);
if (UiUseSpecialEffects && TuiFadePalette != NULL)
{
VideoRestorePaletteState(TuiFadePalette, 64);
MmFreeMemory(TuiFadePalette);
}
}

View file

@ -28,6 +28,9 @@
// Textual User Interface Functions
//
///////////////////////////////////////////////////////////////////////////////////////
BOOL TuiInitialize(VOID); // Initialize User-Interface
VOID TuiUnInitialize(VOID); // Un-initialize User-Interface
VOID TuiDrawBackdrop(VOID); // Fills the entire screen with a backdrop
VOID TuiFillArea(U32 Left, U32 Top, U32 Right, U32 Bottom, UCHAR FillChar, UCHAR Attr /* Color Attributes */); // Fills the area specified with FillChar and Attr
VOID TuiDrawShadow(U32 Left, U32 Top, U32 Right, U32 Bottom); // Draws a shadow on the bottom and right sides of the area specified
@ -46,6 +49,9 @@ VOID TuiDrawProgressBar(U32 Left, U32 Top, U32 Right, U32 Bottom, U32 Position,
UCHAR TuiTextToColor(PUCHAR ColorText); // Converts the text color into it's equivalent color value
UCHAR TuiTextToFillStyle(PUCHAR FillStyleText); // Converts the text fill into it's equivalent fill value
VOID TuiFadeInBackdrop(VOID); // Draws the backdrop and fades the screen in
VOID TuiFadeOut(VOID); // Fades the screen out
///////////////////////////////////////////////////////////////////////////////////////
//
// Menu Functions

View file

@ -24,6 +24,7 @@
#include "keycodes.h"
#include <options.h>
#include <mm.h>
#include <video.h>
BOOL TuiDisplayMenu(PUCHAR MenuItemList[], U32 MenuItemCount, U32 DefaultMenuItem, S32 MenuTimeOut, U32* SelectedMenuItem)
@ -88,7 +89,9 @@ BOOL TuiDisplayMenu(PUCHAR MenuItemList[], U32 MenuItemCount, U32 DefaultMenuIte
//
// Update the date & time
//
UiUpdateDateTime();
TuiUpdateDateTime();
VideoCopyOffScreenBufferToVRAM();
if (MenuInformation.MenuTimeRemaining > 0)
{
@ -104,6 +107,8 @@ BOOL TuiDisplayMenu(PUCHAR MenuItemList[], U32 MenuItemCount, U32 DefaultMenuIte
// Update the menu
//
TuiDrawMenuBox(&MenuInformation);
VideoCopyOffScreenBufferToVRAM();
}
}
else if (MenuInformation.MenuTimeRemaining == 0)
@ -183,6 +188,8 @@ VOID TuiDrawMenu(PTUI_MENU_INFO MenuInfo)
{
TuiDrawMenuItem(MenuInfo, Idx);
}
VideoCopyOffScreenBufferToVRAM();
}
VOID TuiDrawMenuBox(PTUI_MENU_INFO MenuInfo)
@ -347,6 +354,8 @@ U32 TuiProcessMenuKeyboardEvent(PTUI_MENU_INFO MenuInfo)
break;
}
VideoCopyOffScreenBufferToVRAM();
}
return KeyEvent;

View file

@ -57,6 +57,8 @@ BOOL UserInterfaceUp = FALSE; // Tells us if the user interface is display
BOOL UiDisplayMode = DISPLAYMODE_TEXT; // Tells us if we are in text or graphics mode
BOOL UiUseSpecialEffects = FALSE; // Tells us if we should use fade effects
UCHAR UiMonthNames[12][15] = { "January ", "February ", "March ", "April ", "May ", "June ", "July ", "August ", "September ", "October ", "November ", "December " };
@ -86,38 +88,49 @@ BOOL UiInitialize(VOID)
if (BiosDetectVideoCard() == VIDEOCARD_CGA_OR_OTHER)
{
DbgPrint((DPRINT_UI, "CGA or other display adapter detected.\n"));
printf("CGA or other display adapter detected.\n");
printf("Using 80x25 text mode.\n");
VideoMode = VIDEOMODE_NORMAL_TEXT;
}
else if (BiosDetectVideoCard() == VIDEOCARD_EGA)
{
DbgPrint((DPRINT_UI, "EGA display adapter detected.\n"));
}
else if (BiosDetectVideoCard() == VIDEOCARD_VGA)
{
DbgPrint((DPRINT_UI, "VGA display adapter detected.\n"));
}
if (stricmp(SettingText, "NORMAL_VGA") == 0)
{
printf("EGA display adapter detected.\n");
printf("Using 80x25 text mode.\n");
VideoMode = VIDEOMODE_NORMAL_TEXT;
}
else if (stricmp(SettingText, "EXTENDED_VGA") == 0)
else //if (BiosDetectVideoCard() == VIDEOCARD_VGA)
{
VideoMode = VIDEOMODE_EXTENDED_TEXT;
}
else
{
VideoMode = atoi(SettingText);
DbgPrint((DPRINT_UI, "VGA display adapter detected.\n"));
if (stricmp(SettingText, "NORMAL_VGA") == 0)
{
VideoMode = VIDEOMODE_NORMAL_TEXT;
}
else if (stricmp(SettingText, "EXTENDED_VGA") == 0)
{
VideoMode = VIDEOMODE_EXTENDED_TEXT;
}
else
{
VideoMode = atoi(SettingText);
}
}
if (!VideoSetMode(VideoMode))
{
printf("Error: unable to set video display mode 0x%lx\n", VideoMode);
printf("Error: unable to set video display mode 0x%x\n", VideoMode);
printf("Defaulting to 80x25 text mode.\n");
printf("Press any key to continue.\n");
getch();
VideoMode = VIDEOMODE_NORMAL_TEXT;
VideoSetMode(VIDEOMODE_NORMAL_TEXT);
}
UiScreenWidth = VideoGetCurrentModeResolutionX();
UiScreenHeight = VideoGetCurrentModeResolutionY();
UiDisplayMode = VideoGetCurrentModeType();
}
if (IniReadSettingByName(SectionId, "TitleText", SettingText, 260))
{
@ -179,14 +192,39 @@ BOOL UiInitialize(VOID)
{
UiSelectedTextBgColor = UiTextToColor(SettingText);
}
if (IniReadSettingByName(SectionId, "SpecialEffects", SettingText, 260))
{
if (stricmp(SettingText, "Yes") == 0 && strlen(SettingText) == 3)
{
UiUseSpecialEffects = TRUE;
}
else
{
UiUseSpecialEffects = FALSE;
}
}
}
VideoClearScreen();
VideoHideTextCursor();
BiosVideoDisableBlinkBit();
if (UiDisplayMode == DISPLAYMODE_TEXT)
{
if (!TuiInitialize())
{
VideoSetMode(VIDEOMODE_NORMAL_TEXT);
return FALSE;
}
}
else
{
UNIMPLEMENTED();
//if (!GuiInitialize())
//{
// VideoSetMode(VIDEOMODE_NORMAL_TEXT);
// return FALSE;
//}
}
// Draw the backdrop and title box
UiDrawBackdrop();
// Draw the backdrop and fade it in if special effects are enabled
UiFadeInBackdrop();
UserInterfaceUp = TRUE;
@ -195,6 +233,23 @@ BOOL UiInitialize(VOID)
return TRUE;
}
VOID UiUnInitialize(PUCHAR BootText)
{
UiDrawBackdrop();
UiDrawStatusText("Booting...");
UiInfoBox(BootText);
if (UiDisplayMode == DISPLAYMODE_TEXT)
{
TuiUnInitialize();
}
else
{
UNIMPLEMENTED();
//GuiUnInitialize();
}
}
VOID UiDrawBackdrop(VOID)
{
if (UiDisplayMode == DISPLAYMODE_TEXT)
@ -203,7 +258,7 @@ VOID UiDrawBackdrop(VOID)
}
else
{
UNIMPLEMENTED
UNIMPLEMENTED();
//GuiDrawBackdrop();
}
}
@ -216,7 +271,7 @@ VOID UiFillArea(U32 Left, U32 Top, U32 Right, U32 Bottom, UCHAR FillChar, UCHAR
}
else
{
UNIMPLEMENTED
UNIMPLEMENTED();
//GuiFillArea(Left, Top, Right, Bottom, FillChar, Attr);
}
}
@ -229,7 +284,7 @@ VOID UiDrawShadow(U32 Left, U32 Top, U32 Right, U32 Bottom)
}
else
{
UNIMPLEMENTED
UNIMPLEMENTED();
//GuiDrawShadow(Left, Top, Right, Bottom);
}
}
@ -242,7 +297,7 @@ VOID UiDrawBox(U32 Left, U32 Top, U32 Right, U32 Bottom, UCHAR VertStyle, UCHAR
}
else
{
UNIMPLEMENTED
UNIMPLEMENTED();
//GuiDrawBox(Left, Top, Right, Bottom, VertStyle, HorzStyle, Fill, Shadow, Attr);
}
}
@ -255,7 +310,7 @@ VOID UiDrawText(U32 X, U32 Y, PUCHAR Text, UCHAR Attr)
}
else
{
UNIMPLEMENTED
UNIMPLEMENTED();
//GuiDrawText(X, Y, Text, Attr);
}
}
@ -268,7 +323,7 @@ VOID UiDrawCenteredText(U32 Left, U32 Top, U32 Right, U32 Bottom, PUCHAR TextStr
}
else
{
UNIMPLEMENTED
UNIMPLEMENTED();
//GuiDrawCenteredText(Left, Top, Right, Bottom, TextString, Attr);
}
}
@ -281,7 +336,7 @@ VOID UiDrawStatusText(PUCHAR StatusText)
}
else
{
UNIMPLEMENTED
UNIMPLEMENTED();
//GuiDrawStatusText(StatusText);
}
}
@ -294,11 +349,72 @@ VOID UiUpdateDateTime(VOID)
}
else
{
UNIMPLEMENTED
//TuiUpdateDateTime();
UNIMPLEMENTED();
//GuiUpdateDateTime();
}
}
VOID UiInfoBox(PUCHAR MessageText)
{
U32 TextLength;
U32 BoxWidth;
U32 BoxHeight;
U32 LineBreakCount;
U32 Index;
U32 LastIndex;
U32 Left;
U32 Top;
U32 Right;
U32 Bottom;
TextLength = strlen(MessageText);
// Count the new lines and the box width
LineBreakCount = 0;
BoxWidth = 0;
LastIndex = 0;
for (Index=0; Index<TextLength; Index++)
{
if (MessageText[Index] == '\n')
{
LastIndex = Index;
LineBreakCount++;
}
else
{
if ((Index - LastIndex) > BoxWidth)
{
BoxWidth = (Index - LastIndex);
}
}
}
// Calc the box width & height
BoxWidth += 6;
BoxHeight = LineBreakCount + 4;
// Calc the box coordinates
Left = (UiScreenWidth / 2) - (BoxWidth / 2);
Top =(UiScreenHeight / 2) - (BoxHeight / 2);
Right = (UiScreenWidth / 2) + (BoxWidth / 2);
Bottom = (UiScreenHeight / 2) + (BoxHeight / 2);
// Draw the box
UiDrawBox(Left,
Top,
Right,
Bottom,
VERT,
HORZ,
TRUE,
TRUE,
ATTR(UiMenuFgColor, UiMenuBgColor)
);
// Draw the text
UiDrawCenteredText(Left, Top, Right, Bottom, MessageText, ATTR(UiTextColor, UiMenuBgColor));
}
VOID UiMessageBox(PUCHAR MessageText)
{
// We have not yet displayed the user interface
@ -321,7 +437,7 @@ VOID UiMessageBox(PUCHAR MessageText)
}
else
{
UNIMPLEMENTED
UNIMPLEMENTED();
//GuiMessageBox(UiMessageBoxLineText);
}
@ -348,7 +464,7 @@ VOID UiMessageBoxCritical(PUCHAR MessageText)
}
else
{
UNIMPLEMENTED
UNIMPLEMENTED();
//GuiMessageBoxCritical(MessageText);
}
}
@ -367,8 +483,8 @@ UCHAR UiTextToColor(PUCHAR ColorText)
}
else
{
UNIMPLEMENTED
return 0;
UNIMPLEMENTED();
return 0;
//return GuiTextToColor(ColorText);
}
}
@ -381,8 +497,8 @@ UCHAR UiTextToFillStyle(PUCHAR FillStyleText)
}
else
{
UNIMPLEMENTED
return 0;
UNIMPLEMENTED();
return 0;
//return GuiTextToFillStyle(FillStyleText);
}
}
@ -395,7 +511,7 @@ VOID UiDrawProgressBarCenter(U32 Position, U32 Range)
}
else
{
UNIMPLEMENTED
UNIMPLEMENTED();
//GuiDrawProgressBarCenter(Position, Range);
}
}
@ -408,7 +524,7 @@ VOID UiDrawProgressBar(U32 Left, U32 Top, U32 Right, U32 Bottom, U32 Position, U
}
else
{
UNIMPLEMENTED
UNIMPLEMENTED();
//GuiDrawProgressBar(Left, Top, Right, Bottom, Position, Range);
}
}
@ -457,7 +573,10 @@ VOID UiShowMessageBoxesInSection(PUCHAR SectionName)
VOID UiTruncateStringEllipsis(PUCHAR StringText, U32 MaxChars)
{
UNIMPLEMENTED
if (strlen(StringText) > MaxChars)
{
strcpy(&StringText[MaxChars - 3], "...");
}
}
BOOL UiDisplayMenu(PUCHAR MenuItemList[], U32 MenuItemCount, U32 DefaultMenuItem, S32 MenuTimeOut, U32* SelectedMenuItem)
@ -468,8 +587,34 @@ BOOL UiDisplayMenu(PUCHAR MenuItemList[], U32 MenuItemCount, U32 DefaultMenuItem
}
else
{
UNIMPLEMENTED
return FALSE;
UNIMPLEMENTED();
return FALSE;
//return GuiDisplayMenu(MenuItemList, MenuItemCount, DefaultMenuItem, MenuTimeOut, SelectedMenuItem);
}
}
VOID UiFadeInBackdrop(VOID)
{
if (UiDisplayMode == DISPLAYMODE_TEXT)
{
TuiFadeInBackdrop();
}
else
{
UNIMPLEMENTED();
//GuiFadeInBackdrop();
}
}
VOID UiFadeOut(VOID)
{
if (UiDisplayMode == DISPLAYMODE_TEXT)
{
TuiFadeOut();
}
else
{
UNIMPLEMENTED();
//GuiFadeInOut();
}
}

View file

@ -0,0 +1,152 @@
/*
* FreeLoader
* Copyright (C) 1998-2002 Brian Palmer <brianp@sginet.com>
*
* 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
* (at your option) 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.
*/
#include <freeldr.h>
#include <video.h>
#include <comm.h>
#include <rtl.h>
#include <debug.h>
U32 CurrentMemoryBank = 0;
VOID VideoSetMemoryBank(U16 BankNumber)
{
if (CurrentMemoryBank != BankNumber)
{
BiosVesaSetBank(BankNumber);
CurrentMemoryBank = BankNumber;
}
}
U32 VideoGetMemoryBankForPixel(U32 X, U32 Y)
{
U32 Bank;
U32 MemoryPos;
U32 BankSize;
U32 BytesPerPixel;
//BytesPerPixel = ROUND_UP(VesaVideoModeInformation.BitsPerPixel, 8) / 8;
BytesPerPixel = (VesaVideoModeInformation.BitsPerPixel + 7) >> 3;
MemoryPos = (Y * VideoGetBytesPerScanLine()) + (X * BytesPerPixel);
//BankSize = VesaVideoModeInformation.WindowGranularity * 1024;
BankSize = VesaVideoModeInformation.WindowGranularity << 10;
Bank = MemoryPos / BankSize;
return Bank;
}
U32 VideoGetMemoryBankForPixel16(U32 X, U32 Y)
{
U32 Bank;
U32 MemoryPos;
U32 BankSize;
MemoryPos = (Y * VideoGetBytesPerScanLine()) + (X / 2);
//BankSize = VesaVideoModeInformation.WindowGranularity * 1024;
BankSize = VesaVideoModeInformation.WindowGranularity << 10;
Bank = MemoryPos / BankSize;
return Bank;
}
U32 VideoGetBankOffsetForPixel(U32 X, U32 Y)
{
U32 BankOffset;
U32 MemoryPos;
U32 BankSize;
U32 BytesPerPixel;
//BytesPerPixel = ROUND_UP(VesaVideoModeInformation.BitsPerPixel, 8) / 8;
BytesPerPixel = (VesaVideoModeInformation.BitsPerPixel + 7) >> 3;
MemoryPos = (Y * VideoGetBytesPerScanLine()) + (X * BytesPerPixel);
//BankSize = VesaVideoModeInformation.WindowGranularity * 1024;
BankSize = VesaVideoModeInformation.WindowGranularity << 10;
BankOffset = MemoryPos % BankSize;
return BankOffset;
}
U32 VideoGetBankOffsetForPixel16(U32 X, U32 Y)
{
U32 BankOffset;
U32 MemoryPos;
U32 BankSize;
MemoryPos = (Y * VideoGetBytesPerScanLine()) + (X / 2);
//BankSize = VesaVideoModeInformation.WindowGranularity * 1024;
BankSize = VesaVideoModeInformation.WindowGranularity << 10;
BankOffset = MemoryPos % BankSize;
return BankOffset;
}
U32 VideoGetOffScreenMemoryOffsetForPixel(U32 X, U32 Y)
{
U32 MemoryPos;
U32 BytesPerPixel;
//BytesPerPixel = ROUND_UP(VesaVideoModeInformation.BitsPerPixel, 8) / 8;
BytesPerPixel = (VesaVideoModeInformation.BitsPerPixel + 7) >> 3;
MemoryPos = (Y * VesaVideoModeInformation.BytesPerScanLine) + (X * BytesPerPixel);
return MemoryPos;
}
VOID VideoCopyOffScreenBufferToVRAM(VOID)
{
U32 BanksToCopy;
U32 BytesInLastBank;
U32 CurrentBank;
U32 BankSize;
U32 BufferSize;
//VideoWaitForVerticalRetrace();
// Text mode (BIOS or VESA)
if (VideoGetCurrentModeType() == MODETYPE_TEXT)
{
BufferSize = VideoGetCurrentModeResolutionX() * VideoGetBytesPerScanLine();
RtlCopyMemory((PVOID)VIDEOTEXT_MEM_ADDRESS, VideoOffScreenBuffer, BufferSize);
}
// VESA graphics mode
else if (VideoGetCurrentModeType() == MODETYPE_GRAPHICS && VideoIsCurrentModeVesa())
{
BankSize = VesaVideoModeInformation.WindowGranularity << 10;
BanksToCopy = (VesaVideoModeInformation.HeightInPixels * VesaVideoModeInformation.BytesPerScanLine) / BankSize;
BytesInLastBank = (VesaVideoModeInformation.HeightInPixels * VesaVideoModeInformation.BytesPerScanLine) % BankSize;
// Copy all the banks but the last one because
// it is probably a partial bank
for (CurrentBank=0; CurrentBank<BanksToCopy; CurrentBank++)
{
VideoSetMemoryBank(CurrentBank);
RtlCopyMemory((PVOID)VIDEOVGA_MEM_ADDRESS, VideoOffScreenBuffer, BankSize);
}
// Copy the remaining bytes into the last bank
VideoSetMemoryBank(CurrentBank);
RtlCopyMemory((PVOID)VIDEOVGA_MEM_ADDRESS, VideoOffScreenBuffer, BytesInLastBank);
}
// BIOS graphics mode
else
{
UNIMPLEMENTED();
}
}

View file

@ -0,0 +1,130 @@
/*
* FreeLoader
* Copyright (C) 1998-2002 Brian Palmer <brianp@sginet.com>
*
* 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
* (at your option) 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.
*/
#include <freeldr.h>
#include <video.h>
#include <comm.h>
#define RGB_MAX 64
#define RGB_MAX_PER_ITERATION 64
VOID VideoSetAllColorsToBlack(U32 ColorCount)
{
U32 Color;
VideoWaitForVerticalRetrace();
for (Color=0; Color<ColorCount; Color++)
{
VideoSetPaletteColor(Color, 0, 0, 0);
}
}
VOID VideoFadeIn(PPALETTE_ENTRY Palette, U32 ColorCount)
{
U32 Index;
U32 Color;
PALETTE_ENTRY PaletteColors[ColorCount];
for (Index=0; Index<RGB_MAX; Index++)
{
for (Color=0; Color<ColorCount; Color++)
{
VideoGetPaletteColor(Color, &PaletteColors[Color].Red, &PaletteColors[Color].Green, &PaletteColors[Color].Blue);
// Increment each color so it approaches its real value
if (PaletteColors[Color].Red < Palette[Color].Red)
{
PaletteColors[Color].Red++;
}
if (PaletteColors[Color].Green < Palette[Color].Green)
{
PaletteColors[Color].Green++;
}
if (PaletteColors[Color].Blue < Palette[Color].Blue)
{
PaletteColors[Color].Blue++;
}
// Make sure we haven't exceeded the real value
if (PaletteColors[Color].Red > Palette[Color].Red)
{
PaletteColors[Color].Red = Palette[Color].Red;
}
if (PaletteColors[Color].Green > Palette[Color].Green)
{
PaletteColors[Color].Green = Palette[Color].Green;
}
if (PaletteColors[Color].Blue > Palette[Color].Blue)
{
PaletteColors[Color].Blue = Palette[Color].Blue;
}
}
// Set the colors
for (Color=0; Color<ColorCount; Color++)
{
if ((Color % RGB_MAX_PER_ITERATION) == 0)
{
VideoWaitForVerticalRetrace();
}
VideoSetPaletteColor(Color, PaletteColors[Color].Red, PaletteColors[Color].Green, PaletteColors[Color].Blue);
}
}
}
VOID VideoFadeOut(U32 ColorCount)
{
U32 Index;
U32 Color;
U8 Red;
U8 Green;
U8 Blue;
for (Index=0; Index<RGB_MAX; Index++)
{
for (Color=0; Color<ColorCount; Color++)
{
if ((Color % RGB_MAX_PER_ITERATION) == 0)
{
VideoWaitForVerticalRetrace();
}
VideoGetPaletteColor(Color, &Red, &Green, &Blue);
if (Red > 0)
{
Red--;
}
if (Green > 0)
{
Green--;
}
if (Blue > 0)
{
Blue--;
}
VideoSetPaletteColor(Color, Red, Green, Blue);
}
}
}

View file

@ -0,0 +1,61 @@
/*
* FreeLoader
* Copyright (C) 1998-2002 Brian Palmer <brianp@sginet.com>
*
* 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
* (at your option) 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.
*/
#include <freeldr.h>
#include <video.h>
#include <comm.h>
VOID VideoSetPaletteColor(U8 Color, U8 Red, U8 Green, U8 Blue)
{
WRITE_PORT_UCHAR((U8*)VIDEOPORT_PALETTE_WRITE, Color);
WRITE_PORT_UCHAR((U8*)VIDEOPORT_PALETTE_DATA, Red);
WRITE_PORT_UCHAR((U8*)VIDEOPORT_PALETTE_DATA, Green);
WRITE_PORT_UCHAR((U8*)VIDEOPORT_PALETTE_DATA, Blue);
}
VOID VideoGetPaletteColor(U8 Color, U8* Red, U8* Green, U8* Blue)
{
WRITE_PORT_UCHAR((U8*)VIDEOPORT_PALETTE_READ, Color);
*Red = READ_PORT_UCHAR((U8*)VIDEOPORT_PALETTE_DATA);
*Green = READ_PORT_UCHAR((U8*)VIDEOPORT_PALETTE_DATA);
*Blue = READ_PORT_UCHAR((U8*)VIDEOPORT_PALETTE_DATA);
}
VOID VideoSavePaletteState(PPALETTE_ENTRY Palette, U32 ColorCount)
{
U32 Color;
for (Color=0; Color<ColorCount; Color++)
{
VideoGetPaletteColor(Color, &Palette[Color].Red, &Palette[Color].Green, &Palette[Color].Blue);
}
}
VOID VideoRestorePaletteState(PPALETTE_ENTRY Palette, U32 ColorCount)
{
U32 Color;
VideoWaitForVerticalRetrace();
for (Color=0; Color<ColorCount; Color++)
{
VideoSetPaletteColor(Color, Palette[Color].Red, Palette[Color].Green, Palette[Color].Blue);
}
}

View file

@ -0,0 +1,333 @@
/*
* FreeLoader
* Copyright (C) 1998-2002 Brian Palmer <brianp@sginet.com>
*
* 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
* (at your option) 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.
*/
#include <freeldr.h>
#include <video.h>
#include <comm.h>
#include <debug.h>
//
// Arrrggh!
// I really really hate 16 color bit plane modes.
// They should all burn in hell for what they've
// done to my sleeping habits. And I still can't
// get this code to work and I have absolutely
// no idea why...
//
VOID VideoSetPixel16(U32 X, U32 Y, U8 Color)
{
U8 CurrentColor;
U8* MemoryPointer;
U32 ByteOffset;
U8 BitInByte;
U8 ReadByte;
U8 BitToChange;
MemoryPointer = (U8*)(VIDEOVGA_MEM_ADDRESS);
// Calculate the byte offset into the bit-plane
// where the pixel is to be set and the bit
// offset in that byte.
//ByteOffset = (Y * VideoGetBytesPerScanLine()) + (X >> 3);
//ByteOffset = (Y * 80) + (X >> 3);
ByteOffset = (Y * 640) + X;
BitInByte = ByteOffset & 7;
ByteOffset = ByteOffset >> 3;
//BitToChange = 0x80 >> BitInByte;
BitToChange = 0x80;
DbgPrint((DPRINT_WARNING, "X = %d Y = %d Color = %d ByteOffset = %d BitInByte = %d BitToChange = %d\n", X, Y, Color, ByteOffset, BitInByte, BitToChange));
//getch();
// Read the byte of memory to be changed. This is a
// read for the video card latches and the data read
// from memory does not need to be used.
ReadByte = MemoryPointer[ByteOffset];
// Select the bit or bits in the byte that need to be
// changed through index 8 of the VGA card address
// register by sending an 8 out to I/O port 3CEh.
// Next get the bits to be changed (a one-bit represents
// a bit to be changed) and send this out to I/O
// port 3CFh, the bit mask register (BMR).
//WRITE_PORT_USHORT((U16*)0x3CE, (((U16)BitToChange) << 8) + 0x08);
WRITE_PORT_UCHAR((U8*)0x3CE, 0x08);
//WRITE_PORT_UCHAR((U8*)0x3CF, BitToChange);
WRITE_PORT_UCHAR((U8*)0x3CF, BitInByte);
// Next set all mask bits to 1111 in the map mask register
// (MMR) at sequencer offset 2, and write color 0 to the
// VGA card to set the color to black. The mask bits select
// the bit planes to be changed. If all are selected and a
// color of 0 is written, all four bit-planes are clear to zero.
WRITE_PORT_USHORT((U16*)0x3C4, 0x0F02);
//WRITE_PORT_UCHAR((U8*)0x3C4, 0x02);
//WRITE_PORT_UCHAR((U8*)0x3C5, 0x0F); // Mask to 1111 binary
MemoryPointer[ByteOffset] = 0x00;
// Send the desired color number to the map mask register and
// write an FFh to the video memory. This places a logic one
// in only the selected bit planes to write a new color to
// a pixel or dot on the screen.
WRITE_PORT_UCHAR((U8*)0x3C4, 0x02);
//WRITE_PORT_UCHAR((U8*)0x3C5, Color);
WRITE_PORT_UCHAR((U8*)0x3C5, 0x0F);
//WRITE_PORT_USHORT((U16*)0x3C4, 0x0A02);
MemoryPointer[ByteOffset] = 0xFF;
/*CurrentColor = Color;
MemoryPointer = (U8*)(VIDEOVGA_MEM_ADDRESS);
WRITE_PORT_USHORT((U16*)0x3CE, 0x00 | (CurrentColor << 8));
WRITE_PORT_USHORT((U16*)0x3CE, 0x08 | 0x8000 >> (X & 7));
MemoryPointer += (Y * VideoGetBytesPerScanLine()) + (X >> 3);
*MemoryPointer = *MemoryPointer;
getch();*/
// First select the color plane
//ColorPlane = Color;
//ColorPlane = (ColorPlane << 8) + 0x02;
//WRITE_PORT_USHORT((U16*)0x3C4, ColorPlane);
// Now calculate the byte offset in the
// color plane that contains our pixel
// Since there are 8 pixels per byte we
// have to adjust accordingly
/*ByteOffset = (Y * VideoGetCurrentModeResolutionX()) + X;
BitInByte = ByteOffset % 8;
ByteOffset = ByteOffset / 8;
// Shift the color to the right bit
Color = 1;
Color = Color << BitInByte;
// Get the current color
CurrentColor = MemoryPointer[ByteOffset];
// Add the new color
CurrentColor = CurrentColor | Color;
// Now set the color
MemoryPointer[ByteOffset] = CurrentColor;*/
}
VOID VideoSetPixel256(U32 X, U32 Y, U8 Color)
{
U32 Bank;
U32 Offset;
U8* MemoryPointer;
MemoryPointer = (U8*)(VIDEOVGA_MEM_ADDRESS);
Bank = VideoGetMemoryBankForPixel(X, Y);
Offset = VideoGetBankOffsetForPixel(X, Y);
VideoSetMemoryBank(Bank);
MemoryPointer[Offset] = Color;
}
VOID VideoSetPixelRGB_15Bit(U32 X, U32 Y, U8 Red, U8 Green, U8 Blue)
{
U32 Bank;
U32 Offset;
U8* MemoryPointer;
U16 Pixel;
MemoryPointer = (U8*)(VIDEOVGA_MEM_ADDRESS);
Bank = VideoGetMemoryBankForPixel(X, Y);
Offset = VideoGetBankOffsetForPixel(X, Y);
VideoSetMemoryBank(Bank);
Red = Red >> 3;
Green = Green >> 3;
Blue = Blue >> 3;
Pixel = Red << 11 | Green << 6 | Blue << 1;
MemoryPointer[Offset] = Pixel & 0xFF;
MemoryPointer[Offset+1] = Pixel >> 8;
}
VOID VideoSetPixelRGB_16Bit(U32 X, U32 Y, U8 Red, U8 Green, U8 Blue)
{
U32 Bank;
U32 Offset;
U8* MemoryPointer;
U16 Pixel;
MemoryPointer = (U8*)(VIDEOVGA_MEM_ADDRESS);
Bank = VideoGetMemoryBankForPixel(X, Y);
Offset = VideoGetBankOffsetForPixel(X, Y);
VideoSetMemoryBank(Bank);
Red = Red >> 3;
Green = Green >> 2;
Blue = Blue >> 3;
Pixel = (U16)Red << 11 | (U16)Green << 5 | (U16)Blue << 0;
MemoryPointer[Offset] = Pixel & 0xFF;
MemoryPointer[Offset+1] = Pixel >> 8;
}
VOID VideoSetPixelRGB_24Bit(U32 X, U32 Y, U8 Red, U8 Green, U8 Blue)
{
U32 Bank;
U32 Offset;
U8* MemoryPointer;
MemoryPointer = (U8*)(VIDEOVGA_MEM_ADDRESS);
Bank = VideoGetMemoryBankForPixel(X, Y);
Offset = VideoGetBankOffsetForPixel(X, Y);
VideoSetMemoryBank(Bank);
MemoryPointer[Offset] = Blue;
MemoryPointer[Offset+1] = Green;
MemoryPointer[Offset+2] = Red;
}
VOID VideoSetPixelRGB(U32 X, U32 Y, U8 Red, U8 Green, U8 Blue)
{
if (VesaVideoModeInformation.BitsPerPixel >= 24)
{
VideoSetPixelRGB_24Bit(X, Y, Red, Green, Blue);
}
else if (VesaVideoModeInformation.BitsPerPixel >= 16)
{
// 16-bit color modes give green an extra bit (5:6:5)
// 15-bit color modes have just 5:5:5 for R:G:B
if (VesaVideoModeInformation.GreenMaskSize == 6)
{
VideoSetPixelRGB_16Bit(X, Y, Red, Green, Blue);
}
else
{
VideoSetPixelRGB_15Bit(X, Y, Red, Green, Blue);
}
}
else
{
BugCheck((DPRINT_UI, "This function does not support %d bits per pixel!", VesaVideoModeInformation.BitsPerPixel));
}
}
VOID VideoSetPixel16_OffScreen(U32 X, U32 Y, U8 Color)
{
}
VOID VideoSetPixel256_OffScreen(U32 X, U32 Y, U8 Color)
{
U8* MemoryPointer;
MemoryPointer = (U8*)(VideoOffScreenBuffer + VideoGetOffScreenMemoryOffsetForPixel(X, Y));
*MemoryPointer = Color;
}
VOID VideoSetPixelRGB_15Bit_OffScreen(U32 X, U32 Y, U8 Red, U8 Green, U8 Blue)
{
U32 Offset;
U8* MemoryPointer;
U16 Pixel;
MemoryPointer = (U8*)(VideoOffScreenBuffer);
Offset = VideoGetOffScreenMemoryOffsetForPixel(X, Y);
Red = Red >> 3;
Green = Green >> 3;
Blue = Blue >> 3;
Pixel = Red << 11 | Green << 6 | Blue << 1;
MemoryPointer[Offset] = Pixel & 0xFF;
MemoryPointer[Offset+1] = Pixel >> 8;
}
VOID VideoSetPixelRGB_16Bit_OffScreen(U32 X, U32 Y, U8 Red, U8 Green, U8 Blue)
{
U32 Offset;
U8* MemoryPointer;
U16 Pixel;
MemoryPointer = (U8*)(VideoOffScreenBuffer);
Offset = VideoGetOffScreenMemoryOffsetForPixel(X, Y);
Red = Red >> 3;
Green = Green >> 2;
Blue = Blue >> 3;
Pixel = (U16)Red << 11 | (U16)Green << 5 | (U16)Blue << 0;
MemoryPointer[Offset] = Pixel & 0xFF;
MemoryPointer[Offset+1] = Pixel >> 8;
}
VOID VideoSetPixelRGB_24Bit_OffScreen(U32 X, U32 Y, U8 Red, U8 Green, U8 Blue)
{
U32 Offset;
U8* MemoryPointer;
MemoryPointer = (U8*)(VideoOffScreenBuffer);
Offset = VideoGetOffScreenMemoryOffsetForPixel(X, Y);
MemoryPointer[Offset] = Blue;
MemoryPointer[Offset+1] = Green;
MemoryPointer[Offset+2] = Red;
}
VOID VideoSetPixelRGB_OffScreen(U32 X, U32 Y, U8 Red, U8 Green, U8 Blue)
{
if (VesaVideoModeInformation.BitsPerPixel >= 24)
{
VideoSetPixelRGB_24Bit_OffScreen(X, Y, Red, Green, Blue);
}
else if (VesaVideoModeInformation.BitsPerPixel >= 16)
{
// 16-bit color modes give green an extra bit (5:6:5)
// 15-bit color modes have just 5:5:5 for R:G:B
if (VesaVideoModeInformation.GreenMaskSize == 6)
{
VideoSetPixelRGB_16Bit_OffScreen(X, Y, Red, Green, Blue);
}
else
{
VideoSetPixelRGB_15Bit_OffScreen(X, Y, Red, Green, Blue);
}
}
else
{
BugCheck((DPRINT_UI, "This function does not support %d bits per pixel!", VesaVideoModeInformation.BitsPerPixel));
}
}

View file

@ -20,8 +20,11 @@
#include <freeldr.h>
#include <video.h>
#include <comm.h>
#include <mm.h>
PVOID VideoOffScreenBuffer = NULL;
VOID VideoClearScreen(VOID)
{
VideoSetMode(VideoGetCurrentMode());
@ -29,29 +32,36 @@ VOID VideoClearScreen(VOID)
VOID VideoWaitForVerticalRetrace(VOID)
{
while ((READ_PORT_UCHAR((PUCHAR)VIDEOPORT_VERTICAL_RETRACE) & 0x08))
while ((READ_PORT_UCHAR((U8*)VIDEOPORT_VERTICAL_RETRACE) & 0x08) == 1)
{
// Keep reading the port until bit 4 is clear
// Keep reading the port until bit 3 is clear
// This waits for the current retrace to end and
// we can catch the next one so we know we are
// getting a full retrace.
}
while (!(READ_PORT_UCHAR((PUCHAR)VIDEOPORT_VERTICAL_RETRACE) & 0x08))
while ((READ_PORT_UCHAR((U8*)VIDEOPORT_VERTICAL_RETRACE) & 0x08) == 0)
{
// Keep reading the port until bit 4 is set
// Keep reading the port until bit 3 is set
// Now that we know we aren't doing a vertical
// retrace we need to wait for the next one.
}
}
VOID VideoSetPaletteColor(UCHAR Color, UCHAR Red, UCHAR Green, UCHAR Blue)
PVOID VideoAllocateOffScreenBuffer(VOID)
{
WRITE_PORT_UCHAR((PUCHAR)VIDEOPORT_PALETTE_WRITE, Color);
WRITE_PORT_UCHAR((PUCHAR)VIDEOPORT_PALETTE_DATA, Red);
WRITE_PORT_UCHAR((PUCHAR)VIDEOPORT_PALETTE_DATA, Green);
WRITE_PORT_UCHAR((PUCHAR)VIDEOPORT_PALETTE_DATA, Blue);
}
U32 BufferSize;
VOID VideoGetPaletteColor(UCHAR Color, PUCHAR Red, PUCHAR Green, PUCHAR Blue)
{
WRITE_PORT_UCHAR((PUCHAR)VIDEOPORT_PALETTE_READ, Color);
*Red = READ_PORT_UCHAR((PUCHAR)VIDEOPORT_PALETTE_DATA);
*Green = READ_PORT_UCHAR((PUCHAR)VIDEOPORT_PALETTE_DATA);
*Blue = READ_PORT_UCHAR((PUCHAR)VIDEOPORT_PALETTE_DATA);
if (VideoOffScreenBuffer != NULL)
{
MmFreeMemory(VideoOffScreenBuffer);
VideoOffScreenBuffer = NULL;
}
BufferSize = VideoGetCurrentModeResolutionX() * VideoGetBytesPerScanLine();
VideoOffScreenBuffer = MmAllocateMemory(BufferSize);
return VideoOffScreenBuffer;
}

View file

@ -19,41 +19,123 @@
#include <freeldr.h>
#include <video.h>
#include <debug.h>
#include <comm.h>
U32 CurrentVideoMode = VIDEOMODE_NORMAL_TEXT;
U32 VideoResolutionX = 80;
U32 VideoResolutionY = 25;
U32 CurrentVideoMode = VIDEOMODE_NORMAL_TEXT;
U32 VideoResolutionX = 80;
U32 VideoResolutionY = 25;
U32 VideoBytesPerScanLine = 0; // Number of bytes per scan line
U32 CurrentModeType = MODETYPE_TEXT;
BOOL VesaVideoMode = FALSE;
SVGA_MODE_INFORMATION VesaVideoModeInformation;
BOOL VideoSetMode(U32 VideoMode)
{
CurrentMemoryBank = 0;
// Set the values for the default text modes
// If they are setting a graphics mode then
// these values will be changed.
CurrentVideoMode = VideoMode;
VideoResolutionX = 80;
VideoResolutionY = 25;
VideoBytesPerScanLine = 160;
CurrentModeType = MODETYPE_TEXT;
VesaVideoMode = FALSE;
switch (VideoMode)
{
case VIDEOMODE_NORMAL_TEXT:
CurrentVideoMode = VideoMode;
case 0x03: /* BIOS 80x25 text mode number */
return VideoSetMode80x25();
case VIDEOMODE_EXTENDED_TEXT:
CurrentVideoMode = VideoMode;
return VideoSetMode80x50_80x43();
case VIDEOMODE_80X28:
CurrentVideoMode = VideoMode;
return VideoSetMode80x28();
case VIDEOMODE_80X30:
CurrentVideoMode = VideoMode;
return VideoSetMode80x30();
case VIDEOMODE_80X34:
CurrentVideoMode = VideoMode;
return VideoSetMode80x34();
case VIDEOMODE_80X43:
CurrentVideoMode = VideoMode;
return VideoSetMode80x43();
case VIDEOMODE_80X60:
CurrentVideoMode = VideoMode;
return VideoSetMode80x60();
default:
return FALSE;
}
return TRUE;
if (VideoMode == 0x12)
{
// 640x480x16
BiosSetVideoMode(VideoMode);
//WRITE_PORT_USHORT((U16*)0x03CE, 0x0205); // For some reason this is necessary?
WRITE_PORT_USHORT((U16*)0x03CE, 0x0F01); // For some reason this is necessary?
VideoResolutionX = 640;
VideoResolutionY = 480;
VideoBytesPerScanLine = 80;
CurrentVideoMode = 0x12;
CurrentModeType = MODETYPE_GRAPHICS;
return TRUE;
}
else if (VideoMode == 0x13)
{
// 320x200x256
BiosSetVideoMode(VideoMode);
VideoResolutionX = 320;
VideoResolutionY = 200;
VideoBytesPerScanLine = 320;
CurrentVideoMode = 0x13;
CurrentModeType = MODETYPE_GRAPHICS;
return TRUE;
}
else if (VideoMode >= 0x0108 && VideoMode <= 0x010C)
{
// VESA Text Mode
if (!BiosVesaGetSVGAModeInformation(VideoMode, &VesaVideoModeInformation))
{
return FALSE;
}
if (!BiosVesaSetVideoMode(VideoMode))
{
return FALSE;
}
VideoResolutionX = VesaVideoModeInformation.WidthInPixels;
VideoResolutionY = VesaVideoModeInformation.HeightInPixels;
VideoBytesPerScanLine = VesaVideoModeInformation.BytesPerScanLine;
CurrentVideoMode = VideoMode;
CurrentModeType = MODETYPE_TEXT;
VesaVideoMode = TRUE;
return TRUE;
}
else
{
// VESA Graphics Mode
if (!BiosVesaGetSVGAModeInformation(VideoMode, &VesaVideoModeInformation))
{
return FALSE;
}
if (!BiosVesaSetVideoMode(VideoMode))
{
return FALSE;
}
VideoResolutionX = VesaVideoModeInformation.WidthInPixels;
VideoResolutionY = VesaVideoModeInformation.HeightInPixels;
VideoBytesPerScanLine = VesaVideoModeInformation.BytesPerScanLine;
CurrentVideoMode = VideoMode;
CurrentModeType = MODETYPE_GRAPHICS;
VesaVideoMode = TRUE;
return TRUE;
}
return FALSE;
}
BOOL VideoSetMode80x25(VOID)
@ -110,7 +192,7 @@ BOOL VideoSetMode80x28(VOID)
BOOL VideoSetMode80x43(VOID)
{
// FIXME: Is this VGA-only?
BiosSet350ScanLines();
BiosSetVerticalResolution(VERTRES_350_SCANLINES);
VideoSetMode80x25();
BiosSetVideoFont8x8();
BiosSelectAlternatePrintScreen();
@ -173,7 +255,59 @@ U32 VideoGetCurrentModeResolutionY(VOID)
return VideoResolutionY;
}
U32 VideoGetBytesPerScanLine(VOID)
{
return VideoBytesPerScanLine;
}
U32 VideoGetCurrentMode(VOID)
{
return CurrentVideoMode;
}
U32 VideoGetCurrentModeType(VOID)
{
return CurrentModeType;
}
BOOL VideoIsCurrentModeVesa(VOID)
{
return VesaVideoMode;
}
U32 VideoGetCurrentModeColorDepth(VOID)
{
U32 ColorDepth = 2;
U32 i;
if (CurrentModeType == MODETYPE_TEXT)
{
return 0;
}
else // CurrentModeType == MODETYPE_GRAPHICS
{
// Calculate 2^BitsPerPixel'th power
for (i=0; i<(VesaVideoModeInformation.BitsPerPixel-1); i++)
{
ColorDepth *= 2;
}
// This algorithm works great for 24-bit & 8-bit color modes
// but 15-bit color modes really use 16 bits per pixel.
// So check to see if green has an extra bit, if so then
// it is 16-bit, if not it is 15-bit
if (ColorDepth == 65536)
{
if (VesaVideoModeInformation.GreenMaskSize == 6)
{
return ColorDepth;
}
else
{
return 32768;
}
}
return ColorDepth;
}
}

View file

@ -1,8 +1,6 @@
FreeLoader notes
To build FreeLoader you will need DJGPP because Mingw32 doesn't support 16-bit code
ext2 filesystem support needs to be added.
The MessageBox() function needs to not allocate memory. Because it gets called when memory allocation fails.
Memory layout: