diff --git a/Makefile b/Makefile index 15cf69f..912caaf 100644 --- a/Makefile +++ b/Makefile @@ -12,7 +12,7 @@ _bd: all: _bd $(OBJ) @echo "* Linking EFI..." - @ld $(LDFLAGS) gnu-efi/x86_64/gnuefi/crt0-efi-x86_64.o build/boot.o build/graphics/draw.o build/graphics/context.o build/kernel/main.o build/kernel/serial.o build/fonts/pixel_font.o -o build/boot.so $(LDLIBS) + @ld $(LDFLAGS) gnu-efi/x86_64/gnuefi/crt0-efi-x86_64.o $(OBJ) -o build/boot.so $(LDLIBS) @objcopy -j .text -j .sdata -j .data -j .rodata -j .dynamic -j .dynsym -j .rel -j .rela -j .rel.* -j .rela.* -j .reloc --output-target efi-app-x86_64 --subsystem=10 build/boot.so build/BOOTX64.EFI build/%.o: %.c diff --git a/fonts/pixel_font.cpp b/fonts/pixel_font.cpp index 1aef619..188dee3 100644 --- a/fonts/pixel_font.cpp +++ b/fonts/pixel_font.cpp @@ -1,12 +1,28 @@ -#include +#include #include #include #include +static unsigned int pf_x = 0; +static unsigned int pf_y = 1; + +void pf_reset_position(void) { + // 其实应该还要清一下屏,后面思考一个安全的做法 + pf_x = 0; + pf_y = 1; +} + void pf_print_char(char c, unsigned int basex, unsigned int basey, EFI_GRAPHICS_OUTPUT_BLT_PIXEL color) { for (unsigned int y = 0; y < 16; y++) { unsigned char data = hankaku_pixels[c][y]; for (int x = 7; x >= 0; x--) { + // 解码Hankaku字体 + /* + 既然都在这了,就讲一下Hankaku字体是如何解码的 + 比如一个 + {0x00, 0x82, 0x82, 0x44, 0x44, 0x44, 0x28, 0x28, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00} + 每一个Hex代表一行,比如0x82就是一行,转换成Bin得到10000010,1代表有像素,0代表没像素 + */ unsigned int current = data & 1; data >>= 1; if (current) @@ -15,8 +31,27 @@ void pf_print_char(char c, unsigned int basex, unsigned int basey, EFI_GRAPHICS_ } } -void pf_print(char* text, unsigned int basex, unsigned int basey, EFI_GRAPHICS_OUTPUT_BLT_PIXEL color) { +void pf_print(const char* text, EFI_GRAPHICS_OUTPUT_BLT_PIXEL color) { for (unsigned int i = 0; i < strlen(text); i++) { - pf_print_char(text[i], basex + 9 * i, basey, color); + char c = text[i]; + if (c == '\n') { + pf_x = 0; + pf_y++; + if ((pf_y - 1) * 16 >= g_gfx.vr) { + gfx_clear(); + pf_y = 1; + } + continue; + } + if (pf_x * 9 + 9 > g_gfx.hr) { + pf_x = 0; + pf_y++; + if ((pf_y - 1) * 16 >= g_gfx.vr) { + gfx_clear(); + pf_y = 1; + } + } + pf_print_char(c, pf_x * 9, (pf_y - 1) * 16, color); + pf_x++; } } \ No newline at end of file diff --git a/graphics/context.cpp b/graphics/context.cpp index 0042ab9..c90894a 100644 --- a/graphics/context.cpp +++ b/graphics/context.cpp @@ -7,4 +7,9 @@ void gfx_init(EFI_GRAPHICS_OUTPUT_PROTOCOL *GOP) { g_gfx.hr = GOP->Mode->Info->HorizontalResolution; g_gfx.vr = GOP->Mode->Info->VerticalResolution; g_gfx.base = (EFI_GRAPHICS_OUTPUT_BLT_PIXEL *) GOP->Mode->FrameBufferBase; +} + +void gfx_clear(void) { + EFI_GRAPHICS_OUTPUT_BLT_PIXEL black = {0, 0, 0, 0}; + g_gfx.GOP->Blt(g_gfx.GOP, &black, EfiBltVideoFill, 0, 0, 0, 0, g_gfx.hr, g_gfx.vr, 0); } \ No newline at end of file diff --git a/include/BUILD_INFOS.h b/include/BUILD_INFOS.h new file mode 100644 index 0000000..76ddf40 --- /dev/null +++ b/include/BUILD_INFOS.h @@ -0,0 +1,5 @@ +#pragma once + +// 存放各类参数定义,后续给CI用 + +#define ENABLE_SERIAL_PRINTS true \ No newline at end of file diff --git a/include/common.h b/include/common.h index d3e1c6f..11a9603 100644 --- a/include/common.h +++ b/include/common.h @@ -1,6 +1,8 @@ #pragma once -unsigned int strlen(char* arr) { +#define ASM asm volatile + +static unsigned int strlen(const char* arr) { // 获取string长度 int i = 0; while (arr[i++] != '\0'); return i - 1; diff --git a/include/fonts/sylva_sd.h b/include/fonts/hankaku.h similarity index 99% rename from include/fonts/sylva_sd.h rename to include/fonts/hankaku.h index 44fbbfe..542e081 100644 --- a/include/fonts/sylva_sd.h +++ b/include/fonts/hankaku.h @@ -1,6 +1,6 @@ #pragma once -// Hankaku 字体 +// Hankaku 字体,不动 static unsigned char hankaku_pixels[256][16] = { {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, {0x10, 0x10, 0x38, 0x38, 0x7c, 0x7c, 0xfe, 0xfe, 0x7c, 0x7c, 0x38, 0x38, 0x10, 0x10, 0x00, 0x00}, diff --git a/include/fonts/pixel_font.h b/include/fonts/pixel_font.h index 649624b..353328e 100644 --- a/include/fonts/pixel_font.h +++ b/include/fonts/pixel_font.h @@ -2,5 +2,7 @@ #include -void pf_print_char(char c, unsigned int basex, unsigned int basey, EFI_GRAPHICS_OUTPUT_BLT_PIXEL color = {255, 255, 255, 255}); -void pf_print(char* text, unsigned int basex, unsigned int basey, EFI_GRAPHICS_OUTPUT_BLT_PIXEL color = {255, 255, 255, 255}); \ No newline at end of file +void pf_print_char(char c, unsigned int basex, unsigned int basey, + EFI_GRAPHICS_OUTPUT_BLT_PIXEL color = {255, 255, 255, 255}); // Pixel Font 打印字符 +void pf_print(const char* text, EFI_GRAPHICS_OUTPUT_BLT_PIXEL color = {255, 255, 255, 255}); // Pixel Font 打印string +void pf_reset_position(void); // 重设Pixel Font Cursor位置 \ No newline at end of file diff --git a/include/graphics/context.h b/include/graphics/context.h index b872a21..90166c7 100644 --- a/include/graphics/context.h +++ b/include/graphics/context.h @@ -1,5 +1,7 @@ #pragma once +// 这个文件存在的目的是让graphics的draw功能不用每次传 GOP hr vr base + #include struct gfx_context { @@ -11,4 +13,5 @@ struct gfx_context { extern gfx_context g_gfx; -void gfx_init(EFI_GRAPHICS_OUTPUT_PROTOCOL *GOP); \ No newline at end of file +void gfx_init(EFI_GRAPHICS_OUTPUT_PROTOCOL *GOP); // 初始化 GFX +void gfx_clear(void); // 清空 GFX(相当于重置) \ No newline at end of file diff --git a/include/graphics/draw.h b/include/graphics/draw.h index db7cbb4..5b08c9e 100644 --- a/include/graphics/draw.h +++ b/include/graphics/draw.h @@ -3,4 +3,4 @@ #include #include -void draw_pixel(unsigned int x, unsigned int y, EFI_GRAPHICS_OUTPUT_BLT_PIXEL color); \ No newline at end of file +void draw_pixel(unsigned int x, unsigned int y, EFI_GRAPHICS_OUTPUT_BLT_PIXEL color); // 画像素 \ No newline at end of file diff --git a/include/serial.h b/include/serial.h index 7602676..88ae3e0 100644 --- a/include/serial.h +++ b/include/serial.h @@ -3,13 +3,13 @@ #include #include -struct serial_context { +struct serial_context { // 串行内容结构体 EFI_SERIAL_IO_PROTOCOL *SerialIo; }; extern serial_context g_serial; -void serial_init(EFI_SERIAL_IO_PROTOCOL *SerialIo); -void serial_write(const char *str); -void serial_write_char(char c); -char serial_read_char(); \ No newline at end of file +void serial_init(EFI_SERIAL_IO_PROTOCOL *SerialIo); // 初始化串行驱动 +void serial_write(const char *str); // 往串行写string +void serial_write_char(char c); // 往串行写char(不推荐使用) +char serial_read_char(); // 读串行 \ No newline at end of file diff --git a/kernel/main.cpp b/kernel/main.cpp index 40669ef..72bc386 100644 --- a/kernel/main.cpp +++ b/kernel/main.cpp @@ -4,8 +4,10 @@ #include #include #include +#include inline void init_gop() { + // 初始化 GOP EFI_GUID gop_guid = EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID; EFI_GRAPHICS_OUTPUT_PROTOCOL *GOP; uefi_call_wrapper((void*)ST->BootServices->SetWatchdogTimer, 4, 0, 0, 0, NULL); @@ -14,6 +16,7 @@ inline void init_gop() { } inline void init_serial() { + // 初始化串行驱动 EFI_SERIAL_IO_PROTOCOL *SerialIo = NULL; EFI_GUID gEfiSerialIoProtocolGuid = EFI_SERIAL_IO_PROTOCOL_GUID; EFI_HANDLE *SerialHandles = NULL; @@ -41,15 +44,15 @@ extern "C" void kernel_main() { init_gop(); init_serial(); + // 都用uefi_call_wrapper,不用会PF,不知道为什么 uefi_call_wrapper((void*)ST->ConOut->SetCursorPosition, 3, ST->ConOut, 0, 5); uefi_call_wrapper((void*)ST->ConOut->OutputString, 2, ST->ConOut, L"Kernel is running!\n"); uefi_call_wrapper((void*)ST->ConOut->ClearScreen, 1, ST->ConOut); - serial_write("\n\n"); // 防止和前面串了 + serial_write("\n\n"); // 防止和前面串了serial.log看不清 - // pf_print_char('k', 10, 10); - pf_print("Welcome to Sylva OS!", 10, 10); - serial_write("Hello from serial!\n"); - serial_write("Hello from serial line 2!"); - while (1); + pf_print("Welcome to Sylva OS!\n"); + serial_write(" Kernel prepared well, start loop.\n"); + + while (1) ASM ("hlt"); // 《30天》看多了 (doge } \ No newline at end of file diff --git a/kernel/serial.cpp b/kernel/serial.cpp index f47ed62..b625f0b 100644 --- a/kernel/serial.cpp +++ b/kernel/serial.cpp @@ -1,5 +1,7 @@ #include #include +#include +#include serial_context g_serial; @@ -9,12 +11,14 @@ void serial_init(EFI_SERIAL_IO_PROTOCOL *SerialIo) { } void serial_write_char(char c) { + // 不要直接调用,ENABLE_SERIAL_PRINTS有问题,因此不会打印DEBUG if (!g_serial.SerialIo) { uefi_call_wrapper((void*)ST->ConOut->OutputString, 2, ST->ConOut, L"serial: null io\n"); return; } UINTN size = 1; EFI_STATUS status = uefi_call_wrapper((void*)g_serial.SerialIo->Write, 3, g_serial.SerialIo, &size, &c); + // if (ENABLE_SERIAL_PRINTS) pf_print((const char*) c); if (status != EFI_SUCCESS) { uefi_call_wrapper((void*)ST->ConOut->OutputString, 2, ST->ConOut, L"serial: write failed\n"); } @@ -25,12 +29,14 @@ void serial_write(const char *str) { uefi_call_wrapper((void*)ST->ConOut->OutputString, 2, ST->ConOut, L"serial: null io\n"); return; } + if (ENABLE_SERIAL_PRINTS) pf_print(str); while (*str) { serial_write_char(*str++); } } char serial_read_char() { + // 后面可能用的上,比如远程调试? if (!g_serial.SerialIo) return 0; char c = 0; UINTN size = 1;