191 lines
		
	
	
		
			4.3 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			191 lines
		
	
	
		
			4.3 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
/**
 | 
						|
 * PROJECT:         ExectOS
 | 
						|
 * COPYRIGHT:       See COPYING.md in the top level directory
 | 
						|
 * FILE:            xtldr/biosutil.cc
 | 
						|
 * DESCRIPTION:     Legacy BIOS support
 | 
						|
 * DEVELOPERS:      Aiken Harris <harraiken91@gmail.com>
 | 
						|
 */
 | 
						|
 | 
						|
#include <xtldr.hh>
 | 
						|
 | 
						|
 | 
						|
/**
 | 
						|
 * Clears the entire screen and moves the cursor to the top-left corner.
 | 
						|
 *
 | 
						|
 * @return This routine does not return any value.
 | 
						|
 *
 | 
						|
 * @since XT 1.0
 | 
						|
 */
 | 
						|
XTCDECL
 | 
						|
VOID
 | 
						|
BiosUtils::ClearScreen()
 | 
						|
{
 | 
						|
    VOLATILE PUSHORT VgaBuffer = (PUSHORT)0xB8000;
 | 
						|
    USHORT Blank;
 | 
						|
    UINT Index;
 | 
						|
 | 
						|
    /* Set blank character */
 | 
						|
    Blank = (0x0F << 8) | L' ';
 | 
						|
 | 
						|
    /* Fill the entire screen with blank characters */
 | 
						|
    for(Index = 0; Index < VgaWidth * VgaHeight; Index++)
 | 
						|
    {
 | 
						|
        VgaBuffer[Index] = Blank;
 | 
						|
    }
 | 
						|
 | 
						|
    /* Reset cursor position to the top-left corner */
 | 
						|
    CursorX = 0;
 | 
						|
    CursorY = 0;
 | 
						|
 | 
						|
    /* Update the hardware cursor position */
 | 
						|
    UpdateCursor();
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 * Formats the input string and prints it out to the screen.
 | 
						|
 *
 | 
						|
 * @param Format
 | 
						|
 *        The formatted string that is to be written to the output.
 | 
						|
 *
 | 
						|
 * @param ...
 | 
						|
 *        Depending on the format string, this routine might expect a sequence of additional arguments.
 | 
						|
 *
 | 
						|
 * @return This routine does not return any value.
 | 
						|
 *
 | 
						|
 * @since XT 1.0
 | 
						|
 */
 | 
						|
XTCDECL
 | 
						|
VOID
 | 
						|
BiosUtils::Print(IN PCWSTR Format,
 | 
						|
                 IN ...)
 | 
						|
{
 | 
						|
    RTL_PRINT_CONTEXT PrintContext;
 | 
						|
    VA_LIST Arguments;
 | 
						|
 | 
						|
    /* Initialise the print contexts */
 | 
						|
    PrintContext.WriteWideCharacter = PutChar;
 | 
						|
 | 
						|
    /* Initialise the va_list */
 | 
						|
    VA_START(Arguments, Format);
 | 
						|
 | 
						|
    /* Format and print the string to the stdout */
 | 
						|
    RTL::WideString::FormatWideString(&PrintContext, (PWCHAR)Format, Arguments);
 | 
						|
 | 
						|
    /* Clean up the va_list */
 | 
						|
    VA_END(Arguments);
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 * Writes a single wide character to the screen using legacy BIOS VGA text mode.
 | 
						|
 *
 | 
						|
 * @param Character
 | 
						|
 *        The wide character to be printed.
 | 
						|
 *
 | 
						|
 * @return This routine returns a status code.
 | 
						|
 *
 | 
						|
 * @since XT 1.0
 | 
						|
 */
 | 
						|
XTCDECL
 | 
						|
XTSTATUS
 | 
						|
BiosUtils::PutChar(IN WCHAR Character)
 | 
						|
{
 | 
						|
    VOLATILE PUSHORT VgaBuffer = (PUSHORT)0xB8000;
 | 
						|
    USHORT VgaCharacter;
 | 
						|
 | 
						|
    /* Handle special characters */
 | 
						|
    if(Character == L'\n')
 | 
						|
    {
 | 
						|
        /* Move to the next line */
 | 
						|
        CursorX = 0;
 | 
						|
        CursorY++;
 | 
						|
    }
 | 
						|
    else if(Character == L'\r')
 | 
						|
    {
 | 
						|
        /* Move to the beginning of the current line */
 | 
						|
        CursorX = 0;
 | 
						|
    }
 | 
						|
    else
 | 
						|
    {
 | 
						|
        /* Print character and move cursor to the right */
 | 
						|
        VgaCharacter = (0x0F << 8) | (Character & 0xFF);
 | 
						|
        VgaBuffer[CursorY * VgaWidth + CursorX] = VgaCharacter;
 | 
						|
        CursorX++;
 | 
						|
    }
 | 
						|
 | 
						|
    /* Handle moving to the next line if cursor is at the end of the line */
 | 
						|
    if(CursorX >= VgaWidth)
 | 
						|
    {
 | 
						|
        CursorX = 0;
 | 
						|
        CursorY++;
 | 
						|
    }
 | 
						|
 | 
						|
    /* Handle scrolling if cursor is at the end of the screen */
 | 
						|
    if(CursorY >= VgaHeight)
 | 
						|
    {
 | 
						|
        ScrollScreen();
 | 
						|
        CursorY = VgaHeight - 1;
 | 
						|
    }
 | 
						|
 | 
						|
    /* Update the hardware cursor position */
 | 
						|
    UpdateCursor();
 | 
						|
 | 
						|
    /* Return success */
 | 
						|
    return STATUS_EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 * Scrolls the entire screen content up by one line and clears the last line.
 | 
						|
 *
 | 
						|
 * @return This routine does not return any value.
 | 
						|
 *
 | 
						|
 * @since XT 1.0
 | 
						|
 */
 | 
						|
XTCDECL
 | 
						|
VOID
 | 
						|
BiosUtils::ScrollScreen()
 | 
						|
{
 | 
						|
    VOLATILE PUSHORT VgaBuffer = (PUSHORT)0xB8000;
 | 
						|
    USHORT Blank;
 | 
						|
    UINT Index;
 | 
						|
 | 
						|
    /* Set blank character */
 | 
						|
    Blank = (0x0F << 8) | L' ';
 | 
						|
 | 
						|
    /* Move every line up by one */
 | 
						|
    for(Index = 0; Index < (VgaHeight - 1) * VgaWidth; Index++)
 | 
						|
    {
 | 
						|
        VgaBuffer[Index] = VgaBuffer[Index + VgaWidth];
 | 
						|
    }
 | 
						|
 | 
						|
    /* Clear the last line */
 | 
						|
    for(Index = (VgaHeight - 1) * VgaWidth; Index < VgaHeight * VgaWidth; Index++)
 | 
						|
    {
 | 
						|
        VgaBuffer[Index] = Blank;
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 * Updates the hardware cursor position on the screen.
 | 
						|
 *
 | 
						|
 * @return This routine does not return any value.
 | 
						|
 *
 | 
						|
 * @since XT 1.0
 | 
						|
 */
 | 
						|
XTCDECL
 | 
						|
VOID
 | 
						|
BiosUtils::UpdateCursor()
 | 
						|
{
 | 
						|
    USHORT Position;
 | 
						|
 | 
						|
    /* Calculate cursor position */
 | 
						|
    Position = CursorY * VgaWidth + CursorX;
 | 
						|
 | 
						|
    /* Send command to set the high byte of the cursor position */
 | 
						|
    HL::IoPort::WritePort8(0x3D4, 0x0E);
 | 
						|
    HL::IoPort::WritePort8(0x3D5, (UCHAR)((Position >> 8) & 0xFF));
 | 
						|
 | 
						|
    /* Send command to set the low byte of the cursor position */
 | 
						|
    HL::IoPort::WritePort8(0x3D4, 0x0F);
 | 
						|
    HL::IoPort::WritePort8(0x3D5, (UCHAR)(Position & 0xFF));
 | 
						|
}
 |