From: Michael D. Lowis Date: Tue, 14 Feb 2023 04:37:04 +0000 (-0500) Subject: started implementing base system as hybrid of C and assembly. To replace C with assem... X-Git-Url: https://git.mdlowis.com/?a=commitdiff_plain;h=bf14a7538836da4dee35b7360f5d0775cc7516b2;p=proto%2Fuefi.git started implementing base system as hybrid of C and assembly. To replace C with assembly later --- diff --git a/uefi/crt_x86_64.c b/uefi/crt_x86_64.c index b61737d..5a73379 100644 --- a/uefi/crt_x86_64.c +++ b/uefi/crt_x86_64.c @@ -1,14 +1,58 @@ #include #include +#include void StartOnward(void); +//typedef struct word_t { +// struct word_t* link; +// char* name; +// void* code; +//} word_t; +// +//word_t* find(word_t* w, char* s) +//{ +// if (!w) +// { +// return w; +// } +// else +// { +// char* ws = w->name; +// while (1) +// { +// if (!*ws || !*s || *ws != *s) +// { +// return find(w->link, s); +// } +// } +// } +// return w; +//} + + + + +char WordBuf[0x1F]; +long WordLen = 0; +long WordVal; + struct { efi_handle_t IM; efi_system_table_t* ST; efi_boot_services_t* BS; } EFI = {0}; +void PutChar(long c) +{ + wchar_t data[3] = {c,0,0}; + if (c == '\n' || c == '\r') + { + data[0] = '\r'; + data[1] = '\n'; + } + EFI.ST->ConOut->OutputString(EFI.ST->ConOut, data); +} long GetChar(void) { @@ -17,18 +61,80 @@ long GetChar(void) do { status = EFI.ST->ConIn->ReadKeyStroke(EFI.ST->ConIn, &key); } while(status != EFI_SUCCESS); + PutChar(key.UnicodeChar); + return key.UnicodeChar; } -void PutChar(long c) +static inline long whitespace(long c) { - wchar_t data[3] = {c,0,0}; - if (c == '\n' || c == '\r') + return ((c == ' ') || (c == '\t') || (c == '\n') || (c == '\r')); +} + +void GetWord(void) +{ + long c = 0; + long len = 0; + do { - data[0] = '\r'; - data[1] = '\n'; + c = GetChar(); + } while (whitespace(c)); + do + { + WordBuf[len++] = c; + c = GetChar(); + } while (!whitespace(c) && len < 0x1F); + WordLen = len; +} + +long ParseNumber(void) +{ + WordVal = 0; + long base = 10; + long sign = 1; + long i = 0; + if (WordBuf[i] == '0') + { + i++; + char bc = WordBuf[i++]; + if (bc == 'b') base = 2; + else if (bc == 'o') base = 8; + else if (bc == 'd') base = 10; + else if (bc == 'x') base = 16; + else return 0; } - EFI.ST->ConOut->OutputString(EFI.ST->ConOut, data); + else if (WordBuf[i] == '-') + { + sign = -1; + i++; + } + + while (i < WordLen) + { + long c = WordBuf[i]; + if (c >= '0' && c <= '9') + { + c -= '0'; + } + else if (c >= 'a' && c <= 'f') + { + c = (c - ('a' - 'A')) - ('A' - 10); + } + else if (c >= 'A' && c <= 'F') + { + c = c - ('A' - 10); + } + else + { + break; + } + // TODO: check limits here... + WordVal *= base; + WordVal += c; + i++; + } + WordVal *= sign; + return (i == WordLen); } /* @@ -89,7 +195,7 @@ int uefi_init(uintptr_t ldbase, Elf64_Dyn *dyn, efi_system_table_t *systab, efi_ /* handle relocations */ for (int i = 0; dyn[i].tag != DT_NULL; ++i) { switch (dyn[i].tag) { - case DT_RELA: rel = (Elf64_Rel*)((unsigned long)dyn[i].value + ldbase); break; + case DT_RELA: rel = (Elf64_Rel*)(dyn[i].value + ldbase); break; case DT_RELASZ: relsz = dyn[i].value; break; case DT_RELAENT: relent = dyn[i].value; break; default: break; @@ -97,23 +203,16 @@ int uefi_init(uintptr_t ldbase, Elf64_Dyn *dyn, efi_system_table_t *systab, efi_ } if (rel && relent) { while (relsz > 0) { - if(ELF64_R_TYPE (rel->r_info) == R_X86_64_RELATIVE) - { addr = (uintptr_t*)(ldbase + rel->r_offset); *addr += ldbase; break; } + if(ELF64_R_TYPE (rel->r_info) == R_X86_64_RELATIVE) { + addr = (uintptr_t*)(ldbase + rel->r_offset); + *addr += ldbase; + break; + } rel = (Elf64_Rel*) ((char *) rel + relent); relsz -= relent; } } - /* make sure SSE is enabled, because some say there are buggy firmware in the wild not doing that */ - __asm__ __volatile__ ( - " movq %cr0, %rax\n" - " andb $0xF1, %al\n" - " movq %rax, %cr0\n" - " movq %cr4, %rax\n" - " orw $3 << 9, %ax\n" - " mov %rax, %cr4\n" - ); - /* save EFI pointers and loaded image into globals */ EFI.IM = image; EFI.ST = systab; @@ -122,12 +221,12 @@ int uefi_init(uintptr_t ldbase, Elf64_Dyn *dyn, efi_system_table_t *systab, efi_ /* start the REPL */ EFI.ST->ConOut->ClearScreen(EFI.ST->ConOut); EFI.ST->ConOut->EnableCursor(EFI.ST->ConOut, 1); - StartOnward(); - -// while(1) -// { -// PutChar(GetChar()); -// } + while (1){ + GetWord(); + long is_num = ParseNumber(); + PutChar(is_num ? 'N' : 'W'); + PutChar('\n'); + } return 0; } diff --git a/uefi/onward.S b/uefi/onward.S index 0fde90e..6ff8d9e 100644 --- a/uefi/onward.S +++ b/uefi/onward.S @@ -1,8 +1,10 @@ //--------------------------------------------------------------------- -// TODO +// System API //--------------------------------------------------------------------- -/* -*/ +.global PutChar +.global GetChar +.global GetWord +.global ParseNumber //--------------------------------------------------------------------- // Register Usage @@ -42,13 +44,14 @@ .macro defcode name, namelen, flags=0, label .data .p2align 4 +name_\string : + .byte \flags+\namelen + .ascii "\name" .global name_\label name_\label : .quad link + .quad name_\string .set link, name_\label - .byte \flags+\namelen - .ascii "\name" - .p2align 4 .global \label \label : .quad code_\label @@ -62,12 +65,13 @@ code_\label : .data .p2align 4 .global name_\label +name_\string: + .byte \flags+\namelen + .ascii "\name" name_\label : .quad link + .quad name_\string .set link,name_\label - .byte \flags+\namelen - .ascii "\name" - .p2align 4 .globl \label \label : .int DOCOL @@ -194,10 +198,31 @@ defcode "over",4,,over // defcode asp@ // defcode asp! -// defcode getc +// ( - v) Get the next typed character +defcode "getc",4,,getc + call GetChar + push %rax + NEXT + // defcode putc -// defcode word +// (v - ) Put a character to the console +defcode "putc",4,,putc + pop %rcx + call PutChar + NEXT + +// ( - s) Get the next word from input +defcode "word",4,,word + call GetWord + NEXT + // defcode number +// (s - s i) Parse the word as a number +defcode "num",3,,num + call ParseNumber + push %rax + NEXT + // defcode find // defcode >cfa // defcode >dfa