setos

拙OS
Log | Files | Refs | LICENSE

commit 2f4e7e3d071406f34bc10985555cd2abc6079acf
parent f3e87e03934cf941cde711d0d2b6027e6c4e316c
Author: Matsuda Kenji <info@mtkn.jp>
Date:   Mon,  1 Apr 2024 11:52:49 +0900

refactor directory

Diffstat:
MMakefile | 29+++--------------------------
Dkernel/draw.c | 10----------
Dkernel/main.c | 24------------------------
Rkernel/draw.h -> sys/include/draw.h | 0
Rkernel/stdint.h -> sys/include/stdint.h | 0
Ruefi/uefi.h -> sys/include/uefi.h | 0
Ruefi/utils.h -> sys/include/utils.h | 0
Asys/src/boot/Makefile | 16++++++++++++++++
Asys/src/boot/boot.c | 120+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asys/src/boot/utils.c | 265+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asys/src/kernel/Makefile | 17+++++++++++++++++
Asys/src/kernel/draw.c | 10++++++++++
Asys/src/kernel/main.c | 24++++++++++++++++++++++++
Rkernel/memmap.ld -> sys/src/kernel/memmap.ld | 0
Duefi/uefi.c | 120-------------------------------------------------------------------------------
Duefi/utils.c | 265-------------------------------------------------------------------------------
16 files changed, 455 insertions(+), 445 deletions(-)

diff --git a/Makefile b/Makefile @@ -1,38 +1,15 @@ -EFI_CC = x86_64-w64-mingw32-gcc -EFI_CFLAGS = -nostdlib -fpic -mno-red-zone -fno-stack-protector -static \ - -fno-builtin -g -mabi=sysv \ - -mno-stack-arg-probe -Wall -e EfiMain -KERN_CC = tcc -KERN_LD = ld -KERN_CFLAGS = -nostdlib -fpic -mno-red-zone -ffreestanding -Wall -g -KERN_LDFLAGS = -e kernel_main -static -KERN_OBJ = kernel/main.o kernel/draw.o -OBJCOPY = objcopy - all: disk.img -disk.img: uefi/uefi.efi kernel/setos.elf +disk.img: sys/src/boot/boot.efi sys/src/kernel/main.elf qemu-img create -f raw disk.img 200M mkfs.fat -n 'SETOS' -s 2 -f 2 -R 32 -F 32 disk.img mkdir -p image doas mount disk.img image doas mkdir -p image/EFI/BOOT - doas cp uefi/uefi.efi image/EFI/BOOT/BOOTX64.EFI - doas cp kernel/setos.elf image/setos.elf + doas cp sys/src/boot/boot.efi image/EFI/BOOT/BOOTX64.EFI + doas cp sys/src/kernel/main.elf image/setos.elf doas umount image -uefi/uefi.dll: uefi/uefi.c uefi/uefi.h uefi/utils.c uefi/utils.h - $(EFI_CC) $(EFI_CFLAGS) -o $@ uefi/uefi.c uefi/utils.c - -uefi/uefi.efi: uefi/uefi.dll - $(OBJCOPY) --target=efi-app-x86_64 uefi/uefi.dll $@ - -%.o: %.c - $(KERN_CC) $(KERN_CFLAGS) -c -o $@ $< - -kernel/setos.elf: $(KERN_OBJ) - $(KERN_LD) $(KERN_LDFLAGS) -T kernel/memmap.ld -o $@ $(KERN_OBJ) - run: disk.img OVMF.fd qemu-system-x86_64 \ -bios OVMF.fd \ diff --git a/kernel/draw.c b/kernel/draw.c @@ -1,9 +0,0 @@ -#include "draw.h" - -Display root_display; - -int -init_root_display(RGBA32 *fb_base, int fb_size, int hrez, int vrez) -{ - return 1; -} -\ No newline at end of file diff --git a/kernel/main.c b/kernel/main.c @@ -1,23 +0,0 @@ -#include "../uefi/uefi.h" -#include "stdint.h" - -void -kernel_main(EFI_GRAPHICS_OUTPUT_PROTOCOL *gop) -{ - uint32_t *fb_base = (uint32_t *)gop->Mode->FrameBufferBase; - uint32_t hrez = gop->Mode->Info->HorizontalResolution; - uint32_t vrez = gop->Mode->Info->VerticalResolution; - uint32_t sl = gop->Mode->Info->PixelsPerScanLine; - uint32_t cx = hrez / 2; - uint32_t cy = vrez / 2; - for (int i = 0; i < vrez; i++) { - for (int j = 0; j < hrez; j++) { - if ((cx-j)*(cx-j) + (cy-i)*(cy-i) < (vrez/3) * (vrez/3)) { - fb_base[i * sl + j] = 0xff << 16; - } else { - fb_base[i * sl + j] = 0xffffff; - } - } - } - for(;;); -} -\ No newline at end of file diff --git a/kernel/draw.h b/sys/include/draw.h diff --git a/kernel/stdint.h b/sys/include/stdint.h diff --git a/uefi/uefi.h b/sys/include/uefi.h diff --git a/uefi/utils.h b/sys/include/utils.h diff --git a/sys/src/boot/Makefile b/sys/src/boot/Makefile @@ -0,0 +1,16 @@ +CC = x86_64-w64-mingw32-gcc +CFLAGS = -I ../../include \ + -nostdlib -fpic -mno-red-zone -fno-stack-protector -static \ + -fno-builtin -g -mabi=sysv \ + -mno-stack-arg-probe -Wall -e EfiMain + +all: boot.efi + +boot.efi: boot.dll + objcopy --target=efi-app-x86_64 boot.dll $@ + +boot.dll: boot.c utils.c + $(CC) $(CFLAGS) -o $@ boot.c utils.c + +clean: + rm -f boot.efi boot.dll diff --git a/sys/src/boot/boot.c b/sys/src/boot/boot.c @@ -0,0 +1,120 @@ +#include <uefi.h> +#include <utils.h> +EFI_SYSTEM_TABLE *SystemTable; + +EFI_STATUS EFIAPI +EfiMain(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *systab) +{ + // init global variable. + SystemTable = systab; + + EFI_STATUS stat; + + // Output firmware bender. + SystemTable->ConOut->ClearScreen(SystemTable->ConOut); + efi_printf("vendor: %w\n", SystemTable->FirmwareVendor); + efi_printf("EfiMain: 0x%x\n", EfiMain); + + // Output memory map information. + UINTN mmsize = 8196; + char mmbuf[8196]; + EFI_MEMORY_DESCRIPTOR *mmap; + UINTN mkey; + UINTN dsize; + UINT32 dver; + mmap = (EFI_MEMORY_DESCRIPTOR *) mmbuf; + stat = SystemTable->BootServices->GetMemoryMap(&mmsize, mmap, &mkey, &dsize, &dver); + if (stat != EFI_SUCCESS) { + efi_printf("get memory map: %d\n", stat); + return stat; + } + + for (; mmap < (EFI_MEMORY_DESCRIPTOR *)(mmbuf + mmsize); + mmap = (EFI_MEMORY_DESCRIPTOR *) (((char *)mmap) + dsize)) { + if (mmap->Type != EfiConventionalMemory) { + continue; + } + efi_printf("%d\t%x\t%x\t%x\t%x\n", mmap->Type, mmap->VirtualStart, + mmap->PhysicalStart, mmap->NumberOfPages, mmap->Attribute); + } + + EFI_GRAPHICS_OUTPUT_PROTOCOL *gop; + stat = open_gop(ImageHandle, &gop); + if (stat != EFI_SUCCESS) { + efi_printf("open_gop: %d\n", stat); + return stat; + } + UINT32 *frame_buffer = (UINT32 *)gop->Mode->FrameBufferBase; + for (UINTN i = 0; i < gop->Mode->FrameBufferSize/4; i++) { + frame_buffer[i] = 0x427f94; + } + efi_printf("frame buffer: base: %x, size: %x\n", frame_buffer, + gop->Mode->FrameBufferSize); + + EFI_FILE_PROTOCOL *root, *kernel; + stat = open_root(ImageHandle, &root); + if (stat != EFI_SUCCESS) { + efi_printf("open_root: %d\n", stat); + return stat; + } + stat = root->Open(root, &kernel, L"setos.elf", + EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE, 0); + if (stat != EFI_SUCCESS) { + efi_printf("open file \"kernel.elf\": %d\n", stat); + return stat; + } + ElfHdr kernel_ehdr; + stat = read_ehdr(kernel, &kernel_ehdr); + if (stat != EFI_SUCCESS) { + efi_printf("read ehdr of \"kernel.elf\": %d\n", stat); + return stat; + } + efi_printf("type:\t%x\nphoff:\t%x\nphentsize:\t%x\nphnum:\t%x\n", + kernel_ehdr.type, kernel_ehdr.phoff, + kernel_ehdr.phentsize, kernel_ehdr.phnum); + if (kernel_ehdr.phnum > 32) { + efi_printf("too many phdrs\n"); + return EFI_BUFFER_TOO_SMALL; + } + Phdr kernel_phdr[32]; + stat = read_phdr(kernel, &kernel_ehdr, kernel_phdr); + if (stat != EFI_SUCCESS) { + efi_printf("read phdr of \"kernel.elf\": %d\n", stat); + return stat; + } + for (UINT16 i = 0; i < kernel_ehdr.phnum; i++) { + efi_printf("type: %x, offset: %x, vaddr: %x\n", + kernel_phdr[i].type, kernel_phdr[i].offset, kernel_phdr[i].vaddr); + } + stat = load_elf(kernel, &kernel_ehdr, kernel_phdr); + if (stat != EFI_SUCCESS) { + efi_printf("load \"kernel.elf\": %d\n", stat); + return stat; + } + stat = kernel->Close(kernel); + if (stat != EFI_SUCCESS) { + efi_printf("close file: %d\n", stat); + return stat; + } + + efi_printf("frame buffer: base: %x, %x, size: %x\n", frame_buffer, + gop->Mode->FrameBufferBase, + gop->Mode->FrameBufferSize); + + mmsize = 8196; + stat = SystemTable->BootServices->GetMemoryMap(&mmsize, mmap, &mkey, &dsize, &dver); + if (stat != EFI_SUCCESS) { + efi_printf("get memory map: %d\n", stat); + return stat; + } + stat = SystemTable->BootServices->ExitBootServices(ImageHandle, mkey); + if (stat != EFI_SUCCESS) { + efi_printf("exit boot services: %d\n", stat); + return stat; + } + + typedef void (* Kernel) (EFI_GRAPHICS_OUTPUT_PROTOCOL *); + ((Kernel) kernel_ehdr.entry)(gop); + + return EFI_SUCCESS; +} diff --git a/sys/src/boot/utils.c b/sys/src/boot/utils.c @@ -0,0 +1,265 @@ +#include <stdarg.h> // TODO: implement stdarg.h by my self + +#include <uefi.h> +#include <utils.h> + +CHAR16 * +sprinth(UINT64 n, CHAR16 s[19]) +{ + int i; + int d; + s[0] = L'0'; + s[1] = L'x'; + for (i = 0; i < 16; i++) { + d = (n >> (64 - (i + 1) * 4)) & 0xf; + if (d <= 9) + s[i + 2] = L'0' + d; + else + s[i + 2] = L'a' + d - 10; + } + s[19] = L'\0'; + return s; +} + +char * +wstr2str(CHAR16 *s16, char *s8) +{ + char *s = s8; + for (;*s16;) { + *s8++ = (char) (*s16++ & 0xff); + } + *s8 = '\0'; + return s; +} + +int +efi_printf(char *fmt, ...) +{ + va_list ap; + CHAR16 _buf[1024], *buf = _buf; + EFI_STATUS stat; + + char *s; + CHAR16 *w; + long long d, e; + unsigned long long f, g, h; + + va_start(ap, fmt); + for (;*fmt;) { + if (*fmt != '%') { + if (*fmt == '\n') { + *buf++ = (CHAR16) '\n'; + *buf++ = (CHAR16) '\r'; + fmt++; + continue; + } else { + *buf++ = (CHAR16) *fmt++; + continue; + } + } + fmt++; + switch (*fmt++) { + case '%': + *buf++ = L'%'; + break; + case 's': + s = va_arg(ap, char *); + for (;*s;) { + *buf++ = (CHAR16) *s++; + } + break; + case 'w': + w = va_arg(ap, CHAR16 *); + for (;*w;) { + *buf++ = *w++; + } + break; + case 'd': + d = va_arg(ap, int); + if (d == 0) { + *buf++ = '0'; + break; + } else if (d < 0) { + *buf++ = '-'; + d = -d; + } + for (e = 1; e <= d; e *= 10) { + if (e > e * 10) { // integer too big; + return -1; + } + } + for (e /= 10; e >= 1; e /= 10) { + *buf++ = (CHAR16) ('0' + ((d / e) % 10)); + } + break; + case 'x': + f = va_arg(ap, unsigned int); + if (f == 0) { + *buf++ = '0'; + break; + } + for (g = 1; g <= f; g *= 0x10) { + if (g > g * 0x10) { // integer too big. + return -1; + } + } + for (g /= 0x10; g >= 1; g /= 0x10) { + h = ((f / g) % 0x10); + if (h < 0xa) { + *buf++ = (CHAR16) ('0' + h); + } else { + *buf++ = (CHAR16) ('a' + h - 0xa); + } + } + break; + } + } + va_end(ap); + *buf = L'\0'; + + stat = SystemTable->ConOut->OutputString(SystemTable->ConOut, _buf); + if (stat != EFI_SUCCESS) { + return -1; + } + return (int) (buf - _buf); +} + +EFI_STATUS +open_root(EFI_HANDLE ImageHandle, EFI_FILE_PROTOCOL **root) +{ + EFI_STATUS stat; + EFI_LOADED_IMAGE_PROTOCOL *li; + EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *fs; + + stat = SystemTable->BootServices->OpenProtocol( + ImageHandle, &(EFI_GUID)EFI_LOADED_IMAGE_PROTOCOL_GUID, + (VOID **) &li, ImageHandle, NULL, EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL + ); + if (stat != EFI_SUCCESS) { + return stat; + } + + stat = SystemTable->BootServices->OpenProtocol( + li->DeviceHandle, &(EFI_GUID)EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_GUID, + (VOID **) &fs, ImageHandle, NULL, EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL + ); + if (stat != EFI_SUCCESS) { + return stat; + } + + stat = fs->OpenVolume(fs, root); + return stat; +} + +EFI_STATUS +open_gop(EFI_HANDLE ImageHandle, EFI_GRAPHICS_OUTPUT_PROTOCOL **gop) +{ + EFI_STATUS stat; + UINTN n = 0; + EFI_HANDLE *_gop; + stat = SystemTable->BootServices->LocateHandleBuffer( + ByProtocol, &(EFI_GUID)EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID, NULL, + &n, &_gop + ); + if (stat != EFI_SUCCESS) { + efi_printf("locate handle buffer: %d\n", stat); + return stat; + } + stat = SystemTable->BootServices->OpenProtocol( + _gop[0], &(EFI_GUID)EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID, + (VOID **) gop, ImageHandle, NULL, EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL + ); + if (stat != EFI_SUCCESS) { + efi_printf("open protocol: %d\n", stat); + return stat; + } + return EFI_SUCCESS; +} + +EFI_STATUS +read_ehdr(EFI_FILE_PROTOCOL *elf, ElfHdr *ehdr) +{ + EFI_STATUS stat; + UINTN ehdr_size = sizeof(ElfHdr); + + stat = elf->SetPosition(elf, 0); + if (stat != EFI_SUCCESS) { + efi_printf("set position: %d\n", stat); + return stat; + } + stat = elf->Read(elf, &ehdr_size, (VOID *) ehdr); + if (stat != EFI_SUCCESS) { + efi_printf("read: %d\n", stat); + return stat; + } + // TODO: check file format. + // for now, it assumes that elf is 2's complement, 64-bit little endian, + // System V ABI... + if (ehdr->ident[0] != 0x7f || ehdr->ident[1] != 'E' || + ehdr->ident[2] != 'L' || ehdr->ident[3] != 'F') { + efi_printf("not an elf file\n"); + return EFI_INVALID_PARAMETER; + } + + return EFI_SUCCESS; +} + +EFI_STATUS +read_phdr(EFI_FILE_PROTOCOL *elf, ElfHdr *ehdr, Phdr phdr[]) +{ + EFI_STATUS stat; + UINTN n; + + stat = elf->SetPosition(elf, ehdr->phoff); + if (stat != EFI_SUCCESS) { + efi_printf("set position: %d\n", stat); + return stat; + } + // TODO: need overflow check?? + n = ehdr->phentsize * ehdr->phnum; + stat = elf->Read(elf, &n, (VOID *) phdr); + if (stat != EFI_SUCCESS) { + efi_printf("read phdr: %d\n", stat); + return stat; + } + return EFI_SUCCESS; +} + +EFI_STATUS +load_elf(EFI_FILE_PROTOCOL *elf, ElfHdr *ehdr, Phdr phdr[]) +{ + EFI_STATUS stat; + EFI_PHYSICAL_ADDRESS addr; + UINT64 size; + for (UINT16 i = 0; i < ehdr->phnum; i++) { + if (phdr[i].type != PT_LOAD) { + continue; + } + efi_printf("load_elf: allocate %d at %x\n", + phdr[i].memsz, phdr[i].vaddr + ); + stat = SystemTable->BootServices->AllocatePages( + AllocateAddress, EfiLoaderData, + (phdr[i].memsz + 0xfff) / 0x1000, &phdr[i].vaddr + ); + if (stat != EFI_SUCCESS) { + efi_printf("allocate pages: %d\n", stat); + return stat; + } + efi_printf("load_elf: phdr[i].vaddr: %x\n", phdr[i].vaddr); + stat = elf->SetPosition(elf, phdr[i].offset); + if (stat != EFI_SUCCESS) { + efi_printf("set position: %d\n", stat); + return stat; + } + addr = (EFI_PHYSICAL_ADDRESS) phdr[i].vaddr; + efi_printf("load_elf: read to %x\n", addr); + size = phdr[i].filesz; + stat = elf->Read(elf, &size, (VOID *)addr); + if (stat != EFI_SUCCESS) { + efi_printf("read to memory: %d\n", stat); + return stat; + } + } + return EFI_SUCCESS; +} diff --git a/sys/src/kernel/Makefile b/sys/src/kernel/Makefile @@ -0,0 +1,16 @@ +CC = tcc +LD = ld +CFLAGS = -I ../../include -nostdlib -fpic -mno-red-zone -ffreestanding -Wall -g +LDFLAGS = -e kernel_main -static +OBJS = main.o draw.o + +all: main.elf + +main.elf: $(OBJS) memmap.ld + $(LD) $(LDFLAGS) -T memmap.ld -o $@ $(OBJS) + +%.o: %.c + $(CC) $(CFLAGS) -c -o $@ $< + +clean: + rm -f $(OBJS) main.elf +\ No newline at end of file diff --git a/sys/src/kernel/draw.c b/sys/src/kernel/draw.c @@ -0,0 +1,9 @@ +#include <draw.h> + +Display root_display; + +int +init_root_display(RGBA32 *fb_base, int fb_size, int hrez, int vrez) +{ + return 1; +} +\ No newline at end of file diff --git a/sys/src/kernel/main.c b/sys/src/kernel/main.c @@ -0,0 +1,23 @@ +#include <uefi.h> +#include <stdint.h> + +void +kernel_main(EFI_GRAPHICS_OUTPUT_PROTOCOL *gop) +{ + uint32_t *fb_base = (uint32_t *)gop->Mode->FrameBufferBase; + uint32_t hrez = gop->Mode->Info->HorizontalResolution; + uint32_t vrez = gop->Mode->Info->VerticalResolution; + uint32_t sl = gop->Mode->Info->PixelsPerScanLine; + uint32_t cx = hrez / 2; + uint32_t cy = vrez / 2; + for (int i = 0; i < vrez; i++) { + for (int j = 0; j < hrez; j++) { + if ((cx-j)*(cx-j) + (cy-i)*(cy-i) < (vrez/3) * (vrez/3)) { + fb_base[i * sl + j] = 0xff << 16; + } else { + fb_base[i * sl + j] = 0xffffff; + } + } + } + for(;;); +} +\ No newline at end of file diff --git a/kernel/memmap.ld b/sys/src/kernel/memmap.ld diff --git a/uefi/uefi.c b/uefi/uefi.c @@ -1,120 +0,0 @@ -#include "uefi.h" -#include "utils.h" -EFI_SYSTEM_TABLE *SystemTable; - -EFI_STATUS EFIAPI -EfiMain(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *systab) -{ - // init global variable. - SystemTable = systab; - - EFI_STATUS stat; - - // Output firmware bender. - SystemTable->ConOut->ClearScreen(SystemTable->ConOut); - efi_printf("vendor: %w\n", SystemTable->FirmwareVendor); - efi_printf("EfiMain: 0x%x\n", EfiMain); - - // Output memory map information. - UINTN mmsize = 8196; - char mmbuf[8196]; - EFI_MEMORY_DESCRIPTOR *mmap; - UINTN mkey; - UINTN dsize; - UINT32 dver; - mmap = (EFI_MEMORY_DESCRIPTOR *) mmbuf; - stat = SystemTable->BootServices->GetMemoryMap(&mmsize, mmap, &mkey, &dsize, &dver); - if (stat != EFI_SUCCESS) { - efi_printf("get memory map: %d\n", stat); - return stat; - } - - for (; mmap < (EFI_MEMORY_DESCRIPTOR *)(mmbuf + mmsize); - mmap = (EFI_MEMORY_DESCRIPTOR *) (((char *)mmap) + dsize)) { - if (mmap->Type != EfiConventionalMemory) { - continue; - } - efi_printf("%d\t%x\t%x\t%x\t%x\n", mmap->Type, mmap->VirtualStart, - mmap->PhysicalStart, mmap->NumberOfPages, mmap->Attribute); - } - - EFI_GRAPHICS_OUTPUT_PROTOCOL *gop; - stat = open_gop(ImageHandle, &gop); - if (stat != EFI_SUCCESS) { - efi_printf("open_gop: %d\n", stat); - return stat; - } - UINT32 *frame_buffer = (UINT32 *)gop->Mode->FrameBufferBase; - for (UINTN i = 0; i < gop->Mode->FrameBufferSize/4; i++) { - frame_buffer[i] = 0x427f94; - } - efi_printf("frame buffer: base: %x, size: %x\n", frame_buffer, - gop->Mode->FrameBufferSize); - - EFI_FILE_PROTOCOL *root, *kernel; - stat = open_root(ImageHandle, &root); - if (stat != EFI_SUCCESS) { - efi_printf("open_root: %d\n", stat); - return stat; - } - stat = root->Open(root, &kernel, L"setos.elf", - EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE, 0); - if (stat != EFI_SUCCESS) { - efi_printf("open file \"kernel.elf\": %d\n", stat); - return stat; - } - ElfHdr kernel_ehdr; - stat = read_ehdr(kernel, &kernel_ehdr); - if (stat != EFI_SUCCESS) { - efi_printf("read ehdr of \"kernel.elf\": %d\n", stat); - return stat; - } - efi_printf("type:\t%x\nphoff:\t%x\nphentsize:\t%x\nphnum:\t%x\n", - kernel_ehdr.type, kernel_ehdr.phoff, - kernel_ehdr.phentsize, kernel_ehdr.phnum); - if (kernel_ehdr.phnum > 32) { - efi_printf("too many phdrs\n"); - return EFI_BUFFER_TOO_SMALL; - } - Phdr kernel_phdr[32]; - stat = read_phdr(kernel, &kernel_ehdr, kernel_phdr); - if (stat != EFI_SUCCESS) { - efi_printf("read phdr of \"kernel.elf\": %d\n", stat); - return stat; - } - for (UINT16 i = 0; i < kernel_ehdr.phnum; i++) { - efi_printf("type: %x, offset: %x, vaddr: %x\n", - kernel_phdr[i].type, kernel_phdr[i].offset, kernel_phdr[i].vaddr); - } - stat = load_elf(kernel, &kernel_ehdr, kernel_phdr); - if (stat != EFI_SUCCESS) { - efi_printf("load \"kernel.elf\": %d\n", stat); - return stat; - } - stat = kernel->Close(kernel); - if (stat != EFI_SUCCESS) { - efi_printf("close file: %d\n", stat); - return stat; - } - - efi_printf("frame buffer: base: %x, %x, size: %x\n", frame_buffer, - gop->Mode->FrameBufferBase, - gop->Mode->FrameBufferSize); - - mmsize = 8196; - stat = SystemTable->BootServices->GetMemoryMap(&mmsize, mmap, &mkey, &dsize, &dver); - if (stat != EFI_SUCCESS) { - efi_printf("get memory map: %d\n", stat); - return stat; - } - stat = SystemTable->BootServices->ExitBootServices(ImageHandle, mkey); - if (stat != EFI_SUCCESS) { - efi_printf("exit boot services: %d\n", stat); - return stat; - } - - typedef void (* Kernel) (EFI_GRAPHICS_OUTPUT_PROTOCOL *); - ((Kernel) kernel_ehdr.entry)(gop); - - return EFI_SUCCESS; -} diff --git a/uefi/utils.c b/uefi/utils.c @@ -1,265 +0,0 @@ -#include <stdarg.h> // TODO: implement stdarg.h by my self - -#include "uefi.h" -#include "utils.h" - -CHAR16 * -sprinth(UINT64 n, CHAR16 s[19]) -{ - int i; - int d; - s[0] = L'0'; - s[1] = L'x'; - for (i = 0; i < 16; i++) { - d = (n >> (64 - (i + 1) * 4)) & 0xf; - if (d <= 9) - s[i + 2] = L'0' + d; - else - s[i + 2] = L'a' + d - 10; - } - s[19] = L'\0'; - return s; -} - -char * -wstr2str(CHAR16 *s16, char *s8) -{ - char *s = s8; - for (;*s16;) { - *s8++ = (char) (*s16++ & 0xff); - } - *s8 = '\0'; - return s; -} - -int -efi_printf(char *fmt, ...) -{ - va_list ap; - CHAR16 _buf[1024], *buf = _buf; - EFI_STATUS stat; - - char *s; - CHAR16 *w; - long long d, e; - unsigned long long f, g, h; - - va_start(ap, fmt); - for (;*fmt;) { - if (*fmt != '%') { - if (*fmt == '\n') { - *buf++ = (CHAR16) '\n'; - *buf++ = (CHAR16) '\r'; - fmt++; - continue; - } else { - *buf++ = (CHAR16) *fmt++; - continue; - } - } - fmt++; - switch (*fmt++) { - case '%': - *buf++ = L'%'; - break; - case 's': - s = va_arg(ap, char *); - for (;*s;) { - *buf++ = (CHAR16) *s++; - } - break; - case 'w': - w = va_arg(ap, CHAR16 *); - for (;*w;) { - *buf++ = *w++; - } - break; - case 'd': - d = va_arg(ap, int); - if (d == 0) { - *buf++ = '0'; - break; - } else if (d < 0) { - *buf++ = '-'; - d = -d; - } - for (e = 1; e <= d; e *= 10) { - if (e > e * 10) { // integer too big; - return -1; - } - } - for (e /= 10; e >= 1; e /= 10) { - *buf++ = (CHAR16) ('0' + ((d / e) % 10)); - } - break; - case 'x': - f = va_arg(ap, unsigned int); - if (f == 0) { - *buf++ = '0'; - break; - } - for (g = 1; g <= f; g *= 0x10) { - if (g > g * 0x10) { // integer too big. - return -1; - } - } - for (g /= 0x10; g >= 1; g /= 0x10) { - h = ((f / g) % 0x10); - if (h < 0xa) { - *buf++ = (CHAR16) ('0' + h); - } else { - *buf++ = (CHAR16) ('a' + h - 0xa); - } - } - break; - } - } - va_end(ap); - *buf = L'\0'; - - stat = SystemTable->ConOut->OutputString(SystemTable->ConOut, _buf); - if (stat != EFI_SUCCESS) { - return -1; - } - return (int) (buf - _buf); -} - -EFI_STATUS -open_root(EFI_HANDLE ImageHandle, EFI_FILE_PROTOCOL **root) -{ - EFI_STATUS stat; - EFI_LOADED_IMAGE_PROTOCOL *li; - EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *fs; - - stat = SystemTable->BootServices->OpenProtocol( - ImageHandle, &(EFI_GUID)EFI_LOADED_IMAGE_PROTOCOL_GUID, - (VOID **) &li, ImageHandle, NULL, EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL - ); - if (stat != EFI_SUCCESS) { - return stat; - } - - stat = SystemTable->BootServices->OpenProtocol( - li->DeviceHandle, &(EFI_GUID)EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_GUID, - (VOID **) &fs, ImageHandle, NULL, EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL - ); - if (stat != EFI_SUCCESS) { - return stat; - } - - stat = fs->OpenVolume(fs, root); - return stat; -} - -EFI_STATUS -open_gop(EFI_HANDLE ImageHandle, EFI_GRAPHICS_OUTPUT_PROTOCOL **gop) -{ - EFI_STATUS stat; - UINTN n = 0; - EFI_HANDLE *_gop; - stat = SystemTable->BootServices->LocateHandleBuffer( - ByProtocol, &(EFI_GUID)EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID, NULL, - &n, &_gop - ); - if (stat != EFI_SUCCESS) { - efi_printf("locate handle buffer: %d\n", stat); - return stat; - } - stat = SystemTable->BootServices->OpenProtocol( - _gop[0], &(EFI_GUID)EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID, - (VOID **) gop, ImageHandle, NULL, EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL - ); - if (stat != EFI_SUCCESS) { - efi_printf("open protocol: %d\n", stat); - return stat; - } - return EFI_SUCCESS; -} - -EFI_STATUS -read_ehdr(EFI_FILE_PROTOCOL *elf, ElfHdr *ehdr) -{ - EFI_STATUS stat; - UINTN ehdr_size = sizeof(ElfHdr); - - stat = elf->SetPosition(elf, 0); - if (stat != EFI_SUCCESS) { - efi_printf("set position: %d\n", stat); - return stat; - } - stat = elf->Read(elf, &ehdr_size, (VOID *) ehdr); - if (stat != EFI_SUCCESS) { - efi_printf("read: %d\n", stat); - return stat; - } - // TODO: check file format. - // for now, it assumes that elf is 2's complement, 64-bit little endian, - // System V ABI... - if (ehdr->ident[0] != 0x7f || ehdr->ident[1] != 'E' || - ehdr->ident[2] != 'L' || ehdr->ident[3] != 'F') { - efi_printf("not an elf file\n"); - return EFI_INVALID_PARAMETER; - } - - return EFI_SUCCESS; -} - -EFI_STATUS -read_phdr(EFI_FILE_PROTOCOL *elf, ElfHdr *ehdr, Phdr phdr[]) -{ - EFI_STATUS stat; - UINTN n; - - stat = elf->SetPosition(elf, ehdr->phoff); - if (stat != EFI_SUCCESS) { - efi_printf("set position: %d\n", stat); - return stat; - } - // TODO: need overflow check?? - n = ehdr->phentsize * ehdr->phnum; - stat = elf->Read(elf, &n, (VOID *) phdr); - if (stat != EFI_SUCCESS) { - efi_printf("read phdr: %d\n", stat); - return stat; - } - return EFI_SUCCESS; -} - -EFI_STATUS -load_elf(EFI_FILE_PROTOCOL *elf, ElfHdr *ehdr, Phdr phdr[]) -{ - EFI_STATUS stat; - EFI_PHYSICAL_ADDRESS addr; - UINT64 size; - for (UINT16 i = 0; i < ehdr->phnum; i++) { - if (phdr[i].type != PT_LOAD) { - continue; - } - efi_printf("load_elf: allocate %d at %x\n", - phdr[i].memsz, phdr[i].vaddr - ); - stat = SystemTable->BootServices->AllocatePages( - AllocateAddress, EfiLoaderData, - (phdr[i].memsz + 0xfff) / 0x1000, &phdr[i].vaddr - ); - if (stat != EFI_SUCCESS) { - efi_printf("allocate pages: %d\n", stat); - return stat; - } - efi_printf("load_elf: phdr[i].vaddr: %x\n", phdr[i].vaddr); - stat = elf->SetPosition(elf, phdr[i].offset); - if (stat != EFI_SUCCESS) { - efi_printf("set position: %d\n", stat); - return stat; - } - addr = (EFI_PHYSICAL_ADDRESS) phdr[i].vaddr; - efi_printf("load_elf: read to %x\n", addr); - size = phdr[i].filesz; - stat = elf->Read(elf, &size, (VOID *)addr); - if (stat != EFI_SUCCESS) { - efi_printf("read to memory: %d\n", stat); - return stat; - } - } - return EFI_SUCCESS; -}