1 |
/* |
/* |
2 |
* GRUB -- GRand Unified Bootloader |
* GRUB -- GRand Unified Bootloader |
3 |
* Copyright (C) 1999, 2000, 2001 Free Software Foundation, Inc. |
* Copyright (C) 1999,2000,2001,2002 Free Software Foundation, Inc. |
4 |
* |
* |
5 |
* This program is free software; you can redistribute it and/or modify |
* This program is free software; you can redistribute it and/or modify |
6 |
* it under the terms of the GNU General Public License as published by |
* it under the terms of the GNU General Public License as published by |
1313 |
# include "apm.S" |
# include "apm.S" |
1314 |
#endif /* ! STAGE1_5 */ |
#endif /* ! STAGE1_5 */ |
1315 |
|
|
|
/* |
|
|
* console_putchar(c) |
|
|
* |
|
|
* Puts character on the screen, interpreting '\n' as in the UNIX fashion. |
|
|
* |
|
|
* BIOS call "INT 10H Function 0Eh" to write character to console |
|
|
* Call with %ah = 0x0e |
|
|
* %al = character |
|
|
* %bh = page |
|
|
* %bl = foreground color ( graphics modes) |
|
|
*/ |
|
|
|
|
|
|
|
|
ENTRY(console_putchar) |
|
|
push %ebp |
|
|
push %eax |
|
|
push %ebx |
|
|
|
|
|
movb 0x10(%esp), %bl |
|
1316 |
|
|
|
call EXT_C(prot_to_real) |
|
|
.code16 |
|
|
|
|
|
movb %bl, %al |
|
|
movb $0xe, %ah |
|
|
movw $1, %bx |
|
|
int $0x10 |
|
|
|
|
|
DATA32 call EXT_C(real_to_prot) |
|
|
.code32 |
|
|
|
|
|
pop %ebx |
|
|
pop %eax |
|
|
pop %ebp |
|
|
ret |
|
1317 |
|
|
1318 |
#ifndef STAGE1_5 |
#ifndef STAGE1_5 |
1319 |
/* get_code_end() : return the address of the end of the code |
/* get_code_end() : return the address of the end of the code |
1790 |
/* error */ |
/* error */ |
1791 |
call EXT_C(stop) |
call EXT_C(stop) |
1792 |
|
|
1793 |
|
#endif /* ! STAGE1_5 */ |
1794 |
|
|
1795 |
|
/* |
1796 |
|
* void console_putchar (int c) |
1797 |
|
* |
1798 |
|
* Put the character C on the console. Because GRUB wants to write a |
1799 |
|
* character with an attribute, this implementation is a bit tricky. |
1800 |
|
* If C is a control character (CR, LF, BEL, BS), use INT 10, AH = 0Eh |
1801 |
|
* (TELETYPE OUTPUT). Otherwise, save the original position, put a space, |
1802 |
|
* save the current position, restore the original position, write the |
1803 |
|
* character and the attribute, and restore the current position. |
1804 |
|
* |
1805 |
|
* The reason why this is so complicated is that there is no easy way to |
1806 |
|
* get the height of the screen, and the TELETYPE OUPUT BIOS call doesn't |
1807 |
|
* support setting a background attribute. |
1808 |
|
*/ |
1809 |
|
ENTRY(console_putchar) |
1810 |
|
movl 0x4(%esp), %edx |
1811 |
|
pusha |
1812 |
|
#ifdef STAGE1_5 |
1813 |
|
movb $0x07, %bl |
1814 |
|
#else |
1815 |
|
movl EXT_C(console_current_color), %ebx |
1816 |
|
#endif |
1817 |
|
|
1818 |
|
call EXT_C(prot_to_real) |
1819 |
|
.code16 |
1820 |
|
movb %dl, %al |
1821 |
|
xorb %bh, %bh |
1822 |
|
|
1823 |
|
#ifndef STAGE1_5 |
1824 |
|
/* use teletype output if control character */ |
1825 |
|
cmpb $0x7, %al |
1826 |
|
je 1f |
1827 |
|
cmpb $0x8, %al |
1828 |
|
je 1f |
1829 |
|
cmpb $0xa, %al |
1830 |
|
je 1f |
1831 |
|
cmpb $0xd, %al |
1832 |
|
je 1f |
1833 |
|
|
1834 |
|
/* save the character and the attribute on the stack */ |
1835 |
|
pushw %ax |
1836 |
|
pushw %bx |
1837 |
|
|
1838 |
|
/* get the current position */ |
1839 |
|
movb $0x3, %ah |
1840 |
|
int $0x10 |
1841 |
|
|
1842 |
|
/* check the column with the width */ |
1843 |
|
cmpb $79, %dl |
1844 |
|
jl 2f |
1845 |
|
|
1846 |
|
/* print CR and LF, if next write will exceed the width */ |
1847 |
|
movw $0x0e0d, %ax |
1848 |
|
int $0x10 |
1849 |
|
movb $0x0a, %al |
1850 |
|
int $0x10 |
1851 |
|
|
1852 |
|
/* get the current position */ |
1853 |
|
movb $0x3, %ah |
1854 |
|
int $0x10 |
1855 |
|
|
1856 |
|
2: |
1857 |
|
/* restore the character and the attribute */ |
1858 |
|
popw %bx |
1859 |
|
popw %ax |
1860 |
|
|
1861 |
|
/* write the character with the attribute */ |
1862 |
|
movb $0x9, %ah |
1863 |
|
movw $1, %cx |
1864 |
|
int $0x10 |
1865 |
|
|
1866 |
|
/* move the cursor forward */ |
1867 |
|
incb %dl |
1868 |
|
movb $0x2, %ah |
1869 |
|
int $0x10 |
1870 |
|
|
1871 |
|
jmp 3f |
1872 |
|
#endif /* ! STAGE1_5 */ |
1873 |
|
|
1874 |
|
1: movb $0xe, %ah |
1875 |
|
int $0x10 |
1876 |
|
|
1877 |
|
3: DATA32 call EXT_C(real_to_prot) |
1878 |
|
.code32 |
1879 |
|
|
1880 |
|
popa |
1881 |
|
ret |
1882 |
|
|
1883 |
|
|
1884 |
|
#ifndef STAGE1_5 |
1885 |
|
|
1886 |
|
/* this table is used in translate_keycode below */ |
1887 |
|
translation_table: |
1888 |
|
.word KEY_LEFT, 2 |
1889 |
|
.word KEY_RIGHT, 6 |
1890 |
|
.word KEY_UP, 16 |
1891 |
|
.word KEY_DOWN, 14 |
1892 |
|
.word KEY_HOME, 1 |
1893 |
|
.word KEY_END, 5 |
1894 |
|
.word KEY_DC, 4 |
1895 |
|
.word KEY_BACKSPACE, 8 |
1896 |
|
.word 0 |
1897 |
|
|
1898 |
/* |
/* |
1899 |
* console_cls() |
* translate_keycode translates the key code %dx to an ascii code. |
1900 |
* BIOS call "INT 10H Function 0Fh" to get current video mode |
*/ |
1901 |
* Call with %ah = 0x0f |
.code16 |
1902 |
* Returns %al = (video mode) |
|
1903 |
* %bh = (page number) |
translate_keycode: |
1904 |
* BIOS call "INT 10H Function 00h" to set the video mode (clears screen) |
pushw %bx |
1905 |
* Call with %ah = 0x00 |
pushw %si |
1906 |
* %al = (video mode) |
|
1907 |
|
movw $ABS(translation_table), %si |
1908 |
|
|
1909 |
|
1: lodsw |
1910 |
|
/* check if this is the end */ |
1911 |
|
testw %ax, %ax |
1912 |
|
jz 2f |
1913 |
|
/* load the ascii code into %ax */ |
1914 |
|
movw %ax, %bx |
1915 |
|
lodsw |
1916 |
|
/* check if this matches the key code */ |
1917 |
|
cmpw %bx, %dx |
1918 |
|
jne 1b |
1919 |
|
/* translate %dx, if successful */ |
1920 |
|
movw %ax, %dx |
1921 |
|
|
1922 |
|
2: popw %si |
1923 |
|
popw %bx |
1924 |
|
ret |
1925 |
|
|
1926 |
|
.code32 |
1927 |
|
|
1928 |
|
|
1929 |
|
/* |
1930 |
|
* remap_ascii_char remaps the ascii code %dl to another if the code is |
1931 |
|
* contained in ASCII_KEY_MAP. |
1932 |
*/ |
*/ |
1933 |
|
.code16 |
1934 |
|
|
1935 |
|
remap_ascii_char: |
1936 |
|
pushw %si |
1937 |
|
|
1938 |
|
movw $ABS(EXT_C(ascii_key_map)), %si |
1939 |
|
1: |
1940 |
|
lodsw |
1941 |
|
/* check if this is the end */ |
1942 |
|
testw %ax, %ax |
1943 |
|
jz 2f |
1944 |
|
/* check if this matches the ascii code */ |
1945 |
|
cmpb %al, %dl |
1946 |
|
jne 1b |
1947 |
|
/* if so, perform the mapping */ |
1948 |
|
movb %ah, %dl |
1949 |
|
2: |
1950 |
|
/* restore %si */ |
1951 |
|
popw %si |
1952 |
|
|
1953 |
|
ret |
1954 |
|
|
1955 |
ENTRY(console_cls) |
.code32 |
1956 |
|
|
1957 |
|
.align 4 |
1958 |
|
ENTRY(ascii_key_map) |
1959 |
|
.space (KEY_MAP_SIZE + 1) * 2 |
1960 |
|
|
1961 |
|
|
1962 |
|
/* |
1963 |
|
* int console_getkey (void) |
1964 |
|
* BIOS call "INT 16H Function 00H" to read character from keyboard |
1965 |
|
* Call with %ah = 0x0 |
1966 |
|
* Return: %ah = keyboard scan code |
1967 |
|
* %al = ASCII character |
1968 |
|
*/ |
1969 |
|
|
1970 |
|
ENTRY(console_getkey) |
1971 |
push %ebp |
push %ebp |
|
push %ebx /* save EBX */ |
|
1972 |
|
|
1973 |
call EXT_C(prot_to_real) |
call EXT_C(prot_to_real) |
1974 |
.code16 |
.code16 |
1975 |
|
|
1976 |
movb $0xf, %ah |
int $0x16 |
|
int $0x10 /* Get Current Video mode */ |
|
|
xorb %ah, %ah |
|
|
int $0x10 /* Set Video mode (clears screen) */ |
|
1977 |
|
|
1978 |
|
movw %ax, %dx /* real_to_prot uses %eax */ |
1979 |
|
call translate_keycode |
1980 |
|
call remap_ascii_char |
1981 |
|
|
1982 |
DATA32 call EXT_C(real_to_prot) |
DATA32 call EXT_C(real_to_prot) |
1983 |
.code32 |
.code32 |
1984 |
|
|
1985 |
pop %ebx |
movw %dx, %ax |
1986 |
|
|
1987 |
pop %ebp |
pop %ebp |
1988 |
ret |
ret |
1989 |
|
|
1990 |
|
|
1991 |
/* |
/* |
1992 |
* nocursor() |
* int console_checkkey (void) |
1993 |
* BIOS call "INT 10H Function 01h" to set cursor type |
* if there is a character pending, return it; otherwise return -1 |
1994 |
* Call with %ah = 0x01 |
* BIOS call "INT 16H Function 01H" to check whether a character is pending |
1995 |
* %ch = cursor starting scanline |
* Call with %ah = 0x1 |
1996 |
* %cl = cursor ending scanline |
* Return: |
1997 |
|
* If key waiting to be input: |
1998 |
|
* %ah = keyboard scan code |
1999 |
|
* %al = ASCII character |
2000 |
|
* Zero flag = clear |
2001 |
|
* else |
2002 |
|
* Zero flag = set |
2003 |
*/ |
*/ |
2004 |
|
ENTRY(console_checkkey) |
|
ENTRY(nocursor) |
|
2005 |
push %ebp |
push %ebp |
2006 |
push %ebx /* save EBX */ |
xorl %edx, %edx |
2007 |
|
|
2008 |
call EXT_C(prot_to_real) |
call EXT_C(prot_to_real) /* enter real mode */ |
2009 |
.code16 |
.code16 |
2010 |
|
|
2011 |
movw $0x2000, %cx |
movb $0x1, %ah |
2012 |
movb $0x1, %ah |
int $0x16 |
2013 |
int $0x10 |
|
2014 |
|
DATA32 jz notpending |
2015 |
|
|
2016 |
|
movw %ax, %dx |
2017 |
|
call translate_keycode |
2018 |
|
call remap_ascii_char |
2019 |
|
DATA32 jmp pending |
2020 |
|
|
2021 |
|
notpending: |
2022 |
|
movl $0xFFFFFFFF, %edx |
2023 |
|
|
2024 |
|
pending: |
2025 |
DATA32 call EXT_C(real_to_prot) |
DATA32 call EXT_C(real_to_prot) |
2026 |
.code32 |
.code32 |
2027 |
|
|
2028 |
pop %ebx |
mov %edx, %eax |
2029 |
|
|
2030 |
pop %ebp |
pop %ebp |
2031 |
ret |
ret |
|
|
|
2032 |
|
|
2033 |
|
|
2034 |
/* |
/* |
2035 |
* console_getxy() |
* int console_getxy (void) |
2036 |
* BIOS call "INT 10H Function 03h" to get cursor position |
* BIOS call "INT 10H Function 03h" to get cursor position |
2037 |
* Call with %ah = 0x03 |
* Call with %ah = 0x03 |
2038 |
* %bh = page |
* %bh = page |
2066 |
|
|
2067 |
|
|
2068 |
/* |
/* |
2069 |
* console_gotoxy(x,y) |
* void console_gotoxy(int x, int y) |
2070 |
* BIOS call "INT 10H Function 02h" to set cursor position |
* BIOS call "INT 10H Function 02h" to set cursor position |
2071 |
* Call with %ah = 0x02 |
* Call with %ah = 0x02 |
2072 |
* %bh = page |
* %bh = page |
2096 |
pop %ebp |
pop %ebp |
2097 |
ret |
ret |
2098 |
|
|
2099 |
|
|
2100 |
/* |
/* |
2101 |
* console_set_attrib(attr) : Sets the character attributes for character at |
* void console_cls (void) |
2102 |
* current cursor position. |
* BIOS call "INT 10H Function 0Fh" to get current video mode |
2103 |
* |
* Call with %ah = 0x0f |
2104 |
* Bitfields for character's display attribute: |
* Returns %al = (video mode) |
2105 |
* Bit(s) Description |
* %bh = (page number) |
2106 |
* 7 foreground blink |
* BIOS call "INT 10H Function 00h" to set the video mode (clears screen) |
2107 |
* 6-4 background color |
* Call with %ah = 0x00 |
2108 |
* 3 foreground bright |
* %al = (video mode) |
|
* 2-0 foreground color |
|
|
* |
|
|
* Values for character color: |
|
|
* Normal Bright |
|
|
* 000b black dark gray |
|
|
* 001b blue light blue |
|
|
* 010b green light green |
|
|
* 011b cyan light cyan |
|
|
* 100b red light red |
|
|
* 101b magenta light magenta |
|
|
* 110b brown yellow |
|
|
* 111b light gray white |
|
|
* |
|
|
* BIOS call "INT 10H Function 08h" to read character and attribute data |
|
|
* Call with %ah = 0x08 |
|
|
* %bh = page |
|
|
* Returns %ah = character attribute |
|
|
* %al = character value |
|
|
* BIOS call "INT 10H Function 09h" to write character and attribute data |
|
|
* Call with %ah = 0x09 |
|
|
* %al = character value |
|
|
* %bh = page |
|
|
* %bl = character attribute |
|
|
* %cx = count to display (???, possible side-effects!!) |
|
2109 |
*/ |
*/ |
2110 |
|
|
|
ENTRY(console_set_attrib) |
|
|
push %ebp |
|
|
push %ebx |
|
2111 |
|
|
2112 |
movl 0xc(%esp), %ecx |
ENTRY(console_cls) |
2113 |
xorl %ebx, %ebx |
push %ebp |
2114 |
|
push %ebx /* save EBX */ |
2115 |
|
|
2116 |
call EXT_C(prot_to_real) |
call EXT_C(prot_to_real) |
2117 |
.code16 |
.code16 |
2118 |
|
|
2119 |
movb $0x8, %ah |
movb $0xf, %ah |
2120 |
int $0x10 |
int $0x10 /* Get Current Video mode */ |
2121 |
movb $0x9, %ah |
xorb %ah, %ah |
2122 |
movb %cl, %bl |
int $0x10 /* Set Video mode (clears screen) */ |
|
movw $1, %cx |
|
|
int $0x10 |
|
2123 |
|
|
2124 |
DATA32 call EXT_C(real_to_prot) |
DATA32 call EXT_C(real_to_prot) |
2125 |
.code32 |
.code32 |
2128 |
pop %ebp |
pop %ebp |
2129 |
ret |
ret |
2130 |
|
|
2131 |
|
|
2132 |
|
/* |
2133 |
|
* void console_nocursor (void) |
2134 |
|
* BIOS call "INT 10H Function 01h" to set cursor type |
2135 |
|
* Call with %ah = 0x01 |
2136 |
|
* %ch = cursor starting scanline |
2137 |
|
* %cl = cursor ending scanline |
2138 |
|
*/ |
2139 |
|
|
2140 |
|
ENTRY(console_nocursor) |
2141 |
|
push %ebp |
2142 |
|
|
2143 |
|
call EXT_C(prot_to_real) |
2144 |
|
.code16 |
2145 |
|
|
2146 |
|
movw $0x2000, %cx |
2147 |
|
movb $0x1, %ah |
2148 |
|
int $0x10 |
2149 |
|
|
2150 |
|
DATA32 call EXT_C(real_to_prot) |
2151 |
|
.code32 |
2152 |
|
|
2153 |
|
pop %ebp |
2154 |
|
ret |
2155 |
|
|
2156 |
/* |
/* |
2157 |
* getrtsecs() |
* getrtsecs() |
2158 |
* if a seconds value can be read, read it and return it (BCD), |
* if a seconds value can be read, read it and return it (BCD), |
2217 |
popl %ebp |
popl %ebp |
2218 |
ret |
ret |
2219 |
|
|
|
|
|
|
/* |
|
|
* remap_ascii_char remaps the ascii code %bl to another if the code is |
|
|
* contained in ASCII_KEY_MAP. |
|
|
*/ |
|
|
.code16 |
|
|
|
|
|
remap_ascii_char: |
|
|
pushw %si |
|
|
|
|
|
movw $ABS(EXT_C(ascii_key_map)), %si |
|
|
1: |
|
|
lodsw |
|
|
/* check if this is the end */ |
|
|
testw %ax, %ax |
|
|
jz 2f |
|
|
/* check if this matches the ascii code */ |
|
|
cmpb %al, %bl |
|
|
jne 1b |
|
|
/* if so, perform the mapping */ |
|
|
movb %ah, %bl |
|
|
2: |
|
|
/* restore %si */ |
|
|
popw %si |
|
|
|
|
|
ret |
|
|
|
|
|
.code32 |
|
|
|
|
|
.align 4 |
|
|
ENTRY(ascii_key_map) |
|
|
.space (KEY_MAP_SIZE + 1) * 2 |
|
|
|
|
|
|
|
|
/* |
|
|
* console_getkey() |
|
|
* BIOS call "INT 16H Function 00H" to read character from keyboard |
|
|
* Call with %ah = 0x0 |
|
|
* Return: %ah = keyboard scan code |
|
|
* %al = ASCII character |
|
|
*/ |
|
|
|
|
|
ENTRY(console_getkey) |
|
|
push %ebp |
|
|
push %ebx /* save %ebx */ |
|
|
|
|
|
call EXT_C(prot_to_real) |
|
|
.code16 |
|
|
|
|
|
int $0x16 |
|
|
|
|
|
movw %ax, %bx /* real_to_prot uses %eax */ |
|
|
call remap_ascii_char |
|
|
|
|
|
DATA32 call EXT_C(real_to_prot) |
|
|
.code32 |
|
|
|
|
|
movw %bx, %ax |
|
|
|
|
|
pop %ebx |
|
|
pop %ebp |
|
|
ret |
|
|
|
|
|
|
|
|
/* |
|
|
* console_checkkey() |
|
|
* if there is a character pending, return it; otherwise return -1 |
|
|
* BIOS call "INT 16H Function 01H" to check whether a character is pending |
|
|
* Call with %ah = 0x1 |
|
|
* Return: |
|
|
* If key waiting to be input: |
|
|
* %ah = keyboard scan code |
|
|
* %al = ASCII character |
|
|
* Zero flag = clear |
|
|
* else |
|
|
* Zero flag = set |
|
|
*/ |
|
|
ENTRY(console_checkkey) |
|
|
push %ebp |
|
|
push %ebx |
|
|
|
|
|
xorl %ebx, %ebx |
|
|
|
|
|
call EXT_C(prot_to_real) /* enter real mode */ |
|
|
.code16 |
|
|
|
|
|
movb $0x1, %ah |
|
|
int $0x16 |
|
|
|
|
|
DATA32 jz notpending |
|
|
|
|
|
movw %ax, %bx |
|
|
call remap_ascii_char |
|
|
DATA32 jmp pending |
|
|
|
|
|
notpending: |
|
|
movl $0xFFFFFFFF, %ebx |
|
|
|
|
|
pending: |
|
|
DATA32 call EXT_C(real_to_prot) |
|
|
.code32 |
|
|
|
|
|
mov %ebx, %eax |
|
|
|
|
|
pop %ebx |
|
|
pop %ebp |
|
|
ret |
|
|
|
|
2220 |
#endif /* STAGE1_5 */ |
#endif /* STAGE1_5 */ |
2221 |
|
|
2222 |
/* |
/* |