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]
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
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
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
+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)
#
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)
boot.o \
linux.o \
mb.o \
- mem.o \
- biosdisk.o \
- rtlcode.o \
- biosvid.o \
- drvmap.o
-
-RTL_OBJS = memory.o \
- print.o \
+ i386mem.o \
+ i386rtl.o \
+ i386vid.o \
+ drvmap.o \
+ int386.o \
+ i386disk.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 \
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
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)
.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)
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
+++ /dev/null
-/*
- * 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
-
-
+++ /dev/null
-/*
- * 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
-
-
-
--- /dev/null
+/*
+ * 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__
--- /dev/null
+/*
+ * 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;
+}
--- /dev/null
+/*
+ * 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);
+}
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:
i386CommonExceptionHandler:
.code32
+ SAVE_CPU_REGS
+
call i386ClearScreenToBlue
movl $i386ExceptionHandlerText,%esi
EXTERN(i386DivideByZero)
.code32
- SAVE_CPU_REGS
-
movl $i386DivideByZeroText,i386ExceptionDescriptionText
jmp i386CommonExceptionHandler
EXTERN(i386DebugException)
.code32
- SAVE_CPU_REGS
-
movl $i386DebugExceptionText,i386ExceptionDescriptionText
jmp i386CommonExceptionHandler
EXTERN(i386NMIException)
.code32
- SAVE_CPU_REGS
-
movl $i386NMIExceptionText,i386ExceptionDescriptionText
jmp i386CommonExceptionHandler
EXTERN(i386Breakpoint)
.code32
- SAVE_CPU_REGS
-
movl $i386BreakpointText,i386ExceptionDescriptionText
jmp i386CommonExceptionHandler
EXTERN(i386Overflow)
.code32
- SAVE_CPU_REGS
-
movl $i386OverflowText,i386ExceptionDescriptionText
jmp i386CommonExceptionHandler
EXTERN(i386BoundException)
.code32
- SAVE_CPU_REGS
-
movl $i386BoundExceptionText,i386ExceptionDescriptionText
jmp i386CommonExceptionHandler
EXTERN(i386InvalidOpcode)
.code32
- SAVE_CPU_REGS
-
movl $i386InvalidOpcodeText,i386ExceptionDescriptionText
jmp i386CommonExceptionHandler
EXTERN(i386FPUNotAvailable)
.code32
- SAVE_CPU_REGS
-
movl $i386FPUNotAvailableText,i386ExceptionDescriptionText
jmp i386CommonExceptionHandler
EXTERN(i386DoubleFault)
.code32
- SAVE_CPU_REGS_ERROR_CODE
+ popl %eax
+ movl %eax,i386_ERROR_CODE
movl $i386DoubleFaultText,i386ExceptionDescriptionText
jmp i386CommonExceptionHandler
EXTERN(i386CoprocessorSegment)
.code32
- SAVE_CPU_REGS
-
movl $i386CoprocessorSegmentText,i386ExceptionDescriptionText
jmp i386CommonExceptionHandler
EXTERN(i386InvalidTSS)
.code32
- SAVE_CPU_REGS_ERROR_CODE
+ popl %eax
+ movl %eax,i386_ERROR_CODE
movl $i386InvalidTSSText,i386ExceptionDescriptionText
jmp i386CommonExceptionHandler
EXTERN(i386SegmentNotPresent)
.code32
- SAVE_CPU_REGS_ERROR_CODE
+ popl %eax
+ movl %eax,i386_ERROR_CODE
movl $i386SegmentNotPresentText,i386ExceptionDescriptionText
jmp i386CommonExceptionHandler
EXTERN(i386StackException)
.code32
- SAVE_CPU_REGS_ERROR_CODE
+ popl %eax
+ movl %eax,i386_ERROR_CODE
movl $i386StackExceptionText,i386ExceptionDescriptionText
jmp i386CommonExceptionHandler
EXTERN(i386GeneralProtectionFault)
.code32
- SAVE_CPU_REGS_ERROR_CODE
+ popl %eax
+ movl %eax,i386_ERROR_CODE
movl $i386GeneralProtectionFaultText,i386ExceptionDescriptionText
jmp i386CommonExceptionHandler
EXTERN(i386PageFault)
.code32
- SAVE_CPU_REGS_ERROR_CODE
+ popl %eax
+ movl %eax,i386_ERROR_CODE
movl $i386PageFaultText,i386ExceptionDescriptionText
jmp i386CommonExceptionHandler
EXTERN(i386CoprocessorError)
.code32
- SAVE_CPU_REGS
-
movl $i386CoprocessorErrorText,i386ExceptionDescriptionText
jmp i386CommonExceptionHandler
EXTERN(i386AlignmentCheck)
.code32
- SAVE_CPU_REGS
-
movl $i386AlignmentCheckText,i386ExceptionDescriptionText
jmp i386CommonExceptionHandler
EXTERN(i386MachineCheck)
.code32
- SAVE_CPU_REGS
-
movl $i386MachineCheckText,i386ExceptionDescriptionText
jmp i386CommonExceptionHandler
--- /dev/null
+/*
+ * 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;
+}
--- /dev/null
+/*
+ * 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
+++ /dev/null
-/*
- * 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
+++ /dev/null
-/*
- * 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
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));
// 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;
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));
typedef struct
{
U32 DriveNumber;
- BOOL LbaSupported;
GEOMETRY DriveGeometry;
U32 BlockSize; // Block size (in sectors)
#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;
#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;
#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;
+ // Hard disks use drive numbers >= 0x80
+ // So if the drive number indicates a hard disk
+ // then return FALSE
+ if (DriveNumber >= 0x80)
+ {
+ return FALSE;
+ }
- DbgPrint((DPRINT_DISK, "ReadLogicalSectors() DriveNumber: 0x%x SectorNumber: %d SectorCount: %d Buffer: 0x%x\n", DriveNumber, SectorNumber, SectorCount, Buffer));
+ // 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
//
- // 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)))
+ // 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)))
{
- 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))
+ // 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;
}
- 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 (Sector[0] == 1 &&
+ Sector[1] == 'C' &&
+ Sector[2] == 'D' &&
+ Sector[3] == '0' &&
+ Sector[4] == '0' &&
+ Sector[5] == '1');
}
- return TRUE;
+ // 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)
#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
#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;
// 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;
}
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;
// 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;
}
// 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
/*
*
- * 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:
*
* 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
return TRUE;
}
-PFILE OpenFile(PUCHAR FileName)
+PFILE FsOpenFile(PUCHAR FileName)
{
PFILE FileHandle = NULL;
//
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)
{
}
* 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;
}
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:
return FALSE;
}
-U32 GetFileSize(PFILE FileHandle)
+U32 FsGetFileSize(PFILE FileHandle)
{
switch (FileSystemType)
{
return 0;
}
-VOID SetFilePointer(PFILE FileHandle, U32 NewFilePointer)
+VOID FsSetFilePointer(PFILE FileHandle, U32 NewFilePointer)
{
switch (FileSystemType)
{
}
}
-U32 GetFilePointer(PFILE FileHandle)
+U32 FsGetFilePointer(PFILE FileHandle)
{
switch (FileSystemType)
{
return 0;
}
-BOOL IsEndOfFile(PFILE FileHandle)
+BOOL FsIsEndOfFile(PFILE FileHandle)
{
- if (GetFilePointer(FileHandle) >= GetFileSize(FileHandle))
+ if (FsGetFilePointer(FileHandle) >= FsGetFileSize(FileHandle))
{
return TRUE;
}
* 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 */
#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 MAXLOWMEMADDR 0x78000 /* The highest usuable low memory address for our memory allocator */
+#define STACK32ADDR 0x78000 /* The 32-bit stack top will be at 7000:8000, or 0x78000 */
-#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:
#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
#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
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__
#endif // defined DEBUG
-#define UNIMPLEMENTED BugCheck((DPRINT_WARNING, "Unimplemented\n"));
+#define UNIMPLEMENTED() BugCheck((DPRINT_WARNING, "This function is unimplemented!\n"))
#endif // defined __DEBUG_H
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;
///////////////////////////////////////////////////////////////////////////////////////
//
-// 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
#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);
BOOL LinuxReadSetupSector(PFILE LinuxKernelFile);
BOOL LinuxReadKernel(PFILE LinuxKernelFile);
BOOL LinuxCheckKernelVersion(VOID);
-BOOL LinuxReadInitrd(VOID);
+BOOL LinuxReadInitrd(PFILE LinuxInitrdFile);
#endif // defined __LINUX_H
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
// 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);
-
-#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)
+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 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)
///////////////////////////////////////////////////////////////////////////////////////
//
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];
///////////////////////////////////////////////////////////////////////////////////////
//
///////////////////////////////////////////////////////////////////////////////////////
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
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
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
#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
#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
-
-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
+#define VIDEOVGA_MEM_ADDRESS 0xA0000
+#define VIDEOTEXT_MEM_ADDRESS 0xB8000
+
+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
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
}
// 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);
{
PFILE IniFileHandle; // File handle for freeldr.ini
- if (!OpenDiskDrive(BootDriveNumber, BootPartitionNumber))
+ if (!FsOpenVolume(BootDriveNumber, BootPartitionNumber))
{
if (BootPartitionNumber == 0)
{
}
// Try to open freeldr.ini
- IniFileHandle = OpenFile("freeldr.ini");
+ IniFileHandle = FsOpenFile("freeldr.ini");
return IniFileHandle;
}
#include <freeldr.h>
#include <arch.h>
+#include <disk.h>
#include <miscboot.h>
#include <rtl.h>
#include <fs.h>
#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;
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))
{
}
// 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);
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))
{
goto LinuxBootFailed;
}
+ // Calc kernel size
+ LinuxKernelSize = FsGetFileSize(LinuxKernel) - (512 + SetupSectorSize);
+
+ // Get the file size
+ LinuxInitrdSize = FsGetFileSize(LinuxInitrdFile);
+
// Read the kernel
if (!LinuxReadKernel(LinuxKernel))
{
// Read the initrd (if necessary)
if (LinuxHasInitrd)
{
- if (!LinuxReadInitrd())
+ if (!LinuxReadInitrd(LinuxInitrdFile))
{
goto LinuxBootFailed;
}
RtlCopyMemory((PVOID)0x90200, LinuxSetupSector, SetupSectorSize);
RtlCopyMemory((PVOID)0x99000, LinuxCommandLine, LinuxCommandLineSize);
- VideoShowTextCursor();
- VideoClearScreen();
+ UiUnInitialize("Booting Linux...");
- StopFloppyMotor();
+ DiskStopFloppyMotor();
if (LinuxSetupSector->LoadFlags & LINUX_FLAG_LOAD_HIGH)
{
if (LinuxKernel != NULL)
{
- CloseFile(LinuxKernel);
+ FsCloseFile(LinuxKernel);
+ }
+ if (LinuxInitrdFile != NULL)
+ {
+ FsCloseFile(LinuxInitrdFile);
}
if (LinuxBootSector != NULL)
}
// Read linux boot sector
- SetFilePointer(LinuxKernelFile, 0);
- if (!ReadFile(LinuxKernelFile, 512, NULL, LinuxBootSector))
+ FsSetFilePointer(LinuxKernelFile, 0);
+ if (!FsReadFile(LinuxKernelFile, 512, NULL, LinuxBootSector))
{
return FALSE;
}
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;
}
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;
}
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);
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;
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);
// 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;
#include <ui.h>
#include <inifile.h>
#include <disk.h>
-#include <video.h>
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.");
}
// Read boot sector
- if (!ReadFile(FilePointer, 512, &BytesRead, (void*)0x7c00) || (BytesRead != 512))
+ if (!FsReadFile(FilePointer, 512, &BytesRead, (void*)0x7c00) || (BytesRead != 512))
{
return;
}
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
// 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();
}
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
// 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();
}
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
// 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();
}
RtlZeroMemory(BiosMemoryMap, sizeof(BIOS_MEMORY_MAP) * 32);
- BiosMemoryMapEntryCount = GetBiosMemoryMap((PBIOS_MEMORY_MAP_ARRAY)BiosMemoryMap);
+ BiosMemoryMapEntryCount = GetBiosMemoryMap(BiosMemoryMap);
ExtendedMemorySize = GetExtendedMemorySize();
ConventionalMemorySize = GetConventionalMemorySize();
// 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;
// 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++)
* 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;
* 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
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);
/*
* 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++;
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);
/*
* 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++;
#include <arch.h>
#include <reactos.h>
#include <rtl.h>
+#include <disk.h>
#include <fs.h>
#include <ui.h>
#include <multiboot.h>
else
szShortName = szShortName + 1;
- FilePointer = OpenFile(szFileName);
+ FilePointer = FsOpenFile(szFileName);
if (FilePointer == NULL)
{
strcpy(szBuffer, szShortName);
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));
char value[256];
char *p;
- FilePointer = OpenFile(szFileName);
+ FilePointer = FsOpenFile(szFileName);
if (FilePointer == NULL)
{
strcpy(value, szFileName);
char value[256];
char *p;
- FilePointer = OpenFile(szFileName);
+ FilePointer = FsOpenFile(szFileName);
if (FilePointer == NULL)
{
strcpy(value, szFileName);
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;
/*
* Try to open boot drive
*/
- if (!OpenDiskDrive(BootDrive, BootPartition))
+ if (!FsOpenVolume(BootDrive, BootPartition))
{
UiMessageBox("Failed to open boot drive.");
return;
DbgPrint((DPRINT_REACTOS, "SystemHive: '%s'", szFileName));
- FilePointer = OpenFile(szFileName);
+ FilePointer = FsOpenFile(szFileName);
if (FilePointer == NULL)
{
strcat(value, " not found.");
strcat(name, ".");
//MessageBox(name);
+
+ UiUnInitialize("Booting ReactOS...");
+
/*
* Now boot the kernel
*/
- StopFloppyMotor();
+ DiskStopFloppyMotor();
boot_reactos();
}
}
else
{
- UNIMPLEMENTED;
+ UNIMPLEMENTED();
}
return *regChunk ? regChunk : 0;
}
else
{
- UNIMPLEMENTED;
+ UNIMPLEMENTED();
}
return dataSize;
}
else
{
- UNIMPLEMENTED;
+ UNIMPLEMENTED();
}
return *regChunk ? regChunk : 0;
#include <freeldr.h>
#include <debug.h>
#include <arch.h>
+#include <disk.h>
#include <reactos.h>
#include <rtl.h>
#include <fs.h>
else
szShortName = szShortName + 1;
- FilePointer = OpenFile(szFileName);
+ FilePointer = FsOpenFile(szFileName);
if (FilePointer == NULL)
{
printf("Could not find %s\n", szShortName);
szShortName = szShortName + 1;
- FilePointer = OpenFile(szFileName);
+ FilePointer = FsOpenFile(szFileName);
if (FilePointer == NULL)
{
printf("Could not find %s\n", szFileName);
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;
(unsigned int)BootDrive);
/* Open boot drive */
- if (!OpenDiskDrive(BootDrive, BootPartition))
+ if (!FsOpenVolume(BootDrive, BootPartition))
{
printf("Failed to open boot drive.");
return;
/*
* Now boot the kernel
*/
- StopFloppyMotor();
+ DiskStopFloppyMotor();
boot_reactos();
#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;
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);
-}
--- /dev/null
+/*
+ * 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
--- /dev/null
+/*
+ * 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
#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)
{
//
// Draw status bar
//
- TuiDrawStatusText("");
+ TuiDrawStatusText("Welcome to FreeLoader!");
//
// Update the date & time
//
TuiUpdateDateTime();
+
+ VideoCopyOffScreenBufferToVRAM();
}
/*
*/
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
*/
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
*/
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
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)
{
TuiDrawText(i, UiScreenHeight-1, " ", ATTR(UiStatusBarFgColor, UiStatusBarBgColor));
}
+
+ VideoCopyOffScreenBufferToVRAM();
}
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++)
VOID TuiRestoreScreen(PUCHAR Buffer)
{
- PUCHAR ScreenMemory = (PUCHAR)TUI_SCREEN_MEM;
+ PUCHAR ScreenMemory = (PUCHAR)TextVideoBuffer;
U32 i;
for (i=0; i < (UiScreenWidth * UiScreenHeight * 2); i++)
// Draw status text
UiDrawStatusText("Press ENTER to continue");
+ VideoCopyOffScreenBufferToVRAM();
+
for (;;)
{
if (kbhit())
}
TuiUpdateDateTime();
+
+ VideoCopyOffScreenBufferToVRAM();
}
}
}
TuiUpdateDateTime();
+
+ VideoCopyOffScreenBufferToVRAM();
}
UCHAR TuiTextToColor(PUCHAR ColorText)
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);
+ }
+
+}
// 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
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
#include "keycodes.h"
#include <options.h>
#include <mm.h>
+#include <video.h>
BOOL TuiDisplayMenu(PUCHAR MenuItemList[], U32 MenuItemCount, U32 DefaultMenuItem, S32 MenuTimeOut, U32* SelectedMenuItem)
//
// Update the date & time
//
- UiUpdateDateTime();
+ TuiUpdateDateTime();
+
+ VideoCopyOffScreenBufferToVRAM();
if (MenuInformation.MenuTimeRemaining > 0)
{
// Update the menu
//
TuiDrawMenuBox(&MenuInformation);
+
+ VideoCopyOffScreenBufferToVRAM();
}
}
else if (MenuInformation.MenuTimeRemaining == 0)
{
TuiDrawMenuItem(MenuInfo, Idx);
}
+
+ VideoCopyOffScreenBufferToVRAM();
}
VOID TuiDrawMenuBox(PTUI_MENU_INFO MenuInfo)
break;
}
+
+ VideoCopyOffScreenBufferToVRAM();
}
return KeyEvent;
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 " };
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"));
+ printf("EGA display adapter detected.\n");
+ printf("Using 80x25 text mode.\n");
+ VideoMode = VIDEOMODE_NORMAL_TEXT;
}
- else if (BiosDetectVideoCard() == VIDEOCARD_VGA)
+ else //if (BiosDetectVideoCard() == VIDEOCARD_VGA)
{
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 (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))
{
{
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;
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)
}
else
{
- UNIMPLEMENTED
+ UNIMPLEMENTED();
//GuiDrawBackdrop();
}
}
}
else
{
- UNIMPLEMENTED
+ UNIMPLEMENTED();
//GuiFillArea(Left, Top, Right, Bottom, FillChar, Attr);
}
}
}
else
{
- UNIMPLEMENTED
+ UNIMPLEMENTED();
//GuiDrawShadow(Left, Top, Right, Bottom);
}
}
}
else
{
- UNIMPLEMENTED
+ UNIMPLEMENTED();
//GuiDrawBox(Left, Top, Right, Bottom, VertStyle, HorzStyle, Fill, Shadow, Attr);
}
}
}
else
{
- UNIMPLEMENTED
+ UNIMPLEMENTED();
//GuiDrawText(X, Y, Text, Attr);
}
}
}
else
{
- UNIMPLEMENTED
+ UNIMPLEMENTED();
//GuiDrawCenteredText(Left, Top, Right, Bottom, TextString, Attr);
}
}
}
else
{
- UNIMPLEMENTED
+ UNIMPLEMENTED();
//GuiDrawStatusText(StatusText);
}
}
}
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)
}
else
{
- UNIMPLEMENTED
+ UNIMPLEMENTED();
//GuiMessageBox(UiMessageBoxLineText);
}
}
else
{
- UNIMPLEMENTED
+ UNIMPLEMENTED();
//GuiMessageBoxCritical(MessageText);
}
}
}
else
{
- UNIMPLEMENTED
- return 0;
+ UNIMPLEMENTED();
+ return 0;
//return GuiTextToColor(ColorText);
}
}
}
else
{
- UNIMPLEMENTED
- return 0;
+ UNIMPLEMENTED();
+ return 0;
//return GuiTextToFillStyle(FillStyleText);
}
}
}
else
{
- UNIMPLEMENTED
+ UNIMPLEMENTED();
//GuiDrawProgressBarCenter(Position, Range);
}
}
}
else
{
- UNIMPLEMENTED
+ UNIMPLEMENTED();
//GuiDrawProgressBar(Left, Top, Right, Bottom, Position, Range);
}
}
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)
}
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();
+ }
+}
--- /dev/null
+/*
+ * 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();
+ }
+}
--- /dev/null
+/*
+ * 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);
+ }
+ }
+}
--- /dev/null
+/*
+ * 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);
+ }
+}
--- /dev/null
+/*
+ * 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));
+ }
+}
#include <freeldr.h>
#include <video.h>
#include <comm.h>
+#include <mm.h>
+PVOID VideoOffScreenBuffer = NULL;
+
VOID VideoClearScreen(VOID)
{
VideoSetMode(VideoGetCurrentMode());
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;
}
#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)
BOOL VideoSetMode80x43(VOID)
{
// FIXME: Is this VGA-only?
- BiosSet350ScanLines();
+ BiosSetVerticalResolution(VERTRES_350_SCANLINES);
VideoSetMode80x25();
BiosSetVideoFont8x8();
BiosSelectAlternatePrintScreen();
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;
+ }
+}
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: