commit 2f4e7e3d071406f34bc10985555cd2abc6079acf
parent f3e87e03934cf941cde711d0d2b6027e6c4e316c
Author: Matsuda Kenji <info@mtkn.jp>
Date: Mon, 1 Apr 2024 11:52:49 +0900
refactor directory
Diffstat:
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;
-}