From: Michael D. Lowis Date: Thu, 23 Sep 2021 01:23:43 +0000 (-0400) Subject: fixed scrolling logic X-Git-Url: https://git.mdlowis.com/?a=commitdiff_plain;h=d94b4cc975592a43879b84a2eea75aee8f05350a;p=proto%2Fuefi.git fixed scrolling logic --- d94b4cc975592a43879b84a2eea75aee8f05350a diff --cc Makefile index 7692f86,c05f02e..0c2734e --- a/Makefile +++ b/Makefile @@@ -1,12 -1,48 +1,50 @@@ - TARGET = kernel.efi + ARCH = x86_64 + EFIARCH = efi-app-$(ARCH) + TARGET = BOOTX64.EFI + +OVMF = /usr/share/qemu/OVMF.fd - #OVMF = /usr/share/edk2-ovmf/OVMF_CODE.fd + - include uefi/Makefile + CC = gcc + LD = ld + OBJCOPY = objcopy + AR = ar + + CFLAGS = \ + -fshort-wchar \ + -fno-strict-aliasing \ + -ffreestanding \ + -fno-stack-protector \ + -fno-stack-check \ + -mno-red-zone \ + -maccumulate-outgoing-args \ + -Wno-builtin-declaration-mismatch \ + -fpic \ + -fPIC + + CPPFLAGS = \ + -I./core/ \ + -I./uefi \ + -I/usr/include \ + -D__$(ARCH)__ \ + -DHAVE_USE_MS_ABI + + LDFLAGS = \ + -nostdlib \ + -shared \ + -Bsymbolic \ + -Luefi + + LIBS = \ + -o $(TARGET).so \ + -T uefi/elf_$(ARCH)_efi.lds - .PHONY: all run clean + # get source files, generate object names + SRCS = $(wildcard core/*.c uefi/*.c) + OBJS = $(SRCS:.c=.o) - all: boot.img + .PHONY: all clean run + + all: $(TARGET) clean: find -name '*.o' -delete diff --cc core/kernel.h index 8363ca7,c390b6b..98f5c62 --- a/core/kernel.h +++ b/core/kernel.h @@@ -2,21 -5,17 +5,15 @@@ #define FONT_HEIGHT 16 extern uint8_t Font[]; - struct Video { - uint32_t* buffer; - uint32_t stride; - }; - - extern struct Video Video; - - void Video_Init(void); --void Video_PutGlyph(int x, int y, char c); -- static inline void Video_PutPixel(int x, int y, uint32_t pixel) { - int offset = (sizeof(pixel) * Video.stride * y) + (sizeof(pixel) * x); - *(Video.buffer + offset) = pixel; + Video.buffer[Video.stride * y + x] = pixel; } + /* + Terminal/Console Driver + */ ++void Term_Init(void); void Term_Clear(void); void Term_PutChar(int c); void Term_PutString(char* s); diff --cc core/main.c index 0000000,39c0e66..6a79213 mode 000000,100644..100644 --- a/core/main.c +++ b/core/main.c @@@ -1,0 -1,13 +1,20 @@@ + #include ++#include + + int main (int argc, char** argv) + { ++ Term_Init(); + + /* loop forever */ + for (;;) + { -// BS->Stall(1000000); ++ Term_PutString("foo\n"); ++ sleep(250); ++ Term_PutString("bar\n"); ++ sleep(250); ++ Term_PutString("baz\n"); ++ sleep(250); + } + + return 0; + } diff --cc core/term.c index 4132341,e08ca70..0619e24 --- a/core/term.c +++ b/core/term.c @@@ -1,11 -1,29 +1,85 @@@ - #include + #include + #include + ++#define MAX_COLS 240 ++#define MAX_ROWS 75 + static char* Digits = "0123456789abcdef"; ++struct { ++ int cols; ++ int rows; ++ int cursor; ++ char cells[MAX_ROWS * MAX_COLS]; ++} Term = { 0 }; ++ + static void PutGlyph(int x, int y, char c) + { + char* glyph = &Font[c * FONT_HEIGHT]; + for (int row = 0; row < 16; row++) + { + char piece = glyph[row]; + for (int col = 0; col < 8; col++, piece <<= 1) + { + Video_PutPixel( - (x * FONT_WIDTH) + col, - (y * FONT_HEIGHT) + row, ++ x + col, ++ y + row, + (piece & 0x80) ? 0xFFFFFFFF : 0x00000000); + } + } + } + ++static void PutCell(int c) ++{ ++ int max = Term.rows * Term.cols; ++ /* check if we need to scroll and do it */ ++ if (Term.cursor >= max) ++ { ++ int dst = 0; ++ int src = Term.cols; ++ Term.cursor = (Term.rows - 1) * Term.cols; ++ while (src < max) ++ { ++ PutGlyph((dst % Term.cols) * 8, (dst / Term.rows) * 16, Term.cells[src]); ++ Term.cells[dst++] = Term.cells[src++]; ++ } ++ for (int i = Term.cursor; i < Term.cols; i++) ++ { ++ PutGlyph((i % Term.cols) * 8, (i / Term.rows) * 16, ' '); ++ Term.cells[i] = ' '; ++ } ++ } ++ /* now place the new glyph */ ++ Term.cells[Term.cursor] = c; ++ int row = (Term.cursor / Term.cols); ++ int col = (Term.cursor % Term.cols); ++ PutGlyph(col * 8, row * 16, c); ++ Term.cursor++; ++} ++ ++void Term_Init(void) ++{ ++ Term.cols = min(Video.width / FONT_WIDTH, MAX_COLS); ++ Term.rows = min(Video.height / FONT_HEIGHT, MAX_ROWS); ++} + void Term_PutChar(int c) { - wchar_t tmp[2] = { (wchar_t)c, 0 }; - ST->ConOut->OutputString(ST->ConOut, (c == '\n' ? (wchar_t*)L"\r\n" : tmp)); -// wchar_t tmp[2] = { (wchar_t)c, 0 }; -// ST->ConOut->OutputString(ST->ConOut, (c == '\n' ? (wchar_t*)L"\r\n" : tmp)); ++ switch (c) ++ { ++ case '\r': ++ Term.cursor = (Term.cursor / Term.cols) * Term.cols; ++ break; ++ ++ case '\n': ++ Term.cursor = (Term.cursor / Term.cols) * Term.cols; ++ Term.cursor += Term.cols; ++ break; ++ ++ default: ++ PutCell(c); ++ break; ++ } } void Term_PutString(char* s) diff --cc uefi/crt_x86_64.c index f7832f5,253fd93..b5481f6 --- a/uefi/crt_x86_64.c +++ b/uefi/crt_x86_64.c @@@ -1,5 -1,57 +1,64 @@@ + #include + #include + + /* this is implemented by the application */ + extern int main(void); + + /* globals to store system table pointers */ + static efi_handle_t IM = NULL; + static efi_system_table_t *ST = NULL; + static efi_boot_services_t *BS = NULL; + static efi_runtime_services_t *RT = NULL; + static efi_loaded_image_protocol_t *LIP = NULL; + + /* platform specific globals */ + VideoConfig Video = {0}; + ++void sleep(int ms) ++{ ++ BS->Stall(ms * 1000); ++} ++ + static void video_init(void) + { + /* get a handle to the graphics protocol */ + efi_gop_t *gop = NULL; + efi_guid_t gopGuid = EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID; + BS->LocateProtocol(&gopGuid, NULL, (void**)&gop); + + /* query mode 0 to see if mode needs to be set first */ + uintn_t info_size = 0; + efi_gop_mode_info_t *info = NULL; + uintn_t status = gop->QueryMode(gop, 0, &info_size, &info); + + /* some machines need mode set explicitly first */ + if (status == EFI_NOT_STARTED) + { + status = gop->SetMode(gop, 0); + } + + /* + OK, now we have real info for possible modes, pick the max mode. + We assume this one is the best resolution. + */ + if (status == EFI_SUCCESS) + { + status = gop->SetMode(gop, 17); /* pick a smaller resolution for QEMU */ + // status = gop->SetMode(gop, gop->Mode->MaxMode-1); + } + + /* + Now let's save off the info we need to draw pixels and glyphs. + The code in this file assumes 32 bits per pixel. + */ + Video.buffer = (uint32_t*)(gop->Mode->FrameBufferBase); + Video.stride = gop->Mode->Information->PixelsPerScanLine; ++ Video.width = gop->Mode->Information->HorizontalResolution; ++ Video.height = gop->Mode->Information->VerticalResolution; + } + /* - * crt_x86_64.c + * crt_x86_64.c : bootstrap() and uefi_init() * * Copyright (C) 2021 bzt (bztsrc@gitlab) * diff --cc uefi/platform.h index 0000000,538b276..d282b0d mode 000000,100644..100644 --- a/uefi/platform.h +++ b/uefi/platform.h @@@ -1,0 -1,32 +1,34 @@@ + /* define standard type definitions */ + typedef char int8_t; + typedef unsigned char uint8_t; + typedef short int16_t; + typedef unsigned short uint16_t; + typedef int int32_t; + typedef unsigned int uint32_t; + typedef long long int64_t; + typedef unsigned long long uint64_t; + typedef long long intptr_t; + typedef unsigned long long uintptr_t; + + /* sanity check type definitions */ + extern char check_u16[sizeof(uint16_t) == 2 ? 1 : -1]; + extern char check_u32[sizeof(uint32_t) == 4 ? 1 : -1]; + extern char check_u64[sizeof(uint64_t) == 8 ? 1 : -1]; + extern char check_uptr[sizeof(uintptr_t) == 8 ? 1 : -1]; + + #define NULL ((void*)0) + #define abs(x) ((x)<0?-(x):(x)) + #define min(x,y) ((x)<(y)?(x):(y)) + #define max(x,y) ((x)>(y)?(x):(y)) + + /* video memory configuration info */ + typedef struct { + uint32_t* buffer; + uint32_t stride; + uint32_t width; + uint32_t height; + } VideoConfig; + -extern VideoConfig Video; ++extern VideoConfig Video; ++ ++void sleep(int ms);