summaryrefslogtreecommitdiff
path: root/boot/efi
diff options
context:
space:
mode:
Diffstat (limited to 'boot/efi')
-rw-r--r--boot/efi/bind.c52
-rw-r--r--boot/efi/fexecve.c23
-rw-r--r--boot/efi/file.c2
-rw-r--r--boot/efi/handle.h19
-rw-r--r--boot/efi/image.c105
-rw-r--r--boot/efi/start.c18
-rw-r--r--boot/efi/status.h110
-rw-r--r--boot/efi/system_table.h31
-rw-r--r--boot/efi/table.h26
9 files changed, 304 insertions, 82 deletions
diff --git a/boot/efi/bind.c b/boot/efi/bind.c
new file mode 100644
index 0000000..53522a5
--- /dev/null
+++ b/boot/efi/bind.c
@@ -0,0 +1,52 @@
+#include "kjarna_efi.h"
+
+int open(const char *path, int flags, int mode)
+{
+ return efi_open(path, flags, mode);
+}
+
+int close(int fd)
+{
+ return efi_close(fd);
+}
+
+off_t lseek(int fd, off_t offset, int whence)
+{
+ return efi_lseek(fd, offset, whence);
+}
+
+ssize_t read(int fd, void *buffer, size_t length)
+{
+ return efi_read(fd, buffer, length);
+}
+
+ssize_t write(int fd, const void *buffer, size_t length)
+{
+ return efi_write(fd, buffer, length);
+}
+
+void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset)
+{
+ return efi_mmap(addr, length, prot, flags, fd, offset);
+}
+
+int munmap(void *addr, size_t length)
+{
+ return efi_munmap(addr, length);
+}
+
+void *malloc(size_t size)
+{
+ return efi_alloc_pool(size);
+}
+
+void *calloc(size_t count, size_t size)
+{
+ return efi_calloc_pool(count, size);
+}
+
+void free(void *block)
+{
+ efi_free_pool(block);
+}
+
diff --git a/boot/efi/fexecve.c b/boot/efi/fexecve.c
new file mode 100644
index 0000000..57cb035
--- /dev/null
+++ b/boot/efi/fexecve.c
@@ -0,0 +1,23 @@
+#include <posix/unistd.h>
+#include <api/elf/elf64.h>
+
+int fexecve(int fd, char *const argv[] char *const envp[])
+{
+ (void)argv;
+ (void)envp;
+
+ if (!elf64_validate_fd(fd, ET_DYN, EM_X86_64))
+ {
+ return -1;
+ }
+
+ size_t memsz;
+
+ if ((memsz = elf64_size_fd(fd)) == 0)
+ {
+ return -1;
+ }
+
+
+}
+
diff --git a/boot/efi/file.c b/boot/efi/file.c
index 9178654..e45ce78 100644
--- a/boot/efi/file.c
+++ b/boot/efi/file.c
@@ -78,7 +78,7 @@ int efi_open(const char *path, int flags, int mode)
{
static EFI_GUID lip_guid = EFI_LOADED_IMAGE_PROTOCOL_GUID;
static EFI_GUID sfsp_guid = EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_GUID;
-
+
EFI_LOADED_IMAGE_PROTOCOL *lip = efi_get_protocol(efi_context->handle, &lip_guid);
if (lip == nullptr)
diff --git a/boot/efi/handle.h b/boot/efi/handle.h
new file mode 100644
index 0000000..1381a30
--- /dev/null
+++ b/boot/efi/handle.h
@@ -0,0 +1,19 @@
+#pragma once
+
+extern "C"
+{
+ struct efi_handle
+ {
+ void *m_Value;
+ };
+}
+
+namespace Efi
+{
+ class Handle : private efi_handle
+ {
+ public:
+ Handle(efi_handle &);
+ };
+}
+
diff --git a/boot/efi/image.c b/boot/efi/image.c
index 42dab7d..25e1911 100644
--- a/boot/efi/image.c
+++ b/boot/efi/image.c
@@ -2,7 +2,11 @@
#include <posix/fcntl.h>
#include <kjarna/interface.h>
#include <libc/string.h>
+#include <libc/stdio.h>
+#include <libc/stdlib.h>
#include <lib/elf.h>
+#include <posix/unistd.h>
+#include <posix/sys/mman.h>
#include "kjarna_efi.h"
@@ -16,77 +20,26 @@ struct image_buffer
size_t length;
};
-static ssize_t read_ehdr(int fd, Elf64_Ehdr *ehdr)
+static int create_image_buffer(int fd, struct image_buffer *buffer)
{
- ssize_t result;
-
- if (efi_lseek(fd, 0, SEEK_SET) == -1)
- {
- return -1;
- }
- else if ((result = efi_read(fd, ehdr, sizeof(*ehdr))) == -1)
+ if ((buffer->length = elf64_size_fd(fd)) == 0)
{
return -1;
}
- else if (!elf64_validate(ehdr, ET_DYN, EM_X86_64))
- {
- return -1;
- }
-
- return result;
-}
-static ssize_t read_phdrs(int fd, Elf64_Ehdr *ehdr, Elf64_Phdr *phdrs)
-{
- if (efi_lseek(fd, ehdr->e_phoff, SEEK_SET) != -1)
- {
- return efi_read(fd, phdrs, ehdr->e_phnum * ehdr->e_phentsize);
- }
-
- return -1;
-}
-
-static void create_image_buffer(Elf64_Ehdr *ehdr, Elf64_Phdr *phdrs, struct image_buffer *buffer)
-{
- buffer->length = elf64_size(ehdr, phdrs);
- buffer->base = efi_mmap(nullptr, buffer->length, 0, 0, -1, 0);
-}
+ printf("creating image buffer, %d bytes\n", buffer->length);
-static ssize_t load_segment(int fd, Elf64_Phdr *phdr, char *buffer)
-{
- if (efi_lseek(fd, phdr->p_offset, SEEK_SET) == -1)
+ if((buffer->base = mmap(nullptr, buffer->length, 0, 0, -1, 0)) == MAP_FAILED)
{
+ buffer->length = 0;
+ buffer->base = nullptr;
+
return -1;
}
- int result = efi_read(fd, &buffer[phdr->p_offset], phdr->p_filesz);
+ printf("image buffer base %p\n", buffer->base);
- if (result > 0 && phdr->p_memsz > phdr->p_filesz)
- {
- memset(&buffer[phdr->p_offset + phdr->p_filesz], 0, phdr->p_memsz - phdr->p_filesz);
- }
-
- return result;
-}
-
-static ssize_t load_segments(int fd, Elf64_Ehdr *ehdr, Elf64_Phdr *phdrs, char *buffer)
-{
- int i;
-
- for (i = 0; i < ehdr->e_phnum; i++)
- {
- if (phdrs[i].p_type != PT_LOAD)
- {
- continue;
- }
-
- if (load_segment(fd, &phdrs[i], buffer) == -1)
- {
- return -1;
- }
- }
-
- return i;
+ return 0;
}
static struct image_buffer load_image(void)
@@ -97,37 +50,29 @@ static struct image_buffer load_image(void)
struct image_buffer buffer = { nullptr, 0 };
- if ((image_fd = efi_open(image_entry_path, O_RDONLY, 0)) == -1)
+ if ((image_fd = open(image_entry_path, O_RDONLY, 0)) == -1)
{
return buffer;
}
- Elf64_Ehdr ehdr;
-
- if (read_ehdr(image_fd, &ehdr) == -1)
+ if (!elf64_validate_fd(image_fd, ET_DYN, EM_X86_64))
{
return buffer;
}
-
- Elf64_Phdr *phdrs = efi_calloc_pool(ehdr.e_phnum, ehdr.e_phentsize);
-
- if (phdrs == nullptr)
+
+ if (create_image_buffer(image_fd, &buffer) < 0)
{
return buffer;
}
- else if(read_phdrs(image_fd, &ehdr, phdrs) != -1)
- {
- create_image_buffer(&ehdr, phdrs, &buffer);
- }
- if (buffer.base != nullptr && load_segments(image_fd, &ehdr, phdrs, buffer.base) == -1)
+ if (buffer.base != nullptr && elf64_load_segments(image_fd, buffer.length, buffer.base) < 0)
{
- efi_munmap(buffer.base, buffer.length);
+ printf("error detected: buffer {base: %p, length: %zu}\n", buffer.base, buffer.length);
+ munmap(buffer.base, buffer.length);
buffer.base = nullptr;
}
- efi_close(image_fd);
- efi_free_pool(phdrs);
+ close(image_fd);
return buffer;
}
@@ -179,17 +124,17 @@ int image_start(void)
image_entry(&params);
}
- if (efi_munmap(buffer.base, buffer.length) == -1)
+ if (munmap(buffer.base, buffer.length) == -1)
{
- efi_write(STDOUT_FILENO, "failed unmap\r\n", -1);
+ write(STDOUT_FILENO, "failed unmap\r\n", -1);
if (efi_errno == EFI_NOT_FOUND)
{
- efi_write(STDOUT_FILENO, "not found\r\n", -1);
+ write(STDOUT_FILENO, "not found\r\n", -1);
}
else
{
- efi_write(STDOUT_FILENO, "bad alignment?\r\n", -1);
+ write(STDOUT_FILENO, "bad alignment?\r\n", -1);
}
}
diff --git a/boot/efi/start.c b/boot/efi/start.c
index 8ef8cbe..f1f4ec7 100644
--- a/boot/efi/start.c
+++ b/boot/efi/start.c
@@ -4,6 +4,9 @@
#include <efi/tables.h>
#include "../kjarna.h"
+#include "../config.h"
+
+#include <libc/stdio.h>
#include "kjarna_efi.h"
struct efi_context const *efi_context;
@@ -21,12 +24,25 @@ EFI_STATUS _start(EFI_HANDLE handle, EFI_SYSTEM_TABLE *system_table)
system_table->ConOut->ClearScreen(system_table->ConOut);
+#ifdef DEBUG_WAIT
+ EFI_GUID lip_guid = EFI_LOADED_IMAGE_PROTOCOL_GUID;
+ EFI_LOADED_IMAGE_PROTOCOL *lip = efi_get_protocol(efi_context->handle, &lip_guid);
+
+ printf("DEBUG: EFI_LOADED_IMAGE_PROTOCOL { .ImageBase = %p }\n", lip->ImageBase);
+ __asm__ volatile ("movq %0, %%rax" :: "r"(lip->ImageBase) : "rax");
+ bool wait = true;
+
+ while(wait)
+ {
+ __asm__ ("hlt");
+ }
+#endif
+
if (main(0, nullptr) != 0)
{
efi_errno = EFI_ABORTED;
}
-
return _exit(efi_errno);
}
diff --git a/boot/efi/status.h b/boot/efi/status.h
new file mode 100644
index 0000000..bcb6b96
--- /dev/null
+++ b/boot/efi/status.h
@@ -0,0 +1,110 @@
+#pragma once
+
+#include <cstddef>
+#include <limits>
+#include <type_traits>
+
+namespace Efi
+{
+ class Status
+ {
+ using size_t = std::size_t;
+ using ssize_t = std::make_signed_t<size_t>;
+
+ size_t m_Value;
+
+ constexpr Status(size_t value)
+ : m_Value(value)
+ {
+ }
+
+ constexpr bool IsError() const
+ {
+ return static_cast<ssize_t>(m_Value) < 0;
+ }
+
+ constexpr bool IsWarning() const
+ {
+ return m_Value > 0;
+ }
+
+ constexpr bool IsSuccess() const
+ {
+ return m_Value == 0;
+ }
+
+ constexpr static Status ErrorStatus(size_t code)
+ {
+ auto errorBit = std::numeric_limits<ssize_t>::min();
+ return Status(static_cast<size_t>(errorBit) | code);
+ }
+
+ constexpr static Status WarningStatus(size_t code)
+ {
+ return Status(code);
+ }
+
+ public:
+
+ operator size_t() const
+ {
+ return m_Value;
+ }
+
+ static const Status Success;
+
+ class Warning
+ {
+ public:
+
+ static const Status UnknownGlyph;
+ static const Status DeleteFailure;
+ static const Status WriteFailure;
+ static const Status BufferTooSmall;
+ static const Status StaleData;
+ static const Status FileSystem;
+ static const Status ResetRequired;
+ };
+
+ class Error
+ {
+ public:
+
+ static const Status LoadError;
+ static const Status InvalidParameter;
+ static const Status Unsupported;
+ static const Status BadBufferSize;
+ static const Status BufferTooSmall;
+ static const Status NotReady;
+ static const Status DeviceError;
+ static const Status WriteProtected;
+ static const Status OutOfResources;
+ static const Status VolumeCorrupted;
+ static const Status VolumeFull;
+ static const Status NoMedia;
+ static const Status MediaChanged;
+ static const Status NotFound;
+ static const Status AccessDenied;
+ static const Status NoResponse;
+ static const Status NoMapping;
+ static const Status Timeout;
+ static const Status NotStarted;
+ static const Status AlreadyStarted;
+ static const Status Aborted;
+ static const Status IcmpError;
+ static const Status TftpError;
+ static const Status ProtocolError;
+ static const Status IncompatibleVersion;
+ static const Status SecurityViolation;
+ static const Status CrcError;
+ static const Status EndOfMedia;
+ static const Status EndOfFile;
+ static const Status InvalidLanguage;
+ static const Status CompromisedData;
+ static const Status IpAddressConflict;
+ static const Status HttpError;
+ };
+
+ };
+}
+
diff --git a/boot/efi/system_table.h b/boot/efi/system_table.h
new file mode 100644
index 0000000..93e839d
--- /dev/null
+++ b/boot/efi/system_table.h
@@ -0,0 +1,31 @@
+#pragma once
+
+#include "table.h"
+
+extern "C"
+{
+ struct efi_system_table
+ {
+ void *m_Value;
+ };
+}
+
+namespace Efi
+{
+ class SystemTable : private Table
+ {
+ char16_t *m_FirmwareVendor;
+ uint32_t m_FirmwareRevision;
+ Handle m_ConsoleInHandle;
+ void *m_ConIn;
+ Handle m_ConsoleOutHandle;
+ void *m_ConOut;
+ Handle m_StandardErrorHandle;
+ void *m_StdErr;
+ void *m_RuntimeServices;
+ void *m_BootServices;
+ size_t m_NumberOfTableEntries;
+ void *m_ConfigurationTable;
+ };
+}
+
diff --git a/boot/efi/table.h b/boot/efi/table.h
new file mode 100644
index 0000000..660bd1e
--- /dev/null
+++ b/boot/efi/table.h
@@ -0,0 +1,26 @@
+#pragma once
+
+#include <cstddef>
+#include <cstdint>
+
+namespace Efi
+{
+ class TableHeader
+ {
+ using uint64_t = std::uint64_t;
+ using uint32_t = std::uint32_t;
+ using size_t = std::size_t;
+
+ uint64_t m_Signature;
+ uint32_t m_Revision;
+ uint32_t m_HeaderSize;
+ uint32_t m_Crc32;
+ uint32_t m_Reserved;
+ };
+
+ class Table
+ {
+ TableHeader m_Header;
+ };
+}
+