Compare commits

...

4 Commits

Author SHA1 Message Date
Bananymous 9ff9d679e9 Kernel: Fix text mode cursor
Apparently text mode renders cursor in the *foreground* color. My
current clear function used the same color for foreground and background
making the cursor effectively invisible.

Also cursor hiding is now done by moving the cursor off bounds (0, height)
some website I read said this to be valid even on VGA compatible cards
without disable bit.

http://www.osdever.net/FreeVGA/vga/textcur.htm
2025-04-25 02:31:33 +03:00
Bananymous 9f3f8f950a Kernel: Add better panic message for failed shutdown
ACPI shutdown does not work on the web emulator and running `poweroff`
crashes on `ASSERT_NOT_REACHED()`.
2025-04-25 01:52:33 +03:00
Bananymous 006a196e4a LibC: optimize strpbrk, str{,c}spn, strtok{,_r}
These matches are now detected with bitmasks instead of looping over the
second string
2025-04-24 01:39:49 +03:00
Bananymous 418678466c Kernel: Fix text mode palette
ANSI and text mode color indices are not in the same order
2025-04-23 23:07:47 +03:00
4 changed files with 97 additions and 85 deletions

View File

@ -30,6 +30,7 @@ namespace Kernel
{}
BAN::ErrorOr<void> initialize();
void move_cursor_impl(uint32_t x, uint32_t y);
private:
const paddr_t m_paddr;
@ -37,6 +38,10 @@ namespace Kernel
const uint32_t m_height;
const uint32_t m_pitch;
vaddr_t m_vaddr { 0 };
uint32_t m_cursor_x { 0 };
uint32_t m_cursor_y { 0 };
bool m_cursor_shown { true };
static constexpr Color s_cursor_color = TerminalColor::WHITE;
};

View File

@ -562,7 +562,7 @@ acpi_release_global_lock:
}
// system must not execute after sleep registers are written
ASSERT_NOT_REACHED();
panic("ACPI shutdown failed. You can now safely shutdown your computer.");
}
BAN::ErrorOr<void> ACPI::reset()

View File

@ -11,20 +11,21 @@ namespace Kernel
{
TerminalDriver::Palette palette;
palette[ 0] = 0x000000;
palette[ 1] = 0x0000AA;
palette[ 1] = 0xAA0000;
palette[ 2] = 0x00AA00;
palette[ 3] = 0x00AAAA;
palette[ 4] = 0xAA0000;
palette[ 3] = 0xAA5500;
palette[ 4] = 0x0000AA;
palette[ 5] = 0xAA00AA;
palette[ 6] = 0xAA5500;
palette[ 6] = 0x00AAAA;
palette[ 7] = 0xAAAAAA;
palette[ 8] = 0x555555;
palette[ 9] = 0x5555FF;
palette[ 9] = 0xFF5555;
palette[10] = 0x55FF55;
palette[11] = 0x55FFFF;
palette[12] = 0xFF5555;
palette[11] = 0xFFFF55;
palette[12] = 0x5555FF;
palette[13] = 0xFF55FF;
palette[14] = 0xFFFF55;
palette[14] = 0x55FFFF;
palette[15] = 0xFFFFFF;
return palette;
}
@ -47,7 +48,10 @@ namespace Kernel
closest = i;
}
return closest;
constexpr uint8_t terminal_to_text[16] {
0, 4, 2, 6, 1, 5, 3, 7, 8, 12, 10, 14, 9, 13, 11, 15
};
return terminal_to_text[closest];
}
BAN::ErrorOr<BAN::RefPtr<TextModeTerminalDriver>> TextModeTerminalDriver::create_from_boot_info()
@ -118,32 +122,11 @@ namespace Kernel
{
for (uint32_t y = 0; y < m_height; y++)
for (uint32_t x = 0; x < m_width; x++)
putchar_at(' ', x, y, color, color);
putchar_at(' ', x, y, TerminalColor::WHITE, color);
}
void TextModeTerminalDriver::set_cursor_shown(bool shown)
void TextModeTerminalDriver::move_cursor_impl(uint32_t x, uint32_t y)
{
if (shown)
{
IO::outb(0x3D4, 0x0A);
IO::outb(0x3D5, (IO::inb(0x3D5) & 0xC0) | 14);
IO::outb(0x3D4, 0x0B);
IO::outb(0x3D5, (IO::inb(0x3D5) & 0xE0) | 15);
}
else
{
IO::outb(0x3D4, 0x0A);
IO::outb(0x3D5, 0x20);
}
}
void TextModeTerminalDriver::set_cursor_position(uint32_t x, uint32_t y)
{
// NOTE: cursor is allowed to be on width as scrolling only
// happens after character gets printed to next line
if (x == m_width)
return;
const uint16_t pos = y * m_width + x;
IO::outb(0x3D4, 0x0F);
IO::outb(0x3D5, pos & 0xFF);
@ -151,4 +134,32 @@ namespace Kernel
IO::outb(0x3D5, pos >> 8);
}
void TextModeTerminalDriver::set_cursor_shown(bool shown)
{
if (m_cursor_shown == shown)
return;
m_cursor_shown = shown;
if (shown)
move_cursor_impl(m_cursor_x, m_cursor_y);
else
move_cursor_impl(0, m_height);
}
void TextModeTerminalDriver::set_cursor_position(uint32_t x, uint32_t y)
{
ASSERT(x <= m_width);
ASSERT(y < m_height);
m_cursor_x = x;
m_cursor_y = y;
if (!m_cursor_shown)
return;
if (x == m_width)
move_cursor_impl(0, m_height);
else
move_cursor_impl(x, y);
}
}

View File

@ -282,37 +282,39 @@ char* strstr(const char* haystack, const char* needle)
return nullptr;
}
size_t strcspn(const char* s1, const char* s2)
{
size_t i = 0;
for (; s1[i]; i++)
for (size_t j = 0; s2[j]; j++)
if (s1[i] == s2[j])
return i;
return i;
}
#define CHAR_UCHAR(ch) \
static_cast<unsigned char>(ch)
#define CHAR_BITMASK(str) \
uint32_t bitmask[0x100 / 32] {}; \
for (size_t i = 0; str[i]; i++) \
bitmask[CHAR_UCHAR(str[i]) / 32] |= (1 << (CHAR_UCHAR(str[i]) % 32))
#define CHAR_BITMASK_TEST(ch) \
(bitmask[CHAR_UCHAR(ch) / 32] & (1 << (CHAR_UCHAR(ch) % 32)))
char* strpbrk(const char* s1, const char* s2)
{
CHAR_BITMASK(s2);
for (size_t i = 0; s1[i]; i++)
for (size_t j = 0; s2[j]; j++)
if (s1[i] == s2[j])
return const_cast<char*>(s1 + i);
if (CHAR_BITMASK_TEST(s1[i]))
return const_cast<char*>(&s1[i]);
return nullptr;
}
size_t strspn(const char* s1, const char* s2)
{
size_t i = 0;
for (; s1[i]; i++)
{
bool found = false;
for (size_t j = 0; s2[j] && !found; j++)
if (s1[i] == s2[j])
found = true;
if (!found)
break;
}
CHAR_BITMASK(s2);
for (size_t i = 0;; i++)
if (s1[i] == '\0' || !CHAR_BITMASK_TEST(s1[i]))
return i;
}
size_t strcspn(const char* s1, const char* s2)
{
CHAR_BITMASK(s2);
for (size_t i = 0;; i++)
if (s1[i] == '\0' || CHAR_BITMASK_TEST(s1[i]))
return i;
}
@ -324,49 +326,43 @@ char* strtok(char* __restrict s, const char* __restrict sep)
char* strtok_r(char* __restrict str, const char* __restrict sep, char** __restrict state)
{
if (str)
{
while (*str)
{
bool found = false;
for (size_t i = 0; sep[i] && !found; i++)
if (*str == sep[i])
found = true;
if (!found)
break;
str++;
}
CHAR_BITMASK(sep);
if (!*str)
if (str)
*state = str;
if (*state == nullptr)
return nullptr;
str = *state;
for (; *str; str++)
if (!CHAR_BITMASK_TEST(*str))
break;
if (*str == '\0')
{
*state = nullptr;
return nullptr;
}
*state = str;
}
if (!*state)
return nullptr;
str = *state;
for (size_t i = 0; str[i]; i++)
{
for (size_t j = 0; sep[j]; j++)
{
if (str[i] == sep[j])
{
if (!CHAR_BITMASK_TEST(str[i]))
continue;
str[i] = '\0';
*state = str + i + 1;
return str;
}
}
}
*state = nullptr;
return str;
}
#undef CHAR_UCHAR
#undef CHAR_BITMASK
#undef CHAR_BITMASK_TEST
char* strsignal(int signum)
{
static char buffer[128];