diff --git a/freeldr/bootsect/ext2.asm b/freeldr/bootsect/ext2.asm index 6122738c52b..45ed471e7be 100644 --- a/freeldr/bootsect/ext2.asm +++ b/freeldr/bootsect/ext2.asm @@ -29,7 +29,7 @@ start: nop BootDrive db 0x80 -BootPartition db 0 +;BootPartition db 0 ; Moved to end of boot sector to have a standard format across all boot sectors ;SectorsPerTrack db 63 ; Moved to [bp-SECTORS_PER_TRACK] ;NumberOfHeads dw 16 ; Moved to [bp-NUMBER_OF_HEADS] ;BiosCHSDriveSize dd (1024 * 1024 * 63) ; Moved to [bp-BIOS_CHS_DRIVE_SIZE] @@ -274,8 +274,8 @@ ReadSectorsCHSLoop: mov dh,dl ; Head in DH mov dl,[BYTE bp+BootDrive] ; Drive number in DL mov ch,al ; Cylinder in CX - ror ah,1 ; Low 8 bits of cylinder in CH, high 2 bits - ror ah,1 ; in CL shifted to bits 6 & 7 + ror ah,2 ; Low 8 bits of cylinder in CH, high 2 bits + ; in CL shifted to bits 6 & 7 or cl,ah ; Or with sector number mov ax,0201h int 13h ; DISK - READ SECTORS INTO MEMORY @@ -336,7 +336,10 @@ Done: msgDiskError db 'Disk error',0 msgAnyKey db 'Press any key to restart',0 - times 510-($-$$) db 0 ; Pad to 510 bytes + times 509-($-$$) db 0 ; Pad to 509 bytes + +BootPartition db 0 + dw 0aa55h ; BootSector signature diff --git a/freeldr/bootsect/fat32.asm b/freeldr/bootsect/fat32.asm index d18a857f137..f2faa93c0f9 100644 --- a/freeldr/bootsect/fat32.asm +++ b/freeldr/bootsect/fat32.asm @@ -272,7 +272,7 @@ msgDiskError db 'Disk error',0dh,0ah,0 msgFileSystemError db 'File system error',0dh,0ah,0 msgAnyKey db 'Press any key to restart',0dh,0ah,0 - times 509-($-$$) db 0 ; Pad to 510 bytes + times 509-($-$$) db 0 ; Pad to 509 bytes BootPartition: db 0 diff --git a/freeldr/freeldr/CHANGELOG b/freeldr/freeldr/CHANGELOG index 357253a0047..fe3625ffcbb 100644 --- a/freeldr/freeldr/CHANGELOG +++ b/freeldr/freeldr/CHANGELOG @@ -1,3 +1,20 @@ +Changes in v1.7.10 (11/24/2002) (brianp) + +- Added assembler versions of memcmp() memcpy() memset() +- Implemented Int386() so that real-mode interrupts can be called from C-code +- Removed unnecessary call in DbgPrint() macro (freeldr.sys is ~16k smaller now) +- 64-bit lba sector addressing for disk calls +- Re-coded biosdisk.S as i386disk.c +- Re-coded mem.S as i386mem.c +- Re-coded rtlcode.S as i386rtl.c +- Cleaned up i386trap.S so that it only saves the registers once. +- Re-coded biosvid.S as i386vid.c +- Video fade in/out +- VESA text modes supported now +- Offscreen buffering to remove flicker +- Standardized format of boot sector so that BootPartition is stored right before 0xaa55 +- Prefixed all file system functions with 'Fs' + Changes in v1.7.9 (9/30/2002) (brianp) - Fix for bug in BiosInt13ReadExtended() (biosdisk.S) diff --git a/freeldr/freeldr/Makefile b/freeldr/freeldr/Makefile index 334e1b6255d..554c993b28c 100644 --- a/freeldr/freeldr/Makefile +++ b/freeldr/freeldr/Makefile @@ -23,9 +23,9 @@ # TARGET = i386 # Debugging information on (bigger binary) -DEBUG = yes +#DEBUG = yes # Debugging information off (smaller binary) -#DEBUG = no +DEBUG = no OBJDIR = obj OUTPUT_DIR = $(OBJDIR)/$(TARGET) @@ -192,17 +192,20 @@ ARCH_OBJS = fathelp.o \ boot.o \ linux.o \ mb.o \ - mem.o \ - biosdisk.o \ - rtlcode.o \ - biosvid.o \ - drvmap.o + i386mem.o \ + i386rtl.o \ + i386vid.o \ + drvmap.o \ + int386.o \ + i386disk.o -RTL_OBJS = memory.o \ - print.o \ +RTL_OBJS = print.o \ stdlib.o \ string.o \ - list.o + list.o \ + memcmp.o \ + memcpy.o \ + memset.o FS_OBJS = fs.o \ fat.o \ @@ -238,7 +241,11 @@ INIFILE_OBJS= inifile.o \ parse.o VIDEO_OBJS = video.o \ - vidmode.o + vidmode.o \ + fade.o \ + palette.o \ + pixel.o \ + bank.o # libgcc2.o contains code (__udivdi3, __umoddi3) necessary to do # 64-bit division on the i386 (and other 32-bit) architectures diff --git a/freeldr/freeldr/arch/i386/arch.S b/freeldr/freeldr/arch/i386/arch.S index 78e2013bad5..9b315aad37f 100644 --- a/freeldr/freeldr/arch/i386/arch.S +++ b/freeldr/freeldr/arch/i386/arch.S @@ -74,6 +74,19 @@ EXTERN(switch_to_prot) cli /* None of these */ + /* We don't know what values are currently */ + /* in the segment registers. So we are */ + /* going to reload them with sane values. */ + /* Of course CS has to already be valid. */ + /* We are currently in real-mode so we */ + /* need real-mode segment values. */ + movw $0x0000,%ax + movw %ax,%ds + movw %ax,%es + movw %ax,%fs + movw %ax,%gs + movw %ax,%ss + /* Get the return address off the stack */ popw (code32ret) @@ -120,6 +133,19 @@ EXTERN(switch_to_real) .code32 + /* We don't know what values are currently */ + /* in the segment registers. So we are */ + /* going to reload them with sane values. */ + /* Of course CS has to already be valid. */ + /* We are currently in protected-mode so we */ + /* need protected-mode segment values. */ + movw $PMODE_DS,%ax + movw %ax,%ds + movw %ax,%es + movw %ax,%fs + movw %ax,%gs + movw %ax,%ss + /* Get the return address off the stack */ popl (code16ret) @@ -157,9 +183,9 @@ inrmode: movw %ax,%ss /* Clear out the high 16-bits of ESP */ - /* This is needed because I have a stupid */ - /* MS-Win98 boot disk that hangs if there is */ - /* anything other than 0x0000 in the high */ + /* This is needed because I have one */ + /* machine that hangs when booted to dos if */ + /* anything other than 0x0000 is in the high */ /* 16-bits of ESP. Even though real-mode */ /* code should only use SP and not ESP. */ xorl %esp,%esp diff --git a/freeldr/freeldr/arch/i386/biosdisk.S b/freeldr/freeldr/arch/i386/biosdisk.S deleted file mode 100644 index 542a6db82b0..00000000000 --- a/freeldr/freeldr/arch/i386/biosdisk.S +++ /dev/null @@ -1,549 +0,0 @@ -/* - * FreeLoader - * Copyright (C) 1998-2002 Brian Palmer - * - * 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 - - -/* - * 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 - - diff --git a/freeldr/freeldr/arch/i386/biosvid.S b/freeldr/freeldr/arch/i386/biosvid.S deleted file mode 100644 index 5037ec7b83c..00000000000 --- a/freeldr/freeldr/arch/i386/biosvid.S +++ /dev/null @@ -1,622 +0,0 @@ -/* - * FreeLoader - * Copyright (C) 1998-2002 Brian Palmer - * Portions from Linux video.S - Display adapter & video mode setup, version 2.13 (14-May-99) - * Copyright (C) 1995 -- 1999 Martin Mares - * 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 - - - -/* - * 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 - - - diff --git a/freeldr/freeldr/arch/i386/i386disk.c b/freeldr/freeldr/arch/i386/i386disk.c new file mode 100644 index 00000000000..4a59ba5004f --- /dev/null +++ b/freeldr/freeldr/arch/i386/i386disk.c @@ -0,0 +1,431 @@ +/* + * FreeLoader + * Copyright (C) 1998-2002 Brian Palmer + * + * 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 +#include +#include +#include +#include +#include + + +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__ diff --git a/freeldr/freeldr/arch/i386/i386mem.c b/freeldr/freeldr/arch/i386/i386mem.c new file mode 100644 index 00000000000..ecf04f6d3ad --- /dev/null +++ b/freeldr/freeldr/arch/i386/i386mem.c @@ -0,0 +1,208 @@ +/* + * FreeLoader + * Copyright (C) 1998-2002 Brian Palmer + * + * 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 +#include +#include +#include +#include +#include + + +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; +} diff --git a/freeldr/freeldr/arch/i386/i386rtl.c b/freeldr/freeldr/arch/i386/i386rtl.c new file mode 100644 index 00000000000..c180fe36329 --- /dev/null +++ b/freeldr/freeldr/arch/i386/i386rtl.c @@ -0,0 +1,328 @@ +/* + * FreeLoader + * Copyright (C) 1998-2002 Brian Palmer + * + * 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 +#include + + +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); +} diff --git a/freeldr/freeldr/arch/i386/i386trap.S b/freeldr/freeldr/arch/i386/i386trap.S index e750238b785..801387031fe 100644 --- a/freeldr/freeldr/arch/i386/i386trap.S +++ b/freeldr/freeldr/arch/i386/i386trap.S @@ -76,59 +76,6 @@ str i386_TR .endm -.macro SAVE_CPU_REGS_ERROR_CODE - movl %eax,i386_EAX - movl %ebx,i386_EBX - movl %ecx,i386_ECX - movl %edx,i386_EDX - movl %esp,i386_ESP - movl %ebp,i386_EBP - movl %esi,i386_ESI - movl %edi,i386_EDI - movw %ds,%ax - movw %ax,i386_DS - movw %es,%ax - movw %ax,i386_ES - movw %fs,%ax - movw %ax,i386_FS - movw %gs,%ax - movw %ax,i386_GS - movw %ss,%ax - movw %ax,i386_SS - popl %eax - movl %eax,i386_ERROR_CODE - popl %eax - movl %eax,i386_EIP - popl %eax - movw %ax,i386_CS - popl %eax - movl %eax,i386_EFLAGS - movl %cr0,%eax - movl %eax,i386_CR0 - //movl %cr1,%eax - //movl %eax,i386_CR1 - movl %cr2,%eax - movl %eax,i386_CR2 - movl %cr3,%eax - movl %eax,i386_CR3 - movl %dr0,%eax - movl %eax,i386_DR0 - movl %dr1,%eax - movl %eax,i386_DR1 - movl %dr2,%eax - movl %eax,i386_DR2 - movl %dr3,%eax - movl %eax,i386_DR3 - movl %dr6,%eax - movl %eax,i386_DR6 - movl %dr7,%eax - movl %eax,i386_DR7 - sgdt i386_GDTR - sidt i386_IDTR - sldt i386_LDTR - str i386_TR -.endm - i386ExceptionHandlerText: @@ -317,6 +264,8 @@ i386_ScreenPosY: i386CommonExceptionHandler: .code32 + SAVE_CPU_REGS + call i386ClearScreenToBlue movl $i386ExceptionHandlerText,%esi @@ -630,8 +579,6 @@ i386PrintHexByte1: EXTERN(i386DivideByZero) .code32 - SAVE_CPU_REGS - movl $i386DivideByZeroText,i386ExceptionDescriptionText jmp i386CommonExceptionHandler @@ -639,8 +586,6 @@ EXTERN(i386DivideByZero) EXTERN(i386DebugException) .code32 - SAVE_CPU_REGS - movl $i386DebugExceptionText,i386ExceptionDescriptionText jmp i386CommonExceptionHandler @@ -648,8 +593,6 @@ EXTERN(i386DebugException) EXTERN(i386NMIException) .code32 - SAVE_CPU_REGS - movl $i386NMIExceptionText,i386ExceptionDescriptionText jmp i386CommonExceptionHandler @@ -657,8 +600,6 @@ EXTERN(i386NMIException) EXTERN(i386Breakpoint) .code32 - SAVE_CPU_REGS - movl $i386BreakpointText,i386ExceptionDescriptionText jmp i386CommonExceptionHandler @@ -666,8 +607,6 @@ EXTERN(i386Breakpoint) EXTERN(i386Overflow) .code32 - SAVE_CPU_REGS - movl $i386OverflowText,i386ExceptionDescriptionText jmp i386CommonExceptionHandler @@ -675,8 +614,6 @@ EXTERN(i386Overflow) EXTERN(i386BoundException) .code32 - SAVE_CPU_REGS - movl $i386BoundExceptionText,i386ExceptionDescriptionText jmp i386CommonExceptionHandler @@ -684,8 +621,6 @@ EXTERN(i386BoundException) EXTERN(i386InvalidOpcode) .code32 - SAVE_CPU_REGS - movl $i386InvalidOpcodeText,i386ExceptionDescriptionText jmp i386CommonExceptionHandler @@ -693,8 +628,6 @@ EXTERN(i386InvalidOpcode) EXTERN(i386FPUNotAvailable) .code32 - SAVE_CPU_REGS - movl $i386FPUNotAvailableText,i386ExceptionDescriptionText jmp i386CommonExceptionHandler @@ -702,7 +635,8 @@ EXTERN(i386FPUNotAvailable) EXTERN(i386DoubleFault) .code32 - SAVE_CPU_REGS_ERROR_CODE + popl %eax + movl %eax,i386_ERROR_CODE movl $i386DoubleFaultText,i386ExceptionDescriptionText jmp i386CommonExceptionHandler @@ -711,8 +645,6 @@ EXTERN(i386DoubleFault) EXTERN(i386CoprocessorSegment) .code32 - SAVE_CPU_REGS - movl $i386CoprocessorSegmentText,i386ExceptionDescriptionText jmp i386CommonExceptionHandler @@ -720,7 +652,8 @@ EXTERN(i386CoprocessorSegment) EXTERN(i386InvalidTSS) .code32 - SAVE_CPU_REGS_ERROR_CODE + popl %eax + movl %eax,i386_ERROR_CODE movl $i386InvalidTSSText,i386ExceptionDescriptionText jmp i386CommonExceptionHandler @@ -729,7 +662,8 @@ EXTERN(i386InvalidTSS) EXTERN(i386SegmentNotPresent) .code32 - SAVE_CPU_REGS_ERROR_CODE + popl %eax + movl %eax,i386_ERROR_CODE movl $i386SegmentNotPresentText,i386ExceptionDescriptionText jmp i386CommonExceptionHandler @@ -738,7 +672,8 @@ EXTERN(i386SegmentNotPresent) EXTERN(i386StackException) .code32 - SAVE_CPU_REGS_ERROR_CODE + popl %eax + movl %eax,i386_ERROR_CODE movl $i386StackExceptionText,i386ExceptionDescriptionText jmp i386CommonExceptionHandler @@ -747,7 +682,8 @@ EXTERN(i386StackException) EXTERN(i386GeneralProtectionFault) .code32 - SAVE_CPU_REGS_ERROR_CODE + popl %eax + movl %eax,i386_ERROR_CODE movl $i386GeneralProtectionFaultText,i386ExceptionDescriptionText jmp i386CommonExceptionHandler @@ -756,7 +692,8 @@ EXTERN(i386GeneralProtectionFault) EXTERN(i386PageFault) .code32 - SAVE_CPU_REGS_ERROR_CODE + popl %eax + movl %eax,i386_ERROR_CODE movl $i386PageFaultText,i386ExceptionDescriptionText jmp i386CommonExceptionHandler @@ -765,8 +702,6 @@ EXTERN(i386PageFault) EXTERN(i386CoprocessorError) .code32 - SAVE_CPU_REGS - movl $i386CoprocessorErrorText,i386ExceptionDescriptionText jmp i386CommonExceptionHandler @@ -774,8 +709,6 @@ EXTERN(i386CoprocessorError) EXTERN(i386AlignmentCheck) .code32 - SAVE_CPU_REGS - movl $i386AlignmentCheckText,i386ExceptionDescriptionText jmp i386CommonExceptionHandler @@ -783,8 +716,6 @@ EXTERN(i386AlignmentCheck) EXTERN(i386MachineCheck) .code32 - SAVE_CPU_REGS - movl $i386MachineCheckText,i386ExceptionDescriptionText jmp i386CommonExceptionHandler diff --git a/freeldr/freeldr/arch/i386/i386vid.c b/freeldr/freeldr/arch/i386/i386vid.c new file mode 100644 index 00000000000..974b9a060c8 --- /dev/null +++ b/freeldr/freeldr/arch/i386/i386vid.c @@ -0,0 +1,807 @@ +/* + * FreeLoader + * Copyright (C) 1998-2002 Brian Palmer + * Portions from Linux video.S - Display adapter & video mode setup, version 2.13 (14-May-99) + * Copyright (C) 1995 -- 1999 Martin Mares + * 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 +#include +#include +#include +#include +#include + +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; +} diff --git a/freeldr/freeldr/arch/i386/int386.S b/freeldr/freeldr/arch/i386/int386.S new file mode 100644 index 00000000000..b8504f19266 --- /dev/null +++ b/freeldr/freeldr/arch/i386/int386.S @@ -0,0 +1,155 @@ +/* + * FreeLoader + * Copyright (C) 1998-2002 Brian Palmer + * + * 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 + + +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 diff --git a/freeldr/freeldr/arch/i386/mem.S b/freeldr/freeldr/arch/i386/mem.S deleted file mode 100644 index 9054a40cd10..00000000000 --- a/freeldr/freeldr/arch/i386/mem.S +++ /dev/null @@ -1,213 +0,0 @@ -/* - * FreeLoader - * Copyright (C) 1998-2002 Brian Palmer - * - * 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 -#include - - - -/* - * 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 diff --git a/freeldr/freeldr/arch/i386/rtlcode.S b/freeldr/freeldr/arch/i386/rtlcode.S deleted file mode 100644 index 500f15cc859..00000000000 --- a/freeldr/freeldr/arch/i386/rtlcode.S +++ /dev/null @@ -1,470 +0,0 @@ -/* - * FreeLoader - * Copyright (C) 1998-2002 Brian Palmer - * - * 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 - - -/* - * 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 diff --git a/freeldr/freeldr/cache/blocklist.c b/freeldr/freeldr/cache/blocklist.c index 7ef5e8db662..d181a8bff96 100644 --- a/freeldr/freeldr/cache/blocklist.c +++ b/freeldr/freeldr/cache/blocklist.c @@ -214,7 +214,6 @@ VOID CacheInternalDumpBlockList(PCACHE_DRIVE CacheDrive) PCACHE_BLOCK CacheBlock; DbgPrint((DPRINT_CACHE, "Dumping block list for BIOS drive 0x%x.\n", CacheDrive->DriveNumber)); - DbgPrint((DPRINT_CACHE, "LbaSupported = %s.\n", CacheDrive->LbaSupported ? "TRUE" : "FALSE")); DbgPrint((DPRINT_CACHE, "Cylinders: %d.\n", CacheDrive->DriveGeometry.Cylinders)); DbgPrint((DPRINT_CACHE, "Heads: %d.\n", CacheDrive->DriveGeometry.Heads)); DbgPrint((DPRINT_CACHE, "Sectors: %d.\n", CacheDrive->DriveGeometry.Sectors)); diff --git a/freeldr/freeldr/cache/cache.c b/freeldr/freeldr/cache/cache.c index d7551c3e41a..8ac83d49961 100644 --- a/freeldr/freeldr/cache/cache.c +++ b/freeldr/freeldr/cache/cache.c @@ -82,25 +82,13 @@ BOOL CacheInitializeDrive(U32 DriveNumber) // Initialize the structure RtlZeroMemory(&CacheManagerDrive, sizeof(CACHE_DRIVE)); CacheManagerDrive.DriveNumber = DriveNumber; - CacheManagerDrive.LbaSupported = BiosInt13ExtensionsSupported(DriveNumber); if (!DiskGetDriveGeometry(DriveNumber, &CacheManagerDrive.DriveGeometry)) { return FALSE; } - // If LBA is supported then the block size will be 128 sectors (64k) - // If not then the block size is the size of one track - if (CacheManagerDrive.LbaSupported) - { - // FIXME: Temporarily reduced this to - // 64 sectors since not all BIOS calls - // support reading as many as 128 sectors - CacheManagerDrive.BlockSize = 64;//128; - } - else - { - CacheManagerDrive.BlockSize = CacheManagerDrive.DriveGeometry.Sectors; - } + // Get the number of sectors in each cache block + CacheManagerDrive.BlockSize = DiskGetCacheableBlockCount(DriveNumber); CacheBlockCount = 0; CacheSizeLimit = GetSystemMemorySize() / 8; @@ -113,7 +101,6 @@ BOOL CacheInitializeDrive(U32 DriveNumber) CacheManagerInitialized = TRUE; DbgPrint((DPRINT_CACHE, "Initializing BIOS drive 0x%x.\n", DriveNumber)); - DbgPrint((DPRINT_CACHE, "LbaSupported = %s.\n", CacheManagerDrive.LbaSupported ? "TRUE" : "FALSE")); DbgPrint((DPRINT_CACHE, "Cylinders: %d.\n", CacheManagerDrive.DriveGeometry.Cylinders)); DbgPrint((DPRINT_CACHE, "Heads: %d.\n", CacheManagerDrive.DriveGeometry.Heads)); DbgPrint((DPRINT_CACHE, "Sectors: %d.\n", CacheManagerDrive.DriveGeometry.Sectors)); diff --git a/freeldr/freeldr/cache/cm.h b/freeldr/freeldr/cache/cm.h index cb499b912a9..b6fbbf68997 100644 --- a/freeldr/freeldr/cache/cm.h +++ b/freeldr/freeldr/cache/cm.h @@ -56,7 +56,6 @@ typedef struct typedef struct { U32 DriveNumber; - BOOL LbaSupported; GEOMETRY DriveGeometry; U32 BlockSize; // Block size (in sectors) diff --git a/freeldr/freeldr/debug.c b/freeldr/freeldr/debug.c index ee8269966da..c978ba8bb20 100644 --- a/freeldr/freeldr/debug.c +++ b/freeldr/freeldr/debug.c @@ -24,13 +24,13 @@ #ifdef DEBUG -//#define DEBUG_ULTRA +#define DEBUG_ALL //#define DEBUG_INIFILE //#define DEBUG_REACTOS //#define DEBUG_CUSTOM #define DEBUG_NONE -#if defined (DEBUG_ULTRA) +#if defined (DEBUG_ALL) U32 DebugPrintMask = DPRINT_WARNING | DPRINT_MEMORY | DPRINT_FILESYSTEM | DPRINT_UI | DPRINT_DISK | DPRINT_CACHE | DPRINT_REACTOS | DPRINT_LINUX; @@ -55,8 +55,8 @@ U32 DebugPrintMask = 0; #define BOCHS_OUTPUT_PORT 0xe9 -//U32 DebugPort = RS232; -U32 DebugPort = SCREEN; +U32 DebugPort = RS232; +//U32 DebugPort = SCREEN; //U32 DebugPort = BOCHS; U32 ComPort = COM1; //U32 BaudRate = 19200; diff --git a/freeldr/freeldr/disk/disk.c b/freeldr/freeldr/disk/disk.c index 095a3d9ff4f..169956d5d57 100644 --- a/freeldr/freeldr/disk/disk.c +++ b/freeldr/freeldr/disk/disk.c @@ -19,126 +19,95 @@ #include #include -#include +#include #include #include -#include #include +#undef UNIMPLEMENTED +#define UNIMPLEMENTED BugCheck((DPRINT_WARNING, "Unimplemented\n")); + ///////////////////////////////////////////////////////////////////////////////////////////// // FUNCTIONS ///////////////////////////////////////////////////////////////////////////////////////////// -VOID DiskError(PUCHAR ErrorString) +VOID DiskError(PUCHAR ErrorString, U32 ErrorCode) { UCHAR ErrorCodeString[80]; - sprintf(ErrorCodeString, "%s\nError Code: 0x%x", ErrorString, BiosInt13GetLastErrorCode()); + sprintf(ErrorCodeString, "%s\n\nError Code: 0x%x", ErrorString, ErrorCode); DbgPrint((DPRINT_DISK, "%s\n", ErrorCodeString)); UiMessageBox(ErrorCodeString); } -BOOL DiskReadLogicalSectors(U32 DriveNumber, U32 SectorNumber, U32 SectorCount, PVOID Buffer) +// This function is in arch/i386/i386disk.c +//BOOL DiskReadLogicalSectors(U32 DriveNumber, U64 SectorNumber, U32 SectorCount, PVOID Buffer) + +BOOL DiskIsDriveRemovable(U32 DriveNumber) { - U32 PhysicalSector; - U32 PhysicalHead; - U32 PhysicalTrack; - GEOMETRY DriveGeometry; - U32 NumberOfSectorsToRead; - - DbgPrint((DPRINT_DISK, "ReadLogicalSectors() DriveNumber: 0x%x SectorNumber: %d SectorCount: %d Buffer: 0x%x\n", DriveNumber, SectorNumber, SectorCount, Buffer)); - - // - // Check to see if it is a fixed disk drive - // If so then check to see if Int13 extensions work - // If they do then use them, otherwise default back to BIOS calls - // - if ((DriveNumber >= 0x80) && (IsSetupLdr || BiosInt13ExtensionsSupported(DriveNumber))) + // Hard disks use drive numbers >= 0x80 + // So if the drive number indicates a hard disk + // then return FALSE + if (DriveNumber >= 0x80) { - DbgPrint((DPRINT_DISK, "Using Int 13 Extensions for read. BiosInt13ExtensionsSupported(%d) = %s\n", DriveNumber, BiosInt13ExtensionsSupported(DriveNumber) ? "TRUE" : "FALSE")); - - // - // LBA is easy, nothing to calculate - // Just do the read - // - if (!BiosInt13ReadExtended(DriveNumber, SectorNumber, SectorCount, Buffer)) - { - DiskError("Disk read error."); - return FALSE; - } - } - else - { - // - // Get the drive geometry - // - if (!DiskGetDriveGeometry(DriveNumber, &DriveGeometry)) - { - return FALSE; - } - - while (SectorCount) - { - - // - // Calculate the physical disk offsets - // - PhysicalSector = 1 + (SectorNumber % DriveGeometry.Sectors); - PhysicalHead = (SectorNumber / DriveGeometry.Sectors) % DriveGeometry.Heads; - PhysicalTrack = (SectorNumber / DriveGeometry.Sectors) / DriveGeometry.Heads; - - // - // Calculate how many sectors we are supposed to read - // - if (PhysicalSector > 1) - { - if (SectorCount >= (DriveGeometry.Sectors - (PhysicalSector - 1))) - NumberOfSectorsToRead = (DriveGeometry.Sectors - (PhysicalSector - 1)); - else - NumberOfSectorsToRead = SectorCount; - } - else - { - if (SectorCount >= DriveGeometry.Sectors) - NumberOfSectorsToRead = DriveGeometry.Sectors; - else - NumberOfSectorsToRead = SectorCount; - } - - DbgPrint((DPRINT_DISK, "Calling BiosInt13Read() with PhysicalHead: %d\n", PhysicalHead)); - DbgPrint((DPRINT_DISK, "Calling BiosInt13Read() with PhysicalTrack: %d\n", PhysicalTrack)); - DbgPrint((DPRINT_DISK, "Calling BiosInt13Read() with PhysicalSector: %d\n", PhysicalSector)); - DbgPrint((DPRINT_DISK, "Calling BiosInt13Read() with NumberOfSectorsToRead: %d\n", NumberOfSectorsToRead)); - - // - // Make sure the read is within the geometry boundaries - // - if ((PhysicalHead >= DriveGeometry.Heads) || - (PhysicalTrack >= DriveGeometry.Cylinders) || - ((NumberOfSectorsToRead + PhysicalSector) > (DriveGeometry.Sectors + 1)) || - (PhysicalSector > DriveGeometry.Sectors)) - { - DiskError("Disk read exceeds drive geometry limits."); - return FALSE; - } - - // - // Perform the read - // - if (!BiosInt13Read(DriveNumber, PhysicalHead, PhysicalTrack, PhysicalSector, NumberOfSectorsToRead, Buffer)) - { - DiskError("Disk read error."); - return FALSE; - } - - Buffer += (NumberOfSectorsToRead * DriveGeometry.BytesPerSector); - SectorCount -= NumberOfSectorsToRead; - SectorNumber += NumberOfSectorsToRead; - } + return FALSE; } + // Drive is a floppy diskette so return TRUE return TRUE; } + + +BOOL DiskIsDriveCdRom(U32 DriveNumber) +{ + PUCHAR Sector = (PUCHAR)DISKREADBUFFER; + + // FIXME: + // I need to move this code to somewhere else + // probably in the file system code. + // I don't like the fact that the disk code + // reads the on-disk structures to determine + // if it's a CD-ROM drive. Only the file system + // should interpret on-disk data. + // The disk code should use some other method + // to determine if it's a CD-ROM drive. + + // Hard disks use drive numbers >= 0x80 + // So if the drive number indicates a hard disk + // then return FALSE + // + // We first check if we are running as a SetupLoader + // If so then we are probably booting from a CD-ROM + // So we shouldn't call i386DiskInt13ExtensionsSupported() + // because apparently it screws up some BIOSes + if ((DriveNumber >= 0x80) && (IsSetupLdr || DiskInt13ExtensionsSupported(DriveNumber))) + { + + // We are a CD-ROM drive so we should only + // use the extended Int13 disk functions + if (!DiskReadLogicalSectorsLBA(DriveNumber, 16, 1, Sector)) + { + DiskError("Disk read error.", 0); + return FALSE; + } + + return (Sector[0] == 1 && + Sector[1] == 'C' && + Sector[2] == 'D' && + Sector[3] == '0' && + Sector[4] == '0' && + Sector[5] == '1'); + } + + // Drive is not CdRom so return FALSE + return FALSE; +} + +// This function is in arch/i386/i386disk.c +//VOID DiskStopFloppyMotor(VOID) + +// This function is in arch/i386/i386disk.c +//U32 DiskGetCacheableBlockCount(U32 DriveNumber) diff --git a/freeldr/freeldr/disk/geometry.c b/freeldr/freeldr/disk/geometry.c index 25708a0cd05..0aef1443f72 100644 --- a/freeldr/freeldr/disk/geometry.c +++ b/freeldr/freeldr/disk/geometry.c @@ -23,15 +23,22 @@ #include +#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 diff --git a/freeldr/freeldr/disk/partition.c b/freeldr/freeldr/disk/partition.c index 00ddb2c0292..efed2e39866 100644 --- a/freeldr/freeldr/disk/partition.c +++ b/freeldr/freeldr/disk/partition.c @@ -25,51 +25,6 @@ #include - -BOOL DiskIsDriveRemovable(U32 DriveNumber) -{ - // Hard disks use drive numbers >= 0x80 - // So if the drive number indicates a hard disk - // then return FALSE - if (DriveNumber >= 0x80) - { - return FALSE; - } - - // Drive is a floppy diskette so return TRUE - return TRUE; -} - - -BOOL DiskIsDriveCdRom(U32 DriveNumber) -{ - PUCHAR Sector = (PUCHAR)DISKREADBUFFER; - - // Hard disks use drive numbers >= 0x80 - // So if the drive number indicates a hard disk - // then return FALSE - if ((DriveNumber >= 0x80) && (IsSetupLdr || BiosInt13ExtensionsSupported(DriveNumber))) - { - - if (!BiosInt13ReadExtended(DriveNumber, 16, 1, Sector)) - { - DiskError("Disk read error."); - return FALSE; - } - - return (Sector[0] == 1 && - Sector[1] == 'C' && - Sector[2] == 'D' && - Sector[3] == '0' && - Sector[4] == '0' && - Sector[5] == '1'); - } - - // Drive is not CdRom so return FALSE - return FALSE; -} - - BOOL DiskGetActivePartitionEntry(U32 DriveNumber, PPARTITION_TABLE_ENTRY PartitionTableEntry) { U32 BootablePartitionCount = 0; @@ -106,12 +61,12 @@ BOOL DiskGetActivePartitionEntry(U32 DriveNumber, PPARTITION_TABLE_ENTRY Partiti // Make sure there was only one bootable partition if (BootablePartitionCount == 0) { - DiskError("No bootable (active) partitions found."); + DiskError("No bootable (active) partitions found.", 0); return FALSE; } else if (BootablePartitionCount != 1) { - DiskError("Too many bootable (active) partitions found."); + DiskError("Too many bootable (active) partitions found.", 0); return FALSE; } @@ -235,7 +190,7 @@ BOOL DiskGetFirstExtendedPartitionEntry(PMASTER_BOOT_RECORD MasterBootRecord, PP return FALSE; } -BOOL DiskReadBootRecord(U32 DriveNumber, U32 LogicalSectorNumber, PMASTER_BOOT_RECORD BootRecord) +BOOL DiskReadBootRecord(U32 DriveNumber, U64 LogicalSectorNumber, PMASTER_BOOT_RECORD BootRecord) { #ifdef DEBUG U32 Index; @@ -276,7 +231,7 @@ BOOL DiskReadBootRecord(U32 DriveNumber, U32 LogicalSectorNumber, PMASTER_BOOT_R // Check the partition table magic value if (BootRecord->MasterBootRecordMagic != 0xaa55) { - DiskError("Invalid partition table magic (0xaa55)"); + DiskError("Invalid partition table magic (0xaa55)", 0); return FALSE; } diff --git a/freeldr/freeldr/fs/fs.c b/freeldr/freeldr/fs/fs.c index da53165e7f3..71de1c4ae1f 100644 --- a/freeldr/freeldr/fs/fs.c +++ b/freeldr/freeldr/fs/fs.c @@ -33,7 +33,7 @@ // DATA ///////////////////////////////////////////////////////////////////////////////////////////// -U32 FileSystemType = 0; // Type of filesystem on boot device, set by OpenDiskDrive() +U32 FileSystemType = 0; // Type of filesystem on boot device, set by FsOpenVolume() ///////////////////////////////////////////////////////////////////////////////////////////// // FUNCTIONS @@ -48,9 +48,9 @@ VOID FileSystemError(PUCHAR ErrorString) /* * - * BOOL OpenDiskDrive(U32 DriveNumber, U32 PartitionNumber); + * BOOL FsOpenVolume(U32 DriveNumber, U32 PartitionNumber); * - * This function is called to open a disk drive for file access. + * This function is called to open a disk volume for file access. * It must be called before any of the file functions will work. * It takes two parameters: * @@ -61,12 +61,12 @@ VOID FileSystemError(PUCHAR ErrorString) * If it is zero then it opens the active (bootable) partition * */ -BOOL OpenDiskDrive(U32 DriveNumber, U32 PartitionNumber) +BOOL FsOpenVolume(U32 DriveNumber, U32 PartitionNumber) { PARTITION_TABLE_ENTRY PartitionTableEntry; UCHAR ErrorText[80]; - DbgPrint((DPRINT_FILESYSTEM, "OpenDiskDrive() DriveNumber: 0x%x PartitionNumber: 0x%x\n", DriveNumber, PartitionNumber)); + DbgPrint((DPRINT_FILESYSTEM, "FsOpenVolume() DriveNumber: 0x%x PartitionNumber: 0x%x\n", DriveNumber, PartitionNumber)); // Check and see if it is a floppy drive // If so then just assume FAT12 file system type @@ -141,7 +141,7 @@ BOOL OpenDiskDrive(U32 DriveNumber, U32 PartitionNumber) return TRUE; } -PFILE OpenFile(PUCHAR FileName) +PFILE FsOpenFile(PUCHAR FileName) { PFILE FileHandle = NULL; @@ -183,18 +183,18 @@ PFILE OpenFile(PUCHAR FileName) // if (FileHandle != NULL) { - DbgPrint((DPRINT_FILESYSTEM, "OpenFile() succeeded. FileHandle: 0x%x\n", FileHandle)); + DbgPrint((DPRINT_FILESYSTEM, "FsOpenFile() succeeded. FileHandle: 0x%x\n", FileHandle)); } else { - DbgPrint((DPRINT_FILESYSTEM, "OpenFile() failed.\n")); + DbgPrint((DPRINT_FILESYSTEM, "FsOpenFile() failed.\n")); } #endif // defined DEBUG return FileHandle; } -VOID CloseFile(PFILE FileHandle) +VOID FsCloseFile(PFILE FileHandle) { } @@ -202,12 +202,15 @@ VOID CloseFile(PFILE FileHandle) * ReadFile() * returns number of bytes read or EOF */ -BOOL ReadFile(PFILE FileHandle, U32 BytesToRead, U32* BytesRead, PVOID Buffer) +BOOL FsReadFile(PFILE FileHandle, U32 BytesToRead, U32* BytesRead, PVOID Buffer) { + U64 BytesReadBig; + BOOL Success; + // // Set the number of bytes read equal to zero // - if (BytesRead !=NULL) + if (BytesRead != NULL) { *BytesRead = 0; } @@ -224,7 +227,10 @@ BOOL ReadFile(PFILE FileHandle, U32 BytesToRead, U32* BytesRead, PVOID Buffer) case FS_EXT2: - return Ext2ReadFile(FileHandle, BytesToRead, BytesRead, Buffer); + //return Ext2ReadFile(FileHandle, BytesToRead, BytesRead, Buffer); + Success = Ext2ReadFile(FileHandle, BytesToRead, &BytesReadBig, Buffer); + *BytesRead = (U32)BytesReadBig; + return Success; default: @@ -235,7 +241,7 @@ BOOL ReadFile(PFILE FileHandle, U32 BytesToRead, U32* BytesRead, PVOID Buffer) return FALSE; } -U32 GetFileSize(PFILE FileHandle) +U32 FsGetFileSize(PFILE FileHandle) { switch (FileSystemType) { @@ -259,7 +265,7 @@ U32 GetFileSize(PFILE FileHandle) return 0; } -VOID SetFilePointer(PFILE FileHandle, U32 NewFilePointer) +VOID FsSetFilePointer(PFILE FileHandle, U32 NewFilePointer) { switch (FileSystemType) { @@ -284,7 +290,7 @@ VOID SetFilePointer(PFILE FileHandle, U32 NewFilePointer) } } -U32 GetFilePointer(PFILE FileHandle) +U32 FsGetFilePointer(PFILE FileHandle) { switch (FileSystemType) { @@ -311,9 +317,9 @@ U32 GetFilePointer(PFILE FileHandle) return 0; } -BOOL IsEndOfFile(PFILE FileHandle) +BOOL FsIsEndOfFile(PFILE FileHandle) { - if (GetFilePointer(FileHandle) >= GetFileSize(FileHandle)) + if (FsGetFilePointer(FileHandle) >= FsGetFileSize(FileHandle)) { return TRUE; } diff --git a/freeldr/freeldr/include/arch.h b/freeldr/freeldr/include/arch.h index 8da23675bf7..d7699fbd98d 100644 --- a/freeldr/freeldr/include/arch.h +++ b/freeldr/freeldr/include/arch.h @@ -16,7 +16,10 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ - + + +#ifndef __ARCH_H +#define __ARCH_H /* Defines needed for switching between real and protected mode */ #define NULL_DESC 0x00 /* NULL descriptor */ @@ -36,15 +39,14 @@ #define CR0_PE_SET 0x00000001 /* OR this value with CR0 to enable pmode */ #define CR0_PE_CLR 0xFFFFFFFE /* AND this value with CR0 to disable pmode */ -#define NR_TASKS 128 /* Space reserved in the GDT for TSS descriptors */ - #define STACK16ADDR 0x7000 /* The 16-bit stack top will be at 0000:7000 */ -#define STACK32ADDR 0x80000 /* The 32-bit stack top will be at 7000:FFFF, or 0x7FFFF */ +#define STACK32ADDR 0x78000 /* The 32-bit stack top will be at 7000:8000, or 0x78000 */ -#define MAXLOWMEMADDR 0x78000 /* The highest usuable low memory address for our memory allocator */ - -#define FILESYSBUFFER 0x80000 /* Buffer to store file system data (e.g. cluster buffer for FAT) */ -#define DISKREADBUFFER 0x90000 /* Buffer to store data read in from the disk via the BIOS */ +#define BIOSCALLBUFFER 0x78000 /* Buffer to store temporary data for any Int386() call */ +#define BIOSCALLBUFSEGMENT 0x7800 /* Buffer to store temporary data for any Int386() call */ +#define BIOSCALLBUFOFFSET 0x0000 /* Buffer to store temporary data for any Int386() call */ +#define FILESYSBUFFER 0x80000 /* Buffer to store file system data (e.g. cluster buffer for FAT) */ +#define DISKREADBUFFER 0x90000 /* Buffer to store data read in from the disk via the BIOS */ /* Makes "x" a global variable or label */ #define EXTERN(x) .global x; x: @@ -54,7 +56,111 @@ #ifndef ASM + +typedef struct +{ + unsigned long eax; + unsigned long ebx; + unsigned long ecx; + unsigned long edx; + + unsigned long esi; + unsigned long edi; + + unsigned short ds; + unsigned short es; + unsigned short fs; + unsigned short gs; + + unsigned long eflags; + +} PACKED DWORDREGS; + +typedef struct +{ + unsigned short ax, _upper_ax; + unsigned short bx, _upper_bx; + unsigned short cx, _upper_cx; + unsigned short dx, _upper_dx; + + unsigned short si, _upper_si; + unsigned short di, _upper_di; + + unsigned short ds; + unsigned short es; + unsigned short fs; + unsigned short gs; + + unsigned short flags, _upper_flags; + +} PACKED WORDREGS; + +typedef struct +{ + unsigned char al; + unsigned char ah; + unsigned short _upper_ax; + unsigned char bl; + unsigned char bh; + unsigned short _upper_bx; + unsigned char cl; + unsigned char ch; + unsigned short _upper_cx; + unsigned char dl; + unsigned char dh; + unsigned short _upper_dx; + + unsigned short si, _upper_si; + unsigned short di, _upper_di; + + unsigned short ds; + unsigned short es; + unsigned short fs; + unsigned short gs; + + unsigned short flags, _upper_flags; + +} PACKED BYTEREGS; + +typedef union +{ + DWORDREGS x; + DWORDREGS d; + WORDREGS w; + BYTEREGS b; +} REGS; + +// Int386() +// +// Real mode interrupt vector interface +// +// (E)FLAGS can *only* be returned by this function, not set. +// Make sure all memory pointers are in SEG:OFFS format and +// not linear addresses, unless the interrupt handler +// specifically handles linear addresses. +int Int386(int ivec, REGS* in, REGS* out); + +// Flag Masks +#define I386FLAG_CF 0x0001 // Carry Flag +#define I386FLAG_RESV1 0x0002 // Reserved - Must be 1 +#define I386FLAG_PF 0x0004 // Parity Flag +#define I386FLAG_RESV2 0x0008 // Reserved - Must be 0 +#define I386FLAG_AF 0x0010 // Auxiliary Flag +#define I386FLAG_RESV3 0x0020 // Reserved - Must be 0 +#define I386FLAG_ZF 0x0040 // Zero Flag +#define I386FLAG_SF 0x0080 // Sign Flag +#define I386FLAG_TF 0x0100 // Trap Flag (Single Step) +#define I386FLAG_IF 0x0200 // Interrupt Flag +#define I386FLAG_DF 0x0400 // Direction Flag +#define I386FLAG_OF 0x0800 // Overflow Flag + +// This macro tests the Carry Flag +// If CF is set then the call failed (usually) +#define INT386_SUCCESS(regs) ((regs.x.eflags & I386FLAG_CF) == 0) + void EnableA20(void); -void StopFloppyMotor(void); #endif /* ! ASM */ + + +#endif // #defined __ARCH_H diff --git a/freeldr/freeldr/include/debug.h b/freeldr/freeldr/include/debug.h index ec1d7947295..ac712dbb466 100644 --- a/freeldr/freeldr/include/debug.h +++ b/freeldr/freeldr/include/debug.h @@ -23,7 +23,7 @@ #ifdef DEBUG - #define DPRINT_NONE 0x00000000 // Simple debug print + #define DPRINT_NONE 0x00000000 // No debug print #define DPRINT_WARNING 0x00000001 // OR this with DebugPrintMask to enable debugger messages and other misc stuff #define DPRINT_MEMORY 0x00000002 // OR this with DebugPrintMask to enable memory management messages #define DPRINT_FILESYSTEM 0x00000004 // OR this with DebugPrintMask to enable file system messages @@ -39,8 +39,8 @@ VOID DebugPrint(U32 Mask, char *format, ...); VOID DebugDumpBuffer(U32 Mask, PVOID Buffer, U32 Length); - #define DbgPrint(_x_) { DebugPrint(DPRINT_NONE, "%s:%d(%s)\n", __FILE__, __LINE__, __FUNCTION__); DebugPrint _x_ ; } - #define BugCheck(_x_) { DebugPrint(DPRINT_WARNING, "Fatal Error: %s:%d(%s)\n", __FILE__, __LINE__, __FUNCTION__); DebugPrint _x_ ; for (;;); } + #define DbgPrint(_x_) DebugPrint _x_ ; + #define BugCheck(_x_) { DebugPrint(DPRINT_WARNING, "Fatal Error: %s:%d(%s)\n", __FILE__, __LINE__, __FUNCTION__); DebugPrint _x_ ; for (;;); } #define DbgDumpBuffer(_x_, _y_, _z_) DebugDumpBuffer(_x_, _y_, _z_) #ifdef __i386__ @@ -78,6 +78,6 @@ void MEMORY_WRITE_BREAKPOINT4(unsigned long addr); #endif // defined DEBUG -#define UNIMPLEMENTED BugCheck((DPRINT_WARNING, "Unimplemented\n")); +#define UNIMPLEMENTED() BugCheck((DPRINT_WARNING, "This function is unimplemented!\n")) #endif // defined __DEBUG_H diff --git a/freeldr/freeldr/include/disk.h b/freeldr/freeldr/include/disk.h index 08eb60dda6a..9d34ff2c1b4 100644 --- a/freeldr/freeldr/include/disk.h +++ b/freeldr/freeldr/include/disk.h @@ -23,10 +23,10 @@ typedef struct _GEOMETRY { - U32 Cylinders; - U32 Heads; - U32 Sectors; - U32 BytesPerSector; + U32 Cylinders; // Number of cylinders on the disk + U32 Heads; // Number of heads on the disk + U32 Sectors; // Number of sectors per track + U32 BytesPerSector; // Number of bytes per sector } GEOMETRY, *PGEOMETRY; @@ -83,42 +83,44 @@ typedef struct _MASTER_BOOT_RECORD /////////////////////////////////////////////////////////////////////////////////////// // -// BIOS Disk Functions +// i386 BIOS Disk Functions (i386disk.c) // /////////////////////////////////////////////////////////////////////////////////////// -int biosdisk(int cmd, int drive, int head, int track, int sector, int nsects, void *buffer); // Implemented in asmcode.S +#ifdef __i386__ -BOOL BiosInt13Read(U32 Drive, U32 Head, U32 Track, U32 Sector, U32 SectorCount, PVOID Buffer); // Implemented in asmcode.S -BOOL BiosInt13ReadExtended(U32 Drive, U32 Sector, U32 SectorCount, PVOID Buffer); // Implemented in asmcode.S -BOOL BiosInt13ExtensionsSupported(U32 Drive); -U32 BiosInt13GetLastErrorCode(VOID); +//BOOL DiskReadLogicalSectors(U32 DriveNumber, U64 SectorNumber, U32 SectorCount, PVOID Buffer); +BOOL DiskReadLogicalSectorsLBA(U32 DriveNumber, U64 SectorNumber, U32 SectorCount, PVOID Buffer); +BOOL DiskReadLogicalSectorsCHS(U32 DriveNumber, U64 SectorNumber, U32 SectorCount, PVOID Buffer); +BOOL DiskResetController(U32 DriveNumber); +BOOL DiskInt13ExtensionsSupported(U32 DriveNumber); +//VOID DiskStopFloppyMotor(VOID); +BOOL DiskGetDriveParameters(U32 DriveNumber, PGEOMETRY Geometry); +//U32 DiskGetCacheableBlockCount(U32 DriveNumber); -void StopFloppyMotor(void); // Implemented in asmcode.S -int get_heads(int drive); // Implemented in asmcode.S -int get_cylinders(int drive); // Implemented in asmcode.S -int get_sectors(int drive); // Implemented in asmcode.S -BOOL BiosInt13GetDriveParameters(U32 Drive, PGEOMETRY Geometry); // Implemented in disk.S +#endif // defined __i386__ /////////////////////////////////////////////////////////////////////////////////////// // // FreeLoader Disk Functions // /////////////////////////////////////////////////////////////////////////////////////// -VOID DiskError(PUCHAR ErrorString); +VOID DiskError(PUCHAR ErrorString, U32 ErrorCode); BOOL DiskGetDriveGeometry(U32 DriveNumber, PGEOMETRY DriveGeometry); -BOOL DiskReadLogicalSectors(U32 DriveNumber, U32 SectorNumber, U32 SectorCount, PVOID Buffer); +BOOL DiskReadLogicalSectors(U32 DriveNumber, U64 SectorNumber, U32 SectorCount, PVOID Buffer); // Implemented in i386disk.c +BOOL DiskIsDriveRemovable(U32 DriveNumber); +BOOL DiskIsDriveCdRom(U32 DriveNumber); +VOID DiskStopFloppyMotor(VOID); // Implemented in i386disk.c +U32 DiskGetCacheableBlockCount(U32 DriveNumber); // Implemented in i386disk.c /////////////////////////////////////////////////////////////////////////////////////// // // Fixed Disk Partition Management Functions // /////////////////////////////////////////////////////////////////////////////////////// -BOOL DiskIsDriveRemovable(U32 DriveNumber); -BOOL DiskIsDriveCdRom(U32 DriveNumber); BOOL DiskGetActivePartitionEntry(U32 DriveNumber, PPARTITION_TABLE_ENTRY PartitionTableEntry); BOOL DiskGetPartitionEntry(U32 DriveNumber, U32 PartitionNumber, PPARTITION_TABLE_ENTRY PartitionTableEntry); BOOL DiskGetFirstPartitionEntry(PMASTER_BOOT_RECORD MasterBootRecord, PPARTITION_TABLE_ENTRY PartitionTableEntry); BOOL DiskGetFirstExtendedPartitionEntry(PMASTER_BOOT_RECORD MasterBootRecord, PPARTITION_TABLE_ENTRY PartitionTableEntry); -BOOL DiskReadBootRecord(U32 DriveNumber, U32 LogicalSectorNumber, PMASTER_BOOT_RECORD BootRecord); +BOOL DiskReadBootRecord(U32 DriveNumber, U64 LogicalSectorNumber, PMASTER_BOOT_RECORD BootRecord); #endif // defined __DISK_H diff --git a/freeldr/freeldr/include/fs.h b/freeldr/freeldr/include/fs.h index 9bbdaececac..e1bbec08748 100644 --- a/freeldr/freeldr/include/fs.h +++ b/freeldr/freeldr/include/fs.h @@ -33,14 +33,14 @@ #define PFILE FILE * VOID FileSystemError(PUCHAR ErrorString); -BOOL OpenDiskDrive(U32 DriveNumber, U32 PartitionNumber); -PFILE OpenFile(PUCHAR FileName); -VOID CloseFile(PFILE FileHandle); -BOOL ReadFile(PFILE FileHandle, U32 BytesToRead, U32* BytesRead, PVOID Buffer); -U32 GetFileSize(PFILE FileHandle); -VOID SetFilePointer(PFILE FileHandle, U32 NewFilePointer); -U32 GetFilePointer(PFILE FileHandle); -BOOL IsEndOfFile(PFILE FileHandle); +BOOL FsOpenVolume(U32 DriveNumber, U32 PartitionNumber); +PFILE FsOpenFile(PUCHAR FileName); +VOID FsCloseFile(PFILE FileHandle); +BOOL FsReadFile(PFILE FileHandle, U32 BytesToRead, U32* BytesRead, PVOID Buffer); +U32 FsGetFileSize(PFILE FileHandle); +VOID FsSetFilePointer(PFILE FileHandle, U32 NewFilePointer); +U32 FsGetFilePointer(PFILE FileHandle); +BOOL FsIsEndOfFile(PFILE FileHandle); U32 FsGetNumPathParts(PUCHAR Path); VOID FsGetFirstNameFromPath(PUCHAR Buffer, PUCHAR Path); diff --git a/freeldr/freeldr/include/linux.h b/freeldr/freeldr/include/linux.h index f41702c343c..805c72c6d85 100644 --- a/freeldr/freeldr/include/linux.h +++ b/freeldr/freeldr/include/linux.h @@ -127,6 +127,6 @@ BOOL LinuxReadBootSector(PFILE LinuxKernelFile); BOOL LinuxReadSetupSector(PFILE LinuxKernelFile); BOOL LinuxReadKernel(PFILE LinuxKernelFile); BOOL LinuxCheckKernelVersion(VOID); -BOOL LinuxReadInitrd(VOID); +BOOL LinuxReadInitrd(PFILE LinuxInitrdFile); #endif // defined __LINUX_H diff --git a/freeldr/freeldr/include/mm.h b/freeldr/freeldr/include/mm.h index 281cee477d1..0e49555572f 100644 --- a/freeldr/freeldr/include/mm.h +++ b/freeldr/freeldr/include/mm.h @@ -35,18 +35,13 @@ typedef struct U32 Reserved; } PACKED BIOS_MEMORY_MAP, *PBIOS_MEMORY_MAP; -typedef struct -{ - BIOS_MEMORY_MAP BiosMemoryMapArray[32]; -} PACKED BIOS_MEMORY_MAP_ARRAY, *PBIOS_MEMORY_MAP_ARRAY; - U32 GetSystemMemorySize(VOID); // Returns the amount of total memory in the system // These functions are implemented in mem.S U32 GetExtendedMemorySize(VOID); // Returns extended memory size in KB U32 GetConventionalMemorySize(VOID); // Returns conventional memory size in KB -U32 GetBiosMemoryMap(PBIOS_MEMORY_MAP_ARRAY BiosMemoryMap); // Fills structure with BIOS memory map and returns memory map item count +U32 GetBiosMemoryMap(BIOS_MEMORY_MAP BiosMemoryMap[32]); // Fills structure with BIOS memory map and returns memory map item count diff --git a/freeldr/freeldr/include/rtl.h b/freeldr/freeldr/include/rtl.h index 83a9c3509d2..fc239ed2a2b 100644 --- a/freeldr/freeldr/include/rtl.h +++ b/freeldr/freeldr/include/rtl.h @@ -44,14 +44,14 @@ int strnicmp(const char *string1, const char *string2, size_t length); // Memory Functions // /////////////////////////////////////////////////////////////////////////////////////// -int RtlCompareMemory(const PVOID Source1, const PVOID Source2, U32 Length); -VOID RtlCopyMemory(PVOID Destination, const PVOID Source, U32 Length); -VOID RtlFillMemory(PVOID Destination, U32 Length, UCHAR Fill); -VOID RtlZeroMemory(PVOID Destination, U32 Length); +int memcmp(const void *buf1, const void *buf2, size_t count); +void * memcpy(void *to, const void *from, size_t count); +void * memset(void *src, int val, size_t count); -#define memcmp(buf1, buf2, count) RtlCompareMemory(buf1, buf2, count) -#define memcpy(dest, src, count) RtlCopyMemory(dest, src,count) -#define memset(dest, c, count) RtlFillMemory(dest,count, c) +#define RtlCompareMemory(Source1, Source2, Length) memcmp(Source1, Source2, Length) +#define RtlCopyMemory(Destination, Source, Length) memcpy(Destination, Source, Length) +#define RtlFillMemory(Destination, Length, Fill) memset(Destination, Fill, Length) +#define RtlZeroMemory(Destination, Length) memset(Destination, 0, Length) /////////////////////////////////////////////////////////////////////////////////////// // diff --git a/freeldr/freeldr/include/ui.h b/freeldr/freeldr/include/ui.h index 9cc4c4bdbeb..e4150b536a1 100644 --- a/freeldr/freeldr/include/ui.h +++ b/freeldr/freeldr/include/ui.h @@ -44,6 +44,8 @@ extern PUCHAR UiMessageBoxLineText; extern BOOL UserInterfaceUp; // Tells us if the user interface is displayed +extern BOOL UiUseSpecialEffects; // Tells us if we should use fade effects + extern UCHAR UiMonthNames[12][15]; /////////////////////////////////////////////////////////////////////////////////////// @@ -52,6 +54,7 @@ extern UCHAR UiMonthNames[12][15]; // /////////////////////////////////////////////////////////////////////////////////////// BOOL UiInitialize(VOID); // Initialize User-Interface +VOID UiUnInitialize(PUCHAR BootText); // Un-initialize User-Interface VOID UiDrawBackdrop(VOID); // Fills the entire screen with a backdrop VOID UiFillArea(U32 Left, U32 Top, U32 Right, U32 Bottom, UCHAR FillChar, UCHAR Attr /* Color Attributes */); // Fills the area specified with FillChar and Attr VOID UiDrawShadow(U32 Left, U32 Top, U32 Right, U32 Bottom); // Draws a shadow on the bottom and right sides of the area specified @@ -60,6 +63,7 @@ VOID UiDrawText(U32 X, U32 Y, PUCHAR Text, UCHAR Attr); // Draws text at coordin VOID UiDrawCenteredText(U32 Left, U32 Top, U32 Right, U32 Bottom, PUCHAR TextString, UCHAR Attr); // Draws centered text at the coordinates specified and clips the edges VOID UiDrawStatusText(PUCHAR StatusText); // Draws text at the very bottom line on the screen VOID UiUpdateDateTime(VOID); // Updates the date and time +VOID UiInfoBox(PUCHAR MessageText); // Displays a info box on the screen VOID UiMessageBox(PUCHAR MessageText); // Displays a message box on the screen with an ok button VOID UiMessageBoxCritical(PUCHAR MessageText); // Displays a message box on the screen with an ok button using no system resources VOID UiMessageLine(PUCHAR MessageText); // Adds a line of text to the message box buffer @@ -72,6 +76,9 @@ UCHAR UiTextToFillStyle(PUCHAR FillStyleText); // Converts the text fill into VOID UiTruncateStringEllipsis(PUCHAR StringText, U32 MaxChars); // Truncates a string to MaxChars by adding an ellipsis on the end '...' +VOID UiFadeInBackdrop(VOID); // Draws the backdrop and fades the screen in +VOID UiFadeOut(VOID); // Fades the screen out + /////////////////////////////////////////////////////////////////////////////////////// // // Menu Functions diff --git a/freeldr/freeldr/include/video.h b/freeldr/freeldr/include/video.h index 55cc48ac703..a9ad80b5783 100644 --- a/freeldr/freeldr/include/video.h +++ b/freeldr/freeldr/include/video.h @@ -21,10 +21,18 @@ #define __VIDEO_H + #define VIDEOCARD_CGA_OR_OTHER 0 #define VIDEOCARD_EGA 1 #define VIDEOCARD_VGA 2 +#define VERTRES_200_SCANLINES 0x00 +#define VERTRES_350_SCANLINES 0x01 +#define VERTRES_400_SCANLINES 0x02 + +#define MODETYPE_TEXT 0 +#define MODETYPE_GRAPHICS 1 + #define VIDEOMODE_NORMAL_TEXT 0 #define VIDEOMODE_EXTENDED_TEXT 1 #define VIDEOMODE_80X28 0x501C @@ -32,32 +40,114 @@ #define VIDEOMODE_80X34 0x5022 #define VIDEOMODE_80X43 0x502B #define VIDEOMODE_80X60 0x503C +#define VIDEOMODE_132X25 0x8419 +#define VIDEOMODE_132X43 0x842B +#define VIDEOMODE_132X50 0x8432 +#define VIDEOMODE_132X60 0x843C #define VIDEOPORT_PALETTE_READ 0x03C7 #define VIDEOPORT_PALETTE_WRITE 0x03C8 #define VIDEOPORT_PALETTE_DATA 0x03C9 #define VIDEOPORT_VERTICAL_RETRACE 0x03DA -VOID BiosSetVideoMode(U32 VideoMode); // Implemented in biosvid.S -VOID BiosSetVideoFont8x8(VOID); // Implemented in biosvid.S -VOID BiosSetVideoFont8x14(VOID); // Implemented in biosvid.S -VOID BiosSetVideoFont8x16(VOID); // Implemented in biosvid.S -VOID BiosSelectAlternatePrintScreen(VOID); // Implemented in biosvid.S -VOID BiosDisableCursorEmulation(VOID); // Implemented in biosvid.S -VOID BiosDefineCursor(U32 StartScanLine, U32 EndScanLine); // Implemented in biosvid.S -U32 BiosDetectVideoCard(VOID); // Implemented in biosvid.S -VOID BiosSet200ScanLines(VOID); // Implemented in biosvid.S, must be called right before BiosSetVideoMode() -VOID BiosSet350ScanLines(VOID); // Implemented in biosvid.S, must be called right before BiosSetVideoMode() -VOID BiosSet400ScanLines(VOID); // Implemented in biosvid.S, must be called right before BiosSetVideoMode() -VOID BiosSet480ScanLines(VOID); // Implemented in biosvid.S, must be called right after BiosSetVideoMode() -VOID BiosSetVideoDisplayEnd(VOID); // Implemented in biosvid.S -VOID BiosVideoDisableBlinkBit(VOID); // Implemented in biosvid.S +#define VIDEOVGA_MEM_ADDRESS 0xA0000 +#define VIDEOTEXT_MEM_ADDRESS 0xB8000 -VOID VideoSetTextCursorPosition(U32 X, U32 Y); // Implemented in biosvid.S -VOID VideoHideTextCursor(VOID); // Implemented in biosvid.S -VOID VideoShowTextCursor(VOID); // Implemented in biosvid.S -U32 VideoGetTextCursorPositionX(VOID); // Implemented in biosvid.S -U32 VideoGetTextCursorPositionY(VOID); // Implemented in biosvid.S +typedef struct +{ + U8 Red; + U8 Green; + U8 Blue; +} PACKED PALETTE_ENTRY, *PPALETTE_ENTRY; + +typedef struct +{ + U16 ModeAttributes; // mode attributes (see #00080) + U8 WindowAttributesA; // window attributes, window A (see #00081) + U8 WindowsAttributesB; // window attributes, window B (see #00081) + U16 WindowGranularity; // window granularity in KB + U16 WindowSize; // window size in KB + U16 WindowAStartSegment; // start segment of window A (0000h if not supported) + U16 WindowBStartSegment; // start segment of window B (0000h if not supported) + U32 WindowPositioningFunction; // -> FAR window positioning function (equivalent to AX=4F05h) + U16 BytesPerScanLine; // bytes per scan line + //---remainder is optional for VESA modes in v1.0/1.1, needed for OEM modes--- + U16 WidthInPixels; // width in pixels (graphics) or characters (text) + U16 HeightInPixels; // height in pixels (graphics) or characters (text) + U8 CharacterWidthInPixels; // width of character cell in pixels + U8 CharacterHeightInPixels; // height of character cell in pixels + U8 NumberOfMemoryPlanes; // number of memory planes + U8 BitsPerPixel; // number of bits per pixel + U8 NumberOfBanks; // number of banks + U8 MemoryModel; // memory model type (see #00082) + U8 BankSize; // size of bank in KB + U8 NumberOfImagePanes; // number of image pages (less one) that will fit in video RAM + U8 Reserved1; // reserved (00h for VBE 1.0-2.0, 01h for VBE 3.0) + //---VBE v1.2+ --- + U8 RedMaskSize; // red mask size + U8 RedMaskPosition; // red field position + U8 GreenMaskSize; // green mask size + U8 GreenMaskPosition; // green field size + U8 BlueMaskSize; // blue mask size + U8 BlueMaskPosition; // blue field size + U8 ReservedMaskSize; // reserved mask size + U8 ReservedMaskPosition; // reserved mask position + U8 DirectColorModeInfo; // direct color mode info + // bit 0:Color ramp is programmable + // bit 1:Bytes in reserved field may be used by application + //---VBE v2.0+ --- + U32 LinearVideoBufferAddress; // physical address of linear video buffer + U32 OffscreenMemoryPointer; // pointer to start of offscreen memory + U16 OffscreenMemorySize; // KB of offscreen memory + //---VBE v3.0 --- + U16 LinearBytesPerScanLine; // bytes per scan line in linear modes + U8 BankedNumberOfImages; // number of images (less one) for banked video modes + U8 LinearNumberOfImages; // number of images (less one) for linear video modes + U8 LinearRedMaskSize; // linear modes:Size of direct color red mask (in bits) + U8 LinearRedMaskPosition; // linear modes:Bit position of red mask LSB (e.g. shift count) + U8 LinearGreenMaskSize; // linear modes:Size of direct color green mask (in bits) + U8 LinearGreenMaskPosition; // linear modes:Bit position of green mask LSB (e.g. shift count) + U8 LinearBlueMaskSize; // linear modes:Size of direct color blue mask (in bits) + U8 LinearBlueMaskPosition; // linear modes:Bit position of blue mask LSB (e.g. shift count) + U8 LinearReservedMaskSize; // linear modes:Size of direct color reserved mask (in bits) + U8 LinearReservedMaskPosition; // linear modes:Bit position of reserved mask LSB + U32 MaximumPixelClock; // maximum pixel clock for graphics video mode, in Hz + U8 Reserved2[190]; // 190 BYTEs reserved (0) +} PACKED SVGA_MODE_INFORMATION, *PSVGA_MODE_INFORMATION; + + +extern U32 CurrentMemoryBank; +extern SVGA_MODE_INFORMATION VesaVideoModeInformation; + +extern PVOID VideoOffScreenBuffer; + + + + +VOID BiosSetVideoMode(U32 VideoMode); // Implemented in i386vid.S +VOID BiosSetVideoFont8x8(VOID); // Implemented in i386vid.S +VOID BiosSetVideoFont8x14(VOID); // Implemented in i386vid.S +VOID BiosSetVideoFont8x16(VOID); // Implemented in i386vid.S +VOID BiosSelectAlternatePrintScreen(VOID); // Implemented in i386vid.S +VOID BiosDisableCursorEmulation(VOID); // Implemented in i386vid.S +VOID BiosDefineCursor(U32 StartScanLine, U32 EndScanLine); // Implemented in i386vid.S +U32 BiosDetectVideoCard(VOID); // Implemented in i386vid.S +VOID BiosSetVerticalResolution(U32 ScanLines); // Implemented in i386vid.S, must be called right before BiosSetVideoMode() +VOID BiosSet480ScanLines(VOID); // Implemented in i386vid.S, must be called right after BiosSetVideoMode() +VOID BiosSetVideoDisplayEnd(VOID); // Implemented in i386vid.S +VOID BiosVideoDisableBlinkBit(VOID); // Implemented in i386vid.S +VOID BiosVideoEnableBlinkBit(VOID); // Implemented in i386vid.S + +U16 BiosIsVesaSupported(VOID); // Implemented in i386vid.S, returns the VESA version +BOOL BiosVesaSetBank(U16 Bank); // Implemented in i386vid.S +BOOL BiosVesaSetVideoMode(U16 Mode); // Implemented in i386vid.S +BOOL BiosVesaGetSVGAModeInformation(U16 Mode, PSVGA_MODE_INFORMATION ModeInformation); // Implemented in i386vid.S + +VOID VideoSetTextCursorPosition(U32 X, U32 Y); // Implemented in i386vid.S +VOID VideoHideTextCursor(VOID); // Implemented in i386vid.S +VOID VideoShowTextCursor(VOID); // Implemented in i386vid.S +U32 VideoGetTextCursorPositionX(VOID); // Implemented in i386vid.S +U32 VideoGetTextCursorPositionY(VOID); // Implemented in i386vid.S BOOL VideoSetMode(U32 VideoMode); BOOL VideoSetMode80x25(VOID); // Sets 80x25 @@ -69,12 +159,39 @@ BOOL VideoSetMode80x34(VOID); // Sets 80x34. Works on all VGA's. 480 scanli BOOL VideoSetMode80x60(VOID); // Sets 80x60. Works on all VGA's. 480 scanlines, 8-pixel font. U32 VideoGetCurrentModeResolutionX(VOID); U32 VideoGetCurrentModeResolutionY(VOID); +U32 VideoGetBytesPerScanLine(VOID); U32 VideoGetCurrentMode(VOID); +U32 VideoGetCurrentModeType(VOID); // MODETYPE_TEXT or MODETYPE_GRAPHICS +BOOL VideoIsCurrentModeVesa(VOID); +U32 VideoGetCurrentModeColorDepth(VOID); // Returns 0 for text mode, 16 for 4-bit, 256 for 8-bit, 32768 for 15-bit, 65536 for 16-bit, etc. VOID VideoClearScreen(VOID); VOID VideoWaitForVerticalRetrace(VOID); -VOID VideoSetPaletteColor(UCHAR Color, UCHAR Red, UCHAR Green, UCHAR Blue); -VOID VideoGetPaletteColor(UCHAR Color, PUCHAR Red, PUCHAR Green, PUCHAR Blue); +PVOID VideoAllocateOffScreenBuffer(VOID); // Returns a pointer to an off-screen buffer sufficient for the current video mode + +U32 VideoGetMemoryBankForPixel(U32 X, U32 Y); +U32 VideoGetMemoryBankForPixel16(U32 X, U32 Y); +U32 VideoGetBankOffsetForPixel(U32 X, U32 Y); +U32 VideoGetBankOffsetForPixel16(U32 X, U32 Y); +VOID VideoSetMemoryBank(U16 BankNumber); +U32 VideoGetOffScreenMemoryOffsetForPixel(U32 X, U32 Y); +VOID VideoCopyOffScreenBufferToVRAM(VOID); + +VOID VideoSetPaletteColor(U8 Color, U8 Red, U8 Green, U8 Blue); +VOID VideoGetPaletteColor(U8 Color, U8* Red, U8* Green, U8* Blue); +VOID VideoSavePaletteState(PPALETTE_ENTRY Palette, U32 ColorCount); +VOID VideoRestorePaletteState(PPALETTE_ENTRY Palette, U32 ColorCount); + +VOID VideoSetPixel16(U32 X, U32 Y, U8 Color); +VOID VideoSetPixel256(U32 X, U32 Y, U8 Color); +VOID VideoSetPixelRGB(U32 X, U32 Y, U8 Red, U8 Green, U8 Blue); +VOID VideoSetPixel16_OffScreen(U32 X, U32 Y, U8 Color); +VOID VideoSetPixel256_OffScreen(U32 X, U32 Y, U8 Color); +VOID VideoSetPixelRGB_OffScreen(U32 X, U32 Y, U8 Red, U8 Green, U8 Blue); + +VOID VideoSetAllColorsToBlack(U32 ColorCount); +VOID VideoFadeIn(PPALETTE_ENTRY Palette, U32 ColorCount); +VOID VideoFadeOut(U32 ColorCount); #endif // defined __VIDEO_H diff --git a/freeldr/freeldr/inifile/ini_init.c b/freeldr/freeldr/inifile/ini_init.c index 737e1cc402f..d72d51c6442 100644 --- a/freeldr/freeldr/inifile/ini_init.c +++ b/freeldr/freeldr/inifile/ini_init.c @@ -58,26 +58,26 @@ BOOL IniFileInitialize(VOID) } // Get the file size & allocate enough memory for it - FreeLoaderIniFileSize = GetFileSize(Freeldr_Ini); + FreeLoaderIniFileSize = FsGetFileSize(Freeldr_Ini); FreeLoaderIniFileData = MmAllocateMemory(FreeLoaderIniFileSize); // If we are out of memory then return FALSE if (FreeLoaderIniFileData == NULL) { printf("Out of memory while loading freeldr.ini.\n"); - CloseFile(Freeldr_Ini); + FsCloseFile(Freeldr_Ini); return FALSE; } // Read freeldr.ini off the disk - if (!ReadFile(Freeldr_Ini, FreeLoaderIniFileSize, NULL, FreeLoaderIniFileData)) + if (!FsReadFile(Freeldr_Ini, FreeLoaderIniFileSize, NULL, FreeLoaderIniFileData)) { - CloseFile(Freeldr_Ini); + FsCloseFile(Freeldr_Ini); MmFreeMemory(FreeLoaderIniFileData); return FALSE; } - CloseFile(Freeldr_Ini); + FsCloseFile(Freeldr_Ini); // Parse the .ini file data Success = IniParseFile(FreeLoaderIniFileData, FreeLoaderIniFileSize); @@ -91,7 +91,7 @@ PFILE IniOpenIniFile(U8 BootDriveNumber, U8 BootPartitionNumber) { PFILE IniFileHandle; // File handle for freeldr.ini - if (!OpenDiskDrive(BootDriveNumber, BootPartitionNumber)) + if (!FsOpenVolume(BootDriveNumber, BootPartitionNumber)) { if (BootPartitionNumber == 0) { @@ -106,7 +106,7 @@ PFILE IniOpenIniFile(U8 BootDriveNumber, U8 BootPartitionNumber) } // Try to open freeldr.ini - IniFileHandle = OpenFile("freeldr.ini"); + IniFileHandle = FsOpenFile("freeldr.ini"); return IniFileHandle; } diff --git a/freeldr/freeldr/linuxboot.c b/freeldr/freeldr/linuxboot.c index 5d9dbcc86c7..762b236b50d 100644 --- a/freeldr/freeldr/linuxboot.c +++ b/freeldr/freeldr/linuxboot.c @@ -20,6 +20,7 @@ #include #include +#include #include #include #include @@ -31,11 +32,17 @@ #include // For RemoveQuotes() #include + + +#define LINUX_READ_CHUNK_SIZE 0x20000 // Read 128k at a time + + PLINUX_BOOTSECTOR LinuxBootSector = NULL; PLINUX_SETUPSECTOR LinuxSetupSector = NULL; U32 SetupSectorSize = 0; BOOL NewStyleLinuxKernel = FALSE; U32 LinuxKernelSize = 0; +U32 LinuxInitrdSize = 0; UCHAR LinuxKernelName[260]; UCHAR LinuxInitrdName[260]; BOOL LinuxHasInitrd = FALSE; @@ -47,10 +54,14 @@ PVOID LinuxInitrdLoadAddress = NULL; VOID LoadAndBootLinux(PUCHAR OperatingSystemName) { PFILE LinuxKernel = NULL; + PFILE LinuxInitrdFile = NULL; UCHAR TempString[260]; UiDrawBackdrop(); + UiDrawStatusText("Loading Linux..."); + UiDrawProgressBarCenter(0, 100); + // Parse the .ini file section if (!LinuxParseIniSection(OperatingSystemName)) { @@ -58,14 +69,14 @@ VOID LoadAndBootLinux(PUCHAR OperatingSystemName) } // Open the boot volume - if (!OpenDiskDrive(BootDrive, BootPartition)) + if (!FsOpenVolume(BootDrive, BootPartition)) { UiMessageBox("Failed to open boot drive."); goto LinuxBootFailed; } // Open the kernel - LinuxKernel = OpenFile(LinuxKernelName); + LinuxKernel = FsOpenFile(LinuxKernelName); if (LinuxKernel == NULL) { sprintf(TempString, "Linux kernel \'%s\' not found.", LinuxKernelName); @@ -73,6 +84,18 @@ VOID LoadAndBootLinux(PUCHAR OperatingSystemName) goto LinuxBootFailed; } + // Open the initrd file image (if necessary) + if (LinuxHasInitrd) + { + LinuxInitrdFile = FsOpenFile(LinuxInitrdName); + if (LinuxInitrdFile == NULL) + { + sprintf(TempString, "Linux initrd image \'%s\' not found.", LinuxInitrdName); + UiMessageBox(TempString); + goto LinuxBootFailed; + } + } + // Read the boot sector if (!LinuxReadBootSector(LinuxKernel)) { @@ -85,6 +108,12 @@ VOID LoadAndBootLinux(PUCHAR OperatingSystemName) goto LinuxBootFailed; } + // Calc kernel size + LinuxKernelSize = FsGetFileSize(LinuxKernel) - (512 + SetupSectorSize); + + // Get the file size + LinuxInitrdSize = FsGetFileSize(LinuxInitrdFile); + // Read the kernel if (!LinuxReadKernel(LinuxKernel)) { @@ -94,7 +123,7 @@ VOID LoadAndBootLinux(PUCHAR OperatingSystemName) // Read the initrd (if necessary) if (LinuxHasInitrd) { - if (!LinuxReadInitrd()) + if (!LinuxReadInitrd(LinuxInitrdFile)) { goto LinuxBootFailed; } @@ -122,10 +151,9 @@ VOID LoadAndBootLinux(PUCHAR OperatingSystemName) RtlCopyMemory((PVOID)0x90200, LinuxSetupSector, SetupSectorSize); RtlCopyMemory((PVOID)0x99000, LinuxCommandLine, LinuxCommandLineSize); - VideoShowTextCursor(); - VideoClearScreen(); + UiUnInitialize("Booting Linux..."); - StopFloppyMotor(); + DiskStopFloppyMotor(); if (LinuxSetupSector->LoadFlags & LINUX_FLAG_LOAD_HIGH) { @@ -141,7 +169,11 @@ LinuxBootFailed: if (LinuxKernel != NULL) { - CloseFile(LinuxKernel); + FsCloseFile(LinuxKernel); + } + if (LinuxInitrdFile != NULL) + { + FsCloseFile(LinuxInitrdFile); } if (LinuxBootSector != NULL) @@ -237,8 +269,8 @@ BOOL LinuxReadBootSector(PFILE LinuxKernelFile) } // Read linux boot sector - SetFilePointer(LinuxKernelFile, 0); - if (!ReadFile(LinuxKernelFile, 512, NULL, LinuxBootSector)) + FsSetFilePointer(LinuxKernelFile, 0); + if (!FsReadFile(LinuxKernelFile, 512, NULL, LinuxBootSector)) { return FALSE; } @@ -271,8 +303,8 @@ BOOL LinuxReadSetupSector(PFILE LinuxKernelFile) LinuxSetupSector = (PLINUX_SETUPSECTOR)TempLinuxSetupSector; // Read first linux setup sector - SetFilePointer(LinuxKernelFile, 512); - if (!ReadFile(LinuxKernelFile, 512, NULL, TempLinuxSetupSector)) + FsSetFilePointer(LinuxKernelFile, 512); + if (!FsReadFile(LinuxKernelFile, 512, NULL, TempLinuxSetupSector)) { return FALSE; } @@ -303,8 +335,8 @@ BOOL LinuxReadSetupSector(PFILE LinuxKernelFile) RtlCopyMemory(LinuxSetupSector, TempLinuxSetupSector, 512); // Read in the rest of the linux setup sectors - SetFilePointer(LinuxKernelFile, 1024); - if (!ReadFile(LinuxKernelFile, SetupSectorSize - 512, NULL, ((PVOID)LinuxSetupSector) + 512)) + FsSetFilePointer(LinuxKernelFile, 1024); + if (!FsReadFile(LinuxKernelFile, SetupSectorSize - 512, NULL, ((PVOID)LinuxSetupSector) + 512)) { return FALSE; } @@ -338,10 +370,6 @@ BOOL LinuxReadKernel(PFILE LinuxKernelFile) sprintf(StatusText, "Loading %s", LinuxKernelName); UiDrawStatusText(StatusText); - UiDrawProgressBarCenter(0, 100); - - // Calc kernel size - LinuxKernelSize = GetFileSize(LinuxKernelFile) - (512 + SetupSectorSize); // Allocate memory for Linux kernel LinuxKernelLoadAddress = MmAllocateMemoryAtAddress(LinuxKernelSize, (PVOID)LINUX_KERNEL_LOAD_ADDRESS); @@ -353,18 +381,18 @@ BOOL LinuxReadKernel(PFILE LinuxKernelFile) LoadAddress = LinuxKernelLoadAddress; // Read linux kernel to 0x100000 (1mb) - SetFilePointer(LinuxKernelFile, 512 + SetupSectorSize); + FsSetFilePointer(LinuxKernelFile, 512 + SetupSectorSize); for (BytesLoaded=0; BytesLoaded #include #include -#include VOID LoadAndBootBootSector(PUCHAR OperatingSystemName) { @@ -68,13 +67,13 @@ VOID LoadAndBootBootSector(PUCHAR OperatingSystemName) return; } - if (!OpenDiskDrive(BootDrive, BootPartition)) + if (!FsOpenVolume(BootDrive, BootPartition)) { UiMessageBox("Failed to open boot drive."); return; } - FilePointer = OpenFile(FileName); + FilePointer = FsOpenFile(FileName); if (FilePointer == NULL) { strcat(FileName, " not found."); @@ -83,7 +82,7 @@ VOID LoadAndBootBootSector(PUCHAR OperatingSystemName) } // Read boot sector - if (!ReadFile(FilePointer, 512, &BytesRead, (void*)0x7c00) || (BytesRead != 512)) + if (!FsReadFile(FilePointer, 512, &BytesRead, (void*)0x7c00) || (BytesRead != 512)) { return; } @@ -95,8 +94,7 @@ VOID LoadAndBootBootSector(PUCHAR OperatingSystemName) return; } - VideoClearScreen(); - VideoShowTextCursor(); + UiUnInitialize("Booting..."); // Don't stop the floppy drive motor when we // are just booting a bootsector, or drive, or partition. // If we were to stop the floppy motor then @@ -104,7 +102,7 @@ VOID LoadAndBootBootSector(PUCHAR OperatingSystemName) // next read is to a floppy then the BIOS will // still think the motor is on and this will // result in a read error. - //StopFloppyMotor(); + //DiskStopFloppyMotor(); //DisableA20(); ChainLoadBiosBootSectorCode(); } @@ -165,8 +163,7 @@ VOID LoadAndBootPartition(PUCHAR OperatingSystemName) return; } - VideoClearScreen(); - VideoShowTextCursor(); + UiUnInitialize("Booting..."); // Don't stop the floppy drive motor when we // are just booting a bootsector, or drive, or partition. // If we were to stop the floppy motor then @@ -174,7 +171,7 @@ VOID LoadAndBootPartition(PUCHAR OperatingSystemName) // next read is to a floppy then the BIOS will // still think the motor is on and this will // result in a read error. - //StopFloppyMotor(); + //DiskStopFloppyMotor(); //DisableA20(); ChainLoadBiosBootSectorCode(); } @@ -218,8 +215,7 @@ VOID LoadAndBootDrive(PUCHAR OperatingSystemName) return; } - VideoClearScreen(); - VideoShowTextCursor(); + UiUnInitialize("Booting..."); // Don't stop the floppy drive motor when we // are just booting a bootsector, or drive, or partition. // If we were to stop the floppy motor then @@ -227,7 +223,7 @@ VOID LoadAndBootDrive(PUCHAR OperatingSystemName) // next read is to a floppy then the BIOS will // still think the motor is on and this will // result in a read error. - //StopFloppyMotor(); + //DiskStopFloppyMotor(); //DisableA20(); ChainLoadBiosBootSectorCode(); } diff --git a/freeldr/freeldr/mm/meminit.c b/freeldr/freeldr/mm/meminit.c index 1c7143c5bfe..1657891af83 100644 --- a/freeldr/freeldr/mm/meminit.c +++ b/freeldr/freeldr/mm/meminit.c @@ -63,7 +63,7 @@ BOOL MmInitializeMemoryManager(VOID) RtlZeroMemory(BiosMemoryMap, sizeof(BIOS_MEMORY_MAP) * 32); - BiosMemoryMapEntryCount = GetBiosMemoryMap((PBIOS_MEMORY_MAP_ARRAY)BiosMemoryMap); + BiosMemoryMapEntryCount = GetBiosMemoryMap(BiosMemoryMap); ExtendedMemorySize = GetExtendedMemorySize(); ConventionalMemorySize = GetConventionalMemorySize(); @@ -97,7 +97,7 @@ BOOL MmInitializeMemoryManager(VOID) // to handle just a flat extended memory size I'm going // to create a 'fake' memory map entry out of the // extended memory size if GetBiosMemoryMap() fails. - if (BiosMemoryMapEntryCount == 0) + //if (BiosMemoryMapEntryCount == 0) { BiosMemoryMap[0].BaseAddress = 0x100000; // Start at 1MB BiosMemoryMap[0].Length = ExtendedMemorySize * 1024; @@ -385,7 +385,7 @@ VOID MmFixupSystemMemoryMap(BIOS_MEMORY_MAP BiosMemoryMap[32], U32* MapCount) // If the entry type isn't usable then remove // it from the memory map (this will help reduce // the size of our lookup table) - if (BiosMemoryMap[Index].Type != 0) + if (BiosMemoryMap[Index].Type != MEMTYPE_USABLE) { // Slide every entry after this down one for (Index2=Index; Index2<(*MapCount - 1); Index2++) diff --git a/freeldr/freeldr/multiboot.c b/freeldr/freeldr/multiboot.c index 268d49e12b1..03768649dcc 100644 --- a/freeldr/freeldr/multiboot.c +++ b/freeldr/freeldr/multiboot.c @@ -51,7 +51,7 @@ BOOL MultiBootLoadKernel(FILE *KernelImage) * Load the first 8192 bytes of the kernel image * so we can search for the multiboot header */ - if (!ReadFile(KernelImage, 8192, NULL, ImageHeaders)) + if (!FsReadFile(KernelImage, 8192, NULL, ImageHeaders)) { MmFreeMemory(ImageHeaders); return FALSE; @@ -111,13 +111,13 @@ BOOL MultiBootLoadKernel(FILE *KernelImage) * Get the file offset, this should be 0, and move the file pointer */ dwFileLoadOffset = (Idx * sizeof(U32)) - (mb_header.header_addr - mb_header.load_addr); - SetFilePointer(KernelImage, dwFileLoadOffset); + FsSetFilePointer(KernelImage, dwFileLoadOffset); /* * Load the file image */ dwDataSize = (mb_header.load_end_addr - mb_header.load_addr); - ReadFile(KernelImage, dwDataSize, NULL, (void*)mb_header.load_addr); + FsReadFile(KernelImage, dwDataSize, NULL, (void*)mb_header.load_addr); /* * Initialize bss area @@ -150,7 +150,7 @@ BOOL MultiBootLoadModule(FILE *ModuleImage, char *ModuleName) ModuleNameString = multiboot_module_strings[mb_info.mods_count]; - dwModuleSize = GetFileSize(ModuleImage); + dwModuleSize = FsGetFileSize(ModuleImage); pModule->mod_start = next_module_load_base; pModule->mod_end = next_module_load_base + dwModuleSize; strcpy(ModuleNameString, ModuleName); @@ -159,7 +159,7 @@ BOOL MultiBootLoadModule(FILE *ModuleImage, char *ModuleName) /* * Load the file image */ - ReadFile(ModuleImage, dwModuleSize, NULL, (void*)next_module_load_base); + FsReadFile(ModuleImage, dwModuleSize, NULL, (void*)next_module_load_base); next_module_load_base = ROUND_UP(pModule->mod_end, /*PAGE_SIZE*/4096); mb_info.mods_count++; @@ -187,7 +187,7 @@ PVOID MultiBootLoadModule(FILE *ModuleImage, char *ModuleName, U32* ModuleSize) ModuleNameString = multiboot_module_strings[mb_info.mods_count]; - dwModuleSize = GetFileSize(ModuleImage); + dwModuleSize = FsGetFileSize(ModuleImage); pModule->mod_start = next_module_load_base; pModule->mod_end = next_module_load_base + dwModuleSize; strcpy(ModuleNameString, ModuleName); @@ -196,7 +196,7 @@ PVOID MultiBootLoadModule(FILE *ModuleImage, char *ModuleName, U32* ModuleSize) /* * Load the file image */ - ReadFile(ModuleImage, dwModuleSize, NULL, (void*)next_module_load_base); + FsReadFile(ModuleImage, dwModuleSize, NULL, (void*)next_module_load_base); next_module_load_base = ROUND_UP(pModule->mod_end, /*PAGE_SIZE*/4096); mb_info.mods_count++; diff --git a/freeldr/freeldr/reactos/reactos.c b/freeldr/freeldr/reactos/reactos.c index 2d42dc99f1f..b64d1a65fda 100644 --- a/freeldr/freeldr/reactos/reactos.c +++ b/freeldr/freeldr/reactos/reactos.c @@ -23,6 +23,7 @@ #include #include #include +#include #include #include #include @@ -49,7 +50,7 @@ LoadKernel(PCHAR szFileName, int nPos) else szShortName = szShortName + 1; - FilePointer = OpenFile(szFileName); + FilePointer = FsOpenFile(szFileName); if (FilePointer == NULL) { strcpy(szBuffer, szShortName); @@ -108,7 +109,7 @@ LoadSymbolFile(PCHAR szSystemRoot, strncat(SymbolFileName, Start, Length); strcat(SymbolFileName, ".sym"); - FilePointer = OpenFile((PCHAR)&SymbolFileName[0]); + FilePointer = FsOpenFile((PCHAR)&SymbolFileName[0]); if (FilePointer == NULL) { DbgPrint((DPRINT_REACTOS, "Symbol file %s not loaded.\n", SymbolFileName)); @@ -146,7 +147,7 @@ LoadDriver(PCHAR szFileName, int nPos) char value[256]; char *p; - FilePointer = OpenFile(szFileName); + FilePointer = FsOpenFile(szFileName); if (FilePointer == NULL) { strcpy(value, szFileName); @@ -185,7 +186,7 @@ LoadNlsFile(PCHAR szFileName, PCHAR szModuleName) char value[256]; char *p; - FilePointer = OpenFile(szFileName); + FilePointer = FsOpenFile(szFileName); if (FilePointer == NULL) { strcpy(value, szFileName); @@ -463,7 +464,7 @@ LoadAndBootReactOS(PUCHAR OperatingSystemName) mb_info.cmdline = (unsigned long)multiboot_kernel_cmdline; mb_info.mods_count = 0; mb_info.mods_addr = (unsigned long)multiboot_modules; - mb_info.mmap_length = (unsigned long)GetBiosMemoryMap((PBIOS_MEMORY_MAP_ARRAY)&multiboot_memory_map) * sizeof(memory_map_t); + mb_info.mmap_length = (unsigned long)GetBiosMemoryMap((PBIOS_MEMORY_MAP)&multiboot_memory_map) * sizeof(memory_map_t); if (mb_info.mmap_length) { mb_info.mmap_addr = (unsigned long)&multiboot_memory_map; @@ -531,7 +532,7 @@ LoadAndBootReactOS(PUCHAR OperatingSystemName) /* * Try to open boot drive */ - if (!OpenDiskDrive(BootDrive, BootPartition)) + if (!FsOpenVolume(BootDrive, BootPartition)) { UiMessageBox("Failed to open boot drive."); return; @@ -629,7 +630,7 @@ LoadAndBootReactOS(PUCHAR OperatingSystemName) DbgPrint((DPRINT_REACTOS, "SystemHive: '%s'", szFileName)); - FilePointer = OpenFile(szFileName); + FilePointer = FsOpenFile(szFileName); if (FilePointer == NULL) { strcat(value, " not found."); @@ -708,10 +709,13 @@ LoadAndBootReactOS(PUCHAR OperatingSystemName) strcat(name, "."); //MessageBox(name); + + UiUnInitialize("Booting ReactOS..."); + /* * Now boot the kernel */ - StopFloppyMotor(); + DiskStopFloppyMotor(); boot_reactos(); } diff --git a/freeldr/freeldr/reactos/reghive.c b/freeldr/freeldr/reactos/reghive.c index 993dc2210f8..ca8668542ee 100644 --- a/freeldr/freeldr/reactos/reghive.c +++ b/freeldr/freeldr/reactos/reghive.c @@ -225,7 +225,7 @@ getKeyValueTypeFromChunk (PCHAR regChunk, PCHAR dataFormat, int *keyValueType) } else { - UNIMPLEMENTED; + UNIMPLEMENTED(); } return *regChunk ? regChunk : 0; @@ -311,7 +311,7 @@ computeKeyValueDataSize (PCHAR regChunk, PCHAR dataFormat) } else { - UNIMPLEMENTED; + UNIMPLEMENTED(); } return dataSize; @@ -425,7 +425,7 @@ getKeyValueDataFromChunk (PCHAR regChunk, PCHAR dataFormat, PCHAR data) } else { - UNIMPLEMENTED; + UNIMPLEMENTED(); } return *regChunk ? regChunk : 0; diff --git a/freeldr/freeldr/reactos/setupldr.c b/freeldr/freeldr/reactos/setupldr.c index f9df3dcbb06..3da4a012ceb 100644 --- a/freeldr/freeldr/reactos/setupldr.c +++ b/freeldr/freeldr/reactos/setupldr.c @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -44,7 +45,7 @@ LoadKernel(PCHAR szFileName) else szShortName = szShortName + 1; - FilePointer = OpenFile(szFileName); + FilePointer = FsOpenFile(szFileName); if (FilePointer == NULL) { printf("Could not find %s\n", szShortName); @@ -78,7 +79,7 @@ LoadDriver(PCHAR szFileName) szShortName = szShortName + 1; - FilePointer = OpenFile(szFileName); + FilePointer = FsOpenFile(szFileName); if (FilePointer == NULL) { printf("Could not find %s\n", szFileName); @@ -108,7 +109,7 @@ VOID RunLoader(VOID) mb_info.cmdline = (unsigned long)multiboot_kernel_cmdline; mb_info.mods_count = 0; mb_info.mods_addr = (unsigned long)multiboot_modules; - mb_info.mmap_length = (unsigned long)GetBiosMemoryMap((PBIOS_MEMORY_MAP_ARRAY)&multiboot_memory_map); + mb_info.mmap_length = (unsigned long)GetBiosMemoryMap((PBIOS_MEMORY_MAP)&multiboot_memory_map); if (mb_info.mmap_length) { mb_info.mmap_addr = (unsigned long)&multiboot_memory_map; @@ -146,7 +147,7 @@ VOID RunLoader(VOID) (unsigned int)BootDrive); /* Open boot drive */ - if (!OpenDiskDrive(BootDrive, BootPartition)) + if (!FsOpenVolume(BootDrive, BootPartition)) { printf("Failed to open boot drive."); return; @@ -247,7 +248,7 @@ VOID RunLoader(VOID) /* * Now boot the kernel */ - StopFloppyMotor(); + DiskStopFloppyMotor(); boot_reactos(); diff --git a/freeldr/freeldr/rtl/memory.c b/freeldr/freeldr/rtl/memcmp.c similarity index 59% rename from freeldr/freeldr/rtl/memory.c rename to freeldr/freeldr/rtl/memcmp.c index 8f50adc4adc..8395dd5e0d9 100644 --- a/freeldr/freeldr/rtl/memory.c +++ b/freeldr/freeldr/rtl/memcmp.c @@ -19,13 +19,13 @@ #include -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 + * + * 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 + +#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 + * + * 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 + +#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 #include #include +#include + + +PVOID TextVideoBuffer = NULL; + +BOOL TuiInitialize(VOID) +{ + VideoClearScreen(); + VideoHideTextCursor(); + BiosVideoDisableBlinkBit(); + + TextVideoBuffer = VideoAllocateOffScreenBuffer(); + if (TextVideoBuffer == NULL) + { + return FALSE; + } + + return TRUE; +} + +VOID TuiUnInitialize(VOID) +{ + if (UiUseSpecialEffects) + { + TuiFadeOut(); + } + else + { + VideoSetMode(VIDEOMODE_NORMAL_TEXT); + } + + //VideoClearScreen(); + VideoSetMode(VIDEOMODE_NORMAL_TEXT); + VideoShowTextCursor(); + BiosVideoEnableBlinkBit(); +} VOID TuiDrawBackdrop(VOID) { @@ -88,12 +124,14 @@ VOID TuiDrawBackdrop(VOID) // // Draw status bar // - TuiDrawStatusText(""); + TuiDrawStatusText("Welcome to FreeLoader!"); // // Update the date & time // TuiUpdateDateTime(); + + VideoCopyOffScreenBufferToVRAM(); } /* @@ -102,7 +140,7 @@ VOID TuiDrawBackdrop(VOID) */ VOID TuiFillArea(U32 Left, U32 Top, U32 Right, U32 Bottom, UCHAR FillChar, UCHAR Attr /* Color Attributes */) { - PUCHAR ScreenMemory = (PUCHAR)TUI_SCREEN_MEM; + PUCHAR ScreenMemory = (PUCHAR)TextVideoBuffer; U32 i, j; // Clip the area to the screen @@ -138,7 +176,7 @@ VOID TuiFillArea(U32 Left, U32 Top, U32 Right, U32 Bottom, UCHAR FillChar, UCHAR */ VOID TuiDrawShadow(U32 Left, U32 Top, U32 Right, U32 Bottom) { - PUCHAR ScreenMemory = (PUCHAR)TUI_SCREEN_MEM; + PUCHAR ScreenMemory = (PUCHAR)TextVideoBuffer; U32 Idx; // Shade the bottom of the area @@ -270,7 +308,7 @@ VOID TuiDrawBox(U32 Left, U32 Top, U32 Right, U32 Bottom, UCHAR VertStyle, UCHAR */ VOID TuiDrawText(U32 X, U32 Y, PUCHAR Text, UCHAR Attr) { - PUCHAR ScreenMemory = (PUCHAR)TUI_SCREEN_MEM; + PUCHAR ScreenMemory = (PUCHAR)TextVideoBuffer; U32 i, j; // Draw the text @@ -283,6 +321,63 @@ VOID TuiDrawText(U32 X, U32 Y, PUCHAR Text, UCHAR Attr) VOID TuiDrawCenteredText(U32 Left, U32 Top, U32 Right, U32 Bottom, PUCHAR TextString, UCHAR Attr) { + U32 TextLength; + U32 BoxWidth; + U32 BoxHeight; + U32 LineBreakCount; + U32 Index; + U32 LastIndex; + U32 RealLeft; + U32 RealTop; + U32 X; + U32 Y; + UCHAR Temp[2]; + + TextLength = strlen(TextString); + + // Count the new lines and the box width + LineBreakCount = 0; + BoxWidth = 0; + LastIndex = 0; + for (Index=0; Index 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 #include +#include BOOL TuiDisplayMenu(PUCHAR MenuItemList[], U32 MenuItemCount, U32 DefaultMenuItem, S32 MenuTimeOut, U32* SelectedMenuItem) @@ -88,7 +89,9 @@ BOOL TuiDisplayMenu(PUCHAR MenuItemList[], U32 MenuItemCount, U32 DefaultMenuIte // // Update the date & time // - UiUpdateDateTime(); + TuiUpdateDateTime(); + + VideoCopyOffScreenBufferToVRAM(); if (MenuInformation.MenuTimeRemaining > 0) { @@ -104,6 +107,8 @@ BOOL TuiDisplayMenu(PUCHAR MenuItemList[], U32 MenuItemCount, U32 DefaultMenuIte // Update the menu // TuiDrawMenuBox(&MenuInformation); + + VideoCopyOffScreenBufferToVRAM(); } } else if (MenuInformation.MenuTimeRemaining == 0) @@ -183,6 +188,8 @@ VOID TuiDrawMenu(PTUI_MENU_INFO MenuInfo) { TuiDrawMenuItem(MenuInfo, Idx); } + + VideoCopyOffScreenBufferToVRAM(); } VOID TuiDrawMenuBox(PTUI_MENU_INFO MenuInfo) @@ -347,6 +354,8 @@ U32 TuiProcessMenuKeyboardEvent(PTUI_MENU_INFO MenuInfo) break; } + + VideoCopyOffScreenBufferToVRAM(); } return KeyEvent; diff --git a/freeldr/freeldr/ui/ui.c b/freeldr/freeldr/ui/ui.c index 7ea62a6975a..b15c2faaf0e 100644 --- a/freeldr/freeldr/ui/ui.c +++ b/freeldr/freeldr/ui/ui.c @@ -57,6 +57,8 @@ BOOL UserInterfaceUp = FALSE; // Tells us if the user interface is display BOOL UiDisplayMode = DISPLAYMODE_TEXT; // Tells us if we are in text or graphics mode +BOOL UiUseSpecialEffects = FALSE; // Tells us if we should use fade effects + UCHAR UiMonthNames[12][15] = { "January ", "February ", "March ", "April ", "May ", "June ", "July ", "August ", "September ", "October ", "November ", "December " }; @@ -86,38 +88,49 @@ BOOL UiInitialize(VOID) if (BiosDetectVideoCard() == VIDEOCARD_CGA_OR_OTHER) { DbgPrint((DPRINT_UI, "CGA or other display adapter detected.\n")); + printf("CGA or other display adapter detected.\n"); + printf("Using 80x25 text mode.\n"); + VideoMode = VIDEOMODE_NORMAL_TEXT; } else if (BiosDetectVideoCard() == VIDEOCARD_EGA) { DbgPrint((DPRINT_UI, "EGA display adapter detected.\n")); - } - else if (BiosDetectVideoCard() == VIDEOCARD_VGA) - { - DbgPrint((DPRINT_UI, "VGA display adapter detected.\n")); - } - - if (stricmp(SettingText, "NORMAL_VGA") == 0) - { + printf("EGA display adapter detected.\n"); + printf("Using 80x25 text mode.\n"); VideoMode = VIDEOMODE_NORMAL_TEXT; } - else if (stricmp(SettingText, "EXTENDED_VGA") == 0) + else //if (BiosDetectVideoCard() == VIDEOCARD_VGA) { - VideoMode = VIDEOMODE_EXTENDED_TEXT; - } - else - { - VideoMode = atoi(SettingText); + DbgPrint((DPRINT_UI, "VGA display adapter detected.\n")); + + if (stricmp(SettingText, "NORMAL_VGA") == 0) + { + VideoMode = VIDEOMODE_NORMAL_TEXT; + } + else if (stricmp(SettingText, "EXTENDED_VGA") == 0) + { + VideoMode = VIDEOMODE_EXTENDED_TEXT; + } + else + { + VideoMode = atoi(SettingText); + } } if (!VideoSetMode(VideoMode)) { - printf("Error: unable to set video display mode 0x%lx\n", VideoMode); + printf("Error: unable to set video display mode 0x%x\n", VideoMode); + printf("Defaulting to 80x25 text mode.\n"); printf("Press any key to continue.\n"); getch(); + + VideoMode = VIDEOMODE_NORMAL_TEXT; + VideoSetMode(VIDEOMODE_NORMAL_TEXT); } UiScreenWidth = VideoGetCurrentModeResolutionX(); UiScreenHeight = VideoGetCurrentModeResolutionY(); + UiDisplayMode = VideoGetCurrentModeType(); } if (IniReadSettingByName(SectionId, "TitleText", SettingText, 260)) { @@ -179,14 +192,39 @@ BOOL UiInitialize(VOID) { UiSelectedTextBgColor = UiTextToColor(SettingText); } + if (IniReadSettingByName(SectionId, "SpecialEffects", SettingText, 260)) + { + if (stricmp(SettingText, "Yes") == 0 && strlen(SettingText) == 3) + { + UiUseSpecialEffects = TRUE; + } + else + { + UiUseSpecialEffects = FALSE; + } + } } - VideoClearScreen(); - VideoHideTextCursor(); - BiosVideoDisableBlinkBit(); + if (UiDisplayMode == DISPLAYMODE_TEXT) + { + if (!TuiInitialize()) + { + VideoSetMode(VIDEOMODE_NORMAL_TEXT); + return FALSE; + } + } + else + { + UNIMPLEMENTED(); + //if (!GuiInitialize()) + //{ + // VideoSetMode(VIDEOMODE_NORMAL_TEXT); + // return FALSE; + //} + } - // Draw the backdrop and title box - UiDrawBackdrop(); + // Draw the backdrop and fade it in if special effects are enabled + UiFadeInBackdrop(); UserInterfaceUp = TRUE; @@ -195,6 +233,23 @@ BOOL UiInitialize(VOID) return TRUE; } +VOID UiUnInitialize(PUCHAR BootText) +{ + UiDrawBackdrop(); + UiDrawStatusText("Booting..."); + UiInfoBox(BootText); + + if (UiDisplayMode == DISPLAYMODE_TEXT) + { + TuiUnInitialize(); + } + else + { + UNIMPLEMENTED(); + //GuiUnInitialize(); + } +} + VOID UiDrawBackdrop(VOID) { if (UiDisplayMode == DISPLAYMODE_TEXT) @@ -203,7 +258,7 @@ VOID UiDrawBackdrop(VOID) } else { - UNIMPLEMENTED + UNIMPLEMENTED(); //GuiDrawBackdrop(); } } @@ -216,7 +271,7 @@ VOID UiFillArea(U32 Left, U32 Top, U32 Right, U32 Bottom, UCHAR FillChar, UCHAR } else { - UNIMPLEMENTED + UNIMPLEMENTED(); //GuiFillArea(Left, Top, Right, Bottom, FillChar, Attr); } } @@ -229,7 +284,7 @@ VOID UiDrawShadow(U32 Left, U32 Top, U32 Right, U32 Bottom) } else { - UNIMPLEMENTED + UNIMPLEMENTED(); //GuiDrawShadow(Left, Top, Right, Bottom); } } @@ -242,7 +297,7 @@ VOID UiDrawBox(U32 Left, U32 Top, U32 Right, U32 Bottom, UCHAR VertStyle, UCHAR } else { - UNIMPLEMENTED + UNIMPLEMENTED(); //GuiDrawBox(Left, Top, Right, Bottom, VertStyle, HorzStyle, Fill, Shadow, Attr); } } @@ -255,7 +310,7 @@ VOID UiDrawText(U32 X, U32 Y, PUCHAR Text, UCHAR Attr) } else { - UNIMPLEMENTED + UNIMPLEMENTED(); //GuiDrawText(X, Y, Text, Attr); } } @@ -268,7 +323,7 @@ VOID UiDrawCenteredText(U32 Left, U32 Top, U32 Right, U32 Bottom, PUCHAR TextStr } else { - UNIMPLEMENTED + UNIMPLEMENTED(); //GuiDrawCenteredText(Left, Top, Right, Bottom, TextString, Attr); } } @@ -281,7 +336,7 @@ VOID UiDrawStatusText(PUCHAR StatusText) } else { - UNIMPLEMENTED + UNIMPLEMENTED(); //GuiDrawStatusText(StatusText); } } @@ -294,11 +349,72 @@ VOID UiUpdateDateTime(VOID) } else { - UNIMPLEMENTED - //TuiUpdateDateTime(); + UNIMPLEMENTED(); + //GuiUpdateDateTime(); } } +VOID UiInfoBox(PUCHAR MessageText) +{ + U32 TextLength; + U32 BoxWidth; + U32 BoxHeight; + U32 LineBreakCount; + U32 Index; + U32 LastIndex; + U32 Left; + U32 Top; + U32 Right; + U32 Bottom; + + TextLength = strlen(MessageText); + + // Count the new lines and the box width + LineBreakCount = 0; + BoxWidth = 0; + LastIndex = 0; + for (Index=0; Index BoxWidth) + { + BoxWidth = (Index - LastIndex); + } + } + } + + // Calc the box width & height + BoxWidth += 6; + BoxHeight = LineBreakCount + 4; + + // Calc the box coordinates + Left = (UiScreenWidth / 2) - (BoxWidth / 2); + Top =(UiScreenHeight / 2) - (BoxHeight / 2); + Right = (UiScreenWidth / 2) + (BoxWidth / 2); + Bottom = (UiScreenHeight / 2) + (BoxHeight / 2); + + // Draw the box + UiDrawBox(Left, + Top, + Right, + Bottom, + VERT, + HORZ, + TRUE, + TRUE, + ATTR(UiMenuFgColor, UiMenuBgColor) + ); + + // Draw the text + UiDrawCenteredText(Left, Top, Right, Bottom, MessageText, ATTR(UiTextColor, UiMenuBgColor)); +} + VOID UiMessageBox(PUCHAR MessageText) { // We have not yet displayed the user interface @@ -321,7 +437,7 @@ VOID UiMessageBox(PUCHAR MessageText) } else { - UNIMPLEMENTED + UNIMPLEMENTED(); //GuiMessageBox(UiMessageBoxLineText); } @@ -348,7 +464,7 @@ VOID UiMessageBoxCritical(PUCHAR MessageText) } else { - UNIMPLEMENTED + UNIMPLEMENTED(); //GuiMessageBoxCritical(MessageText); } } @@ -367,8 +483,8 @@ UCHAR UiTextToColor(PUCHAR ColorText) } else { - UNIMPLEMENTED - return 0; + UNIMPLEMENTED(); + return 0; //return GuiTextToColor(ColorText); } } @@ -381,8 +497,8 @@ UCHAR UiTextToFillStyle(PUCHAR FillStyleText) } else { - UNIMPLEMENTED - return 0; + UNIMPLEMENTED(); + return 0; //return GuiTextToFillStyle(FillStyleText); } } @@ -395,7 +511,7 @@ VOID UiDrawProgressBarCenter(U32 Position, U32 Range) } else { - UNIMPLEMENTED + UNIMPLEMENTED(); //GuiDrawProgressBarCenter(Position, Range); } } @@ -408,7 +524,7 @@ VOID UiDrawProgressBar(U32 Left, U32 Top, U32 Right, U32 Bottom, U32 Position, U } else { - UNIMPLEMENTED + UNIMPLEMENTED(); //GuiDrawProgressBar(Left, Top, Right, Bottom, Position, Range); } } @@ -457,7 +573,10 @@ VOID UiShowMessageBoxesInSection(PUCHAR SectionName) VOID UiTruncateStringEllipsis(PUCHAR StringText, U32 MaxChars) { - UNIMPLEMENTED + if (strlen(StringText) > MaxChars) + { + strcpy(&StringText[MaxChars - 3], "..."); + } } BOOL UiDisplayMenu(PUCHAR MenuItemList[], U32 MenuItemCount, U32 DefaultMenuItem, S32 MenuTimeOut, U32* SelectedMenuItem) @@ -468,8 +587,34 @@ BOOL UiDisplayMenu(PUCHAR MenuItemList[], U32 MenuItemCount, U32 DefaultMenuItem } else { - UNIMPLEMENTED - return FALSE; + UNIMPLEMENTED(); + return FALSE; //return GuiDisplayMenu(MenuItemList, MenuItemCount, DefaultMenuItem, MenuTimeOut, SelectedMenuItem); } } + +VOID UiFadeInBackdrop(VOID) +{ + if (UiDisplayMode == DISPLAYMODE_TEXT) + { + TuiFadeInBackdrop(); + } + else + { + UNIMPLEMENTED(); + //GuiFadeInBackdrop(); + } +} + +VOID UiFadeOut(VOID) +{ + if (UiDisplayMode == DISPLAYMODE_TEXT) + { + TuiFadeOut(); + } + else + { + UNIMPLEMENTED(); + //GuiFadeInOut(); + } +} diff --git a/freeldr/freeldr/video/bank.c b/freeldr/freeldr/video/bank.c new file mode 100644 index 00000000000..27685dcdd91 --- /dev/null +++ b/freeldr/freeldr/video/bank.c @@ -0,0 +1,152 @@ +/* + * FreeLoader + * Copyright (C) 1998-2002 Brian Palmer + * + * 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 +#include +#include +#include +#include + + +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 + * + * 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 +#include +#include + + +#define RGB_MAX 64 +#define RGB_MAX_PER_ITERATION 64 + +VOID VideoSetAllColorsToBlack(U32 ColorCount) +{ + U32 Color; + + VideoWaitForVerticalRetrace(); + + for (Color=0; Color 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 0) + { + Red--; + } + if (Green > 0) + { + Green--; + } + if (Blue > 0) + { + Blue--; + } + + VideoSetPaletteColor(Color, Red, Green, Blue); + } + } +} diff --git a/freeldr/freeldr/video/palette.c b/freeldr/freeldr/video/palette.c new file mode 100644 index 00000000000..a1fd773a978 --- /dev/null +++ b/freeldr/freeldr/video/palette.c @@ -0,0 +1,61 @@ +/* + * FreeLoader + * Copyright (C) 1998-2002 Brian Palmer + * + * 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 +#include +#include + + +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 + * + * 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 +#include +#include +#include + + + + + +// +// 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)); + } +} diff --git a/freeldr/freeldr/video/video.c b/freeldr/freeldr/video/video.c index 587f4aa49c0..df9f0e1cd7e 100644 --- a/freeldr/freeldr/video/video.c +++ b/freeldr/freeldr/video/video.c @@ -20,8 +20,11 @@ #include #include #include +#include +PVOID VideoOffScreenBuffer = NULL; + VOID VideoClearScreen(VOID) { VideoSetMode(VideoGetCurrentMode()); @@ -29,29 +32,36 @@ VOID VideoClearScreen(VOID) VOID VideoWaitForVerticalRetrace(VOID) { - while ((READ_PORT_UCHAR((PUCHAR)VIDEOPORT_VERTICAL_RETRACE) & 0x08)) + + while ((READ_PORT_UCHAR((U8*)VIDEOPORT_VERTICAL_RETRACE) & 0x08) == 1) { - // Keep reading the port until bit 4 is clear + // Keep reading the port until bit 3 is clear + // This waits for the current retrace to end and + // we can catch the next one so we know we are + // getting a full retrace. } - while (!(READ_PORT_UCHAR((PUCHAR)VIDEOPORT_VERTICAL_RETRACE) & 0x08)) + while ((READ_PORT_UCHAR((U8*)VIDEOPORT_VERTICAL_RETRACE) & 0x08) == 0) { - // Keep reading the port until bit 4 is set + // Keep reading the port until bit 3 is set + // Now that we know we aren't doing a vertical + // retrace we need to wait for the next one. } } -VOID VideoSetPaletteColor(UCHAR Color, UCHAR Red, UCHAR Green, UCHAR Blue) +PVOID VideoAllocateOffScreenBuffer(VOID) { - WRITE_PORT_UCHAR((PUCHAR)VIDEOPORT_PALETTE_WRITE, Color); - WRITE_PORT_UCHAR((PUCHAR)VIDEOPORT_PALETTE_DATA, Red); - WRITE_PORT_UCHAR((PUCHAR)VIDEOPORT_PALETTE_DATA, Green); - WRITE_PORT_UCHAR((PUCHAR)VIDEOPORT_PALETTE_DATA, Blue); -} + U32 BufferSize; -VOID VideoGetPaletteColor(UCHAR Color, PUCHAR Red, PUCHAR Green, PUCHAR Blue) -{ - WRITE_PORT_UCHAR((PUCHAR)VIDEOPORT_PALETTE_READ, Color); - *Red = READ_PORT_UCHAR((PUCHAR)VIDEOPORT_PALETTE_DATA); - *Green = READ_PORT_UCHAR((PUCHAR)VIDEOPORT_PALETTE_DATA); - *Blue = READ_PORT_UCHAR((PUCHAR)VIDEOPORT_PALETTE_DATA); + if (VideoOffScreenBuffer != NULL) + { + MmFreeMemory(VideoOffScreenBuffer); + VideoOffScreenBuffer = NULL; + } + + BufferSize = VideoGetCurrentModeResolutionX() * VideoGetBytesPerScanLine(); + + VideoOffScreenBuffer = MmAllocateMemory(BufferSize); + + return VideoOffScreenBuffer; } diff --git a/freeldr/freeldr/video/vidmode.c b/freeldr/freeldr/video/vidmode.c index 1626972671a..fe885397146 100644 --- a/freeldr/freeldr/video/vidmode.c +++ b/freeldr/freeldr/video/vidmode.c @@ -19,41 +19,123 @@ #include #include +#include +#include -U32 CurrentVideoMode = VIDEOMODE_NORMAL_TEXT; -U32 VideoResolutionX = 80; -U32 VideoResolutionY = 25; +U32 CurrentVideoMode = VIDEOMODE_NORMAL_TEXT; +U32 VideoResolutionX = 80; +U32 VideoResolutionY = 25; +U32 VideoBytesPerScanLine = 0; // Number of bytes per scan line +U32 CurrentModeType = MODETYPE_TEXT; +BOOL VesaVideoMode = FALSE; + +SVGA_MODE_INFORMATION VesaVideoModeInformation; BOOL VideoSetMode(U32 VideoMode) { + CurrentMemoryBank = 0; + + // Set the values for the default text modes + // If they are setting a graphics mode then + // these values will be changed. + CurrentVideoMode = VideoMode; + VideoResolutionX = 80; + VideoResolutionY = 25; + VideoBytesPerScanLine = 160; + CurrentModeType = MODETYPE_TEXT; + VesaVideoMode = FALSE; + switch (VideoMode) { case VIDEOMODE_NORMAL_TEXT: - CurrentVideoMode = VideoMode; + case 0x03: /* BIOS 80x25 text mode number */ return VideoSetMode80x25(); case VIDEOMODE_EXTENDED_TEXT: - CurrentVideoMode = VideoMode; return VideoSetMode80x50_80x43(); case VIDEOMODE_80X28: - CurrentVideoMode = VideoMode; return VideoSetMode80x28(); case VIDEOMODE_80X30: - CurrentVideoMode = VideoMode; return VideoSetMode80x30(); case VIDEOMODE_80X34: - CurrentVideoMode = VideoMode; return VideoSetMode80x34(); case VIDEOMODE_80X43: - CurrentVideoMode = VideoMode; return VideoSetMode80x43(); case VIDEOMODE_80X60: - CurrentVideoMode = VideoMode; return VideoSetMode80x60(); - default: - return FALSE; } - return TRUE; + if (VideoMode == 0x12) + { + // 640x480x16 + BiosSetVideoMode(VideoMode); + //WRITE_PORT_USHORT((U16*)0x03CE, 0x0205); // For some reason this is necessary? + WRITE_PORT_USHORT((U16*)0x03CE, 0x0F01); // For some reason this is necessary? + VideoResolutionX = 640; + VideoResolutionY = 480; + VideoBytesPerScanLine = 80; + CurrentVideoMode = 0x12; + CurrentModeType = MODETYPE_GRAPHICS; + + return TRUE; + } + else if (VideoMode == 0x13) + { + // 320x200x256 + BiosSetVideoMode(VideoMode); + VideoResolutionX = 320; + VideoResolutionY = 200; + VideoBytesPerScanLine = 320; + CurrentVideoMode = 0x13; + CurrentModeType = MODETYPE_GRAPHICS; + + return TRUE; + } + else if (VideoMode >= 0x0108 && VideoMode <= 0x010C) + { + // VESA Text Mode + if (!BiosVesaGetSVGAModeInformation(VideoMode, &VesaVideoModeInformation)) + { + return FALSE; + } + + if (!BiosVesaSetVideoMode(VideoMode)) + { + return FALSE; + } + + VideoResolutionX = VesaVideoModeInformation.WidthInPixels; + VideoResolutionY = VesaVideoModeInformation.HeightInPixels; + VideoBytesPerScanLine = VesaVideoModeInformation.BytesPerScanLine; + CurrentVideoMode = VideoMode; + CurrentModeType = MODETYPE_TEXT; + VesaVideoMode = TRUE; + + return TRUE; + } + else + { + // VESA Graphics Mode + if (!BiosVesaGetSVGAModeInformation(VideoMode, &VesaVideoModeInformation)) + { + return FALSE; + } + + if (!BiosVesaSetVideoMode(VideoMode)) + { + return FALSE; + } + + VideoResolutionX = VesaVideoModeInformation.WidthInPixels; + VideoResolutionY = VesaVideoModeInformation.HeightInPixels; + VideoBytesPerScanLine = VesaVideoModeInformation.BytesPerScanLine; + CurrentVideoMode = VideoMode; + CurrentModeType = MODETYPE_GRAPHICS; + VesaVideoMode = TRUE; + + return TRUE; + } + + return FALSE; } BOOL VideoSetMode80x25(VOID) @@ -110,7 +192,7 @@ BOOL VideoSetMode80x28(VOID) BOOL VideoSetMode80x43(VOID) { // FIXME: Is this VGA-only? - BiosSet350ScanLines(); + BiosSetVerticalResolution(VERTRES_350_SCANLINES); VideoSetMode80x25(); BiosSetVideoFont8x8(); BiosSelectAlternatePrintScreen(); @@ -173,7 +255,59 @@ U32 VideoGetCurrentModeResolutionY(VOID) return VideoResolutionY; } +U32 VideoGetBytesPerScanLine(VOID) +{ + return VideoBytesPerScanLine; +} + U32 VideoGetCurrentMode(VOID) { return CurrentVideoMode; } + +U32 VideoGetCurrentModeType(VOID) +{ + return CurrentModeType; +} + +BOOL VideoIsCurrentModeVesa(VOID) +{ + return VesaVideoMode; +} + +U32 VideoGetCurrentModeColorDepth(VOID) +{ + U32 ColorDepth = 2; + U32 i; + + if (CurrentModeType == MODETYPE_TEXT) + { + return 0; + } + else // CurrentModeType == MODETYPE_GRAPHICS + { + // Calculate 2^BitsPerPixel'th power + for (i=0; i<(VesaVideoModeInformation.BitsPerPixel-1); i++) + { + ColorDepth *= 2; + } + + // This algorithm works great for 24-bit & 8-bit color modes + // but 15-bit color modes really use 16 bits per pixel. + // So check to see if green has an extra bit, if so then + // it is 16-bit, if not it is 15-bit + if (ColorDepth == 65536) + { + if (VesaVideoModeInformation.GreenMaskSize == 6) + { + return ColorDepth; + } + else + { + return 32768; + } + } + + return ColorDepth; + } +} diff --git a/freeldr/notes.txt b/freeldr/notes.txt index 73ef6e90cf1..01486b317e0 100644 --- a/freeldr/notes.txt +++ b/freeldr/notes.txt @@ -1,8 +1,6 @@ FreeLoader notes To build FreeLoader you will need DJGPP because Mingw32 doesn't support 16-bit code -ext2 filesystem support needs to be added. -The MessageBox() function needs to not allocate memory. Because it gets called when memory allocation fails. Memory layout: